nfs4: Fix write commit race condition

This commit is contained in:
Pawel Dziepak
2013-01-17 03:54:33 +01:00
parent ce851e2bac
commit 15a18a6b89
3 changed files with 12 additions and 4 deletions
@@ -37,6 +37,7 @@ Inode::Inode()
rw_lock_init(&fDelegationLock, NULL); rw_lock_init(&fDelegationLock, NULL);
mutex_init(&fStateLock, NULL); mutex_init(&fStateLock, NULL);
mutex_init(&fFileCacheLock, NULL); mutex_init(&fFileCacheLock, NULL);
rw_lock_init(&fWriteLock, NULL);
mutex_init(&fAIOLock, NULL); mutex_init(&fAIOLock, NULL);
} }
@@ -147,6 +148,7 @@ Inode::~Inode()
mutex_destroy(&fStateLock); mutex_destroy(&fStateLock);
mutex_destroy(&fFileCacheLock); mutex_destroy(&fFileCacheLock);
rw_lock_destroy(&fDelegationLock); rw_lock_destroy(&fDelegationLock);
rw_lock_destroy(&fWriteLock);
ASSERT(fAIOCount == 0); ASSERT(fAIOCount == 0);
} }
@@ -938,8 +940,10 @@ Inode::ReleaseOpenState()
{ {
ASSERT(fOpenState != NULL); ASSERT(fOpenState != NULL);
if (fOpenState->ReleaseReference() == 1) if (fOpenState->ReleaseReference() == 1) {
ASSERT(fAIOCount == 0);
fOpenState = NULL; fOpenState = NULL;
}
} }
@@ -161,6 +161,7 @@ private:
OpenState* fOpenState; OpenState* fOpenState;
mutex fStateLock; mutex fStateLock;
rw_lock fWriteLock;
bool fWriteDirty; bool fWriteDirty;
sem_id fAIOWait; sem_id fAIOWait;
@@ -36,8 +36,6 @@ Inode::CreateState(const char* name, int mode, int perms, OpenState* state,
if (result != B_OK) if (result != B_OK)
return result; return result;
RevalidateFileCache();
FileInfo fi; FileInfo fi;
fi.fFileId = fileID; fi.fFileId = fileID;
fi.fHandle = handle; fi.fHandle = handle;
@@ -186,6 +184,7 @@ status_t
Inode::Close(OpenFileCookie* cookie) Inode::Close(OpenFileCookie* cookie)
{ {
ASSERT(cookie != NULL); ASSERT(cookie != NULL);
ASSERT(fOpenState == cookie->fOpenState);
SyncAndCommit(); SyncAndCommit();
@@ -371,8 +370,10 @@ Inode::WriteDirect(OpenStateCookie* cookie, off_t pos, const void* _buffer,
state = cookie->fOpenState; state = cookie->fOpenState;
} }
if (!attribute) if (!attribute) {
ReadLocker _(fWriteLock);
fWriteDirty = true; fWriteDirty = true;
}
while (size < *_length) { while (size < *_length) {
uint32 len = *_length - size; uint32 len = *_length - size;
@@ -432,6 +433,8 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer,
status_t status_t
Inode::Commit() Inode::Commit()
{ {
WriteLocker _(fWriteLock);
if (!fWriteDirty) if (!fWriteDirty)
return B_OK; return B_OK;
status_t result = CommitWrites(); status_t result = CommitWrites();