Read a RAID device directly using read(2) - c

I have create a Linux Software RAID, with chunk size 4096B, and 4 disks.
Then, I'm trying to do write and read test on the RAID, say /dev/md0.
The following code is read test and BLOCK_SIZE is the amount I want to read. However, whenever I set it not power of 2, such as 3*4096, I will get an error after read, saying "Invalid Argument". And it is the same case with write.
As far as I can understand, read(2) and write(2) should be able to perform operation on any amount of bytes the user wants, so please help me with it and the code.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#define BLOCK_SIZE 8*4096 //bytes
#define BUFF_OFFSET 8*4096
int main(int argc, char *argv[]){
char device[64];
int fd;
void *buff;
int size; //bytes
int seek;
fd = open(argv[1], O_DIRECT | O_RSYNC | O_RDONLY);
posix_memalign(&buff, BUFF_OFFSET, BLOCK_SIZE);
int load;
seek = lseek(fd,0,SEEK_SET);
load = read(fd,buff,BLOCK_SIZE);
if (load < 0){
printf("Cannot read\n");
perror("because");
break;
}
else{
printf("%d\n",load);
}
close(fd);
return 0;
}

Related

How many structs go into a file? in c

I need to open a file that contains information and map that data using mmap. The data will be accessed by casting the mmap call with a struct. The problem is the file has information to fill approximately 3 structs because the data is repeated. So I need to access that information in chunks, I don't know if the explanation makes any sense.
The file has 384 bytes and the struct covers 128 bytes so I will need something like 3 structs in total.
I don't know how to do that. I already have mapped the file and printed the first struct.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>
struct mapped
{
/* Struct fields */
};
int main (int argc, char **argv){
int fd = open("file",O_RDONLY,S_IRUSR | S_IWUSR);
struct stat st;
if(fstat(fd,&st)==-1) perror("Error\n");
struct mapped *data = mmap(0,st.st_size,PROT_READ | PROT_WRITE,MAP_PRIVATE,fd,0);
printf("\n");
printf("File size: %li",st.st_size);
printf("\n");
printf(": %li",st.st_size);
printf("\n");
printf("\n");
// print the struct data;
printf("\n");
close(fd);
munmap(data,st.st_size);
exit(EXIT_SUCCESS);
}

Reading and writng with named pipes C

I'm writing a program that should run indefinitely maintaining the value of a variable. Two other programs could change the value of the variable. I use named pipes to receive and send the variable value to external programs.
Here is my code for the manager of the variable.
manager.c:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
char a = 'a';
void *editTask(void *dummy)
{
int fd;
char* editor = "editor";
mkfifo(editor, 0666);
while(1)
{
fd = open(editor, O_RDONLY);
read(fd, &a, 1);
close(fd);
}
}
void *readTask(void *dummy)
{
int fd;
char* reader = "reader";
mkfifo(reader, 0666);
while(1)
{
fd = open(reader, O_WRONLY);
write(fd,&a,1);
close(fd);
}
}
int main()
{
pthread_t editor_thread, reader_thread;
pthread_create(&editor_thread, NULL, editTask, NULL);
pthread_create(&reader_thread, NULL, readTask, NULL);
pthread_join (editor_thread, NULL);
pthread_join (reader_thread, NULL);
return 0;
}
This program uses pthreads to separately get external values for the variable and to communicate the current value of the variable to external programs.
The program that is able to write values to the variable is:
writer.c:
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char** argv)
{
if(argc != 2)
{
printf("Need an argument!\n");
return 0;
}
int fd;
char * myfifo = "editor";
fd = open(myfifo, O_WRONLY);
write(fd, argv[0], 1);
close(fd);
return 0;
}
The program that could read the current value is:
reader.c:
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int fd;
char * myfifo = "reader";
fd = open(myfifo, O_RDONLY);
char value = 'z';
read(fd, &value, 1);
printf("The current value of the variable is:%c\n",value);
close(fd);
return 0;
}
I ran these programs in my Ubuntu system as follows:
$ ./manager &
[1] 5226
$ ./writer k
$ ./reader
bash: ./reader: Text file busy
Why doesn't my system allow me to run this program?
Thank you.
You are trying to call both the FIFO and the reader program "reader".
Also, you have no error checking. You have no idea whether those calls to mkfifo and open succeeded or not. Adding this is critical before you attempt to do any troubleshooting.

sending a string between two programs using named pipes

I am trying to send a string to another program
but i am having problem using O_WRONLY | O_NONBLOCK,
if i replace that with O_RDWR the program works fine
but i wanted to know if there is a way to send/read the
string without using O_RDWR. Right now it returns a
empty string for some reason.
Writer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define MAX_LINE 1024
int main(int argc, char **argv)
{
char line[MAX_LINE];
int pipe;
printf("Enter line: \n");
fgets(line, MAX_LINE, stdin);
pipe = open("link1", O_WRONLY | O_NONBLOCK);
write(pipe, line, strlen(line));
system("./run"); //executing the reader
close(pipe);
return 0;
}
reader:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define MAX_BUF 1024
int main(int argc, char **argv)
{
int fd;
char * link1 = "link1";
char buf[MAX_BUF];
fd = open(link1, O_RDONLY | O_NONBLOCK);
read(fd, buf, MAX_BUF);
printf("%s\n", buf);
close(fd);
return 0;
}
Are you running the reader first? If no process has the FIFO open for reading when the writer attempts to open it write only, then the open will fail.
From the Open Group man page:
When opening a FIFO with O_RDONLY or O_WRONLY set: If O_NONBLOCK is set:
An open() for reading only will return without delay. An open() for writing only will return an error if no process currently has the file open for reading.

IPC FIFO Producer-Consumer Deadlock

This is the producer.
// speak.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
char s[300];
int num, fd;
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for readers...\n");
fd = open(FIFO_NAME, O_WRONLY);
printf("got a reader--type some stuff\n");
while (gets(s), !feof(stdin)) {
if ((num = write(fd, s, strlen(s))) == -1)
perror("write");
else
printf("speak: wrote %d bytes\n", num);
}
return 0;
}
And this is the consumer.
//tick.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
char s[300];
int num, fd;
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for writers...\n");
fd = open(FIFO_NAME, O_RDONLY);
printf("got a writer\n");
do {
if ((num = read(fd, s, 300)) == -1)
perror("read");
else {
s[num] = '\0';
printf("tick: read %d bytes: \"%s\"\n", num, s);
}
} while (num > 0);
return 0;
}
When I run them, Producer outputs,
waiting for readers...
And consumer outputs,
waiting for writers...
speak doesn't find the reader, tick. As from the theory here I got that, open() (speak.c) will be keep blocked until open() (tick.c) is opened. And the vice versa. So I guess there a deadlock or something happening. I need a solution of this.
It looks like you have a race condition between the reader and the writer.
To fix this, you need a method of not launching the reader until the writer is "active". For this, I'd suggest making a pipe and writing to it when the writer is ready. Then, when reading from the read end of the fork succeeds, the fifo is prepared and the reader should work.
You need to use forks here because coordinating mutexes between a parent and a child process is non-trivial and properly done pipes is easier.
Also, you called mknod() twice. Granted, it'll return -1 with errno == EEXIST, but be more careful. To avoid this, make the reader and writer a function that takes a path as an argument.
Rewrite your writer as int speak(const char *fifo, int pipefd) and your reader as int tick(const char *fifo).
Then make a wrapper like this:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
const char fifo_name[] /* = ... */;
int speak(const char *fifo, int pipefd);
int tick(const char *fifo);
int main() {
int pipefd[2];
pipe(pipefd);
mknod(fifo_name, S_IFIFO | 0666, 0);
if (fork() == 0) {
close(pipefd[0]);
return speak(fifo_name, pipefd[1]);
} else {
close(pipefd[1]);
char foo;
read(pipefd[0], &foo, 1);
return tick(fifo_name);
}
}
Modify your writer to print a byte (of anything) to the passed fd after the fifo is created (i.e. right after the call to open(..., O_WRONLY)).
Don't use my code verbatim, as I've omitted error checking for the sake of brevity.
it runs ok in my env. and if reader and writer is ready, open will return. because open is blocked, so in my opinion, mknod function is success. May be you excute these two process at different path.

problem with O_DIRECT IO with aligned stack buffer

The following code fails when the buffer is on the stack, but succeeds when it's allocated on the heap. I tested it on RHEL 5.3 with a Raid drive. Is it possible to use O_DIRECT with stack buffers?
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <malloc.h>
#define K 1024
#define ALIGNMENT (4*K)
#define RDSIZE (16*K)
#define BLOCKSIZE (512*K)
int main()
{
int flags = O_RDONLY | O_LARGEFILE;
int n = 0;
int fd = 0;
char* buf = (char *) memalign(ALIGNMENT, BLOCKSIZE);
//char buf[BLOCKSIZE] __attribute__((__aligned__(ALIGNMENT)));
assert(((long)buf) % ALIGNMENT == 0);
fd = open("test", flags | O_DIRECT);
if (fd < 0) {
perror("file open");
return -1;
}
n = read(fd, buf, RDSIZE);
if (n < 0) {
perror("file read");
return -1;
}
printf("%d\n", n);
close(fd);
}
UPDATE: Same code when compiled with Intel CC succeeds.
Check your stack size 512K is quite a lot.
If the problem is gcc misaligning buf, try this portable version instead:
char x_buf[BLOCKSIZE+PAGE_SIZE];
char *buf = buf + (PAGE_SIZE-1 & -(uintptr_t)x_buf);

Resources