diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp index 25ed74b9b4..cc4611b9d8 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 95e95ae2f0..f4eb9906d4 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(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 7b99ef720a..4c5df282e4 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 c0abd7b0fd..1887ee2430 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 cb8988178f..1c6722b3ef 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 73c5e3a5bb..073fd01c6c 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 4959199340..236ff7c243 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 00da687bd2..ecf10a8a41 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 651ccc5426..5a64700092 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 56ba582894..2b74de3b17 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 ed3a2695a1..892e34cc41 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 c9d2408503..c6a0e80cda 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 a8f2d7618d..13db57de2b 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);