/* Program to generate different byte pattern to help debug drsnapd. */ #include #include #include #include #include #include #include #include #include #include static long long getnow() { struct timeval t; gettimeofday(&t,NULL); return (long long)t.tv_sec *1000000 + t.tv_usec; } static void pattern_seek (int fd, int pos, int blocksize) { if (pos != 0){ unsigned long long offset = (unsigned long long)pos * blocksize; if (lseek64(fd,offset,SEEK_SET)==-1){ tlmp_error ("Can't seek at position %Lu (%s), exiting\n" ,offset,strerror(errno)); exit (-1); } } } static void pattern_duration( long long start, unsigned long long bytes, const char *verb) { long long end = getnow(); double diff = (end - start)/1000000.0; if (diff == 0) diff = 0.000001; printf ("%'Lu bytes %s in %.3lf seconds (thoughput %'.3lfk/s)\n" ,bytes,verb,diff,(bytes/1024)/diff); } static void pattern_throughput( long long start, long long last, long long now, int cumulblock, int partblock, int totalblock, unsigned long long blocksize) { unsigned long long cumulbytes = cumulblock * blocksize; unsigned long long partbytes = partblock * blocksize; double diff1 = (now - start)/1000000.0; if (diff1 == 0) diff1 = 0.000001; double t1 = (cumulbytes/1024)/diff1; double diff2 = (now - last)/1000000.0; if (diff2 == 0) diff2 = 0.000001; double t2 = (partbytes/1024)/diff2; double eta = diff1 * totalblock/cumulblock - diff1; printf ("%'9Luk in %7.3lf seconds: %'10.3lfk/s current %'10.3lfk/s eta %'10.3lf \r" ,cumulbytes/1024,diff1,t1 ,t2,eta); fflush (stdout); } int main (int argc, char *argv[]) { glocal int val = -1; glocal const char *blocksize = "1024k"; glocal int count; glocal int seek=0; glocal int ret = -1; glocal bool write=false; glocal bool verify=false; glocal bool throughput=false; glocal bool odirect=false; glocal.ret = (argc,argv); extern const char *version; setproginfo ("pattern",version,"Write or verify binary pattern"); setgrouparg ("Content"); setarg ('b',"blocksize","Block size used for writing (suffix b,k,m)" ,glocal.blocksize,false); setarg ('c',"count","Number of block written",glocal.count,true); setarg ('s',"seek","Jump N blocksize",glocal.seek,false); setarg ('v',"value","Integer value used to fill the block" ,glocal.val,false); setgrouparg ("Operations"); setarg ('V',"verify","Check if the pattern is already in place" ,glocal.verify,false); setarg ('W',"write","Write the pattern to the file" ,glocal.write,false); setgrouparg ("Misc."); setarg ('d',"direct","Use unbuffered O_DIRECT I/O" ,glocal.odirect,false); setarg ('t',"throughput","Show throughput on a regular basis" ,glocal.throughput,false); int ret = -1; int blocksize = atoi(glocal.blocksize); int odirect = glocal.odirect ? O_DIRECT : 0; { const char *pt = str_skipdig(glocal.blocksize); if (*pt != '\0'){ if (strcasecmp(pt,"b")==0){ blocksize *=1; }else if (strcasecmp(pt,"k")==0){ blocksize *=1024; }else if (strcasecmp(pt,"m")==0){ blocksize *=1024*1024; } printf ("blocksize %s -> %d\n",glocal.blocksize,blocksize); } } // Setup a buffer with a suitably aligned start // buf is a pointer inside obuf char obuf[blocksize+1024*2]; int *buf = (int*)((long)(obuf + 1023)&(~1023)); int b4 = blocksize/4; long long start = getnow(); unsigned long long bytes = (unsigned long long)blocksize*glocal.count; if (argc != 1){ usage(); }else if (glocal.write){ int fd = open (argv[0],O_RDWR|odirect,0); if (fd == -1){ tlmp_error ("Can't open file %s for writing (%s)\n" ,argv[0],strerror(errno)); }else{ ret = 0; pattern_seek (fd,glocal.seek,blocksize); long long last = start; int lasti = 0; for (int i=0; i return glocal.ret; }