nfs4: Allow the server to release unused lock owners
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user