size_t airDioRead(int fd, void *_ptr, size_t size) { size_t red, totalred; int align, min, max, flags; size_t remain, part; char *ptr; if (!( _ptr && airNoDio_okay == airDioTest(fd, _ptr, size) )) { return 0; } flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, flags | FDIRECT); airDioInfo(&align, &min, &max, fd); remain = size; totalred = 0; ptr = (char*)_ptr; do { part = AIR_MIN(remain, max); red = read(fd, ptr, part); totalred += red; if (red != part) { break; } ptr += red; remain -= red; } while (remain); fcntl(fd, F_SETFL, flags); return totalred; }
size_t airDioWrite(int fd, const void *_ptr, size_t size) { size_t rit, totalrit; int align, min, max, flags; size_t remain, part; char *ptr; if (!( _ptr && (airNoDio_okay == airDioTest(fd, _ptr, size)) )) { return 0; } flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, flags | FDIRECT); airDioInfo(&align, &min, &max, fd); remain = size; totalrit = 0; ptr = (char*)_ptr; do { part = AIR_MIN(remain, max); rit = write(fd, ptr, part); totalrit += rit; if (rit != part) { break; } ptr += rit; remain -= rit; } while (remain); fcntl(fd, F_SETFL, flags); return totalrit; }
void * airDioMalloc(size_t size, int fd) { int align, min, max; airDioInfo(&align, &min, &max, fd); return memalign(align, size); }
int main(int argc, char *argv[]) { #if TEEM_DIO == 0 AIR_UNUSED(argc); fprintf(stderr, "%s: no direct-io testing for you\n", argv[0]); return 1; #else char *me, *fname, *multS, *data; FILE *file; double time0, time1, time2; int fd, align, mult, min, max, ret; size_t size; airArray *mop; me = argv[0]; if (3 != argc) { /* 0 1 2 (3) */ fprintf(stderr, "usage: %s <filename> <mult>\n", me); return 1; } fname = argv[1]; multS = argv[2]; if (1 != sscanf(multS, "%d", &mult)) { fprintf(stderr, "%s: couln't parse mult %s as int\n", me, multS); return 1; } mop = airMopNew(); if (!(file = fopen(fname, "w"))) { fprintf(stderr, "%s: couldn't open %s for writing\n", me, fname); airMopError(mop); return 1; } airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); fd = fileno(file); if (-1 == fd) { fprintf(stderr, "%s: couldn't get underlying descriptor\n", me); airMopError(mop); return 1; } fprintf(stderr, "%s: fd(%s) = %d\n", me, fname, fd); ret = airDioTest(fd, NULL, 0); if (airNoDio_okay != ret) { fprintf(stderr, "%s: no good: \"%s\"\n", me, airNoDioErr(ret)); airMopError(mop); return 1; } airDioInfo(&align, &min, &max, fd); fprintf(stderr, "%s: --> align=%d, min=%d, max=%d\n", me, align, min, max); size = (size_t)max*mult; data = airDioMalloc(size, fd); if (!data) { fprintf(stderr, "%s: airDioMalloc(" _AIR_SIZE_T_CNV ") failed\n", me, size); airMopError(mop); return 1; } airMopAdd(mop, data, airFree, airMopAlways); fprintf(stderr, "\ndata size = %g MB\n", (double)size/(1024*1024)); /* -------------------------------------------------------------- */ fprintf(stderr, "(1) non-aligned memory, regular write:\n"); time0 = airTime(); if (size-1 != write(fd, data+1, size-1)) { fprintf(stderr, "%s: write failed\n", me); airMopError(mop); return 1; } time1 = airTime(); fsync(fd); time2 = airTime(); fprintf(stderr, " time = %g + %g = %g (%g MB/sec)\n", time1 - time0, time2 - time1, time2 - time0, (size/(1024*1024)) / (time2 - time0)); airMopSub(mop, file, (airMopper)airFclose); fclose(file); /* -------------------------------------------------------------- */ /* -------------------------------------------------------------- */ fprintf(stderr, "(2) aligned memory, regular write:\n"); file = fopen(fname, "w"); airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); fd = fileno(file); time0 = airTime(); if (size != write(fd, data, size)) { fprintf(stderr, "%s: write failed\n", me); airMopError(mop); return 1; } time1 = airTime(); fsync(fd); time2 = airTime(); fprintf(stderr, " time = %g + %g = %g (%g MB/sec)\n", time1 - time0, time2 - time1, time2 - time0, (size/(1024*1024)) / (time2 - time0)); airMopSub(mop, file, (airMopper)airFclose); fclose(file); /* -------------------------------------------------------------- */ /* -------------------------------------------------------------- */ fprintf(stderr, "(3) aligned memory, air's direct IO:\n"); file = fopen(fname, "w"); airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); fd = fileno(file); time0 = airTime(); if (size != airDioWrite(fd, data, size)) { fprintf(stderr, "%s: write failed\n", me); airMopError(mop); return 1; } time1 = airTime(); fsync(fd); time2 = airTime(); fprintf(stderr, " time = %g + %g = %g (%g MB/sec)\n", time1 - time0, time2 - time1, time2 - time0, (size/(1024*1024)) / (time2 - time0)); airMopSub(mop, file, (airMopper)airFclose); fclose(file); /* -------------------------------------------------------------- */ /* -------------------------------------------------------------- */ fprintf(stderr, "(4) aligned memory, direct IO by hand:\n"); { /* "input": fname, size, data */ int flags; struct dioattr dio; char *ptr; size_t remain, totalrit, rit, part; file = fopen(fname, "w"); if (-1 == (fd = fileno(file))) { fprintf(stderr, "%s: couldn't get underlying descriptor\n", me); airMopError(mop); return 1; } airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); flags = fcntl(fd, F_GETFL); if (-1 == fcntl(fd, F_SETFL, flags | FDIRECT)) { fprintf(stderr, "%s: couldn't turn on direct IO\n", me); airMopError(mop); return 1; } if (0 != fcntl(fd, F_DIOINFO, &dio)) { fprintf(stderr, "%s: couldn't learn direct IO specifics", me); airMopError(mop); return 1; } remain = size; totalrit = 0; ptr = data; time0 = airTime(); do { part = remain > dio.d_maxiosz ? dio.d_maxiosz : remain; rit = write(fd, ptr, part); if (rit != part) { fprintf(stderr, "%s: write failed\n", me); airMopError(mop); return 1; } totalrit += rit; ptr += rit; remain -= rit; } while (remain); time1 = airTime(); fsync(fd); time2 = airTime(); fprintf(stderr, " time = %g + %g = %g (%g MB/sec)\n", time1 - time0, time2 - time1, time2 - time0, (size/(1024*1024)) / (time2 - time0)); airMopSub(mop, file, (airMopper)airFclose); fclose(file); } /* -------------------------------------------------------------- */ airMopError(mop); exit(0); #endif }