nfs4: close() should also wake snoozing threads

When server returns error codes like LOCKED, DEALY, etc the client waits
some time before retrying (unless in O_NONBLOCK mode), close() should wake
snoozing threads.
This commit is contained in:
Pawel Dziepak
2012-06-29 02:15:23 +02:00
parent f7bf941a8c
commit 0e1fd494e5
3 changed files with 29 additions and 3 deletions
@@ -18,14 +18,17 @@ vint64 OpenFileCookie::fLastOwnerId = 0;
Cookie::Cookie()
:
fRequests(NULL)
fRequests(NULL),
fSnoozeCancel(create_sem(1, NULL))
{
acquire_sem(fSnoozeCancel);
mutex_init(&fRequestLock, NULL);
}
Cookie::~Cookie()
{
delete_sem(fSnoozeCancel);
mutex_destroy(&fRequestLock);
}
@@ -74,6 +77,8 @@ Cookie::UnregisterRequest(RPC::Request* req)
status_t
Cookie::CancelAll()
{
release_sem(fSnoozeCancel);
mutex_lock(&fRequestLock);
RequestEntry* ent = fRequests;
while (ent != NULL) {
@@ -38,6 +38,8 @@ struct Cookie {
RequestEntry* fRequests;
mutex fRequestLock;
sem_id fSnoozeCancel;
Cookie();
virtual ~Cookie();
+21 -2
View File
@@ -1533,18 +1533,37 @@ Inode::_HandleErrors(uint32 nfs4Error, RPC::Server* serv,
// server needs more time, we need to wait
case NFS4ERR_LOCKED:
case NFS4ERR_DELAY:
if (cookie == NULL || (cookie->fMode & O_NONBLOCK) == 0) {
if (cookie == NULL) {
snooze_etc(5 * 1000000, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT);
return true;
} else if ((cookie->fMode & O_NONBLOCK) == 0) {
status_t result = acquire_sem_etc(cookie->fSnoozeCancel, 1,
B_RELATIVE_TIMEOUT, 5 * 1000000);
if (result == B_TIMED_OUT)
return true;
else {
release_sem(cookie->fSnoozeCancel);
return false;
}
} else
return false;
// server is in grace period, we need to wait
case NFS4ERR_GRACE:
if (cookie == NULL || (cookie->fMode & O_NONBLOCK) == 0) {
if (cookie == NULL) {
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT);
return true;
} else if ((cookie->fMode & O_NONBLOCK) == 0) {
status_t result = acquire_sem_etc(cookie->fSnoozeCancel, 1,
B_RELATIVE_TIMEOUT,
fFilesystem->NFSServer()->LeaseTime() / 3);
if (result == B_TIMED_OUT)
return true;
else {
release_sem(cookie->fSnoozeCancel);
return false;
}
} else
return false;