/ Check-in [8dbe89d0]
Login

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

Overview
Comment:Fix a case where a checkpoint operation could write to an invalid part of a memory mapped region.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental-mmap
Files: files | file ages | folders
SHA1: 8dbe89d05ce91428c69003f0da79d883fa23e2b5
User & Date: dan 2013-03-23 14:20:42
Context
2013-03-23
17:29
Improve a comment in wal.c. No code changes. check-in: 60b9f5e4 user: dan tags: experimental-mmap
14:20
Fix a case where a checkpoint operation could write to an invalid part of a memory mapped region. check-in: 8dbe89d0 user: dan tags: experimental-mmap
12:15
In the winMremap VFS function, unmap the region prior to attempting to truncate the file. check-in: 8870c4cc user: mistachkin tags: experimental-mmap
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

  4228   4228   **   * If mmap is being used, then the mapping is extended to szReq
  4229   4229   **     bytes in size.
  4230   4230   **
  4231   4231   ** SQLITE_OK is returned if successful, or an error code if an error occurs.
  4232   4232   */
  4233   4233   int sqlite3PagerSetFilesize(Pager *pPager, i64 szReq){
  4234   4234     int rc;
  4235         -  sqlite3_int64 sz;
         4235  +  i64 sz;                         /* Size of file on disk in bytes */
  4236   4236   
  4237   4237     assert( pPager->eState==PAGER_OPEN );
  4238   4238     assert( pPager->nMmapOut==0 );
  4239   4239   
  4240   4240     rc = sqlite3OsFileSize(pPager->fd, &sz);
  4241   4241     if( rc==SQLITE_OK ){
  4242   4242       if( sz>szReq ){
  4243   4243         sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &sz);
  4244   4244       }
  4245   4245     }
  4246   4246   
  4247         -  if( rc==SQLITE_OK 
  4248         -   && pPager->nMapLimit>0 
  4249         -   && pPager->nMapValid<szReq 
  4250         -   && pPager->nMapValid<pPager->nMapLimit 
  4251         -  ){
  4252         -    pPager->dbFileSize = (szReq / pPager->pageSize);
  4253         -    rc = pagerMap(pPager, 1);
         4247  +
         4248  +  if( rc==SQLITE_OK ){
         4249  +    i64 szMap = (szReq > pPager->nMapLimit) ? pPager->nMapLimit : szReq;
         4250  +    if( pPager->nMapValid!=pPager->nMap || szMap!=pPager->nMap ){
         4251  +      pPager->dbFileSize = (szReq / pPager->pageSize);
         4252  +      rc = pagerMap(pPager, 1);
         4253  +    }
  4254   4254     }
  4255   4255   
  4256   4256     return rc;
  4257   4257   }
  4258   4258   
  4259   4259   /*
  4260   4260   ** The argument is the first in a linked list of dirty pages connected

Changes to test/mmap1.test.

    19     19     set bt [btree_from_db $db]
    20     20     db_enter $db
    21     21     array set stats [btree_pager_stats $bt]
    22     22     db_leave $db
    23     23     return $stats(read)
    24     24   }
    25     25   
    26         -foreach {t mmap_size nRead} {
    27         -  1 { PRAGMA mmap_size = -65536 }   4
    28         -  2 { PRAGMA mmap_size = -50    } 156
    29         -  3 { PRAGMA mmap_size = 0      } 344
           26  +foreach {t mmap_size nRead c2init} {
           27  +  1.1 { PRAGMA mmap_size = -65536 }   4 {}
           28  +  1.2 { PRAGMA mmap_size = -50    } 156 {}
           29  +  1.3 { PRAGMA mmap_size = 0      } 344 {}
           30  +  1.4 { PRAGMA mmap_size = -65536 }   4 {PRAGMA mmap_size = -65536}
           31  +  1.5 { PRAGMA mmap_size = -50    } 156 {PRAGMA mmap_size = -65536}
           32  +  1.6 { PRAGMA mmap_size = 0      } 344 {PRAGMA mmap_size = -65536}
    30     33   } {
    31     34     do_multiclient_test tn {
    32     35       sql1 $mmap_size
           36  +    sql2 $c2init
    33     37   
    34     38       code2 {
    35     39         set ::rcnt 0
    36     40         proc rblob {n} {
    37     41           set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF]
    38     42           set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]] 
    39     43           string range [string repeat $str [expr $n/4]] 1 $n
................................................................................
    75     79   
    76     80       # Check that the number of pages read by connection 1 indicates that the
    77     81       # "PRAGMA mmap_size" command worked.
    78     82       do_test $t.$tn.5 { nRead db } $nRead
    79     83     }
    80     84   }
    81     85   
           86  +set ::rcnt 0
           87  +proc rblob {n} {
           88  +  set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF]
           89  +  set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]] 
           90  +  string range [string repeat $str [expr $n/4]] 1 $n
           91  +}
           92  +
           93  +reset_db
           94  +db func rblob rblob
           95  +
           96  +do_execsql_test 2.1 {
           97  +  PRAGMA auto_vacuum = 1;
           98  +  PRAGMA mmap_size = -65536;
           99  +  PRAGMA journal_mode = wal;
          100  +  CREATE TABLE t1(a, b, UNIQUE(a, b));
          101  +  INSERT INTO t1 VALUES(rblob(500), rblob(500));
          102  +  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    2
          103  +  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    4
          104  +  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    8
          105  +  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   16
          106  +  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   32
          107  +  PRAGMA wal_checkpoint;
          108  +} {wal 0 103 103}
          109  +
          110  +do_execsql_test 2.2 {
          111  +  PRAGMA auto_vacuum;
          112  +  SELECT count(*) FROM t1;
          113  +} {1 32}
          114  +
          115  +do_test 2.3 {
          116  +  sqlite3 db2 test.db
          117  +  db2 func rblob rblob
          118  +  db2 eval { 
          119  +    DELETE FROM t1 WHERE (rowid%4);
          120  +    PRAGMA wal_checkpoint;
          121  +  }
          122  +  db2 eval { 
          123  +    INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    16
          124  +    SELECT count(*) FROM t1;
          125  +  }
          126  +} {16}
          127  +
          128  +do_execsql_test 2.4 {
          129  +  PRAGMA wal_checkpoint;
          130  +} {0 24 24}
    82    131   
    83    132   finish_test
    84    133   

Changes to test/speed1p.test.

    61     61     return $txt
    62     62   }
    63     63   
    64     64   # Create a database schema.
    65     65   #
    66     66   do_test speed1p-1.0 {
    67     67     execsql {
    68         -    PRAGMA mmap_size=65536;
    69         -    PRAGMA journal_mode=wal;
    70         -
    71     68       PRAGMA page_size=1024;
    72     69       PRAGMA cache_size=500;
    73     70       PRAGMA locking_mode=EXCLUSIVE;
    74     71       CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT);
    75     72       CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT);
    76     73       CREATE INDEX i2a ON t2(a);
    77     74       CREATE INDEX i2b ON t2(b);