diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp index ba0398e0d0..6c39b970a9 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp @@ -134,6 +134,7 @@ Cookie::CancelAll() OpenFileCookie::OpenFileCookie() : + fLocks(NULL), fLockOwners(NULL) { mutex_init(&fLocksLock, NULL); @@ -151,8 +152,6 @@ OpenFileCookie::~OpenFileCookie() LockOwner* OpenFileCookie::GetLockOwner(uint32 owner) { - MutexLocker _(fOwnerLock); - LockOwner* current = fLockOwners; while (current != NULL) { if (current->fOwner == owner) @@ -211,7 +210,26 @@ OpenFileCookie::DeleteLock(LockInfo* lock) if (owner->fNext) owner->fNext->fPrev = owner->fPrev; + _ReleaseLockOwner(owner); delete owner; } } + +status_t +OpenFileCookie::_ReleaseLockOwner(LockOwner* owner) +{ + Request request(fFilesystem->Server()); + RequestBuilder& req = request.Builder(); + + req.ReleaseLockOwner(this, owner); + + status_t result = request.Send(); + if (result != B_OK) + return result; + + ReplyInterpreter &reply = request.Reply(); + + return reply.ReleaseLockOwner(); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.h b/src/add-ons/kernel/file_systems/nfs4/Cookie.h index d9711a6f5a..ef312beb0f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.h +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.h @@ -100,6 +100,9 @@ struct OpenFileCookie : public Cookie { void AddLock(LockInfo* lock); void RemoveLock(LockInfo* lock, LockInfo* prev); void DeleteLock(LockInfo* lock); + +private: + status_t _ReleaseLockOwner(LockOwner* owner); }; struct OpenDirCookie : public Cookie { diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 0856e4d017..232581d09d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -735,6 +735,8 @@ Inode::AcquireLock(OpenFileCookie* cookie, const struct flock* lock, thread_info info; get_thread_info(find_thread(NULL), &info); + + MutexLocker locker(cookie->fOwnerLock); LockOwner* owner = cookie->GetLockOwner(info.team); if (owner == NULL) return B_NO_MEMORY; @@ -742,6 +744,7 @@ Inode::AcquireLock(OpenFileCookie* cookie, const struct flock* lock, LockInfo* linfo = new LockInfo(owner); if (linfo == NULL) return B_NO_MEMORY; + locker.Unlock(); linfo->fStart = lock->l_start; if (lock->l_len + lock->l_start == OFF_MAX) @@ -862,35 +865,38 @@ status_t Inode::ReleaseAllLocks(OpenFileCookie* cookie) { MutexLocker _(cookie->fLocksLock); - while (cookie->fLocks != NULL) { + LockInfo* linfo = cookie->fLocks; + while (linfo != NULL) { do { - MutexLocker ownerLocker(cookie->fLocks->fOwner->fLock); + MutexLocker ownerLocker(linfo->fOwner->fLock); RPC::Server* serv = fFilesystem->Server(); Request request(serv); RequestBuilder& req = request.Builder(); req.PutFH(fHandle); - req.LockU(cookie->fLocks); + req.LockU(linfo); status_t result = request.Send(); - if (result != B_OK); - return result; + if (result != B_OK) + break; - ReplyInterpreter &reply = request.Reply(); + ReplyInterpreter& reply = request.Reply(); reply.PutFH(); - reply.LockU(cookie->fLocks); + reply.LockU(linfo); ownerLocker.Unlock(); if (_HandleErrors(reply.NFS4Error(), serv, cookie)) continue; + break; } while (true); - - LockInfo* linfo = cookie->fLocks; + cookie->RemoveLock(linfo, NULL); cookie->DeleteLock(linfo); + + linfo = cookie->fLocks; } return B_OK; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index f83cc011d4..853c783d8a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -49,7 +49,8 @@ enum Opcode { OpSetClientID = 35, OpSetClientIDConfirm = 36, OpVerify = 37, - OpWrite = 38 + OpWrite = 38, + OpReleaseLockOwner = 39 }; enum Access { diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index c0cbb1dd4d..0595a8bbbf 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -95,6 +95,7 @@ public: inline status_t SetClientIDConfirm(); inline status_t Verify(); status_t Write(uint32* size); + inline status_t ReleaseLockOwner(); private: void _ParseHeader(); @@ -206,5 +207,12 @@ ReplyInterpreter::Verify() } +inline status_t +ReplyInterpreter::ReleaseLockOwner() +{ + return _OperationError(OpReleaseLockOwner); +} + + #endif // REPLYINTERPRETER_H diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index 77883fa637..1f37a9045a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -148,6 +148,19 @@ RequestBuilder::GetFH() } +void +RequestBuilder::_GenerateLockOwner(XDR::WriteStream& stream, + OpenFileCookie* cookie, LockOwner* owner) +{ + stream.AddUHyper(cookie->fClientId); + + uint64 lockOwner[2]; + lockOwner[0] = owner->fOwner; + lockOwner[1] = cookie->fOwnerId; + stream.AddOpaque(lockOwner, sizeof(lockOwner)); +} + + status_t RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim) { @@ -178,12 +191,7 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim) // lock seq owner fRequest->Stream().AddUInt(lock->fOwner->fSequence++); - fRequest->Stream().AddUHyper(cookie->fClientId); - - uint64 owner[2]; - owner[0] = lock->fOwner->fOwner; - owner[1] = cookie->fOwnerId; - fRequest->Stream().AddOpaque(owner, sizeof(owner)); + _GenerateLockOwner(fRequest->Stream(), cookie, lock->fOwner); } else { fRequest->Stream().AddBoolean(false); // old lock owner @@ -681,6 +689,23 @@ RequestBuilder::Write(const uint32* id, uint32 stateSeq, const void* buffer, } +status_t +RequestBuilder::ReleaseLockOwner(OpenFileCookie* cookie, LockOwner* owner) +{ + if (fProcedure != ProcCompound) + return B_BAD_VALUE; + if (fRequest == NULL) + return B_NO_MEMORY; + + fRequest->Stream().AddUInt(OpReleaseLockOwner); + _GenerateLockOwner(fRequest->Stream(), cookie, owner); + + fOpCount++; + + return B_OK; +} + + RPC::Call* RequestBuilder::Request() { diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index 68dbb418f1..0143a9a65d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -20,6 +20,7 @@ class OpenFileCookie; class LockInfo; +class LockOwner; class RequestBuilder { public: @@ -72,12 +73,18 @@ public: status_t Write(const uint32* id, uint32 stateSeq, const void* buffer, uint64 pos, uint32 len); + status_t ReleaseLockOwner(OpenFileCookie* cookie, + LockOwner* owner); RPC::Call* Request(); private: void _InitHeader(); + void _GenerateLockOwner(XDR::WriteStream& stream, + OpenFileCookie* cookie, + LockOwner* owner); + void _EncodeAttrs(XDR::WriteStream& stream, AttrValue* attr, uint32 count); void _AttrBitmap(XDR::WriteStream& stream,