nfs4: Behave correctly if server is in grace period
This commit is contained in:
@@ -336,32 +336,49 @@ Inode::Stat(struct stat* st)
|
|||||||
status_t
|
status_t
|
||||||
Inode::Open(int mode, OpenFileCookie* cookie)
|
Inode::Open(int mode, OpenFileCookie* cookie)
|
||||||
{
|
{
|
||||||
cookie->fClientId = fFilesystem->NFSServer()->ClientId();
|
|
||||||
|
|
||||||
Request request(fFilesystem->Server());
|
|
||||||
RequestBuilder& req = request.Builder();
|
|
||||||
|
|
||||||
req.PutFH(fParentFH);
|
|
||||||
req.Open(fFilesystem->NFSServer()->SequenceId(), OPEN4_SHARE_ACCESS_READ,
|
|
||||||
cookie->fClientId, OPEN4_NOCREATE, fName);
|
|
||||||
|
|
||||||
status_t result = request.Send();
|
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
|
||||||
|
|
||||||
result = reply.PutFH();
|
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
bool confirm;
|
bool confirm;
|
||||||
result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm);
|
status_t result;
|
||||||
if (result != B_OK)
|
do {
|
||||||
return result;
|
cookie->fClientId = fFilesystem->NFSServer()->ClientId();
|
||||||
|
|
||||||
|
Request request(fFilesystem->Server());
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
|
req.PutFH(fParentFH);
|
||||||
|
req.Open(fFilesystem->NFSServer()->SequenceId(),
|
||||||
|
OPEN4_SHARE_ACCESS_READ, cookie->fClientId, OPEN4_NOCREATE, fName);
|
||||||
|
|
||||||
|
result = request.Send();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// server is in grace period, we need to wait
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
||||||
|
fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId);
|
||||||
|
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
|
||||||
|
B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = reply.PutFH();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
|
||||||
|
result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
request.Reset();
|
Request request(fFilesystem->Server());
|
||||||
|
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
req.PutFH(fHandle);
|
req.PutFH(fHandle);
|
||||||
req.OpenConfirm(fFilesystem->NFSServer()->SequenceId(),
|
req.OpenConfirm(fFilesystem->NFSServer()->SequenceId(),
|
||||||
cookie->fStateId, cookie->fStateSeq);
|
cookie->fStateId, cookie->fStateSeq);
|
||||||
@@ -370,6 +387,8 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
|||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -386,28 +405,39 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
|||||||
status_t
|
status_t
|
||||||
Inode::Close(OpenFileCookie* cookie)
|
Inode::Close(OpenFileCookie* cookie)
|
||||||
{
|
{
|
||||||
Request request(fFilesystem->Server());
|
do {
|
||||||
RequestBuilder& req = request.Builder();
|
Request request(fFilesystem->Server());
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
req.PutFH(fHandle);
|
req.PutFH(fHandle);
|
||||||
req.Close(fFilesystem->NFSServer()->SequenceId(), cookie->fStateId,
|
req.Close(fFilesystem->NFSServer()->SequenceId(), cookie->fStateId,
|
||||||
cookie->fStateSeq);
|
cookie->fStateSeq);
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
result = reply.PutFH();
|
// server is in grace period, we need to wait
|
||||||
if (result != B_OK)
|
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
||||||
return result;
|
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
|
||||||
|
B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.Close();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId);
|
result = reply.Close();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -421,28 +451,40 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
|
|||||||
uint32 len = 0;
|
uint32 len = 0;
|
||||||
|
|
||||||
while (size < *_length && !eof) {
|
while (size < *_length && !eof) {
|
||||||
Request request(fFilesystem->Server());
|
do {
|
||||||
RequestBuilder& req = request.Builder();
|
Request request(fFilesystem->Server());
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
req.PutFH(fHandle);
|
req.PutFH(fHandle);
|
||||||
req.Read(cookie->fStateId, cookie->fStateSeq, pos + size,
|
req.Read(cookie->fStateId, cookie->fStateSeq, pos + size,
|
||||||
*_length - size);
|
*_length - size);
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
result = reply.PutFH();
|
// server is in grace period, we need to wait
|
||||||
if (result != B_OK)
|
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
||||||
return result;
|
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
|
||||||
|
B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.Read(reinterpret_cast<char*>(buffer) + size, &len, &eof);
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
size += len;
|
result = reply.Read(reinterpret_cast<char*>(buffer) + size, &len,
|
||||||
|
&eof);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
size += len;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
*_length = size;
|
*_length = size;
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ public:
|
|||||||
void ReleaseCID(uint64 cid);
|
void ReleaseCID(uint64 cid);
|
||||||
|
|
||||||
inline uint32 SequenceId();
|
inline uint32 SequenceId();
|
||||||
|
|
||||||
|
inline uint32 LeaseTime();
|
||||||
private:
|
private:
|
||||||
status_t _GetLeaseTime();
|
status_t _GetLeaseTime();
|
||||||
|
|
||||||
@@ -43,12 +45,22 @@ private:
|
|||||||
RPC::Server* fServer;
|
RPC::Server* fServer;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32
|
inline uint32
|
||||||
NFS4Server::SequenceId()
|
NFS4Server::SequenceId()
|
||||||
{
|
{
|
||||||
return static_cast<uint32>(atomic_add(&fSequenceId, 1));
|
return static_cast<uint32>(atomic_add(&fSequenceId, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint32
|
||||||
|
NFS4Server::LeaseTime()
|
||||||
|
{
|
||||||
|
if (fLeaseTime == 0)
|
||||||
|
_GetLeaseTime();
|
||||||
|
|
||||||
|
return fLeaseTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // NFS4SERVER_H
|
#endif // NFS4SERVER_H
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user