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()
:
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();
}
@@ -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 {
+15 -9
View File
@@ -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;
@@ -49,7 +49,8 @@ enum Opcode {
OpSetClientID = 35,
OpSetClientIDConfirm = 36,
OpVerify = 37,
OpWrite = 38
OpWrite = 38,
OpReleaseLockOwner = 39
};
enum Access {
@@ -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
@@ -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()
{
@@ -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,