mirror of
https://review.haiku-os.org/haiku
synced 2025-02-07 06:16:11 +01:00
nfs4: Renew all owned and used leases
This commit is contained in:
parent
6ee3ed0f6f
commit
27a291de54
@ -33,6 +33,7 @@ enum Opcode {
|
||||
OpPutRootFH = 24,
|
||||
OpRead = 25,
|
||||
OpReadDir = 26,
|
||||
OpRenew = 30,
|
||||
OpSetClientID = 35,
|
||||
OpSetClientIDConfirm = 36
|
||||
};
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
NFS4Server::NFS4Server(RPC::Server* serv)
|
||||
:
|
||||
fThreadCancel(true),
|
||||
fLeaseTime(0),
|
||||
fCIDUseCount(0),
|
||||
fSequenceId(0),
|
||||
fServer(serv)
|
||||
@ -23,6 +25,12 @@ NFS4Server::NFS4Server(RPC::Server* serv)
|
||||
|
||||
NFS4Server::~NFS4Server()
|
||||
{
|
||||
fThreadCancel = true;
|
||||
fCIDUseCount = 0;
|
||||
interrupt_thread(fThread);
|
||||
status_t result;
|
||||
wait_for_thread(fThread, &result);
|
||||
|
||||
mutex_destroy(&fLock);
|
||||
}
|
||||
|
||||
@ -54,6 +62,8 @@ NFS4Server::ClientId(uint64 prevId, bool forceNew)
|
||||
result = request.Reply().SetClientIDConfirm();
|
||||
if (result != B_OK)
|
||||
goto out_unlock;
|
||||
|
||||
_StartRenewing();
|
||||
}
|
||||
|
||||
fCIDUseCount++;
|
||||
@ -72,3 +82,101 @@ NFS4Server::ReleaseCID(uint64 cid)
|
||||
mutex_unlock(&fLock);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NFS4Server::_GetLeaseTime()
|
||||
{
|
||||
Request request(fServer);
|
||||
request.Builder().PutRootFH();
|
||||
Attribute attr[] = { FATTR4_LEASE_TIME };
|
||||
request.Builder().GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
ReplyInterpreter& reply = request.Reply();
|
||||
|
||||
result = reply.PutRootFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
AttrValue* values;
|
||||
uint32 count;
|
||||
result = reply.GetAttr(&values, &count);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
// FATTR4_LEASE_TIM is mandatory
|
||||
if (count < 1 || values[0].fAttribute != FATTR4_LEASE_TIME) {
|
||||
delete[] values;
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
fLeaseTime = values[0].fData.fValue32 * 1000000;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NFS4Server::_StartRenewing()
|
||||
{
|
||||
if (!fThreadCancel)
|
||||
return B_OK;
|
||||
|
||||
|
||||
if (fLeaseTime == 0) {
|
||||
status_t result = _GetLeaseTime();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
fThreadCancel = false;
|
||||
fThread = spawn_kernel_thread(&NFS4Server::_RenewalThreadStart,
|
||||
"NFSv4 Renewal", B_NORMAL_PRIORITY, this);
|
||||
if (fThread < B_OK)
|
||||
return fThread;
|
||||
|
||||
status_t result = resume_thread(fThread);
|
||||
if (result != B_OK) {
|
||||
kill_thread(fThread);
|
||||
return result;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NFS4Server::_Renewal()
|
||||
{
|
||||
while (!fThreadCancel) {
|
||||
// TODO: operations like OPEN, READ, CLOSE, etc also renew leases
|
||||
snooze_etc(fLeaseTime - 2, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT
|
||||
| B_CAN_INTERRUPT);
|
||||
mutex_lock(&fLock);
|
||||
if (fCIDUseCount == 0) {
|
||||
fThreadCancel = true;
|
||||
mutex_unlock(&fLock);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
Request request(fServer);
|
||||
request.Builder().Renew(fClientId);
|
||||
request.Send();
|
||||
|
||||
mutex_unlock(&fLock);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NFS4Server::_RenewalThreadStart(void* ptr)
|
||||
{
|
||||
NFS4Server* server = reinterpret_cast<NFS4Server*>(ptr);
|
||||
return server->_Renewal();
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,16 @@ public:
|
||||
|
||||
inline uint32 SequenceId();
|
||||
private:
|
||||
status_t _GetLeaseTime();
|
||||
|
||||
status_t _StartRenewing();
|
||||
status_t _Renewal();
|
||||
static status_t _RenewalThreadStart(void* ptr);
|
||||
thread_id fThread;
|
||||
bool fThreadCancel;
|
||||
|
||||
uint32 fLeaseTime;
|
||||
|
||||
uint64 fClientId;
|
||||
uint32 fCIDUseCount;
|
||||
mutex fLock;
|
||||
|
@ -323,6 +323,12 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
||||
current++;
|
||||
}
|
||||
|
||||
if (sIsAttrSet(FATTR4_LEASE_TIME, bitmap, bcount)) {
|
||||
values[current].fAttribute = FATTR4_LEASE_TIME;
|
||||
values[current].fData.fValue32 = stream.GetUInt();
|
||||
current++;
|
||||
}
|
||||
|
||||
if (sIsAttrSet(FATTR4_FILEID, bitmap, bcount)) {
|
||||
values[current].fAttribute = FATTR4_FILEID;
|
||||
values[current].fData.fValue64 = stream.GetUHyper();
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
status_t Read(void* buffer, uint32* size, bool* eof);
|
||||
status_t ReadDir(uint64* cookie, DirEntry** dirents,
|
||||
uint32* count, bool* eof);
|
||||
inline status_t Renew();
|
||||
status_t SetClientID(uint64* clientid, uint64* verifier);
|
||||
inline status_t SetClientIDConfirm();
|
||||
|
||||
@ -125,6 +126,13 @@ ReplyInterpreter::PutRootFH()
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
ReplyInterpreter::Renew()
|
||||
{
|
||||
return _OperationError(OpRenew);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
ReplyInterpreter::SetClientIDConfirm()
|
||||
{
|
||||
|
@ -262,7 +262,7 @@ RequestBuilder::Read(const uint32* id, uint32 stateSeq, uint64 pos, uint32 len)
|
||||
|
||||
status_t
|
||||
RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs,
|
||||
uint32 attr_count)
|
||||
uint32 attrCount)
|
||||
{
|
||||
(void)count;
|
||||
|
||||
@ -278,7 +278,24 @@ RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs,
|
||||
// consider predicting this values basing on count or buffer size
|
||||
fRequest->Stream().AddUInt(0x2000);
|
||||
fRequest->Stream().AddUInt(0x8000);
|
||||
_AttrBitmap(fRequest->Stream(), attrs, attr_count);
|
||||
_AttrBitmap(fRequest->Stream(), attrs, attrCount);
|
||||
|
||||
fOpCount++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::Renew(uint64 clientId)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
if (fRequest == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fRequest->Stream().AddUInt(OpRenew);
|
||||
fRequest->Stream().AddUHyper(clientId);
|
||||
|
||||
fOpCount++;
|
||||
|
||||
|
@ -40,7 +40,8 @@ public:
|
||||
status_t Read(const uint32* id, uint32 stateSeq,
|
||||
uint64 pos, uint32 len);
|
||||
status_t ReadDir(uint32 count, uint64* cookie,
|
||||
Attribute* attrs, uint32 attr_count);
|
||||
Attribute* attrs, uint32 attrCount);
|
||||
status_t Renew(uint64 clientId);
|
||||
status_t SetClientID(const RPC::Server* serv);
|
||||
status_t SetClientIDConfirm(uint64 id, uint64 ver);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user