/ Check-in [6ec7367d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add a test that simulates an error in mmap().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental-mmap
Files: files | file ages | folders
SHA1: 6ec7367d8e98425f00eeb8215ca8964313c1d0b7
User & Date: dan 2013-03-25 19:05:07
Context
2013-03-25
19:57
Merge all recent trunk changes into the experimental-mmap branch. check-in: a607d63f user: drh tags: experimental-mmap
19:05
Add a test that simulates an error in mmap(). check-in: 6ec7367d user: dan tags: experimental-mmap
18:25
Simulate OOM errors in the sqlite3OsFetch() function. Run malloc.test as part of the "mmap" permutation. check-in: 77443ef2 user: dan tags: experimental-mmap
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

   440    440   
   441    441     { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
   442    442   #define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)
   443    443   
   444    444     { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
   445    445   #define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
   446    446   
          447  +  { "mmap",       (sqlite3_syscall_ptr)mmap,     0 },
          448  +#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
          449  +
   447    450   }; /* End of the overrideable system calls */
   448    451   
   449    452   /*
   450    453   ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
   451    454   ** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
   452    455   ** system call pointer, or SQLITE_NOTFOUND if there is no configurable
   453    456   ** system call named zName.
................................................................................
  4543   4546     if( nMap!=pFd->mmapSize ){
  4544   4547       unixUnmapfile(pFd);
  4545   4548   
  4546   4549       if( nMap>0 ){
  4547   4550         void *pNew;
  4548   4551         int flags = PROT_READ;
  4549   4552         if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
  4550         -      pNew = mmap(0, nMap, flags, MAP_SHARED, pFd->h, 0);
         4553  +      pNew = osMmap(0, nMap, flags, MAP_SHARED, pFd->h, 0);
  4551   4554         if( pNew==MAP_FAILED ){
  4552   4555           return SQLITE_IOERR_MMAP;
  4553   4556         }
  4554   4557   
  4555   4558         pFd->pMapRegion = pNew;
  4556   4559         pFd->mmapSize = nMap;
  4557   4560         pFd->mmapOrigsize = nMap;
................................................................................
  7182   7185       UNIXVFS("unix-proxy",    proxyIoFinder ),
  7183   7186   #endif
  7184   7187     };
  7185   7188     unsigned int i;          /* Loop counter */
  7186   7189   
  7187   7190     /* Double-check that the aSyscall[] array has been constructed
  7188   7191     ** correctly.  See ticket [bb3a86e890c8e96ab] */
  7189         -  assert( ArraySize(aSyscall)==21 );
         7192  +  assert( ArraySize(aSyscall)==22 );
  7190   7193   
  7191   7194     /* Register all VFSes defined in the aVfs[] array */
  7192   7195     for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
  7193   7196       sqlite3_vfs_register(&aVfs[i], i==0);
  7194   7197     }
  7195   7198     return SQLITE_OK; 
  7196   7199   }

Changes to src/test_syscall.c.

    19     19   **   test_syscall install LIST
    20     20   **     Install wrapper functions for all system calls in argument LIST.
    21     21   **     LIST must be a list consisting of zero or more of the following
    22     22   **     literal values:
    23     23   **
    24     24   **         open        close      access   getcwd   stat      fstat    
    25     25   **         ftruncate   fcntl      read     pread    pread64   write
    26         -**         pwrite      pwrite64   fchmod   fallocate
           26  +**         pwrite      pwrite64   fchmod   fallocate mmap
    27     27   **
    28     28   **   test_syscall uninstall
    29     29   **     Uninstall all wrapper functions.
    30     30   **
    31     31   **   test_syscall fault ?COUNT PERSIST?
    32     32   **     If [test_syscall fault] is invoked without the two arguments, fault
    33     33   **     injection is disabled. Otherwise, fault injection is configured to
................................................................................
    77     77   
    78     78   #include "sqliteInt.h"
    79     79   #if SQLITE_OS_UNIX
    80     80   
    81     81   /* From test1.c */
    82     82   extern const char *sqlite3TestErrorName(int);
    83     83   
           84  +#include <sys/mman.h>
    84     85   #include <sys/types.h>
    85     86   #include <errno.h>
    86     87   
    87     88   static struct TestSyscallGlobal {
    88     89     int bPersist;                   /* 1 for persistent errors, 0 for transient */
    89     90     int nCount;                     /* Fail after this many more calls */
    90     91     int nFail;                      /* Number of failures that have occurred */
................................................................................
   102    103   static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off);
   103    104   static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off);
   104    105   static int ts_write(int fd, const void *aBuf, size_t nBuf);
   105    106   static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off);
   106    107   static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off);
   107    108   static int ts_fchmod(int fd, mode_t mode);
   108    109   static int ts_fallocate(int fd, off_t off, off_t len);
          110  +static void *ts_mmap(void *, size_t, int, int, int, off_t);
   109    111   
   110    112   
   111    113   struct TestSyscallArray {
   112    114     const char *zName;
   113    115     sqlite3_syscall_ptr xTest;
   114    116     sqlite3_syscall_ptr xOrig;
   115    117     int default_errno;              /* Default value for errno following errors */
................................................................................
   127    129     /*  9 */ { "pread",     (sqlite3_syscall_ptr)ts_pread,     0, 0, 0 },
   128    130     /* 10 */ { "pread64",   (sqlite3_syscall_ptr)ts_pread64,   0, 0, 0 },
   129    131     /* 11 */ { "write",     (sqlite3_syscall_ptr)ts_write,     0, 0, 0 },
   130    132     /* 12 */ { "pwrite",    (sqlite3_syscall_ptr)ts_pwrite,    0, 0, 0 },
   131    133     /* 13 */ { "pwrite64",  (sqlite3_syscall_ptr)ts_pwrite64,  0, 0, 0 },
   132    134     /* 14 */ { "fchmod",    (sqlite3_syscall_ptr)ts_fchmod,    0, 0, 0 },
   133    135     /* 15 */ { "fallocate", (sqlite3_syscall_ptr)ts_fallocate, 0, 0, 0 },
          136  +  /* 16 */ { "mmap",      (sqlite3_syscall_ptr)ts_mmap,      0, 0, 0 },
   134    137              { 0, 0, 0, 0, 0 }
   135    138   };
   136    139   
   137    140   #define orig_open      ((int(*)(const char *, int, int))aSyscall[0].xOrig)
   138    141   #define orig_close     ((int(*)(int))aSyscall[1].xOrig)
   139    142   #define orig_access    ((int(*)(const char*,int))aSyscall[2].xOrig)
   140    143   #define orig_getcwd    ((char*(*)(char*,size_t))aSyscall[3].xOrig)
................................................................................
   148    151   #define orig_write     ((ssize_t(*)(int,const void*,size_t))aSyscall[11].xOrig)
   149    152   #define orig_pwrite    ((ssize_t(*)(int,const void*,size_t,off_t))\
   150    153                          aSyscall[12].xOrig)
   151    154   #define orig_pwrite64  ((ssize_t(*)(int,const void*,size_t,off_t))\
   152    155                          aSyscall[13].xOrig)
   153    156   #define orig_fchmod    ((int(*)(int,mode_t))aSyscall[14].xOrig)
   154    157   #define orig_fallocate ((int(*)(int,off_t,off_t))aSyscall[15].xOrig)
          158  +#define orig_mmap      ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[16].xOrig)
   155    159   
   156    160   /*
   157    161   ** This function is called exactly once from within each invocation of a
   158    162   ** system call wrapper in this file. It returns 1 if the function should
   159    163   ** fail, or 0 if it should succeed.
   160    164   */
   161    165   static int tsIsFail(void){
................................................................................
   372    376   */
   373    377   static int ts_fallocate(int fd, off_t off, off_t len){
   374    378     if( tsIsFail() ){
   375    379       return tsErrno("fallocate");
   376    380     }
   377    381     return orig_fallocate(fd, off, len);
   378    382   }
          383  +
          384  +static void *ts_mmap(
          385  +  void *pAddr, 
          386  +  size_t nByte, 
          387  +  int prot, 
          388  +  int flags, 
          389  +  int fd, 
          390  +  off_t iOff
          391  +){
          392  +  if( tsIsFailErrno("mmap") ){
          393  +    return MAP_FAILED;
          394  +  }
          395  +  return orig_mmap(pAddr, nByte, prot, flags, fd, iOff);
          396  +}
   379    397   
   380    398   static int test_syscall_install(
   381    399     void * clientData,
   382    400     Tcl_Interp *interp,
   383    401     int objc,
   384    402     Tcl_Obj *CONST objv[]
   385    403   ){

Changes to test/malloc_common.tcl.

   260    260   # by -test scripts.
   261    261   #
   262    262   proc faultsim_test_result_int {args} {
   263    263     upvar testrc testrc testresult testresult testnfail testnfail
   264    264     set t [list $testrc $testresult]
   265    265     set r $args
   266    266     if { ($testnfail==0 && $t != [lindex $r 0]) || [lsearch $r $t]<0 } {
   267         -    error "nfail=$testnfail rc=$testrc result=$testresult"
          267  +    error "nfail=$testnfail rc=$testrc result=$testresult list=$r"
   268    268     }
   269    269   }
   270    270   
   271    271   #--------------------------------------------------------------------------
   272    272   # Usage do_one_faultsim_test NAME ?OPTIONS...? 
   273    273   #
   274    274   # The first argument, <test number>, is used as a prefix of the test names

Changes to test/sysfault.test.

   238    238       INSERT INTO t1 VALUES(randomblob(10000), randomblob(10000));
   239    239       SELECT length(a) + length(b) FROM t1;
   240    240       COMMIT;
   241    241     }
   242    242   } -test {
   243    243     faultsim_test_result {0 20000}
   244    244   }
          245  +
          246  +#-------------------------------------------------------------------------
          247  +# Test errors in mmap().
          248  +#
          249  +proc vfsfault_install {} { 
          250  +  test_syscall reset
          251  +  test_syscall install {mmap}
          252  +}
          253  +
          254  +faultsim_delete_and_reopen
          255  +execsql {
          256  +  CREATE TABLE t1(a, b);
          257  +  INSERT INTO t1 VALUES(1, 2);
          258  +}
          259  +faultsim_save_and_close
          260  +
          261  +do_faultsim_test 4 -faults vfsfault-* -prep {
          262  +  faultsim_restore_and_reopen
          263  +  file_control_chunksize_test db main 8192
          264  +  execsql { 
          265  +    PRAGMA mmap_size = 1000000;
          266  +  }
          267  +} -body {
          268  +  test_syscall errno mmap     EACCES
          269  +
          270  +  execsql {
          271  +    SELECT * FROM t1;
          272  +  }
          273  +} -test {
          274  +  faultsim_test_result {0 {1 2}} {1 {disk I/O error}}
          275  +}
   245    276   
   246    277   finish_test
   247    278