/* */ #include #define __USE_XOPEN2K #include #include #include #define __USE_GNU #include #include #include #include #define BUFSIZE 8192 #define NBLKS 10 int main(int argc, char *argv[]) { int fd; int i, n; char *buf, *ptr; /* Open file */ if ((fd = open("file", O_DIRECT|/*O_SYNC|*/O_RDWR|O_CREAT, 0666)) < 0) { perror("open failed: "); exit(-1); } /* From: Terje Eggestad (terje.eggestad@scali.no) * Date: Sun Dec 16 2001 - 08:57:53 EST * * The problem is that the kernel that don't support O_DIRECT has * erronous handling of the O_DIRECT flag. Meaning they happily accept * it. * * In order to figure out if the running kernel support O_DIRECT you * MUST attempt an unaligned read/write, if it succed the kernel DON'T * support O_DIRECT. * * Martin Habets: man open states for O_DIRECT the buffer must be * aligned to 512 bytes at least. */ ptr = malloc(16); buf = ptr; /* Got an aligned buffer? Make it unaligned. */ if ((((unsigned) buf) & (512-1)) == 0) { buf = &ptr[8]; } memset(buf, 1, 8); n = write(fd, buf, 8); if (n == -1) { if (errno != EINVAL) { perror("unaligned write"); goto out; } printf("unaligned write failed, O_DIRECT is supported.\n"); } else if (n == 8) { printf("unaligned write suceeded, O_DIRECT is not supported.\n"); goto out; } free(ptr); lseek(fd, 0, SEEK_SET); /* Allocate aligned buffer, Create output file. */ n = posix_memalign((void **)&buf, 512, BUFSIZE*NBLKS); if (n != 0) { perror("posix_memalign() failed:"); exit(-1); } for (i = 1; i < NBLKS; i++) { memset(&buf[i*BUFSIZE], (i % 256), BUFSIZE); n = write(fd, &buf[i*BUFSIZE], BUFSIZE); if (n != BUFSIZE) { printf("write failed: %d %s\n", n, strerror(errno)); break; } /* This does not seem to help if (fsync(fd) != 0) { printf("sync failed: %s\n", strerror(errno)); break; } sleep(1); */ } out: /* Cleanup */ close(fd); free(buf); return 0; }