From d072da23441ac6843722b30a8d2df68cbee16b5e Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Fri, 21 Feb 2014 04:08:49 +0100 Subject: [PATCH] nfs4: Don't flush cache when closing read only share reservation NFS4 specification requires that modified data has to be flushed before sending CLOSE request. Our original implementation was stricter than that by flushing all modified data at each file close. That caused problems with e.g. Tracker, which likes to periodically open files for read only, in a situation when there were still asynchronous writes pending (e.g. large file copied). --- src/add-ons/kernel/file_systems/nfs4/Inode.cpp | 12 ++++++------ .../kernel/file_systems/nfs4/InodeRegular.cpp | 15 ++++++++++----- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 9e2f687686..cb13665156 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -170,17 +170,16 @@ Inode::RevalidateFileCache() MutexLocker _(fFileCacheLock); if (change == fChange) return B_OK; - SyncAndCommit(true); + file_cache_delete(fFileCache); struct stat st; fMetaCache.InvalidateStat(); result = Stat(&st); - if (result != B_OK) - return result; - - fFileCache = file_cache_create(fFileSystem->DevId(), ID(), st.st_size); + if (result == B_OK) + fMaxFileSize = st.st_size; + fFileCache = file_cache_create(fFileSystem->DevId(), ID(), fMaxFileSize); change = fChange; return B_OK; @@ -833,7 +832,8 @@ Inode::ReleaseAllLocks(OpenFileCookie* cookie) { ASSERT(cookie != NULL); - SyncAndCommit(); + if (cookie->fLocks) + SyncAndCommit(); OpenState* state = cookie->fOpenState; MutexLocker _(state->fLocksLock); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 4b7b692ac9..30c5a55c0f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -106,8 +106,6 @@ Inode::Open(int mode, OpenFileCookie* cookie) OpenDelegationData data; data.fType = OPEN_DELEGATE_NONE; if (fOpenState == NULL) { - RevalidateFileCache(); - OpenState* state = new(std::nothrow) OpenState; if (state == NULL) return B_NO_MEMORY; @@ -125,6 +123,8 @@ Inode::Open(int mode, OpenFileCookie* cookie) fOpenState = state; cookie->fOpenState = state; locker.Unlock(); + + RevalidateFileCache(); } else { fOpenState->AcquireReference(); cookie->fOpenState = fOpenState; @@ -143,6 +143,9 @@ Inode::Open(int mode, OpenFileCookie* cookie) return result; } fOpenState->fMode = O_RDWR; + + if (oldMode == O_RDONLY) + RevalidateFileCache(); } else { int newMode = mode & O_RWMASK; uint32 allowed = 0; @@ -190,7 +193,9 @@ Inode::Close(OpenFileCookie* cookie) ASSERT(cookie != NULL); ASSERT(fOpenState == cookie->fOpenState); - SyncAndCommit(); + int mode = cookie->fMode & O_RWMASK; + if (mode == O_RDWR || mode == O_WRONLY) + SyncAndCommit(); MutexLocker _(fStateLock); ReleaseOpenState(); @@ -437,10 +442,10 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, status_t Inode::Commit() { - WriteLocker _(fWriteLock); - if (!fWriteDirty) return B_OK; + + WriteLocker _(fWriteLock); status_t result = CommitWrites(); if (result != B_OK) return result;