Author: avg
Date: Tue Nov 19 18:35:38 2013
New Revision: 258352
URL: http://svnweb.freebsd.org/changeset/base/258352

Log:
  fsx: add an option to randomly call msync(MS_INVALIDATE)
  
  This call should be a sufficiently close approximation of what happens
  when a filesystem is unmounted and remounted.  To be more specific, it
  should test that the data that was in the page cache is the same data
  that ends up on a stable storage or in a filesystem's internal cache,
  if any.
  This will catch the cases where a page with modified data is marked as
  a clean page for whatever reason.
  
  While there, make logging of the special events (open+close before
  plus invalidation now) more generic and slightly better than the previous
  hack.
  
  MFC after:    10 days

Modified:
  head/tools/regression/fsx/fsx.c

Modified: head/tools/regression/fsx/fsx.c
==============================================================================
--- head/tools/regression/fsx/fsx.c     Tue Nov 19 18:35:01 2013        
(r258351)
+++ head/tools/regression/fsx/fsx.c     Tue Nov 19 18:35:38 2013        
(r258352)
@@ -90,6 +90,7 @@ int                   logcount = 0;   /* total ops */
 #define OP_MAPREAD     5
 #define OP_MAPWRITE    6
 #define OP_SKIPPED     7
+#define OP_INVALIDATE  8
 
 int page_size;
 int page_mask;
@@ -107,6 +108,7 @@ unsigned long       testcalls = 0;          /* calls t
 
 unsigned long  simulatedopcount = 0;   /* -b flag */
 int    closeprob = 0;                  /* -c flag */
+int    invlprob = 0;                   /* -i flag */
 int    debug = 0;                      /* -d flag */
 unsigned long  debugstart = 0;         /* -D flag */
 unsigned long  maxfilelen = 256 * 1024;        /* -l flag */
@@ -131,6 +133,7 @@ int fsxgoodfd = 0;
 FILE * fsxlogf = NULL;
 int badoff = -1;
 int closeopen = 0;
+int invl = 0;
 
 
 void
@@ -182,14 +185,12 @@ prterr(char *prefix)
 
 
 void
-log4(int operation, int arg0, int arg1, int arg2)
+do_log4(int operation, int arg0, int arg1, int arg2)
 {
        struct log_entry *le;
 
        le = &oplog[logptr];
        le->operation = operation;
-       if (closeopen)
-               le->operation = ~ le->operation;
        le->args[0] = arg0;
        le->args[1] = arg1;
        le->args[2] = arg2;
@@ -201,10 +202,21 @@ log4(int operation, int arg0, int arg1, 
 
 
 void
+log4(int operation, int arg0, int arg1, int arg2)
+{
+       do_log4(operation, arg0, arg1, arg2);
+       if (closeopen)
+               do_log4(OP_CLOSEOPEN, 0, 0, 0);
+       if (invl)
+               do_log4(OP_INVALIDATE, 0, 0, 0);
+}
+
+
+void
 logdump(void)
 {
-       int     i, count, down;
        struct log_entry        *lp;
+       int     i, count, down, opnum;
 
        prt("LOG DUMP (%d total operations):\n", logcount);
        if (logcount < LOGSIZE) {
@@ -214,15 +226,28 @@ logdump(void)
                i = logptr;
                count = LOGSIZE;
        }
+
+       opnum = i + 1 + (logcount/LOGSIZE)*LOGSIZE;
        for ( ; count > 0; count--) {
-               int opnum;
+               lp = &oplog[i];
+
+               if (lp->operation == OP_CLOSEOPEN ||
+                   lp->operation == OP_INVALIDATE) {
+                       switch (lp->operation) {
+                       case OP_CLOSEOPEN:
+                               prt("\t\tCLOSE/OPEN\n");
+                               break;
+                       case OP_INVALIDATE:
+                               prt("\t\tMS_INVALIDATE\n");
+                               break;
+                       }
+                       i++;
+                       if (i == LOGSIZE)
+                               i = 0;
+                       continue;
+               }
 
-               opnum = i+1 + (logcount/LOGSIZE)*LOGSIZE;
                prt("%d(%d mod 256): ", opnum, opnum%256);
-               lp = &oplog[i];
-               if ((closeopen = lp->operation < 0))
-                       lp->operation = ~ lp->operation;
-                       
                switch (lp->operation) {
                case OP_MAPREAD:
                        prt("MAPREAD\t0x%x thru 0x%x\t(0x%x bytes)",
@@ -275,9 +300,8 @@ logdump(void)
                        prt("BOGUS LOG ENTRY (operation code = %d)!",
                            lp->operation);
                }
-               if (closeopen)
-                       prt("\n\t\tCLOSE/OPEN");
                prt("\n");
+               opnum++;
                i++;
                if (i == LOGSIZE)
                        i = 0;
@@ -779,6 +803,36 @@ docloseopen(void)
 
 
 void
+doinvl(void)
+{
+       char *p;
+
+       if (file_size == 0)
+               return;
+       if (testcalls <= simulatedopcount)
+               return;
+       if (debug)
+               prt("%lu msync(MS_INVALIDATE)\n", testcalls);
+
+       if ((p = (char *)mmap(0, file_size, PROT_READ | PROT_WRITE,
+                             MAP_FILE | MAP_SHARED, fd, 0)) == MAP_FAILED) {
+               prterr("doinvl: mmap");
+               report_failure(205);
+       }
+
+       if (msync(p, 0, MS_SYNC | MS_INVALIDATE) != 0) {
+               prterr("doinvl: msync");
+               report_failure(206);
+       }
+
+       if (munmap(p, file_size) != 0) {
+               prterr("doinvl: munmap");
+               report_failure(207);
+       }
+}
+
+
+void
 test(void)
 {
        unsigned long   offset;
@@ -798,6 +852,8 @@ test(void)
 
        if (closeprob)
                closeopen = (rv >> 3) < (1 << 28) / closeprob;
+       if (invlprob)
+               invl = (rv >> 3) < (1 << 28) / invlprob;
 
        if (debugstart > 0 && testcalls >= debugstart)
                debug = 1;
@@ -845,6 +901,8 @@ test(void)
        }
        if (sizechecks && testcalls > simulatedopcount)
                check_size();
+       if (invl)
+               doinvl();
        if (closeopen)
                docloseopen();
 }
@@ -869,6 +927,7 @@ usage(void)
        -b opnum: beginning operation number (default 1)\n\
        -c P: 1 in P chance of file close+open at each op (default infinity)\n\
        -d: debug output for all operations\n\
+       -i P: 1 in P chance of calling msync(MS_INVALIDATE) (default 
infinity)\n\
        -l flen: the upper bound on file size (default 262144)\n\
        -m startop:endop: monitor (print debug output) specified byte range 
(default 0:infinity)\n\
        -n: no verifications of file size\n\
@@ -944,7 +1003,7 @@ main(int argc, char **argv)
        setvbuf(stdout, (char *)0, _IOLBF, 0); /* line buffered stdout */
 
        while ((ch = getopt(argc, argv,
-           "b:c:dl:m:no:p:qr:s:t:w:D:LN:OP:RS:UW")) != -1)
+           "b:c:di:l:m:no:p:qr:s:t:w:D:LN:OP:RS:UW")) != -1)
                switch (ch) {
                case 'b':
                        simulatedopcount = getnum(optarg, &endp);
@@ -967,6 +1026,15 @@ main(int argc, char **argv)
                case 'd':
                        debug = 1;
                        break;
+               case 'i':
+                       invlprob = getnum(optarg, &endp);
+                       if (!quiet)
+                               fprintf(stdout,
+                                       "Chance of MS_INVALIDATE is 1 in %d\n",
+                                       invlprob);
+                       if (invlprob <= 0)
+                               usage();
+                       break;
                case 'l':
                        maxfilelen = getnum(optarg, &endp);
                        if (maxfilelen <= 0)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to