/ Check-in [765615f9]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Add assert statements to os_unix.c to ensure that any mapped region of the database file is not being read or written using the xRead() or xWrite() methods.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental-mmap
Files: files | file ages | folders
SHA1: 765615f9fba7c1765eb741cb98a09a28b464ee55
User & Date: dan 2013-03-22 08:58:38
Context
2013-03-22
17:46
Add a fix for the assert() statements added by the previous commit. check-in: 19345416 user: dan tags: experimental-mmap
08:58
Add assert statements to os_unix.c to ensure that any mapped region of the database file is not being read or written using the xRead() or xWrite() methods. check-in: 765615f9 user: dan tags: experimental-mmap
2013-03-21
20:39
Fix cases where xRead() was being used to read from a memory mapped part of the database file. check-in: 5c9e9df2 user: dan tags: experimental-mmap
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

245
246
247
248
249
250
251


252
253
254
255
256
257
258
....
3068
3069
3070
3071
3072
3073
3074

3075
3076
3077
3078
3079
3080
3081
....
3150
3151
3152
3153
3154
3155
3156

3157
3158
3159
3160
3161
3162
3163
....
4453
4454
4455
4456
4457
4458
4459


4460
4461
4462
4463
4464
4465
4466
....
4490
4491
4492
4493
4494
4495
4496

4497
4498
4499
4500
4501
4502
4503
4504

4505
4506
4507
4508
4509
4510
4511
4512
4513

4514


4515
4516
4517
4518
4519
4520
4521
....
4842
4843
4844
4845
4846
4847
4848

4849
4850
4851
4852
4853
4854
4855
  ** occur if a file is updated without also updating the transaction
  ** counter.  This test is made to avoid new problems similar to the
  ** one described by ticket #3584. 
  */
  unsigned char transCntrChng;   /* True if the transaction counter changed */
  unsigned char dbUpdate;        /* True if any part of database file changed */
  unsigned char inNormalWrite;   /* True if in a normal write operation */


#endif
#ifdef SQLITE_TEST
  /* In test mode, increase the size of this structure a bit so that 
  ** it is larger than the struct CrashFile defined in test6.c.
  */
  char aPadding[32];
#endif
................................................................................
  void *pBuf, 
  int amt,
  sqlite3_int64 offset
){
  unixFile *pFile = (unixFile *)id;
  int got;
  assert( id );


  /* If this is a database file (not a journal, master-journal or temp
  ** file), the bytes in the locking range should never be read or written. */
#if 0
  assert( pFile->pUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
................................................................................
  int amt,
  sqlite3_int64 offset 
){
  unixFile *pFile = (unixFile*)id;
  int wrote = 0;
  assert( id );
  assert( amt>0 );


  /* If this is a database file (not a journal, master-journal or temp
  ** file), the bytes in the locking range should never be read or written. */
#if 0
  assert( pFile->pUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
................................................................................
  unixFile *p = (unixFile *)fd;   /* The underlying database file */
  int rc = SQLITE_OK;             /* Return code */
  void *pNew = 0;                 /* New mapping */
  i64 nNewRnd;                    /* nNew rounded up */
  i64 nOldRnd;                    /* nOld rounded up */

  assert( iOff==0 );



  /* If the SQLITE_MREMAP_EXTEND flag is set, then the size of the requested 
  ** mapping (nNew bytes) may be greater than the size of the database file.
  ** If this is the case, extend the file on disk using ftruncate().  */
  assert( nNew>0 || (flags & SQLITE_MREMAP_EXTEND)==0 );
  if( flags & SQLITE_MREMAP_EXTEND ){
    struct stat statbuf;          /* Low-level file information */
................................................................................
  nNewRnd = ROUNDUP(nNew, 4096*1);
  nOldRnd = ROUNDUP(nOld, 4096*1);
#endif

  /* On OSX or Linux, reuse the old mapping if it is the right size. */
#if defined(__APPLE__) || defined(__linux__)
  if( nNewRnd==nOldRnd ){

    return SQLITE_OK;
  }
#endif

  /* If we get this far, unmap any old mapping. */
  if( nOldRnd!=0 ){
    void *pOld = *ppMap;
    munmap(pOld, nOldRnd);

  }

  /* And, if required, use mmap() to create a new mapping. */
  if( nNewRnd>0 ){
    int flags = PROT_READ;
    if( (p->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
    pNew = mmap(0, nNewRnd, flags, MAP_SHARED, p->h, iOff);
    if( pNew==MAP_FAILED ){
      pNew = 0;

      rc = SQLITE_IOERR_MREMAP;


    }
  }

  *ppMap = pNew;
  return rc;
}

................................................................................
  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;
  pNew->pVfs = pVfs;
  pNew->zPath = zFilename;
  pNew->ctrlFlags = (u8)ctrlFlags;

  if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pNew->ctrlFlags |= UNIXFILE_PSOW;
  }
  if( strcmp(pVfs->zName,"unix-excl")==0 ){
    pNew->ctrlFlags |= UNIXFILE_EXCL;
  }







>
>







 







>







 







>







 







>
>







 







>








>









>

>
>







 







>







245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
....
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
....
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
....
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
....
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
....
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
  ** occur if a file is updated without also updating the transaction
  ** counter.  This test is made to avoid new problems similar to the
  ** one described by ticket #3584. 
  */
  unsigned char transCntrChng;   /* True if the transaction counter changed */
  unsigned char dbUpdate;        /* True if any part of database file changed */
  unsigned char inNormalWrite;   /* True if in a normal write operation */
  sqlite3_int64 mmapSize;        /* Size of xMremap() */
  void *pMapRegion;              /* Area memory mapped */
#endif
#ifdef SQLITE_TEST
  /* In test mode, increase the size of this structure a bit so that 
  ** it is larger than the struct CrashFile defined in test6.c.
  */
  char aPadding[32];
#endif
................................................................................
  void *pBuf, 
  int amt,
  sqlite3_int64 offset
){
  unixFile *pFile = (unixFile *)id;
  int got;
  assert( id );
  assert( offset>=pFile->mmapSize );  /* Never read from the mmapped region */

  /* If this is a database file (not a journal, master-journal or temp
  ** file), the bytes in the locking range should never be read or written. */
#if 0
  assert( pFile->pUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
................................................................................
  int amt,
  sqlite3_int64 offset 
){
  unixFile *pFile = (unixFile*)id;
  int wrote = 0;
  assert( id );
  assert( amt>0 );
  assert( offset>=pFile->mmapSize );   /* Never write into the mmapped region */

  /* If this is a database file (not a journal, master-journal or temp
  ** file), the bytes in the locking range should never be read or written. */
#if 0
  assert( pFile->pUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
................................................................................
  unixFile *p = (unixFile *)fd;   /* The underlying database file */
  int rc = SQLITE_OK;             /* Return code */
  void *pNew = 0;                 /* New mapping */
  i64 nNewRnd;                    /* nNew rounded up */
  i64 nOldRnd;                    /* nOld rounded up */

  assert( iOff==0 );
  assert( p->mmapSize==nOld );
  assert( p->pMapRegion==0 || p->pMapRegion==(*ppMap) );

  /* If the SQLITE_MREMAP_EXTEND flag is set, then the size of the requested 
  ** mapping (nNew bytes) may be greater than the size of the database file.
  ** If this is the case, extend the file on disk using ftruncate().  */
  assert( nNew>0 || (flags & SQLITE_MREMAP_EXTEND)==0 );
  if( flags & SQLITE_MREMAP_EXTEND ){
    struct stat statbuf;          /* Low-level file information */
................................................................................
  nNewRnd = ROUNDUP(nNew, 4096*1);
  nOldRnd = ROUNDUP(nOld, 4096*1);
#endif

  /* On OSX or Linux, reuse the old mapping if it is the right size. */
#if defined(__APPLE__) || defined(__linux__)
  if( nNewRnd==nOldRnd ){
    VVA_ONLY( p->mmapSize = nNew; )
    return SQLITE_OK;
  }
#endif

  /* If we get this far, unmap any old mapping. */
  if( nOldRnd!=0 ){
    void *pOld = *ppMap;
    munmap(pOld, nOldRnd);
    VVA_ONLY( p->mmapSize = 0; p->pMapRegion = 0; );
  }

  /* And, if required, use mmap() to create a new mapping. */
  if( nNewRnd>0 ){
    int flags = PROT_READ;
    if( (p->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
    pNew = mmap(0, nNewRnd, flags, MAP_SHARED, p->h, iOff);
    if( pNew==MAP_FAILED ){
      pNew = 0;
      VVA_ONLY( p->mmapSize = 0; p->pMapRegion = 0; )
      rc = SQLITE_IOERR_MREMAP;
    }else{
      VVA_ONLY( p->mmapSize = nNew; p->pMapRegion = pNew; )
    }
  }

  *ppMap = pNew;
  return rc;
}

................................................................................
  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;
  pNew->pVfs = pVfs;
  pNew->zPath = zFilename;
  pNew->ctrlFlags = (u8)ctrlFlags;
  VVA_ONLY( pNew->mmapSize = 0; )
  if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pNew->ctrlFlags |= UNIXFILE_PSOW;
  }
  if( strcmp(pVfs->zName,"unix-excl")==0 ){
    pNew->ctrlFlags |= UNIXFILE_EXCL;
  }