added 7 changesets to branch 'refs/remotes/pdziepak-github/nfs4' old head: feb15cc63ce6f32dc73e8322c165266d4a11b149 new head: e2e5f06d6e736c019ed37c475ff4f68e3c4f401c ---------------------------------------------------------------------------- 5a9212d: nfs4: NFS4Object::HandleErrors needs OpenState or OpenFileCookie object 9909222: nfs4: Use global open owner, check whether delegation was granted 52aaad1: nfs4: Use one open state per inode e743e24: nfs4: Move cache management inside Inode class 4a15375: nfs4: Return delegations when asked to bfa2037: nfs4: Reclaim delegations after server reboot e2e5f06: nfs4: Do not sync too often if delegation is held [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 37 files changed, 1267 insertions(+), 418 deletions(-) .../kernel/file_systems/nfs4/Connection.cpp | 11 +- src/add-ons/kernel/file_systems/nfs4/Cookie.cpp | 93 +------- src/add-ons/kernel/file_systems/nfs4/Cookie.h | 26 +-- .../kernel/file_systems/nfs4/Delegation.cpp | 66 ++++++ src/add-ons/kernel/file_systems/nfs4/Delegation.h | 58 +++++ src/add-ons/kernel/file_systems/nfs4/FileInfo.h | 21 ++ .../kernel/file_systems/nfs4/FileSystem.cpp | 72 ++++-- src/add-ons/kernel/file_systems/nfs4/FileSystem.h | 48 +++- src/add-ons/kernel/file_systems/nfs4/Inode.cpp | 110 +++++++-- src/add-ons/kernel/file_systems/nfs4/Inode.h | 40 +++- src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h | 1 + .../kernel/file_systems/nfs4/InodeRegular.cpp | 185 +++++++-------- src/add-ons/kernel/file_systems/nfs4/Jamfile | 3 + src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h | 26 +++ src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp | 68 ++++-- src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h | 3 +- .../kernel/file_systems/nfs4/NFS4Object.cpp | 28 ++- src/add-ons/kernel/file_systems/nfs4/NFS4Object.h | 2 +- .../kernel/file_systems/nfs4/NFS4Server.cpp | 130 ++++++----- src/add-ons/kernel/file_systems/nfs4/NFS4Server.h | 11 +- src/add-ons/kernel/file_systems/nfs4/OpenState.cpp | 187 +++++++++++++++- src/add-ons/kernel/file_systems/nfs4/OpenState.h | 24 +- .../kernel/file_systems/nfs4/RPCCallback.cpp | 11 +- src/add-ons/kernel/file_systems/nfs4/RPCCallback.h | 4 + .../file_systems/nfs4/RPCCallbackRequest.cpp | 6 + .../kernel/file_systems/nfs4/RPCCallbackServer.cpp | 10 +- src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp | 2 +- src/add-ons/kernel/file_systems/nfs4/RPCServer.h | 3 + .../kernel/file_systems/nfs4/ReplyBuilder.cpp | 85 +++++++ .../kernel/file_systems/nfs4/ReplyBuilder.h | 43 ++++ .../kernel/file_systems/nfs4/ReplyInterpreter.cpp | 53 ++++- .../kernel/file_systems/nfs4/ReplyInterpreter.h | 12 +- .../kernel/file_systems/nfs4/RequestBuilder.cpp | 56 +++-- .../kernel/file_systems/nfs4/RequestBuilder.h | 18 +- .../file_systems/nfs4/RequestInterpreter.cpp | 52 +++++ .../kernel/file_systems/nfs4/RequestInterpreter.h | 54 +++++ .../kernel/file_systems/nfs4/kernel_interface.cpp | 63 +++--- ############################################################################ Commit: 5a9212d612306df5df3ca1b2f0eb0112c57e2def Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sun Aug 5 13:44:16 2012 UTC nfs4: NFS4Object::HandleErrors needs OpenState or OpenFileCookie object ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index a95c3b9..cb89881 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -539,7 +539,7 @@ NFS4Inode::OpenFile(OpenState* state, int mode) ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv)) + if (HandleErrors(reply.NFS4Error(), serv, NULL, state)) continue; // Verify if the file we want to open is the file this Inode @@ -592,7 +592,7 @@ NFS4Inode::ReadFile(OpenFileCookie* cookie, OpenState* state, uint64 position, ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv, cookie)) + if (HandleErrors(reply.NFS4Error(), serv, cookie, state)) continue; reply.PutFH(); @@ -625,7 +625,7 @@ NFS4Inode::WriteFile(OpenFileCookie* cookie, OpenState* state, uint64 position, ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv, cookie)) + if (HandleErrors(reply.NFS4Error(), serv, cookie, state)) continue; reply.PutFH(); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp index e5db3e6..73c5e3a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp @@ -15,7 +15,7 @@ bool NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, - OpenFileCookie* cookie) + OpenFileCookie* cookie, OpenState* state) { uint32 leaseTime; @@ -62,8 +62,14 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, // server has rebooted, reclaim share and try again case NFS4ERR_STALE_CLIENTID: case NFS4ERR_STALE_STATEID: - fFileSystem->NFSServer()->ServerRebooted(cookie->fClientID); - return true; + if (cookie != NULL) { + fFileSystem->NFSServer()->ServerRebooted(cookie->fClientID); + return true; + } else if (state != NULL) { + fFileSystem->NFSServer()->ServerRebooted(state->fClientID); + return true; + } + return false; // FileHandle has expired case NFS4ERR_FHEXPIRED: @@ -82,6 +88,9 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, if (cookie != NULL) { fFileSystem->NFSServer()->ClientId(cookie->fClientID, true); return true; + } else if (state != NULL) { + fFileSystem->NFSServer()->ClientId(state->fClientID, true); + return true; } return false; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h index 7ffcf4b..79df6f1 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h @@ -19,7 +19,7 @@ class OpenState; class NFS4Object { public: bool HandleErrors(uint32 nfs4Error, RPC::Server* serv, - OpenFileCookie* cookie = NULL); + OpenFileCookie* cookie = NULL, OpenState* state = NULL); status_t ConfirmOpen(const FileHandle& fileHandle, OpenState* state); diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp index 26a4df5..4959199 100644 --- a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp @@ -101,7 +101,7 @@ OpenState::Close() ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv)) + if (HandleErrors(reply.NFS4Error(), serv, NULL, this)) continue; reply.PutFH(); ############################################################################ Commit: 990922235b448d860c0dbcf596c21bfdbeab8831 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sun Aug 5 17:37:58 2012 UTC nfs4: Use global open owner, check whether delegation was granted ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp index 25ed74b..cc4611b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp @@ -551,7 +551,7 @@ ConnectionBase::Disconnect() status_t -ConnectionListener::Listen(ConnectionListener** _listener, uint16 port) +ConnectionListener::Listen(ConnectionListener** listener, uint16 port) { int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) @@ -577,16 +577,13 @@ ConnectionListener::Listen(ConnectionListener** _listener, uint16 port) address.fProtocol = IPPROTO_TCP; memset(&address.fAddress, 0, sizeof(address.fAddress)); - ConnectionListener* listener; - listener = new(std::nothrow) ConnectionListener(address); - if (listener == NULL) { + *listener = new(std::nothrow) ConnectionListener(address); + if (*listener == NULL) { close(sock); return B_NO_MEMORY; } - listener->fSocket = sock; - - *_listener = listener; + (*listener)->fSocket = sock; return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp index 95e95ae..f4eb990 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp @@ -27,10 +27,16 @@ FileSystem::FileSystem() fPrev(NULL), fOpenFiles(NULL), fOpenCount(0), + fOpenOwnerSequence(0), fPath(NULL), fRoot(NULL), fId(1) { + fOpenOwner = rand(); + fOpenOwner <<= 32; + fOpenOwner |= rand(); + + mutex_init(&fOpenOwnerLock, NULL); mutex_init(&fOpenLock, NULL); } @@ -40,6 +46,7 @@ FileSystem::~FileSystem() NFSServer()->RemoveFileSystem(this); mutex_destroy(&fOpenLock); + mutex_destroy(&fOpenOwnerLock); free(const_cast<char*>(fPath)); delete fRoot; diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h index 7b99ef7..4c5df28 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h @@ -51,6 +51,10 @@ public: inline dev_t DevId() const; inline InodeIdMap* InoIdMap(); + inline uint64 OpenOwner() const; + inline uint32 OpenOwnerSequenceLock(); + inline void OpenOwnerSequenceUnlock(bool increment = true); + FileSystem* fNext; FileSystem* fPrev; private: @@ -62,6 +66,10 @@ private: uint32 fOpenCount; mutex fOpenLock; + uint64 fOpenOwner; + uint32 fOpenOwnerSequence; + mutex fOpenOwnerLock; + uint32 fExpireType; uint32 fSupAttrs[2]; @@ -163,5 +171,29 @@ FileSystem::InoIdMap() } +inline uint64 +FileSystem::OpenOwner() const +{ + return fOpenOwner; +} + + +inline uint32 +FileSystem::OpenOwnerSequenceLock() +{ + mutex_lock(&fOpenOwnerLock); + return fOpenOwnerSequence; +} + + +inline void +FileSystem::OpenOwnerSequenceUnlock(bool increment = true) +{ + if (increment) + fOpenOwnerSequence++; + mutex_unlock(&fOpenOwnerLock); +} + + #endif // FILESYSTEM_H diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index c0abd7b..1887ee2 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -207,11 +207,32 @@ enum OpenClaim { CLAIM_DELEGATE_PREV = 3 }; +enum OpenDelegation { + OPEN_DELEGATE_NONE = 0, + OPEN_DELEGATE_READ = 1, + OPEN_DELEGATE_WRITE = 2 +}; + +struct OpenDelegationData { + OpenDelegation fType; + + uint32 fStateSeq; + uint32 fStateID[3]; + + bool fRecall; + uint64 fSpaceLimit; +}; + enum OpenFlags { OPEN4_RESULT_CONFIRM = 2, OPEN4_RESULT_LOCKTYPE_POSIX = 4 }; +enum { + NFS_LIMIT_SIZE = 1, + NFS_LIMIT_BLOCKS = 2 +}; + struct ChangeInfo { bool fAtomic; uint64 fBefore; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index cb89881..1c6722b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -389,6 +389,8 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, status_t result; bool badOwner = false; + OpenDelegationData delegation; + uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); do { state->fClientID = fFileSystem->NFSServer()->ClientId(); @@ -396,8 +398,6 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, Request request(serv); RequestBuilder& req = request.Builder(); - state->fOwnerID = atomic_add64(&state->fLastOwnerID, 1); - req.PutFH(fInfo.fHandle); AttrValue cattr[4]; @@ -427,9 +427,9 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, i++; } - req.Open(CLAIM_NULL, state->fSequence++, sModeToAccess(mode), - state->fClientID, OPEN4_CREATE, state->fOwnerID, name, cattr, - i, (mode & O_EXCL) == O_EXCL); + req.Open(CLAIM_NULL, sequence, sModeToAccess(mode), + state->fClientID, OPEN4_CREATE, fFileSystem->OpenOwner(), name, + cattr, i, (mode & O_EXCL) == O_EXCL); req.GetFH(); @@ -439,22 +439,29 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, } result = request.Send(); - if (result != B_OK) + if (result != B_OK) { + fFileSystem->OpenOwnerSequenceUnlock(false); return result; + } ReplyInterpreter& reply = request.Reply(); if (reply.NFS4Error() == NFS4ERR_BADOWNER) { + fFileSystem->OpenOwnerSequenceUnlock(); + sequence = fFileSystem->OpenOwnerSequenceLock(); + badOwner = true; continue; } if (HandleErrors(reply.NFS4Error(), serv)) continue; + fFileSystem->OpenOwnerSequenceUnlock(); + reply.PutFH(); result = reply.Open(state->fStateID, &state->fStateSeq, &confirm, - &changeInfo->fBefore, &changeInfo->fAfter, &changeInfo->fAtomic); + &delegation, changeInfo); if (result != B_OK) return result; @@ -488,8 +495,10 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, status_t NFS4Inode::OpenFile(OpenState* state, int mode) { + OpenDelegationData delegation; bool confirm; status_t result; + uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); do { state->fClientID = fFileSystem->NFSServer()->ClientId(); @@ -497,8 +506,6 @@ NFS4Inode::OpenFile(OpenState* state, int mode) Request request(serv); RequestBuilder& req = request.Builder(); - state->fOwnerID = atomic_add64(&state->fLastOwnerID, 1); - // Since we are opening the file using a pair (parentFH, name) we // need to check for race conditions. if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) { @@ -526,22 +533,27 @@ NFS4Inode::OpenFile(OpenState* state, int mode) attr.fAttribute = FATTR4_SIZE; attr.fFreePointer = false; attr.fData.fValue64 = 0; - req.Open(CLAIM_NULL, state->fSequence++, sModeToAccess(mode), - state->fClientID, OPEN4_CREATE, state->fOwnerID, fInfo.fName, - &attr, 1, false); + req.Open(CLAIM_NULL, sequence, sModeToAccess(mode), + state->fClientID, OPEN4_CREATE, fFileSystem->OpenOwner(), + fInfo.fName, &attr, 1, false); } else - req.Open(CLAIM_NULL, state->fSequence++, sModeToAccess(mode), - state->fClientID, OPEN4_NOCREATE, state->fOwnerID, fInfo.fName); + req.Open(CLAIM_NULL, sequence, sModeToAccess(mode), state->fClientID, + OPEN4_NOCREATE, fFileSystem->OpenOwner(), fInfo.fName); + req.GetFH(); result = request.Send(); - if (result != B_OK) + if (result != B_OK) { + fFileSystem->OpenOwnerSequenceUnlock(false); return result; + } ReplyInterpreter& reply = request.Reply(); if (HandleErrors(reply.NFS4Error(), serv, NULL, state)) continue; + fFileSystem->OpenOwnerSequenceUnlock(); + // Verify if the file we want to open is the file this Inode // represents. if (fFileSystem->IsAttrSupported(FATTR4_FILEID) || @@ -558,7 +570,12 @@ NFS4Inode::OpenFile(OpenState* state, int mode) } reply.PutFH(); - result = reply.Open(state->fStateID, &state->fStateSeq, &confirm); + result = reply.Open(state->fStateID, &state->fStateSeq, &confirm, + &delegation); + + FileHandle handle; + reply.GetFH(&handle); + if (result != B_OK) return result; @@ -570,6 +587,9 @@ NFS4Inode::OpenFile(OpenState* state, int mode) if (confirm) return ConfirmOpen(fInfo.fHandle, state); + if (delegation.fType != OPEN_DELEGATE_NONE) + dprintf("GOT A DELEGATION!\n"); + return B_OK; } @@ -891,6 +911,7 @@ NFS4Inode::TestLock(OpenFileCookie* cookie, LockType* type, uint64* position, status_t NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait) { + uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); do { MutexLocker ownerLocker(lockInfo->fOwner->fLock); @@ -899,11 +920,13 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait) RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); - req.Lock(cookie, lockInfo); + req.Lock(cookie, lockInfo, sequence); status_t result = request.Send(); - if (result != B_OK) + if (result != B_OK) { + fFileSystem->OpenOwnerSequenceUnlock(false); return result; + } ReplyInterpreter &reply = request.Reply(); @@ -912,13 +935,16 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait) ownerLocker.Unlock(); if (wait && reply.NFS4Error() == NFS4ERR_DENIED) { + fFileSystem->OpenOwnerSequenceUnlock(); snooze_etc(sSecToBigTime(5), B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT); + sequence = fFileSystem->OpenOwnerSequenceLock(); continue; } if (HandleErrors(reply.NFS4Error(), serv, cookie)) continue; + fFileSystem->OpenOwnerSequenceUnlock(); if (result != B_OK) return result; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp index 73c5e3a..073fd01 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp @@ -103,6 +103,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, status_t NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state) { + uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); do { RPC::Server* serv = fFileSystem->Server(); Request request(serv); @@ -110,17 +111,21 @@ NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state) RequestBuilder& req = request.Builder(); req.PutFH(fh); - req.OpenConfirm(state->fSequence++, state->fStateID, state->fStateSeq); + req.OpenConfirm(sequence, state->fStateID, state->fStateSeq); status_t result = request.Send(); - if (result != B_OK) + if (result != B_OK) { + fFileSystem->OpenOwnerSequenceUnlock(false); return result; + } ReplyInterpreter& reply = request.Reply(); if (HandleErrors(reply.NFS4Error(), serv)) continue; + fFileSystem->OpenOwnerSequenceUnlock(); + reply.PutFH(); result = reply.OpenConfirm(&state->fStateSeq); if (result != B_OK) diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp index 4959199..236ff7c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp @@ -15,11 +15,8 @@ #include "Request.h" -vint64 OpenState::fLastOwnerID = 0; - OpenState::OpenState() : - fSequence(0), fOpened(false) { mutex_init(&fLock, NULL); @@ -46,27 +43,34 @@ OpenState::Reclaim(uint64 newClientID) fClientID = newClientID; bool confirm; + OpenDelegationData delegation; + + uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); do { RPC::Server* server = fFileSystem->Server(); Request request(server); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); - req.Open(CLAIM_PREVIOUS, fSequence++, sModeToAccess(fMode), newClientID, - OPEN4_NOCREATE, fOwnerID, NULL); + req.Open(CLAIM_PREVIOUS, sequence, sModeToAccess(fMode), newClientID, + OPEN4_NOCREATE, fFileSystem->OpenOwner(), NULL); status_t result = request.Send(); - if (result != B_OK) + if (result != B_OK) { + fFileSystem->OpenOwnerSequenceUnlock(false); return result; + } ReplyInterpreter& reply = request.Reply(); if (HandleErrors(reply.NFS4Error(), server)) continue; + fFileSystem->OpenOwnerSequenceUnlock(); + reply.PutFH(); - result = reply.Open(fStateID, &fStateSeq, &confirm); + result = reply.Open(fStateID, &fStateSeq, &confirm, &delegation); if (result != B_OK) return result; } while (true); @@ -87,24 +91,29 @@ OpenState::Close() MutexLocker _(fLock); fOpened = false; + uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); do { RPC::Server* serv = fFileSystem->Server(); Request request(serv); RequestBuilder& req = request.Builder(); req.PutFH(fInfo.fHandle); - req.Close(fSequence++, fStateID, fStateSeq); + req.Close(sequence, fStateID, fStateSeq); status_t result = request.Send(); - if (result != B_OK) + if (result != B_OK) { + fFileSystem->OpenOwnerSequenceUnlock(false); return result; + } ReplyInterpreter& reply = request.Reply(); if (HandleErrors(reply.NFS4Error(), serv, NULL, this)) continue; + fFileSystem->OpenOwnerSequenceUnlock(); reply.PutFH(); + return reply.Close(); } while (true); } diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.h b/src/add-ons/kernel/file_systems/nfs4/OpenState.h index 00da687..ecf10a8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/OpenState.h +++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.h @@ -28,14 +28,8 @@ struct OpenState : public NFS4Object, public KernelReferenceable { uint32 fStateID[3]; uint32 fStateSeq; - uint32 fSequence; - - uint64 fOwnerID; - static vint64 fLastOwnerID; - bool fOpened; - status_t Reclaim(uint64 newClientID); status_t Close(); diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp index 651ccc5..5a64700 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp @@ -287,6 +287,7 @@ CallbackServer::ListenerThread() { while (fThreadRunning) { Connection* connection; + status_t result = fListener->AcceptConnection(&connection); if (result != B_OK) { fThreadRunning = false; diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index 56ba582..2b74de3 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -266,8 +266,8 @@ ReplyInterpreter::LockU(LockInfo* linfo) status_t -ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, uint64* _before, - uint64* _after, bool* _atomic) +ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, + OpenDelegationData* delegData, ChangeInfo* changeInfo) { status_t res = _OperationError(OpOpen); if (res != B_OK) @@ -280,14 +280,13 @@ ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, uint64* _before, // change info bool atomic = fReply->Stream().GetBoolean(); - if (_atomic != NULL) - *_atomic = atomic; uint64 before = fReply->Stream().GetUHyper(); - if (_before != NULL) - *_before = before; uint64 after = fReply->Stream().GetUHyper(); - if (_after != NULL) - *_after = after; + if (changeInfo != NULL) { + changeInfo->fAtomic = atomic; + changeInfo->fBefore = before; + changeInfo->fAfter = after; + } uint32 flags = fReply->Stream().GetUInt(); *confirm = (flags & OPEN4_RESULT_CONFIRM) == OPEN4_RESULT_CONFIRM; @@ -298,7 +297,41 @@ ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, uint64* _before, fReply->Stream().GetUInt(); // delegation info + uint32 delegation = fReply->Stream().GetUInt(); + if (delegation == OPEN_DELEGATE_NONE) { + delegData->fType = OPEN_DELEGATE_NONE; + return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK; + } + + delegData->fStateSeq = fReply->Stream().GetUInt(); + delegData->fStateID[0] = fReply->Stream().GetUInt(); + delegData->fStateID[1] = fReply->Stream().GetUInt(); + delegData->fStateID[2] = fReply->Stream().GetUInt(); + + delegData->fRecall = fReply->Stream().GetBoolean(); + + switch (delegation) { + case OPEN_DELEGATE_READ: + delegData->fType = OPEN_DELEGATE_READ; + break; + case OPEN_DELEGATE_WRITE: + delegData->fType = OPEN_DELEGATE_WRITE; + + int32 limitBy = fReply->Stream().GetInt(); + if (limitBy == NFS_LIMIT_SIZE) + delegData->fSpaceLimit = fReply->Stream().GetUHyper(); + else if (limitBy == NFS_LIMIT_BLOCKS) { + uint32 numBlocks = fReply->Stream().GetUInt(); + delegData->fSpaceLimit = fReply->Stream().GetUInt() * numBlocks; + } + break; + } + + // ACE data + fReply->Stream().GetUInt(); fReply->Stream().GetUInt(); + fReply->Stream().GetUInt(); + fReply->Stream().GetOpaque(NULL); return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index ed3a269..892e34c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -81,8 +81,8 @@ public: inline status_t LookUpUp(); inline status_t Nverify(); status_t Open(uint32* id, uint32* seq, bool* confirm, - uint64* before = NULL, uint64* after = NULL, - bool* atomic = NULL); + OpenDelegationData* delegData, + ChangeInfo* changeInfo = NULL); status_t OpenConfirm(uint32* stateSeq); inline status_t PutFH(); inline status_t PutRootFH(); diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index c9d2408..c6a0e80 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -186,7 +186,8 @@ RequestBuilder::_GenerateLockOwner(XDR::WriteStream& stream, status_t -RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim) +RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, uint32 sequence, + bool reclaim) { if (fProcedure != ProcCompound) return B_BAD_VALUE; @@ -213,7 +214,7 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim) else state = cookie->fWriteState; - fRequest->Stream().AddUInt(state->fSequence++); + fRequest->Stream().AddUInt(sequence); fRequest->Stream().AddUInt(state->fStateSeq); fRequest->Stream().AddUInt(state->fStateID[0]); fRequest->Stream().AddUInt(state->fStateID[1]); diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index a8f2d76..13db57d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -41,7 +41,8 @@ public: status_t GetFH(); status_t Link(const char* name); status_t Lock(OpenFileCookie* cookie, - LockInfo* lock, bool reclaim = false); + LockInfo* lock, uint32 sequence, + bool reclaim = false); status_t LockT(LockType type, uint64 pos, uint64 len, OpenFileCookie* cookie); status_t LockU(LockInfo* lock); ############################################################################ Commit: 52aaad172fd93ba9b286d237dd299746e6458e1b Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sun Aug 5 20:07:44 2012 UTC nfs4: Use one open state per inode ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp index 83d0336..a2970b7 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp @@ -161,7 +161,6 @@ OpenFileCookie::GetLockOwner(uint32 owner) if (current == NULL) return NULL; - current->fClientId = fClientID; current->fNext = fLockOwners; if (fLockOwners != NULL) fLockOwners->fPrev = current; diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.h b/src/add-ons/kernel/file_systems/nfs4/Cookie.h index baeca67..4af8899 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.h +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.h @@ -71,10 +71,7 @@ struct Cookie { }; struct OpenFileCookie : public Cookie { - uint64 fClientID; - - OpenState* fReadState; - OpenState* fWriteState; + OpenState* fOpenState; uint32 fMode; diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.h b/src/add-ons/kernel/file_systems/nfs4/Delegation.h new file mode 100644 index 0000000..31fea04 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ +#ifndef DELEGATION_H +#define DELEGATION_H + + +#include <lock.h> +#include <SupportDefs.h> + +#include "NFS4Object.h" + + +class Delegation : public NFS4Object { +public: + Delegation(OpenDelegationData data, Inode* inode, + uint64 clientID); + ~Delegation(); + + status_t Write(void* buffer, uint32* size); + status_t Read(void* buffer, uint32* size); + + // TODO: locks + + status_t Reclaim(uint64 newClientID); + + status_t GiveUp(bool flush); + +private: + uint64 fClientID; + OpenDelegationData fData; + Inode* fInode; + + rw_lock fLock; +}; + + +#endif // DELEGATION_H + diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 007890e..edfbddf 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -24,8 +24,7 @@ Inode::Inode() : fCache(NULL), fFileCache(NULL), - fWriteState(NULL), - fReadState(NULL), + fOpenState(NULL), fWriteDirty(false) { mutex_init(&fStateLock, NULL); @@ -530,7 +529,7 @@ Inode::WriteStat(const struct stat* st, uint32 mask) } MutexLocker stateLocker(fStateLock); - result = NFS4Inode::WriteStat(fWriteState, attr, i); + result = NFS4Inode::WriteStat(fOpenState, attr, i); stateLocker.Unlock(); fMetaCache.InvalidateStat(); diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index e4bfa9a..58250e7 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -14,6 +14,8 @@ #include "OpenState.h" +class Delegation; + class Inode : public NFS4Inode { public: static status_t CreateInode(FileSystem* fs, const FileInfo& fi, @@ -25,6 +27,8 @@ public: inline const char* Name() const; inline FileSystem* GetFileSystem() const; + inline void SetOpenState(OpenState* state); + inline void* FileCache(); status_t RevalidateFileCache(); @@ -93,17 +97,20 @@ protected: static inline ino_t FileIdToInoT(uint64 fileid); +private: uint32 fType; MetadataCache fMetaCache; DirectoryCache* fCache; + rw_lock fDelegationLock; + Delegation* fDelegation; + uint64 fChange; void* fFileCache; mutex fFileCacheLock; - OpenState* fWriteState; - OpenState* fReadState; + OpenState* fOpenState; mutex fStateLock; bool fWriteDirty; @@ -156,5 +163,13 @@ Inode::FileCache() } +inline void +Inode::SetOpenState(OpenState* state) +{ + MutexLocker _(fStateLock); + fOpenState = state; +} + + #endif // INODE_H diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h index 63ec1b0..2a29e07 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h +++ b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h @@ -52,6 +52,7 @@ inline status_t InodeIdMap::AddEntry(const FileInfo& fi, ino_t id) { MutexLocker _(fLock); + fMap.Remove(id); return fMap.Insert(id, fi); } diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 51d4122..c82c507 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -70,44 +70,19 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, cookie->fLocks = NULL; MutexLocker _(fStateLock); - int openMode = mode & O_RWMASK; - if (openMode == O_WRONLY || openMode == O_RDWR) { - OpenState* state = new OpenState; - status_t result = CreateState(name, O_WRONLY, perms, state); - if (result != B_OK) - return result; - - fWriteState = state; - *id = FileIdToInoT(cookie->fWriteState->fInfo.fFileId); - cookie->fWriteState = fWriteState; - } - - if (openMode == O_RDONLY || openMode == O_RDWR) { - OpenState* state = new OpenState; - state->fInfo = fInfo; - state->fFileSystem = fFileSystem; - - status_t result; - if (openMode == O_RDWR) - result = OpenFile(state, O_RDONLY); - else - result = CreateState(name, O_RDONLY, perms, state); + OpenState* state = new OpenState; + status_t result = CreateState(name, mode, perms, state); + if (result != B_OK) + return result; - if (result != B_OK) { - if (fWriteState != NULL) - if (fWriteState->ReleaseReference() == 1) - fWriteState = NULL; - return result; - } + cookie->fOpenState = state; + fOpenState = state; - fReadState = state; - *id = FileIdToInoT(cookie->fReadState->fInfo.fFileId); - cookie->fReadState = fReadState; - } + *id = FileIdToInoT(state->fInfo.fFileId); + cookie->fOpenState = fOpenState; cookie->fFileSystem = fFileSystem; - cookie->fClientID = fFileSystem->NFSServer()->ClientId(); fFileSystem->AddOpenFile(cookie); fFileSystem->Root()->MakeInfoInvalid(); @@ -120,55 +95,33 @@ status_t Inode::Open(int mode, OpenFileCookie* cookie) { MutexLocker _(fStateLock); - int openMode = mode & O_RWMASK; - if (openMode == O_WRONLY || openMode == O_RDWR) { - if (fWriteState == NULL) { - OpenState* state = new OpenState; - if (state == NULL) - return B_NO_MEMORY; + if (fOpenState == NULL) { + OpenState* state = new OpenState; + if (state == NULL) + return B_NO_MEMORY; + + state->fInfo = fInfo; + state->fFileSystem = fFileSystem; + status_t result = OpenFile(state, mode, NULL); + if (result != B_OK) + return result; - state->fInfo = fInfo; - state->fFileSystem = fFileSystem; - status_t result = OpenFile(state, O_WRONLY); + fOpenState = state; + } else { + int newMode = mode & O_RWMASK; + int oldMode = fOpenState->fMode & O_RWMASK; + if (oldMode != newMode && oldMode != O_RDWR) { + status_t result = OpenFile(fOpenState, O_RDWR, NULL); if (result != B_OK) return result; - - fWriteState = state; - } else - fWriteState->AcquireReference(); - - cookie->fWriteState = fWriteState; + fOpenState->fMode = O_RDWR; + } + fOpenState->AcquireReference(); } - if (openMode == O_RDONLY || openMode == O_RDWR) { - if (fReadState == NULL) { - OpenState* state = new OpenState; - if (state == NULL) { - if (fWriteState != NULL) - if (fWriteState->ReleaseReference() == 1) - fWriteState = NULL; - return B_NO_MEMORY; - } - - state->fInfo = fInfo; - state->fFileSystem = fFileSystem; - status_t result = OpenFile(state, O_RDONLY); - if (result != B_OK) { - if (fWriteState != NULL) - if (fWriteState->ReleaseReference() == 1) - fWriteState = NULL; - return result; - } - - fReadState = state; - } else - fReadState->AcquireReference(); + cookie->fOpenState = fOpenState; - cookie->fReadState = fReadState; - } - - cookie->fClientID = fFileSystem->NFSServer()->ClientId(); cookie->fFileSystem = fFileSystem; cookie->fMode = mode; cookie->fLocks = NULL; @@ -185,13 +138,9 @@ Inode::Close(OpenFileCookie* cookie) fFileSystem->RemoveOpenFile(cookie); MutexLocker _(fStateLock); - if (cookie->fWriteState != NULL) - if (cookie->fWriteState->ReleaseReference() == 1) - fWriteState = NULL; - - if (cookie->fReadState != NULL) - if (cookie->fReadState->ReleaseReference() == 1) - fReadState = NULL; + if (cookie->fOpenState != NULL) + if (cookie->fOpenState->ReleaseReference() == 1) + fOpenState = NULL; return B_OK; } @@ -207,7 +156,7 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length, status_t result; while (size < *_length && !*eof) { uint32 len = *_length - size; - result = ReadFile(cookie, fReadState, pos + size, &len, + result = ReadFile(cookie, fOpenState, pos + size, &len, reinterpret_cast<char*>(buffer) + size, eof); if (result != B_OK) { if (size == 0) @@ -236,7 +185,7 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, while (size < *_length) { uint32 len = *_length - size; - status_t result = WriteFile(cookie, fWriteState, pos + size, &len, + status_t result = WriteFile(cookie, fOpenState, pos + size, &len, buffer + size); if (result != B_OK) { if (size == 0) diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index 1c6722b..c2208fb 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -493,9 +493,8 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, status_t -NFS4Inode::OpenFile(OpenState* state, int mode) +NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation) { - OpenDelegationData delegation; bool confirm; status_t result; uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); @@ -571,7 +570,7 @@ NFS4Inode::OpenFile(OpenState* state, int mode) reply.PutFH(); result = reply.Open(state->fStateID, &state->fStateSeq, &confirm, - &delegation); + delegation); FileHandle handle; reply.GetFH(&handle); @@ -587,9 +586,6 @@ NFS4Inode::OpenFile(OpenState* state, int mode) if (confirm) return ConfirmOpen(fInfo.fHandle, state); - if (delegation.fType != OPEN_DELEGATE_NONE) - dprintf("GOT A DELEGATION!\n"); - return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h index 027f6a4..dbcf90a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h @@ -33,7 +33,7 @@ protected: status_t LookUp(const char* name, uint64* change, uint64* fileID, FileHandle* handle); - status_t Link(Inode* dir, const char* name, + status_t Link(Inode* dir, const char* name,s ChangeInfo* changeInfo); static status_t Rename(Inode* from, Inode* to, const char* fromName, @@ -47,7 +47,8 @@ protected: status_t CreateFile(const char* name, int mode, int perms, OpenState* state, ChangeInfo* changeInfo, uint64* fileID, FileHandle* handle); - status_t OpenFile(OpenState* state, int mode); + status_t OpenFile(OpenState* state, int mode, + OpenDelegationData* delegation); status_t ReadFile(OpenFileCookie* cookie, OpenState* state, uint64 position, uint32* length, void* buffer, diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp index 073fd01..327c075 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp @@ -19,6 +19,9 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, { uint32 leaseTime; + if (cookie != NULL) + state = cookie->fOpenState; + switch (nfs4Error) { case NFS4_OK: return false; @@ -62,10 +65,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, // server has rebooted, reclaim share and try again case NFS4ERR_STALE_CLIENTID: case NFS4ERR_STALE_STATEID: - if (cookie != NULL) { - fFileSystem->NFSServer()->ServerRebooted(cookie->fClientID); - return true; - } else if (state != NULL) { + if (state != NULL) { fFileSystem->NFSServer()->ServerRebooted(state->fClientID); return true; } @@ -85,10 +85,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, // lease has expired case NFS4ERR_EXPIRED: - if (cookie != NULL) { - fFileSystem->NFSServer()->ClientId(cookie->fClientID, true); - return true; - } else if (state != NULL) { + if (state != NULL) { fFileSystem->NFSServer()->ClientId(state->fClientID, true); return true; } @@ -121,7 +118,7 @@ NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state) ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv)) + if (HandleErrors(reply.NFS4Error(), serv, NULL, state)) continue; fFileSystem->OpenOwnerSequenceUnlock(); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index 412a653..ec38c3a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -59,7 +59,6 @@ NFS4Server::ServerRebooted(uint64 clientId) while (fs != NULL) { OpenFileCookie* current = fs->OpenFilesLock(); while (current != NULL) { - current->fClientID = fClientId; _ReclaimOpen(current); _ReclaimLocks(current); current = current->fNext; @@ -75,10 +74,8 @@ NFS4Server::ServerRebooted(uint64 clientId) status_t NFS4Server::_ReclaimOpen(OpenFileCookie* cookie) { - if (cookie->fWriteState != NULL) - cookie->fWriteState->Reclaim(fClientId); - if (cookie->fReadState != NULL) - cookie->fReadState->Reclaim(fClientId); + if (cookie->fOpenState != NULL) + cookie->fOpenState->Reclaim(fClientId); return B_OK; } @@ -100,10 +97,7 @@ NFS4Server::_ReclaimLocks(OpenFileCookie* cookie) Request request(fServer); RequestBuilder& req = request.Builder(); - if (cookie->fWriteState != NULL) - req.PutFH(cookie->fWriteState->fInfo.fHandle); - else - req.PutFH(cookie->fReadState->fInfo.fHandle); + req.PutFH(cookie->fOpenState->fInfo.fHandle); req.Lock(cookie, linfo, true); status_t result = request.Send(); diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index 2b74de3..b26082d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -298,6 +298,10 @@ ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, // delegation info uint32 delegation = fReply->Stream().GetUInt(); + OpenDelegationData data; + if (delegData == NULL) + delegData = &data; + if (delegation == OPEN_DELEGATE_NONE) { delegData->fType = OPEN_DELEGATE_NONE; return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK; diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index c6a0e80..c05b873 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -173,14 +173,11 @@ void RequestBuilder::_GenerateLockOwner(XDR::WriteStream& stream, OpenFileCookie* cookie, LockOwner* owner) { - stream.AddUHyper(cookie->fClientID); + stream.AddUHyper(cookie->fOpenState->fClientID); uint64 lockOwner[2]; lockOwner[0] = owner->fOwner; - if (cookie->fWriteState != NULL) - lockOwner[1] = cookie->fWriteState->fInfo.fFileId; - else - lockOwner[1] = cookie->fReadState->fInfo.fFileId; + lockOwner[1] = cookie->fOpenState->fInfo.fFileId; stream.AddOpaque(lockOwner, sizeof(lockOwner)); } @@ -208,11 +205,7 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, uint32 sequence, fRequest->Stream().AddBoolean(true); // new lock owner // open seq stateid - OpenState* state; - if (lock->fType == READ_LT || lock->fType == READW_LT) - state = cookie->fReadState; - else - state = cookie->fWriteState; + OpenState* state = cookie->fOpenState; fRequest->Stream().AddUInt(sequence); fRequest->Stream().AddUInt(state->fStateSeq); @@ -258,7 +251,7 @@ RequestBuilder::LockT(LockType type, uint64 pos, uint64 len, fRequest->Stream().AddUHyper(pos); fRequest->Stream().AddUHyper(len); - fRequest->Stream().AddUHyper(cookie->fClientID); + fRequest->Stream().AddUHyper(cookie->fOpenState->fClientID); uint32 owner = find_thread(NULL); fRequest->Stream().AddOpaque(&owner, sizeof(owner)); diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index 95b8bd8..d1a447b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -400,10 +400,24 @@ nfs4_create(fs_volume* volume, fs_vnode* dir, const char* name, int openMode, return result; } - void* ptr; - result = get_vnode(volume, *_newVnodeID, &ptr); - if (result != B_OK) - delete cookie; + Inode* child; + result = get_vnode(volume, *_newVnodeID, reinterpret_cast<void**>(&child)); + if (result != B_OK) { + result = inode->GetFileSystem()->GetInode(*_newVnodeID, &child); + if (result != B_OK) { + delete cookie; + return result; + } + + result = new_vnode(volume, *_newVnodeID, child, &gNFSv4VnodeOps); + if (result != B_OK) { + delete child; + delete cookie; + return result; + } + } + + child->SetOpenState(cookie->fOpenState); return result; } ############################################################################ Commit: e743e243206509ccb41281a1aab140597bfb40b7 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sun Aug 5 20:49:44 2012 UTC nfs4: Move cache management inside Inode class ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index edfbddf..a573f49 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -24,6 +24,7 @@ Inode::Inode() : fCache(NULL), fFileCache(NULL), + fMaxFileSize(0), fOpenState(NULL), fWriteDirty(false) { @@ -638,6 +639,9 @@ Inode::AcquireLock(OpenFileCookie* cookie, const struct flock* lock, status_t Inode::ReleaseLock(OpenFileCookie* cookie, const struct flock* lock) { + file_cache_sync(fFileCache); + Commit(); + LockInfo* prev = NULL; thread_info info; @@ -673,6 +677,9 @@ Inode::ReleaseLock(OpenFileCookie* cookie, const struct flock* lock) status_t Inode::ReleaseAllLocks(OpenFileCookie* cookie) { + file_cache_sync(fFileCache); + Commit(); + MutexLocker _(cookie->fLocksLock); LockInfo* linfo = cookie->fLocks; while (linfo != NULL) { diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 58250e7..a44c12b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -32,6 +32,8 @@ public: inline void* FileCache(); status_t RevalidateFileCache(); + inline uint64 MaxFileSize(); + status_t LookUp(const char* name, ino_t* id); status_t Access(int mode); @@ -57,10 +59,15 @@ public: status_t Open(int mode, OpenFileCookie* cookie); status_t Close(OpenFileCookie* cookie); status_t Read(OpenFileCookie* cookie, off_t pos, - void* buffer, size_t* length, bool* eof); + void* buffer, size_t* length); status_t Write(OpenFileCookie* cookie, off_t pos, const void* buffer, size_t *_length); + status_t ReadDirect(OpenFileCookie* cookie, off_t pos, + void* buffer, size_t* length, bool* eof); + status_t WriteDirect(OpenFileCookie* cookie, off_t pos, + const void* buffer, size_t *_length); + status_t CreateDir(const char* name, int mode); status_t OpenDir(OpenDirCookie* cookie); status_t ReadDir(void* buffer, uint32 size, @@ -109,6 +116,7 @@ private: uint64 fChange; void* fFileCache; mutex fFileCacheLock; + uint64 fMaxFileSize; OpenState* fOpenState; mutex fStateLock; @@ -171,5 +179,12 @@ Inode::SetOpenState(OpenState* state) } +inline uint64 +Inode::MaxFileSize() +{ + return fMaxFileSize; +} + + #endif // INODE_H diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index c82c507..34ca35e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -135,6 +135,9 @@ Inode::Open(int mode, OpenFileCookie* cookie) status_t Inode::Close(OpenFileCookie* cookie) { + file_cache_sync(fFileCache); + Commit(); + fFileSystem->RemoveOpenFile(cookie); MutexLocker _(fStateLock); @@ -147,12 +150,15 @@ Inode::Close(OpenFileCookie* cookie) status_t -Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length, +Inode::ReadDirect(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length, bool* eof) { *eof = false; uint32 size = 0; + uint32 ioSize = fFileSystem->Root()->IOSize(); + *_length = min_c(ioSize, *_length); + status_t result; while (size < *_length && !*eof) { uint32 len = *_length - size; @@ -175,12 +181,25 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length, status_t -Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, +Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length) +{ + bool eof = false; + if ((cookie->fMode & O_NOCACHE) != 0) + return ReadDirect(cookie, pos, buffer, _length, &eof); + return file_cache_read(fFileCache, cookie, pos, buffer, _length); +} + + +status_t +Inode::WriteDirect(OpenFileCookie* cookie, off_t pos, const void* _buffer, size_t *_length) { uint32 size = 0; const char* buffer = reinterpret_cast<const char*>(_buffer); + uint32 ioSize = fFileSystem->Root()->IOSize(); + *_length = min_c(ioSize, *_length); + fWriteDirty = true; while (size < *_length) { @@ -207,6 +226,34 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, status_t +Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, + size_t *_length) +{ + struct stat st; + status_t result = Stat(&st); + if (result != B_OK) + return result; + + if ((cookie->fMode & O_APPEND) != 0) + pos = st.st_size; + + uint64 fileSize = max_c(st.st_size, pos + *_length); + fMaxFileSize = max_c(fMaxFileSize, fileSize); + + if ((cookie->fMode & O_NOCACHE) != 0) { + WriteDirect(cookie, pos, _buffer, _length); + Commit(); + } + + result = file_cache_set_size(fFileCache, fileSize); + if (result != B_OK) + return result; + + return file_cache_write(fFileCache, cookie, pos, _buffer, _length); +} + + +status_t Inode::Commit() { if (!fWriteDirty) diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h index dbcf90a..968e670 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h @@ -33,7 +33,7 @@ protected: status_t LookUp(const char* name, uint64* change, uint64* fileID, FileHandle* handle); - status_t Link(Inode* dir, const char* name,s + status_t Link(Inode* dir, const char* name, ChangeInfo* changeInfo); static status_t Rename(Inode* from, Inode* to, const char* fromName, diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index d1a447b..4804c6c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -230,7 +230,7 @@ nfs4_read_pages(fs_volume* _volume, fs_vnode* vnode, void* _cookie, off_t pos, do { size_t bytesRead = bytesLeft; - result = inode->Read(cookie, pos, buffer, &bytesRead, &eof); + result = inode->ReadDirect(cookie, pos, buffer, &bytesRead, &eof); if (result != B_OK) return result; @@ -255,15 +255,17 @@ nfs4_write_pages(fs_volume* _volume, fs_vnode* vnode, void* _cookie, off_t pos, OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie); status_t result; - uint32 ioSize = inode->GetFileSystem()->Root()->IOSize(); for (size_t i = 0; i < count; i++) { - size_t bytesLeft = vecs[i].iov_len; + uint64 bytesLeft = vecs[i].iov_len; + if (pos + bytesLeft > inode->MaxFileSize()) + bytesLeft = inode->MaxFileSize() - pos; + char* buffer = reinterpret_cast<char*>(vecs[i].iov_base); do { - size_t bytesWritten = min_c(ioSize, bytesLeft); + size_t bytesWritten = bytesLeft; - result = inode->Write(cookie, pos, buffer, &bytesWritten); + result = inode->WriteDirect(cookie, pos, buffer, &bytesWritten); if (result != B_OK) return result; @@ -468,8 +470,6 @@ nfs4_free_cookie(fs_volume* volume, fs_vnode* vnode, void* _cookie) return B_OK; OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie); - file_cache_sync(inode->FileCache()); - inode->Commit(); inode->Close(cookie); delete cookie; @@ -479,7 +479,7 @@ nfs4_free_cookie(fs_volume* volume, fs_vnode* vnode, void* _cookie) static status_t -nfs4_read(fs_volume* volume, fs_vnode* vnode, void* cookie, off_t pos, +nfs4_read(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos, void* buffer, size_t* length) { Inode* inode = reinterpret_cast<Inode*>(vnode->private_node); @@ -490,7 +490,9 @@ nfs4_read(fs_volume* volume, fs_vnode* vnode, void* cookie, off_t pos, if (inode->Type() == S_IFLNK) return B_BAD_VALUE; - return file_cache_read(inode->FileCache(), cookie, pos, buffer, length); + OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie); + + return inode->Read(cookie, pos, buffer, length); } @@ -508,17 +510,7 @@ nfs4_write(fs_volume* volume, fs_vnode* vnode, void* _cookie, off_t pos, OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie); - struct stat stat; - status_t result = inode->Stat(&stat); - if (result != B_OK) - return result; - - uint64 fileSize = max_c(stat.st_size, pos + *length); - result = file_cache_set_size(inode->FileCache(), fileSize); - if (result != B_OK) - return result; - - return file_cache_write(inode->FileCache(), cookie, pos, _buffer, length); + return inode->Write(cookie, pos, _buffer, length); } @@ -627,9 +619,6 @@ nfs4_release_lock(fs_volume* volume, fs_vnode* vnode, void* _cookie, OpenFileCookie* cookie = reinterpret_cast<OpenFileCookie*>(_cookie); - file_cache_sync(inode->FileCache()); - inode->Commit(); - if (lock != NULL) return inode->ReleaseLock(cookie, lock); else ############################################################################ Commit: 4a153753100503cf374d01079fb29ca83d3ac44b Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Mon Aug 6 00:03:28 2012 UTC nfs4: Return delegations when asked to ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp new file mode 100644 index 0000000..299cf21 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp @@ -0,0 +1,70 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ + + +#include "Delegation.h" + +#include "Inode.h" +#include "Request.h" + + +Delegation::Delegation(const OpenDelegationData& data, Inode* inode, + uint64 clientID) + : + fClientID(clientID), + fData(data), + fInode(inode) +{ + rw_lock_init(&fLock, NULL); +} + + +Delegation::~Delegation() +{ + rw_lock_destroy(&fLock); +} + +status_t +Delegation::GiveUp(bool truncate) +{ + if (!truncate) { + // save buffers + } + + ReturnDelegation(); + + return B_OK; +} + + +status_t +Delegation::ReturnDelegation() +{ + do { + RPC::Server* serv = fFileSystem->Server(); + Request request(serv); + RequestBuilder& req = request.Builder(); + + req.PutFH(fInfo.fHandle); + req.DelegReturn(fData.fStateID, fData.fStateSeq); + + status_t result = request.Send(); + if (result != B_OK) + return result; + + ReplyInterpreter& reply = request.Reply(); + + if (HandleErrors(reply.NFS4Error(), serv)) + continue; + + reply.PutFH(); + + return reply.DelegReturn(); + } while (true); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.h b/src/add-ons/kernel/file_systems/nfs4/Delegation.h index 31fea04..d54da15 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Delegation.h +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.h @@ -15,9 +15,12 @@ #include "NFS4Object.h" -class Delegation : public NFS4Object { +class Inode; + +class Delegation : public NFS4Object, + public DoublyLinkedListLinkImpl<Delegation> { public: - Delegation(OpenDelegationData data, Inode* inode, + Delegation(const OpenDelegationData& data, Inode* inode, uint64 clientID); ~Delegation(); @@ -28,7 +31,12 @@ public: status_t Reclaim(uint64 newClientID); - status_t GiveUp(bool flush); + status_t GiveUp(bool truncate); + + inline Inode* GetInode(); + +protected: + status_t ReturnDelegation(); private: uint64 fClientID; @@ -39,5 +47,12 @@ private: }; +inline Inode* +Delegation::GetInode() +{ + return fInode; +} + + #endif // DELEGATION_H diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.h b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h index 28b5412..5cd0f2a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileInfo.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h @@ -24,6 +24,9 @@ struct FileHandle { inline FileHandle(); inline FileHandle(const FileHandle& fh); inline FileHandle& operator=(const FileHandle& fh); + + inline bool operator>(const FileHandle& handle) const; + inline bool operator<(const FileHandle& handle) const; }; @@ -87,6 +90,24 @@ FileHandle::operator=(const FileHandle& fh) } +inline bool +FileHandle::operator>(const FileHandle& handle) const +{ + if (fSize > handle.fSize) + return true; + return memcmp(fData, handle.fData, fSize) > 0; +} + + +inline bool +FileHandle::operator<(const FileHandle& handle) const +{ + if (fSize < handle.fSize) + return true; + return memcmp(fData, handle.fData, fSize) < 0; +} + + inline FileInfo::FileInfo() : diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp index f4eb990..d5e3d8b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp @@ -38,6 +38,7 @@ FileSystem::FileSystem() mutex_init(&fOpenOwnerLock, NULL); mutex_init(&fOpenLock, NULL); + mutex_init(&fDelegationLock, NULL); } @@ -45,6 +46,7 @@ FileSystem::~FileSystem() { NFSServer()->RemoveFileSystem(this); + mutex_destroy(&fDelegationLock); mutex_destroy(&fOpenLock); mutex_destroy(&fOpenOwnerLock); @@ -308,3 +310,43 @@ FileSystem::RemoveOpenFile(OpenFileCookie* cookie) NFSServer()->DecUsage(); } + +void +FileSystem::AddDelegation(Delegation* delegation) +{ + MutexLocker _(fDelegationLock); + + fOpenDelegations.InsertBefore(fOpenDelegations.Head(), delegation); + + fHandleToDelegation.Remove(delegation->fInfo.fHandle); + fHandleToDelegation.Insert(delegation->fInfo.fHandle, delegation); + + NFSServer()->IncUsage(); +} + + +void +FileSystem::RemoveDelegation(Delegation* delegation) +{ + MutexLocker _(fDelegationLock); + + fOpenDelegations.Remove(delegation); + fHandleToDelegation.Remove(delegation->fInfo.fHandle); + + NFSServer()->DecUsage(); +} + + +Delegation* +FileSystem::GetDelegation(const FileHandle& handle) +{ + MutexLocker _(fDelegationLock); + + AVLTreeMap<FileHandle, Delegation*>::Iterator it; + it = fHandleToDelegation.Find(handle); + if (!it.HasCurrent()) + return NULL; + + return it.Current(); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h index 4c5df28..7814f8e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h @@ -10,6 +10,7 @@ #include "CacheRevalidator.h" +#include "Delegation.h" #include "InodeIdMap.h" #include "NFS4Defs.h" #include "NFS4Server.h" @@ -35,6 +36,12 @@ public: void AddOpenFile(OpenFileCookie* cookie); void RemoveOpenFile(OpenFileCookie* cookie); + OpenFileCookie* DelegationsLock(); + void DelegationsUnlock(); + void AddDelegation(Delegation* delegation); + void RemoveDelegation(Delegation* delegation); + Delegation* GetDelegation(const FileHandle& handle); + inline CacheRevalidator& Revalidator(); inline bool IsAttrSupported(Attribute attr) const; @@ -62,6 +69,10 @@ private: CacheRevalidator fCacheRevalidator; + DoublyLinkedList<Delegation> fOpenDelegations; + mutex fDelegationLock; + AVLTreeMap<FileHandle, Delegation*> fHandleToDelegation; + OpenFileCookie* fOpenFiles; uint32 fOpenCount; mutex fOpenLock; diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index a573f49..0f0846e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -23,11 +23,13 @@ Inode::Inode() : fCache(NULL), + fDelegation(NULL), fFileCache(NULL), fMaxFileSize(0), fOpenState(NULL), fWriteDirty(false) { + rw_lock_init(&fDelegationLock, NULL); mutex_init(&fStateLock, NULL); mutex_init(&fFileCacheLock, NULL); } @@ -121,12 +123,16 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode) Inode::~Inode() { + if (fDelegation != NULL) + RecallDelegation(); + if (fFileCache != NULL) file_cache_delete(fFileCache); delete fCache; mutex_destroy(&fStateLock); mutex_destroy(&fFileCacheLock); + rw_lock_destroy(&fDelegationLock); } @@ -721,3 +727,26 @@ Inode::ChildAdded(const char* name, uint64 fileID, return fFileSystem->InoIdMap()->AddEntry(fi, FileIdToInoT(fileID)); } + +void +Inode::SetDelegation(Delegation* delegation) +{ + WriteLocker _(fDelegationLock); + fDelegation = delegation; + fFileSystem->AddDelegation(delegation); +} + + +void +Inode::RecallDelegation(bool truncate) +{ + WriteLocker _(fDelegationLock); + if (fDelegation == NULL) + return; + + fDelegation->GiveUp(truncate); + fFileSystem->RemoveDelegation(fDelegation); + delete fDelegation; + fDelegation = NULL; +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index a44c12b..4c56e75 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -34,6 +34,9 @@ public: inline uint64 MaxFileSize(); + void SetDelegation(Delegation* delegation); + void RecallDelegation(bool truncate = false); + status_t LookUp(const char* name, ino_t* id); status_t Access(int mode); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 34ca35e..9208215 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -96,6 +96,8 @@ Inode::Open(int mode, OpenFileCookie* cookie) { MutexLocker _(fStateLock); + OpenDelegationData data; + data.fType = OPEN_DELEGATE_NONE; if (fOpenState == NULL) { OpenState* state = new OpenState; if (state == NULL) @@ -103,7 +105,7 @@ Inode::Open(int mode, OpenFileCookie* cookie) state->fInfo = fInfo; state->fFileSystem = fFileSystem; - status_t result = OpenFile(state, mode, NULL); + status_t result = OpenFile(state, mode, &data); if (result != B_OK) return result; @@ -112,7 +114,7 @@ Inode::Open(int mode, OpenFileCookie* cookie) int newMode = mode & O_RWMASK; int oldMode = fOpenState->fMode & O_RWMASK; if (oldMode != newMode && oldMode != O_RDWR) { - status_t result = OpenFile(fOpenState, O_RDWR, NULL); + status_t result = OpenFile(fOpenState, O_RDWR, &data); if (result != B_OK) return result; fOpenState->fMode = O_RDWR; @@ -128,6 +130,16 @@ Inode::Open(int mode, OpenFileCookie* cookie) fFileSystem->AddOpenFile(cookie); + if (data.fType != OPEN_DELEGATE_NONE) { + Delegation* delegation + = new(std::nothrow) Delegation(data, this, fOpenState->fClientID); + if (delegation != NULL) { + delegation->fInfo = fOpenState->fInfo; + delegation->fFileSystem = fFileSystem; + SetDelegation(delegation); + } + } + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/Jamfile b/src/add-ons/kernel/file_systems/nfs4/Jamfile index b6aeed8..a3a4194 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Jamfile +++ b/src/add-ons/kernel/file_systems/nfs4/Jamfile @@ -7,6 +7,7 @@ KernelAddon nfs4 : CacheRevalidator.cpp Cookie.cpp Connection.cpp + Delegation.cpp DirectoryCache.cpp FileInfo.cpp FileSystem.cpp @@ -20,9 +21,11 @@ KernelAddon nfs4 : NFS4Object.cpp NFS4Server.cpp OpenState.cpp + ReplyBuilder.cpp ReplyInterpreter.cpp Request.cpp RequestBuilder.cpp + RequestInterpreter.cpp RootInode.cpp RPCAuth.cpp RPCCall.cpp diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index 1887ee2..c162462 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -25,11 +25,16 @@ enum CallbackProcedure { CallbackProcCompound = 1 }; +enum CallbackOpcode { + OpCallbackRecall = 4 +}; + enum Opcode { OpAccess = 3, OpClose = 4, OpCommit = 5, OpCreate = 6, + OpDelegReturn = 8, OpGetAttr = 9, OpGetFH = 10, OpLink = 11, diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index ec38c3a..88fbce1 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -315,3 +315,71 @@ NFS4Server::_RenewalThreadStart(void* ptr) return server->_Renewal(); } + +status_t +NFS4Server::ProcessCallback(RPC::CallbackRequest* request, + Connection* connection) +{ + RequestInterpreter req(request); + ReplyBuilder reply(request->XID()); + + status_t result; + uint32 count = req.OperationCount(); + + for (uint32 i = 0; i < count; i++) { + switch (req.Operation()) { + case OpCallbackRecall: + result = CallbackRecall(&req, &reply); + break; + default: + result = B_NOT_SUPPORTED; + } + + if (result != B_OK) + break; + } + + XDR::WriteStream& stream = reply.Reply()->Stream(); + connection->Send(stream.Buffer(), stream.Size()); + + return B_OK; +} + + +status_t +NFS4Server::CallbackRecall(RequestInterpreter* request, ReplyBuilder* reply) +{ + uint32 stateID[3]; + uint32 stateSeq; + bool truncate; + FileHandle handle; + + status_t result = request->Recall(&handle, truncate, &stateSeq, stateID); + if (result != B_OK) + return result; + + MutexLocker locker(fFSLock); + + Delegation* delegation = NULL; + FileSystem* current = fFileSystems; + while (current != NULL) { + delegation = current->GetDelegation(handle); + if (delegation != NULL) + break; + + current = current->fNext; + } + locker.Unlock(); + + if (delegation == NULL) { + reply->Recall(B_FILE_NOT_FOUND); + return B_FILE_NOT_FOUND; + } + + // TODO: should be asynchronous + delegation->GetInode()->RecallDelegation(truncate); + + reply->Recall(B_OK); + return B_OK; +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h index 46134e8..4d37a96 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h @@ -11,6 +11,8 @@ #include <lock.h> +#include "ReplyBuilder.h" +#include "RequestInterpreter.h" #include "RPCServer.h" @@ -34,6 +36,12 @@ public: uint64 ClientId(uint64 prevId = 0, bool forceNew = false); inline uint32 LeaseTime(); + + virtual status_t ProcessCallback(RPC::CallbackRequest* request, + Connection* connection); + + status_t CallbackRecall(RequestInterpreter* request, + ReplyBuilder* reply); private: status_t _ReclaimOpen(OpenFileCookie* cookie); status_t _ReclaimLocks(OpenFileCookie* cookie); diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.cpp index 70da61c..ddf5b63 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.cpp @@ -10,15 +10,22 @@ #include "RPCCallback.h" #include "RPCCallbackRequest.h" +#include "RPCServer.h" using namespace RPC; +Callback::Callback(Server* server) + : + fServer(server) +{ +} + + status_t Callback::EnqueueRequest(CallbackRequest* request, Connection* connection) { - dprintf("GOT A CALLBACK REQUEST %x\n", (int)request->XID()); - return B_OK; + return fServer->PrivateData()->ProcessCallback(request, connection); } diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h index 66d60ac..b729156 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h @@ -15,9 +15,12 @@ namespace RPC { class CallbackRequest; +class Server; class Callback { public: + Callback(Server* server); + inline void SetID(int32 id); inline int32 ID(); @@ -25,6 +28,7 @@ public: Connection* connection); private: + Server* fServer; int32 fID; }; diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackRequest.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackRequest.cpp index 4b10efb..90fce4d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackRequest.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackRequest.cpp @@ -45,7 +45,10 @@ CallbackRequest::CallbackRequest(void *buffer, int size) fProcedure = fStream.GetUInt(); + fStream.GetUInt(); fStream.GetOpaque(NULL); + + fStream.GetUInt(); fStream.GetOpaque(NULL); if (fProcedure == CallbackProcCompound) { @@ -54,6 +57,9 @@ CallbackRequest::CallbackRequest(void *buffer, int size) return; fID = fStream.GetUInt(); + + fRPCError = SUCCESS; + fError = B_OK; } else if (fProcedure == CallbackProcNull) { fRPCError = SUCCESS; fError = B_OK; diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp index 5a64700..b007a3b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp @@ -26,7 +26,7 @@ CallbackServer::CallbackServer() fConnectionList(NULL), fListener(NULL), fThreadRunning(false), - fCallbackArray(NULL), + //fCallbackArray(NULL), fArraySize(0), fFreeSlot(-1) { @@ -40,7 +40,7 @@ CallbackServer::~CallbackServer() { StopServer(); - free(fCallbackArray); + //free(fCallbackArray); rw_lock_destroy(&fArrayLock); mutex_destroy(&fThreadLock); mutex_destroy(&fConnectionLock); @@ -68,7 +68,7 @@ CallbackServer::RegisterCallback(Callback* callback) for (uint32 i = fArraySize; i < newSize; i++) array[i].fNext = i + 1; - array[fArraySize * 2 - 1].fNext = -1; + array[newSize - 1].fNext = -1; fCallbackArray = array; fFreeSlot = fArraySize; @@ -240,7 +240,7 @@ CallbackServer::ConnectionThread(ConnectionEntry* entry) if (request == NULL || request->Error() != B_OK) { free(buffer); continue; - } else if (request != NULL) { + } else if (request != NULL && request->Error() != B_OK) { reply = CallbackReply::Create(request->XID(), request->RPCError()); if (reply != NULL) { connection->Send(reply->Stream().Buffer(), @@ -251,7 +251,6 @@ CallbackServer::ConnectionThread(ConnectionEntry* entry) continue; } - switch (request->Procedure()) { case CallbackProcCompound: GetCallback(request->ID())->EnqueueRequest(request, connection); diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp index fce6f5a..70876f6 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp @@ -228,7 +228,7 @@ Server::GetCallback() { MutexLocker _(fCallbackLock); if (fCallback == NULL) { - fCallback = new Callback; + fCallback = new(std::nothrow) Callback(this); gRPCCallbackServer->RegisterCallback(fCallback); } diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.h b/src/add-ons/kernel/file_systems/nfs4/RPCServer.h index ddcb80e..f4afd7f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.h +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.h @@ -48,6 +48,9 @@ private: class ProgramData { public: + virtual status_t ProcessCallback(CallbackRequest* request, + Connection* connection) = 0; + virtual ~ProgramData() { } }; diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp new file mode 100644 index 0000000..e18a4a6 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ + + +#include "ReplyBuilder.h" + +#include "NFS4Defs.h" +#include "RPCCallbackReply.h" + + +ReplyBuilder::ReplyBuilder(uint32 xid) + : + fStatus(B_OK), + fOpCount(0), + fReply(RPC::CallbackReply::Create(xid)) +{ + _InitHeader(); +} + + +ReplyBuilder::~ReplyBuilder() +{ + delete fReply; +} + + +void +ReplyBuilder::_InitHeader() +{ + fStatusPosition = fReply->Stream().Current(); + fReply->Stream().AddUInt(0); + + fReply->Stream().AddOpaque(NULL, 0); + + fOpCountPosition = fReply->Stream().Current(); + fReply->Stream().AddUInt(0); + +} + + +RPC::CallbackReply* +ReplyBuilder::Reply() +{ + fReply->Stream().InsertUInt(fStatusPosition, _HaikuErrorToNFS4(fStatus)); + fReply->Stream().InsertUInt(fOpCountPosition, fOpCount); + + if (fReply == NULL || fReply->Stream().Error() == B_OK) + return fReply; + else + return NULL; +} + + +status_t +ReplyBuilder::Recall(status_t status) +{ + if (fStatus != B_OK) + return B_ERROR; + + fReply->Stream().AddUInt(OpCallbackRecall); + fReply->Stream().AddUInt(_HaikuErrorToNFS4(fStatus)); + fStatus = status; + + fOpCount++; + + return B_OK; +} + + +uint32 +ReplyBuilder::_HaikuErrorToNFS4(status_t error) +{ + switch (error) { + case B_OK: return NFS4_OK; + case B_FILE_NOT_FOUND: return NFS4ERR_BADHANDLE; + case B_NOT_SUPPORTED: return NFS4ERR_OP_ILLEGAL; + default: return NFS4ERR_RESOURCE; + } +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h new file mode 100644 index 0000000..be85416 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ +#ifndef REPLYBUILDER_H +#define REPLYBUILDER_H + + +#include <SupportDefs.h> + +#include "RPCCallbackReply.h" +#include "XDR.h" + + +class ReplyBuilder { +public: + ReplyBuilder(uint32 xid); + ~ReplyBuilder(); + + RPC::CallbackReply* Reply(); + + status_t Recall(status_t status); + +private: + void _InitHeader(); + + static uint32 _HaikuErrorToNFS4(status_t error); + + status_t fStatus; + XDR::Stream::Position fStatusPosition; + + uint32 fOpCount; + XDR::Stream::Position fOpCountPosition; + + RPC::CallbackReply* fReply; +}; + + +#endif // REPLYBUILDER_H + diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index 892e34c..986fcd8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -71,6 +71,7 @@ public: status_t Close(); status_t Commit(); status_t Create(uint64* before, uint64* after, bool& atomic); + inline status_t DelegReturn(); status_t GetAttr(AttrValue** attrs, uint32* count); status_t GetFH(FileHandle* fh); status_t Link(uint64* before, uint64* after, bool& atomic); @@ -151,6 +152,13 @@ ReplyInterpreter::NFS4Error() inline status_t +ReplyInterpreter::DelegReturn() +{ + return _OperationError(OpDelegReturn); +} + + +inline status_t ReplyInterpreter::LookUp() { return _OperationError(OpLookUp); diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index c05b873..17d8259 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -138,6 +138,27 @@ RequestBuilder::Create(FileType type, const char* name, AttrValue* attr, status_t +RequestBuilder::DelegReturn(const uint32* id, uint32 seq) +{ + if (fProcedure != ProcCompound) + return B_BAD_VALUE; + if (fRequest == NULL) + return B_NO_MEMORY; + + fRequest->Stream().AddUInt(OpDelegReturn); + + fRequest->Stream().AddUInt(seq); + fRequest->Stream().AddUInt(id[0]); + fRequest->Stream().AddUInt(id[1]); + fRequest->Stream().AddUInt(id[2]); + + fOpCount++; + + return B_OK; +} + + +status_t RequestBuilder::GetAttr(Attribute* attrs, uint32 count) { if (fProcedure != ProcCompound) diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index 13db57d..d850c3c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -37,6 +37,7 @@ public: status_t Create(FileType type, const char* name, AttrValue* attr, uint32 count, const char* path = NULL); + status_t DelegReturn(const uint32* id, uint32 seq); status_t GetAttr(Attribute* attrs, uint32 count); status_t GetFH(); status_t Link(const char* name); diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp new file mode 100644 index 0000000..c129cde --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ + + +#include "RequestInterpreter.h" + +#include <string.h> + +#include <util/kernel_cpp.h> + + +RequestInterpreter::RequestInterpreter(RPC::CallbackRequest* request) + : + fRequest(request) +{ + fOperationCount = fRequest->Stream().GetUInt(); +} + + [ *** diff truncated: 88 lines dropped *** ] ############################################################################ Commit: bfa20379a3d5756dda6f3ebab0dcf52b6f4ca749 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Mon Aug 6 01:18:46 2012 UTC nfs4: Reclaim delegations after server reboot ---------------------------------------------------------------------------- ############################################################################ Commit: e2e5f06d6e736c019ed37c475ff4f68e3c4f401c Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Mon Aug 6 01:25:02 2012 UTC nfs4: Do not sync too often if delegation is held ----------------------------------------------------------------------------