From: drh Date: Mon, 13 Aug 2018 22:50:34 +0000 (+0000) Subject: Stop requiring the global VFS mutex to access the unixInodeInfo.pUnused field. X-Git-Tag: version-3.25.0~71 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ef52b36a6b7401c44e5031fd14ded929b93076e8;p=thirdparty%2Fsqlite.git Stop requiring the global VFS mutex to access the unixInodeInfo.pUnused field. The unixInodeInfo mutex is sufficient. FossilOrigin-Name: e3ea43dabf099dc2954c23d348638e7b2a8b9122d2994154bc649a2c09260c46 --- diff --git a/manifest b/manifest index 894fda23ab..09410ced16 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Take\sextra\sprecautions\sto\sensure\saccess\sto\sunixInodeInfo.pUnused\sis\sprotected\nby\sall\snecessary\smutexes. -D 2018-08-13T20:46:18.212 +C Stop\srequiring\sthe\sglobal\sVFS\smutex\sto\saccess\sthe\sunixInodeInfo.pUnused\sfield.\nThe\sunixInodeInfo\smutex\sis\ssufficient. +D 2018-08-13T22:50:34.627 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -482,7 +482,7 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c 443f6331828b9d0d05f9528a2ae30d927ab988a951ea783dc85538dc9109d489 +F src/os_unix.c e681b2a3ab1085be3eb2e81254449782ca0bd0c38b73c48cb0c2480b8f2f25b9 F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9 @@ -1754,7 +1754,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 90f7c193b42f0d8120a8e429bdea5e1cec5d3f45b901db8fc5a5c2ca3e69cba8 -R de3b1179403c76c7e851316aaadc94be +P 8b1e0010b9e0b548a90087f4d25843d2b40f7e9551722ac587fa925d37b510c2 +R c0b44ea86365eec38ab4ca860c436c2d U drh -Z 4ac850f8e532f34d7b8e835a0f2cfeb4 +Z 61c21fbc1d363c0a3fe7befb1f84f230 diff --git a/manifest.uuid b/manifest.uuid index 5db1a564ff..2e68ed46d5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8b1e0010b9e0b548a90087f4d25843d2b40f7e9551722ac587fa925d37b510c2 \ No newline at end of file +e3ea43dabf099dc2954c23d348638e7b2a8b9122d2994154bc649a2c09260c46 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 5a2b6b523a..ab0a5d919a 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1126,17 +1126,13 @@ struct unixFileId { ** ** (1) Only the pLockMutex mutex must be held in order to read or write ** any of the locking fields: -** nShared, nLock, eFileLock, or bProcessLock +** nShared, nLock, eFileLock, bProcessLock, pUnused ** ** (2) When nRef>0, then the following fields are unchanging and can ** be read (but not written) without holding any mutex: ** fileId, pLockMutex ** -** (3) The pUnused field may only be changed while holding bo the -** pLockMutex and the bigUnixLock mutex. But it may be read -** while holding either. -** -** (4) With the exceptions above, all the fields may only be read +** (3) With the exceptions above, all the fields may only be read ** or written while holding the global unixBigLock mutex. ** ** Deadlock prevention: The global unixBigLock mutex may not @@ -1150,7 +1146,7 @@ struct unixInodeInfo { int nLock; /* Number of outstanding file locks */ unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ unsigned char bProcessLock; /* An exclusive process lock is held */ - UnixUnusedFd *pUnused; /* Unused file descriptors to close */ + UnixUnusedFd *pUnused; /* Unused file descriptors to close */ int nRef; /* Number of pointers to this structure */ unixShmNode *pShmNode; /* Shared memory associated with this inode */ unixInodeInfo *pNext; /* List of all unixInodeInfo objects */ @@ -1288,16 +1284,13 @@ static void closePendingFds(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; UnixUnusedFd *p; UnixUnusedFd *pNext; - assert( unixMutexHeld() ); - assert( unixFileMutexNotheld(pFile) ); - sqlite3_mutex_enter(pInode->pLockMutex); + assert( unixFileMutexHeld(pFile) ); for(p=pInode->pUnused; p; p=pNext){ pNext = p->pNext; robust_close(pFile, p->fd, __LINE__); sqlite3_free(p); } pInode->pUnused = 0; - sqlite3_mutex_leave(pInode->pLockMutex); } /* @@ -1314,7 +1307,9 @@ static void releaseInodeInfo(unixFile *pFile){ pInode->nRef--; if( pInode->nRef==0 ){ assert( pInode->pShmNode==0 ); + sqlite3_mutex_enter(pInode->pLockMutex); closePendingFds(pFile); + sqlite3_mutex_leave(pInode->pLockMutex); if( pInode->pPrev ){ assert( pInode->pPrev->pNext==pInode ); pInode->pPrev->pNext = pInode->pNext; @@ -1863,12 +1858,9 @@ end_lock: static void setPendingFd(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; UnixUnusedFd *p = pFile->pPreallocatedUnused; - assert( unixMutexHeld() ); - assert( unixFileMutexNotheld(pFile) ); - sqlite3_mutex_enter(pInode->pLockMutex); + assert( unixFileMutexHeld(pFile) ); p->pNext = pInode->pUnused; pInode->pUnused = p; - sqlite3_mutex_leave(pInode->pLockMutex); pFile->h = -1; pFile->pPreallocatedUnused = 0; } @@ -1891,7 +1883,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ unixInodeInfo *pInode; struct flock lock; int rc = SQLITE_OK; - int wantToClosePending = 0; /* True to try to close file old descriptors */ assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock, @@ -2029,20 +2020,13 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ */ pInode->nLock--; assert( pInode->nLock>=0 ); - if( pInode->nLock==0 && pInode->pUnused!=0 ){ - wantToClosePending = 1; - } + if( pInode->nLock==0 ) closePendingFds(pFile); } end_unlock: sqlite3_mutex_leave(pInode->pLockMutex); if( rc==SQLITE_OK ){ pFile->eFileLock = eFileLock; - if( wantToClosePending ){ - unixEnterMutex(); - if( pInode->nLock==0 ) closePendingFds(pFile); - unixLeaveMutex(); - } } return rc; } @@ -2114,6 +2098,9 @@ static int closeUnixFile(sqlite3_file *id){ static int unixClose(sqlite3_file *id){ int rc = SQLITE_OK; unixFile *pFile = (unixFile *)id; + unixInodeInfo *pInode = pFile->pInode; + + assert( pInode!=0 ); verifyDbFile(pFile); unixUnlock(id, NO_LOCK); assert( unixFileMutexNotheld(pFile) ); @@ -2123,7 +2110,8 @@ static int unixClose(sqlite3_file *id){ ** routine (e.g. nolockClose()) would be called instead. */ assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); - if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){ + sqlite3_mutex_enter(pInode->pLockMutex); + if( pFile->pInode->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pInode->pUnused list. It will be automatically closed @@ -2131,6 +2119,7 @@ static int unixClose(sqlite3_file *id){ */ setPendingFd(pFile); } + sqlite3_mutex_leave(pInode->pLockMutex); releaseInodeInfo(pFile); rc = closeUnixFile(id); unixLeaveMutex(); @@ -3086,7 +3075,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { unixInodeInfo *pInode; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; int skipShared = 0; - int wantToClosePending = 0; #ifdef SQLITE_TEST int h = pFile->h; #endif @@ -3170,18 +3158,13 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { if( rc==SQLITE_OK ){ pInode->nLock--; assert( pInode->nLock>=0 ); - if( pInode->nLock==0 && pInode->pUnused!=0 ) wantToClosePending = 1; + if( pInode->nLock==0 ) closePendingFds(pFile); } } sqlite3_mutex_leave(pInode->pLockMutex); if( rc==SQLITE_OK ){ pFile->eFileLock = eFileLock; - if( wantToClosePending ){ - unixEnterMutex(); - if( pInode->nLock==0 ) closePendingFds(pFile); - unixLeaveMutex(); - } } return rc; } @@ -3196,13 +3179,18 @@ static int afpClose(sqlite3_file *id) { afpUnlock(id, NO_LOCK); assert( unixFileMutexNotheld(pFile) ); unixEnterMutex(); - if( pFile->pInode && pFile->pInode->nLock ){ - /* If there are outstanding locks, do not actually close the file just - ** yet because that would clear those locks. Instead, add the file - ** descriptor to pInode->aPending. It will be automatically closed when - ** the last lock is cleared. - */ - setPendingFd(pFile); + if( pFile->pInode ){ + unixInodeInfo *pInode = pFile->pInode; + sqlite3_mutex_enter(pInode->pLockMutex); + if( pFile->pInode->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pInode->aPending. It will be automatically closed when + ** the last lock is cleared. + */ + setPendingFd(pFile); + } + sqlite3_mutex_leave(pInode->pLockMutex); } releaseInodeInfo(pFile); sqlite3_free(pFile->lockingContext);