diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp index a539c256e8..7dd4674630 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp @@ -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) { diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.h b/src/add-ons/kernel/file_systems/nfs4/Cookie.h index c1d3b07af9..e1d9badd4b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.h +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.h @@ -38,6 +38,8 @@ struct Cookie { RequestEntry* fRequests; mutex fRequestLock; + sem_id fSnoozeCancel; + Cookie(); virtual ~Cookie(); diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 1e18c32bca..59c499a037 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -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;