nfs4: Allow the server to release unused lock owners

This commit is contained in:
Pawel Dziepak
2012-07-03 01:12:27 +02:00
parent 62869605c5
commit 1a0820703b
7 changed files with 86 additions and 18 deletions
@@ -134,6 +134,7 @@ Cookie::CancelAll()
OpenFileCookie::OpenFileCookie() OpenFileCookie::OpenFileCookie()
: :
fLocks(NULL),
fLockOwners(NULL) fLockOwners(NULL)
{ {
mutex_init(&fLocksLock, NULL); mutex_init(&fLocksLock, NULL);
@@ -151,8 +152,6 @@ OpenFileCookie::~OpenFileCookie()
LockOwner* LockOwner*
OpenFileCookie::GetLockOwner(uint32 owner) OpenFileCookie::GetLockOwner(uint32 owner)
{ {
MutexLocker _(fOwnerLock);
LockOwner* current = fLockOwners; LockOwner* current = fLockOwners;
while (current != NULL) { while (current != NULL) {
if (current->fOwner == owner) if (current->fOwner == owner)
@@ -211,7 +210,26 @@ OpenFileCookie::DeleteLock(LockInfo* lock)
if (owner->fNext) if (owner->fNext)
owner->fNext->fPrev = owner->fPrev; owner->fNext->fPrev = owner->fPrev;
_ReleaseLockOwner(owner);
delete 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();
}
@@ -100,6 +100,9 @@ struct OpenFileCookie : public Cookie {
void AddLock(LockInfo* lock); void AddLock(LockInfo* lock);
void RemoveLock(LockInfo* lock, LockInfo* prev); void RemoveLock(LockInfo* lock, LockInfo* prev);
void DeleteLock(LockInfo* lock); void DeleteLock(LockInfo* lock);
private:
status_t _ReleaseLockOwner(LockOwner* owner);
}; };
struct OpenDirCookie : public Cookie { struct OpenDirCookie : public Cookie {
+15 -9
View File
@@ -735,6 +735,8 @@ Inode::AcquireLock(OpenFileCookie* cookie, const struct flock* lock,
thread_info info; thread_info info;
get_thread_info(find_thread(NULL), &info); get_thread_info(find_thread(NULL), &info);
MutexLocker locker(cookie->fOwnerLock);
LockOwner* owner = cookie->GetLockOwner(info.team); LockOwner* owner = cookie->GetLockOwner(info.team);
if (owner == NULL) if (owner == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -742,6 +744,7 @@ Inode::AcquireLock(OpenFileCookie* cookie, const struct flock* lock,
LockInfo* linfo = new LockInfo(owner); LockInfo* linfo = new LockInfo(owner);
if (linfo == NULL) if (linfo == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
locker.Unlock();
linfo->fStart = lock->l_start; linfo->fStart = lock->l_start;
if (lock->l_len + lock->l_start == OFF_MAX) if (lock->l_len + lock->l_start == OFF_MAX)
@@ -862,35 +865,38 @@ status_t
Inode::ReleaseAllLocks(OpenFileCookie* cookie) Inode::ReleaseAllLocks(OpenFileCookie* cookie)
{ {
MutexLocker _(cookie->fLocksLock); MutexLocker _(cookie->fLocksLock);
while (cookie->fLocks != NULL) { LockInfo* linfo = cookie->fLocks;
while (linfo != NULL) {
do { do {
MutexLocker ownerLocker(cookie->fLocks->fOwner->fLock); MutexLocker ownerLocker(linfo->fOwner->fLock);
RPC::Server* serv = fFilesystem->Server(); RPC::Server* serv = fFilesystem->Server();
Request request(serv); Request request(serv);
RequestBuilder& req = request.Builder(); RequestBuilder& req = request.Builder();
req.PutFH(fHandle); req.PutFH(fHandle);
req.LockU(cookie->fLocks); req.LockU(linfo);
status_t result = request.Send(); status_t result = request.Send();
if (result != B_OK); if (result != B_OK)
return result; break;
ReplyInterpreter &reply = request.Reply(); ReplyInterpreter& reply = request.Reply();
reply.PutFH(); reply.PutFH();
reply.LockU(cookie->fLocks); reply.LockU(linfo);
ownerLocker.Unlock(); ownerLocker.Unlock();
if (_HandleErrors(reply.NFS4Error(), serv, cookie)) if (_HandleErrors(reply.NFS4Error(), serv, cookie))
continue; continue;
break;
} while (true); } while (true);
LockInfo* linfo = cookie->fLocks;
cookie->RemoveLock(linfo, NULL); cookie->RemoveLock(linfo, NULL);
cookie->DeleteLock(linfo); cookie->DeleteLock(linfo);
linfo = cookie->fLocks;
} }
return B_OK; return B_OK;
@@ -49,7 +49,8 @@ enum Opcode {
OpSetClientID = 35, OpSetClientID = 35,
OpSetClientIDConfirm = 36, OpSetClientIDConfirm = 36,
OpVerify = 37, OpVerify = 37,
OpWrite = 38 OpWrite = 38,
OpReleaseLockOwner = 39
}; };
enum Access { enum Access {
@@ -95,6 +95,7 @@ public:
inline status_t SetClientIDConfirm(); inline status_t SetClientIDConfirm();
inline status_t Verify(); inline status_t Verify();
status_t Write(uint32* size); status_t Write(uint32* size);
inline status_t ReleaseLockOwner();
private: private:
void _ParseHeader(); void _ParseHeader();
@@ -206,5 +207,12 @@ ReplyInterpreter::Verify()
} }
inline status_t
ReplyInterpreter::ReleaseLockOwner()
{
return _OperationError(OpReleaseLockOwner);
}
#endif // REPLYINTERPRETER_H #endif // REPLYINTERPRETER_H
@@ -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 status_t
RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim) RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim)
{ {
@@ -178,12 +191,7 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, bool reclaim)
// lock seq owner // lock seq owner
fRequest->Stream().AddUInt(lock->fOwner->fSequence++); fRequest->Stream().AddUInt(lock->fOwner->fSequence++);
fRequest->Stream().AddUHyper(cookie->fClientId); _GenerateLockOwner(fRequest->Stream(), cookie, lock->fOwner);
uint64 owner[2];
owner[0] = lock->fOwner->fOwner;
owner[1] = cookie->fOwnerId;
fRequest->Stream().AddOpaque(owner, sizeof(owner));
} else { } else {
fRequest->Stream().AddBoolean(false); // old lock owner 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* RPC::Call*
RequestBuilder::Request() RequestBuilder::Request()
{ {
@@ -20,6 +20,7 @@
class OpenFileCookie; class OpenFileCookie;
class LockInfo; class LockInfo;
class LockOwner;
class RequestBuilder { class RequestBuilder {
public: public:
@@ -72,12 +73,18 @@ public:
status_t Write(const uint32* id, uint32 stateSeq, status_t Write(const uint32* id, uint32 stateSeq,
const void* buffer, uint64 pos, const void* buffer, uint64 pos,
uint32 len); uint32 len);
status_t ReleaseLockOwner(OpenFileCookie* cookie,
LockOwner* owner);
RPC::Call* Request(); RPC::Call* Request();
private: private:
void _InitHeader(); void _InitHeader();
void _GenerateLockOwner(XDR::WriteStream& stream,
OpenFileCookie* cookie,
LockOwner* owner);
void _EncodeAttrs(XDR::WriteStream& stream, void _EncodeAttrs(XDR::WriteStream& stream,
AttrValue* attr, uint32 count); AttrValue* attr, uint32 count);
void _AttrBitmap(XDR::WriteStream& stream, void _AttrBitmap(XDR::WriteStream& stream,