#define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE #include #include #include #include #include #include #include #include #include #include #include #ifndef O_DIRECT #define O_DIRECT 040000 /* direct disk access hint */ #endif const char *progname; #define NBLK 10 #define NTRL 100 #define BLKSZ 1024 int displaywidth; char *what; static void usage(void) { fprintf(stderr, "Usage: %s blockdevice\n", progname); exit(1); } char b[NBLK][BLKSZ]; struct { off64_t where; int which; } trials[NTRL]; static uint64_t rnd(uint64_t limit) { double r = (unsigned long)random(); r *= limit; r /= RAND_MAX; return (uint64_t)r; } static void do_randomise(void) { int i; int j; for (i = 0; i < NBLK; i++) { for (j = 0; j < BLKSZ; j++) b[i][j] = random(); } } static void setup_display(void) { int cols = 80; struct winsize w; if (ioctl(0, TIOCGWINSZ, &w) == 0) cols = w.ws_col; what = malloc(cols + 1); memset(what, ' ', cols); what[cols] = 0; displaywidth = cols; } static void update_display(int i, off64_t sz) { int x = trials[i].where * displaywidth / sz; switch (what[x]) { case ' ': what[x] = '.'; break; case '.': what[x] = '-'; break; case '-': what[x] = '_'; break; case '_': what[x] = '+'; break; case '+': what[x] = '='; break; case '=': what[x] = 'o'; break; case 'o': what[x] = 'a'; break; case 'a': what[x] = 'x'; break; case 'x': what[x] = '%'; break; default: what[x] = '#'; break; } printf("\r%s", what); fflush(stdout); } static void endit(void) { printf("\n"); exit(0); } static void do_writes(int fd, off64_t sz) { int i; int n; for (i = 0; i < NTRL; i++) { trials[i].where = rnd(sz) & ~511ULL; trials[i].which = random() % NBLK; update_display(i, sz); if (lseek64(fd, trials[i].where, SEEK_SET) == -1) { fprintf(stderr, "\nFailed to seek to %llu for writing: %s\n", trials[i].where, strerror(errno)); endit(); } if ((n = write(fd, b[trials[i].which], BLKSZ)) != BLKSZ) { fprintf(stderr, "\nFailed to write %d bytes at %llu:%s \n", BLKSZ - (n == -1 ? 0 : n), trials[i].where, strerror(errno)); endit(); } } } static void do_reads(int fd) { int i; char buf[BLKSZ]; for (i = 0; i < NTRL; i++) { if (lseek64(fd, trials[i].where, SEEK_SET) == -1) { fprintf(stderr, "\nFailed to seek to %llu for reading: %s\n", trials[i].where, strerror(errno)); endit(); } if (read(fd, buf, BLKSZ) != BLKSZ) { fprintf(stderr, "\nFailed to read BLKSZ bytes at %llu\n: %s", trials[i].where, strerror(errno)); endit(); } if (memcmp(buf, b[trials[i].which], BLKSZ)) { fprintf(stderr, "\nBlock read from %llu not the same as was written\n", trials[i].where); endit(); } } } int main(int ac, char *av[]) { int fd; off64_t sz; int i; progname = av[0]; if (av[1] == NULL) usage(); srandom(10); setup_display(); if ((fd = open(av[1], O_RDWR|O_LARGEFILE)) == -1) { perror(av[1]); return 1; } sz = lseek64(fd, 0, SEEK_END); for (i = 0; i < 1000; i++) { do_randomise(); do_writes(fd, sz); do_reads(fd); } endit(); return 0; }