1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Stop requiring the global VFS mutex to access the unixInodeInfo.pUnused field.

The unixInodeInfo mutex is sufficient.

FossilOrigin-Name: e3ea43dabf099dc2954c23d348638e7b2a8b9122d2994154bc649a2c09260c46
This commit is contained in:
drh
2018-08-13 22:50:34 +00:00
parent 095908e1c7
commit ef52b36a6b
3 changed files with 34 additions and 46 deletions

View File

@@ -1,5 +1,5 @@
C Take\sextra\sprecautions\sto\sensure\saccess\sto\sunixInodeInfo.pUnused\sis\sprotected\nby\sall\snecessary\smutexes. C Stop\srequiring\sthe\sglobal\sVFS\smutex\sto\saccess\sthe\sunixInodeInfo.pUnused\sfield.\nThe\sunixInodeInfo\smutex\sis\ssufficient.
D 2018-08-13T20:46:18.212 D 2018-08-13T22:50:34.627
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6
@@ -482,7 +482,7 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 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.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9 F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9
@@ -1754,7 +1754,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 90f7c193b42f0d8120a8e429bdea5e1cec5d3f45b901db8fc5a5c2ca3e69cba8 P 8b1e0010b9e0b548a90087f4d25843d2b40f7e9551722ac587fa925d37b510c2
R de3b1179403c76c7e851316aaadc94be R c0b44ea86365eec38ab4ca860c436c2d
U drh U drh
Z 4ac850f8e532f34d7b8e835a0f2cfeb4 Z 61c21fbc1d363c0a3fe7befb1f84f230

View File

@@ -1 +1 @@
8b1e0010b9e0b548a90087f4d25843d2b40f7e9551722ac587fa925d37b510c2 e3ea43dabf099dc2954c23d348638e7b2a8b9122d2994154bc649a2c09260c46

View File

@@ -1126,17 +1126,13 @@ struct unixFileId {
** **
** (1) Only the pLockMutex mutex must be held in order to read or write ** (1) Only the pLockMutex mutex must be held in order to read or write
** any of the locking fields: ** 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 ** (2) When nRef>0, then the following fields are unchanging and can
** be read (but not written) without holding any mutex: ** be read (but not written) without holding any mutex:
** fileId, pLockMutex ** fileId, pLockMutex
** **
** (3) The pUnused field may only be changed while holding bo the ** (3) With the exceptions above, all the fields may only be read
** 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
** or written while holding the global unixBigLock mutex. ** or written while holding the global unixBigLock mutex.
** **
** Deadlock prevention: The global unixBigLock mutex may not ** Deadlock prevention: The global unixBigLock mutex may not
@@ -1288,16 +1284,13 @@ static void closePendingFds(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode; unixInodeInfo *pInode = pFile->pInode;
UnixUnusedFd *p; UnixUnusedFd *p;
UnixUnusedFd *pNext; UnixUnusedFd *pNext;
assert( unixMutexHeld() ); assert( unixFileMutexHeld(pFile) );
assert( unixFileMutexNotheld(pFile) );
sqlite3_mutex_enter(pInode->pLockMutex);
for(p=pInode->pUnused; p; p=pNext){ for(p=pInode->pUnused; p; p=pNext){
pNext = p->pNext; pNext = p->pNext;
robust_close(pFile, p->fd, __LINE__); robust_close(pFile, p->fd, __LINE__);
sqlite3_free(p); sqlite3_free(p);
} }
pInode->pUnused = 0; pInode->pUnused = 0;
sqlite3_mutex_leave(pInode->pLockMutex);
} }
/* /*
@@ -1314,7 +1307,9 @@ static void releaseInodeInfo(unixFile *pFile){
pInode->nRef--; pInode->nRef--;
if( pInode->nRef==0 ){ if( pInode->nRef==0 ){
assert( pInode->pShmNode==0 ); assert( pInode->pShmNode==0 );
sqlite3_mutex_enter(pInode->pLockMutex);
closePendingFds(pFile); closePendingFds(pFile);
sqlite3_mutex_leave(pInode->pLockMutex);
if( pInode->pPrev ){ if( pInode->pPrev ){
assert( pInode->pPrev->pNext==pInode ); assert( pInode->pPrev->pNext==pInode );
pInode->pPrev->pNext = pInode->pNext; pInode->pPrev->pNext = pInode->pNext;
@@ -1863,12 +1858,9 @@ end_lock:
static void setPendingFd(unixFile *pFile){ static void setPendingFd(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode; unixInodeInfo *pInode = pFile->pInode;
UnixUnusedFd *p = pFile->pPreallocatedUnused; UnixUnusedFd *p = pFile->pPreallocatedUnused;
assert( unixMutexHeld() ); assert( unixFileMutexHeld(pFile) );
assert( unixFileMutexNotheld(pFile) );
sqlite3_mutex_enter(pInode->pLockMutex);
p->pNext = pInode->pUnused; p->pNext = pInode->pUnused;
pInode->pUnused = p; pInode->pUnused = p;
sqlite3_mutex_leave(pInode->pLockMutex);
pFile->h = -1; pFile->h = -1;
pFile->pPreallocatedUnused = 0; pFile->pPreallocatedUnused = 0;
} }
@@ -1891,7 +1883,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
unixInodeInfo *pInode; unixInodeInfo *pInode;
struct flock lock; struct flock lock;
int rc = SQLITE_OK; int rc = SQLITE_OK;
int wantToClosePending = 0; /* True to try to close file old descriptors */
assert( pFile ); assert( pFile );
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock, 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--; pInode->nLock--;
assert( pInode->nLock>=0 ); assert( pInode->nLock>=0 );
if( pInode->nLock==0 && pInode->pUnused!=0 ){ if( pInode->nLock==0 ) closePendingFds(pFile);
wantToClosePending = 1;
}
} }
end_unlock: end_unlock:
sqlite3_mutex_leave(pInode->pLockMutex); sqlite3_mutex_leave(pInode->pLockMutex);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
pFile->eFileLock = eFileLock; pFile->eFileLock = eFileLock;
if( wantToClosePending ){
unixEnterMutex();
if( pInode->nLock==0 ) closePendingFds(pFile);
unixLeaveMutex();
}
} }
return rc; return rc;
} }
@@ -2114,6 +2098,9 @@ static int closeUnixFile(sqlite3_file *id){
static int unixClose(sqlite3_file *id){ static int unixClose(sqlite3_file *id){
int rc = SQLITE_OK; int rc = SQLITE_OK;
unixFile *pFile = (unixFile *)id; unixFile *pFile = (unixFile *)id;
unixInodeInfo *pInode = pFile->pInode;
assert( pInode!=0 );
verifyDbFile(pFile); verifyDbFile(pFile);
unixUnlock(id, NO_LOCK); unixUnlock(id, NO_LOCK);
assert( unixFileMutexNotheld(pFile) ); assert( unixFileMutexNotheld(pFile) );
@@ -2123,7 +2110,8 @@ static int unixClose(sqlite3_file *id){
** routine (e.g. nolockClose()) would be called instead. ** routine (e.g. nolockClose()) would be called instead.
*/ */
assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); 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 /* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file ** yet because that would clear those locks. Instead, add the file
** descriptor to pInode->pUnused list. It will be automatically closed ** descriptor to pInode->pUnused list. It will be automatically closed
@@ -2131,6 +2119,7 @@ static int unixClose(sqlite3_file *id){
*/ */
setPendingFd(pFile); setPendingFd(pFile);
} }
sqlite3_mutex_leave(pInode->pLockMutex);
releaseInodeInfo(pFile); releaseInodeInfo(pFile);
rc = closeUnixFile(id); rc = closeUnixFile(id);
unixLeaveMutex(); unixLeaveMutex();
@@ -3086,7 +3075,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
unixInodeInfo *pInode; unixInodeInfo *pInode;
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
int skipShared = 0; int skipShared = 0;
int wantToClosePending = 0;
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
int h = pFile->h; int h = pFile->h;
#endif #endif
@@ -3170,18 +3158,13 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
pInode->nLock--; pInode->nLock--;
assert( pInode->nLock>=0 ); assert( pInode->nLock>=0 );
if( pInode->nLock==0 && pInode->pUnused!=0 ) wantToClosePending = 1; if( pInode->nLock==0 ) closePendingFds(pFile);
} }
} }
sqlite3_mutex_leave(pInode->pLockMutex); sqlite3_mutex_leave(pInode->pLockMutex);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
pFile->eFileLock = eFileLock; pFile->eFileLock = eFileLock;
if( wantToClosePending ){
unixEnterMutex();
if( pInode->nLock==0 ) closePendingFds(pFile);
unixLeaveMutex();
}
} }
return rc; return rc;
} }
@@ -3196,7 +3179,10 @@ static int afpClose(sqlite3_file *id) {
afpUnlock(id, NO_LOCK); afpUnlock(id, NO_LOCK);
assert( unixFileMutexNotheld(pFile) ); assert( unixFileMutexNotheld(pFile) );
unixEnterMutex(); unixEnterMutex();
if( pFile->pInode && pFile->pInode->nLock ){ 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 /* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file ** yet because that would clear those locks. Instead, add the file
** descriptor to pInode->aPending. It will be automatically closed when ** descriptor to pInode->aPending. It will be automatically closed when
@@ -3204,6 +3190,8 @@ static int afpClose(sqlite3_file *id) {
*/ */
setPendingFd(pFile); setPendingFd(pFile);
} }
sqlite3_mutex_leave(pInode->pLockMutex);
}
releaseInodeInfo(pFile); releaseInodeInfo(pFile);
sqlite3_free(pFile->lockingContext); sqlite3_free(pFile->lockingContext);
rc = closeUnixFile(id); rc = closeUnixFile(id);