From 55f2930931f8ec0739f5fcabb8942813ff891d28 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Thu, 28 Jun 2012 21:01:33 +0200 Subject: [PATCH] nfs4: Filesystem is responsible for its opened files --- .../kernel/file_systems/nfs4/Filesystem.cpp | 58 +++++++++- .../kernel/file_systems/nfs4/Filesystem.h | 20 ++++ .../kernel/file_systems/nfs4/Inode.cpp | 16 +-- .../kernel/file_systems/nfs4/NFS4Server.cpp | 102 +++++++++--------- .../kernel/file_systems/nfs4/NFS4Server.h | 38 +++++-- 5 files changed, 165 insertions(+), 69 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp b/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp index 1d3f11f999..0f07306cd6 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp @@ -9,9 +9,10 @@ #include "Filesystem.h" +#include #include -#include +#include #include #include "Request.h" @@ -24,15 +25,24 @@ extern RPC::ProgramData* CreateNFS4Server(RPC::Server* serv); Filesystem::Filesystem() : + fNext(NULL), + fPrev(NULL), + fOpenFiles(NULL), + fOpenCount(0), fPath(NULL), fName(NULL), fId(1) { + mutex_init(&fOpenLock, NULL); } Filesystem::~Filesystem() { + NFSServer()->RemoveFilesystem(this); + + mutex_destroy(&fOpenLock); + free(const_cast(fName)); free(const_cast(fPath)); } @@ -170,6 +180,8 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath, *pfs = fs; delete[] values; + + fs->NFSServer()->AddFilesystem(fs); return B_OK; } @@ -351,3 +363,47 @@ Filesystem::Migrate(const Filehandle& fh, const RPC::Server* serv) return B_OK; } + +OpenFileCookie* +Filesystem::OpenFilesLock() +{ + mutex_lock(&fOpenLock); + return fOpenFiles; +} + + +void +Filesystem::OpenFilesUnlock() +{ + mutex_unlock(&fOpenLock); +} + + +void +Filesystem::AddOpenFile(OpenFileCookie* cookie) +{ + MutexLocker _(fOpenLock); + + cookie->fPrev = NULL; + cookie->fNext = fOpenFiles; + if (fOpenFiles != NULL) + fOpenFiles->fPrev = cookie; + fOpenFiles = cookie; + NFSServer()->IncUsage(); +} + + +void +Filesystem::RemoveOpenFile(OpenFileCookie* cookie) +{ + MutexLocker _(fOpenLock); + if (cookie == fOpenFiles) + fOpenFiles = cookie->fNext; + + if (cookie->fNext) + cookie->fNext->fPrev = cookie->fPrev; + if (cookie->fPrev) + cookie->fPrev->fNext = cookie->fNext; + NFSServer()->DecUsage(); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/Filesystem.h b/src/add-ons/kernel/file_systems/nfs4/Filesystem.h index fe50ff4766..e115dd47ff 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filesystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/Filesystem.h @@ -33,6 +33,12 @@ public: status_t Migrate(const Filehandle& fh, const RPC::Server* serv); + OpenFileCookie* OpenFilesLock(); + void OpenFilesUnlock(); + inline uint32 OpenFilesCount(); + void AddOpenFile(OpenFileCookie* cookie); + void RemoveOpenFile(OpenFileCookie* cookie); + inline bool IsAttrSupported(Attribute attr) const; inline uint32 ExpireType() const; @@ -46,9 +52,16 @@ public: inline dev_t DevId() const; inline InodeIdMap* InoIdMap(); + + Filesystem* fNext; + Filesystem* fPrev; private: Filesystem(); + OpenFileCookie* fOpenFiles; + uint32 fOpenCount; + mutex fOpenLock; + uint32 fExpireType; uint32 fSupAttrs[2]; @@ -69,6 +82,13 @@ private: }; +inline uint32 +Filesystem::OpenFilesCount() +{ + return fOpenCount; +} + + inline bool Filesystem::IsAttrSupported(Attribute attr) const { diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 0100868ac2..3d3a56ba44 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -676,7 +676,7 @@ sConfirmOpen(Filesystem* fs, Filehandle& fh, OpenFileCookie* cookie) status_t result = request.Send(); if (result != B_OK) { - fs->NFSServer()->RemoveOpenFile(cookie); + fs->RemoveOpenFile(cookie); return result; } @@ -686,7 +686,7 @@ sConfirmOpen(Filesystem* fs, Filehandle& fh, OpenFileCookie* cookie) result = reply.OpenConfirm(&cookie->fStateSeq); if (result != B_OK) { - fs->NFSServer()->RemoveOpenFile(cookie); + fs->RemoveOpenFile(cookie); return result; } @@ -745,8 +745,6 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, ReplyInterpreter& reply = request.Reply(); - if (reply.NFS4Error() == NFS4ERR_GRACE) - fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId); if (_HandleErrors(reply.NFS4Error(), serv)) continue; @@ -791,7 +789,7 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, break; } while (true); - fFilesystem->NFSServer()->AddOpenFile(cookie); + fFilesystem->AddOpenFile(cookie); if (confirm) return sConfirmOpen(fFilesystem, fh, cookie); @@ -861,8 +859,6 @@ Inode::Open(int mode, OpenFileCookie* cookie) ReplyInterpreter& reply = request.Reply(); - if (reply.NFS4Error() == NFS4ERR_GRACE) - fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId); if (_HandleErrors(reply.NFS4Error(), serv)) continue; @@ -889,7 +885,7 @@ Inode::Open(int mode, OpenFileCookie* cookie) break; } while (true); - fFilesystem->NFSServer()->AddOpenFile(cookie); + fFilesystem->AddOpenFile(cookie); if (confirm) return sConfirmOpen(fFilesystem, fHandle, cookie); @@ -901,7 +897,7 @@ Inode::Open(int mode, OpenFileCookie* cookie) status_t Inode::Close(OpenFileCookie* cookie) { - fFilesystem->NFSServer()->RemoveOpenFile(cookie); + fFilesystem->RemoveOpenFile(cookie); do { RPC::Server* serv = fFilesystem->Server(); @@ -926,8 +922,6 @@ Inode::Close(OpenFileCookie* cookie) if (result != B_OK) return result; - fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId); - return B_OK; } while (true); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index 9107f13c1d..0d071de338 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -7,6 +7,7 @@ */ +#include "Filesystem.h" #include "Inode.h" #include "NFS4Server.h" #include "Request.h" @@ -16,25 +17,26 @@ NFS4Server::NFS4Server(RPC::Server* serv) : fThreadCancel(true), fLeaseTime(0), - fCIDUseCount(0), - fOpenFiles(NULL), + fClientIdLastUse(0), + fUseCount(0), + fFilesystems(NULL), fServer(serv) { - mutex_init(&fLock, NULL); - mutex_init(&fOpenLock, NULL); + mutex_init(&fClientIdLock, NULL); + mutex_init(&fFSLock, NULL); } NFS4Server::~NFS4Server() { fThreadCancel = true; - fCIDUseCount = 0; + fUseCount = 0; interrupt_thread(fThread); status_t result; wait_for_thread(fThread, &result); - mutex_destroy(&fLock); - mutex_destroy(&fOpenLock); + mutex_destroy(&fClientIdLock); + mutex_destroy(&fFSLock); } @@ -46,13 +48,18 @@ NFS4Server::ServerRebooted(uint64 clientId) fClientId = ClientId(clientId, true); - // reclaim all open files - MutexLocker _(fOpenLock); - OpenFileCookie* current = fOpenFiles; - while (current != NULL) { - _ReclaimOpen(current); - _ReclaimLocks(current); - current = current->fNext; + // reclaim all opened files and held locks from all filesystems + MutexLocker _(fFSLock); + Filesystem* fs = fFilesystems; + while (fs != NULL) { + OpenFileCookie* current = fs->OpenFilesLock(); + while (current != NULL) { + _ReclaimOpen(current); + _ReclaimLocks(current); + current = current->fNext; + } + fs->OpenFilesUnlock(); + fs = fs->fNext; } return fClientId; @@ -141,36 +148,42 @@ NFS4Server::_ReclaimLocks(OpenFileCookie* cookie) void -NFS4Server::AddOpenFile(OpenFileCookie* cookie) +NFS4Server::AddFilesystem(Filesystem* fs) { - MutexLocker _(fOpenLock); - cookie->fPrev = NULL; - cookie->fNext = fOpenFiles; - if (fOpenFiles != NULL) - fOpenFiles->fPrev = cookie; - fOpenFiles = cookie; + MutexLocker _(fFSLock); + fs->fPrev = NULL; + fs->fNext = fFilesystems; + if (fFilesystems != NULL) + fFilesystems->fPrev = fs; + fFilesystems = fs; + fUseCount += fs->OpenFilesCount(); + if (fs->OpenFilesCount() > 0 && fThreadCancel) + _StartRenewing(); } void -NFS4Server::RemoveOpenFile(OpenFileCookie* cookie) +NFS4Server::RemoveFilesystem(Filesystem* fs) { - MutexLocker _(fOpenLock); - if (cookie == fOpenFiles) - fOpenFiles = cookie->fNext; + MutexLocker _(fFSLock); + if (fs == fFilesystems) + fFilesystems = fs->fNext; - if (cookie->fNext) - cookie->fNext->fPrev = cookie->fPrev; - if (cookie->fPrev) - cookie->fPrev->fNext = cookie->fNext; + if (fs->fNext) + fs->fNext->fPrev = fs->fPrev; + if (fs->fPrev) + fs->fPrev->fNext = fs->fNext; + fUseCount -= fs->OpenFilesCount(); } uint64 NFS4Server::ClientId(uint64 prevId, bool forceNew) { - MutexLocker _(fLock); - if ((forceNew && fClientId == prevId) || fCIDUseCount == 0) { + MutexLocker _(fClientIdLock); + if (fClientIdLastUse + (time_t)LeaseTime() < time(NULL) + || forceNew && fClientId == prevId) { + Request request(fServer); request.Builder().SetClientID(fServer); @@ -193,24 +206,13 @@ NFS4Server::ClientId(uint64 prevId, bool forceNew) result = request.Reply().SetClientIDConfirm(); if (result != B_OK) return fClientId; - - _StartRenewing(); } - fCIDUseCount++; - + fClientIdLastUse = time(NULL); return fClientId; } -void -NFS4Server::ReleaseCID(uint64 cid) -{ - MutexLocker _(fLock); - fCIDUseCount--; -} - - status_t NFS4Server::_GetLeaseTime() { @@ -233,7 +235,7 @@ NFS4Server::_GetLeaseTime() if (result != B_OK) return result; - // FATTR4_LEASE_TIM is mandatory + // FATTR4_LEASE_TIME is mandatory if (count < 1 || values[0].fAttribute != FATTR4_LEASE_TIME) { delete[] values; return B_BAD_VALUE; @@ -251,7 +253,6 @@ NFS4Server::_StartRenewing() if (!fThreadCancel) return B_OK; - if (fLeaseTime == 0) { status_t result = _GetLeaseTime(); if (result != B_OK) @@ -281,19 +282,20 @@ NFS4Server::_Renewal() // TODO: operations like OPEN, READ, CLOSE, etc also renew leases snooze_etc(fLeaseTime - 2, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT); - MutexLocker locker(fLock); uint64 clientId = fClientId; - if (fCIDUseCount == 0) { - fThreadCancel = true; - return B_OK; + if (fUseCount == 0) { + MutexLocker _(fFSLock); + if (fUseCount == 0) { + fThreadCancel = true; + return B_OK; + } } Request request(fServer); request.Builder().Renew(fClientId); request.Send(); - locker.Unlock(); if (request.Reply().NFS4Error() == NFS4ERR_STALE_CLIENTID) ServerRebooted(clientId); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h index 264e34af3e..a13f642584 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h @@ -14,6 +14,7 @@ #include "RPCServer.h" +class Filesystem; class OpenFileCookie; class NFS4Server : public RPC::ProgramData { @@ -22,11 +23,14 @@ public: virtual ~NFS4Server(); uint64 ServerRebooted(uint64 clientId); - void AddOpenFile(OpenFileCookie* cookie); - void RemoveOpenFile(OpenFileCookie* cookie); + + void AddFilesystem(Filesystem* fs); + void RemoveFilesystem(Filesystem* fs); + + inline void IncUsage(); + inline void DecUsage(); uint64 ClientId(uint64 prevId = 0, bool forceNew = false); - void ReleaseCID(uint64 cid); inline uint32 LeaseTime(); private: @@ -44,16 +48,36 @@ private: uint32 fLeaseTime; uint64 fClientId; - uint32 fCIDUseCount; - mutex fLock; + bool fClientIdInit; + time_t fClientIdLastUse; + mutex fClientIdLock; - OpenFileCookie* fOpenFiles; - mutex fOpenLock; + uint32 fUseCount; + Filesystem* fFilesystems; + mutex fFSLock; RPC::Server* fServer; }; +inline void +NFS4Server::IncUsage() +{ + MutexLocker _(fFSLock); + fUseCount++; + if (fThreadCancel) + _StartRenewing(); +} + + +inline void +NFS4Server::DecUsage() +{ + MutexLocker _(fFSLock); + fUseCount--; +} + + inline uint32 NFS4Server::LeaseTime() {