From ee71a62af22213303b0499938577c38eca45a403 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Thu, 7 Jul 2011 13:48:48 -0400 Subject: [PATCH] deleg: make use of delegation stateids combined nfs41_lock_stateid_arg() into nfs41_open_stateid_arg(). if a delegation is present, use the delegation stateid before looking at lock/open stateids. if a delegation recall is in progress, wait on its condition variable before falling back to the open stateid made nfs41_lock_stateid_arg() static to lock.c because of its special semantics; open_to_lock_owner4 for LOCK won't accept a delegation stateid, so nfs41_delegation_to_open() is called to convert it Signed-off-by: Casey Bodley --- daemon/acl.c | 2 +- daemon/lock.c | 24 ++++++++++++------ daemon/nfs41.h | 5 ---- daemon/open.c | 58 +++++++++++++++++++++++++++++++++++++++----- daemon/pnfs_layout.c | 2 +- daemon/readwrite.c | 4 +-- daemon/setattr.c | 6 ++--- 7 files changed, 75 insertions(+), 26 deletions(-) diff --git a/daemon/acl.c b/daemon/acl.c index 4b7be5e..c24e58f 100644 --- a/daemon/acl.c +++ b/daemon/acl.c @@ -785,7 +785,7 @@ static int handle_setacl(nfs41_upcall *upcall) } } - nfs41_lock_stateid_arg(state, &stateid); + nfs41_open_stateid_arg(state, &stateid); status = nfs41_setattr(state->session, &state->file, &stateid, &info); if (status) { dprintf(1, "handle_setacl: nfs41_setattr() failed with error %s.\n", diff --git a/daemon/lock.c b/daemon/lock.c index 1386577..0aaef0f 100644 --- a/daemon/lock.c +++ b/daemon/lock.c @@ -25,6 +25,7 @@ #include #include "daemon_debug.h" +#include "delegation.h" #include "nfs41_ops.h" #include "upcall.h" #include "util.h" @@ -33,19 +34,26 @@ #define LKLVL 2 /* dprintf level for lock logging */ -void nfs41_lock_stateid_arg( +static void lock_stateid_arg( IN nfs41_open_state *state, OUT stateid_arg *arg) { + arg->open = state; + + /* open_to_lock_owner4 requires an open stateid; if we + * have a delegation, convert it to an open stateid */ + nfs41_delegation_to_open(state, TRUE); + AcquireSRWLockShared(&state->lock); if (state->locks.stateid.seqid) { - /* use lock stateid where available */ memcpy(&arg->stateid, &state->locks.stateid, sizeof(stateid4)); arg->type = STATEID_LOCK; - arg->open = state; + } else if (state->do_close) { + memcpy(&arg->stateid, &state->stateid, sizeof(stateid4)); + arg->type = STATEID_OPEN; } else { - /* fall back on open stateid */ - nfs41_open_stateid_arg(state, arg); + memset(&arg->stateid, 0, sizeof(stateid4)); + arg->type = STATEID_SPECIAL; } ReleaseSRWLockShared(&state->lock); } @@ -153,7 +161,7 @@ static int handle_lock(nfs41_upcall *upcall) const uint32_t type = get_lock_type(args->exclusive, args->blocking); int status; - nfs41_lock_stateid_arg(state, &stateid); + lock_stateid_arg(state, &stateid); /* 18.10.3. Operation 12: LOCK - Create Lock * "To lock the file from a specific offset through the end-of-file @@ -190,7 +198,7 @@ static void cancel_lock(IN nfs41_upcall *upcall) if (upcall->status) goto out; - nfs41_lock_stateid_arg(state, &stateid); + lock_stateid_arg(state, &stateid); status = nfs41_unlock(state->session, &state->file, args->offset, args->length, &stateid); @@ -236,7 +244,7 @@ static int handle_unlock(nfs41_upcall *upcall) uint64_t length; int status = NO_ERROR; - nfs41_lock_stateid_arg(state, &stateid); + lock_stateid_arg(state, &stateid); if (stateid.type != STATEID_LOCK) { eprintf("attempt to unlock a file with no lock state\n"); status = ERROR_NOT_LOCKED; diff --git a/daemon/nfs41.h b/daemon/nfs41.h index 433aa3d..9ca8664 100644 --- a/daemon/nfs41.h +++ b/daemon/nfs41.h @@ -466,9 +466,4 @@ int nfs41_open( IN bool_t try_recovery, OUT OPTIONAL nfs41_file_info *info); -/* lock.c */ -void nfs41_lock_stateid_arg( - IN nfs41_open_state *state, - OUT struct __stateid_arg *arg); - #endif /* __NFS41__ */ diff --git a/daemon/open.c b/daemon/open.c index 27adfdd..3e25f8d 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -111,15 +111,57 @@ void nfs41_open_state_deref( open_state_free(state); } +/* 8.2.5. Stateid Use for I/O Operations + * o If the client holds a delegation for the file in question, the + * delegation stateid SHOULD be used. + * o Otherwise, if the entity corresponding to the lock-owner (e.g., a + * process) sending the I/O has a byte-range lock stateid for the + * associated open file, then the byte-range lock stateid for that + * lock-owner and open file SHOULD be used. + * o If there is no byte-range lock stateid, then the OPEN stateid for + * the open file in question SHOULD be used. + * o Finally, if none of the above apply, then a special stateid SHOULD + * be used. */ void nfs41_open_stateid_arg( IN nfs41_open_state *state, OUT stateid_arg *arg) { - AcquireSRWLockShared(&state->lock); - memcpy(&arg->stateid, &state->stateid, sizeof(stateid4)); - ReleaseSRWLockShared(&state->lock); - arg->type = STATEID_OPEN; arg->open = state; + + AcquireSRWLockShared(&state->lock); + + if (state->delegation.state) { + nfs41_delegation_state *deleg = state->delegation.state; + AcquireSRWLockShared(&deleg->lock); + if (!deleg->state.recalled) { + arg->type = STATEID_DELEG_FILE; + memcpy(&arg->stateid, &deleg->state.stateid, sizeof(stateid4)); + } + ReleaseSRWLockShared(&deleg->lock); + + if (arg->type == STATEID_DELEG_FILE) + goto out; + + dprintf(2, "delegation recalled, waiting for open stateid..\n"); + + /* wait for nfs41_delegation_to_open() to recover open stateid */ + while (!state->do_close) + SleepConditionVariableSRW(&state->delegation.cond, &state->lock, + INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED); + } + + if (state->locks.stateid.seqid) { + memcpy(&arg->stateid, &state->locks.stateid, sizeof(stateid4)); + arg->type = STATEID_LOCK; + } else if (state->do_close) { + memcpy(&arg->stateid, &state->stateid, sizeof(stateid4)); + arg->type = STATEID_OPEN; + } else { + memset(&arg->stateid, 0, sizeof(stateid4)); + arg->type = STATEID_SPECIAL; + } +out: + ReleaseSRWLockShared(&state->lock); } /* client list of associated open state */ @@ -615,7 +657,9 @@ static void cancel_open(IN nfs41_upcall *upcall) if (state->do_close) { stateid_arg stateid; - nfs41_open_stateid_arg(state, &stateid); + stateid.open = state; + stateid.type = STATEID_OPEN; + memcpy(&stateid.stateid, &state->stateid, sizeof(stateid4)); status = nfs41_close(state->session, &state->file, &stateid); if (status) @@ -689,7 +733,9 @@ static int handle_close(nfs41_upcall *upcall) if (state->do_close) { stateid_arg stateid; - nfs41_open_stateid_arg(state, &stateid); + stateid.open = state; + stateid.type = STATEID_OPEN; + memcpy(&stateid.stateid, &state->stateid, sizeof(stateid4)); status = nfs41_close(state->session, &state->file, &stateid); if (status) { diff --git a/daemon/pnfs_layout.c b/daemon/pnfs_layout.c index 2e90acd..5fd47a7 100644 --- a/daemon/pnfs_layout.c +++ b/daemon/pnfs_layout.c @@ -719,7 +719,7 @@ enum pnfs_status pnfs_layout_state_open( goto out; } - nfs41_lock_stateid_arg(state, &stateid); + nfs41_open_stateid_arg(state, &stateid); /* make sure the layout can satisfy this request */ status = file_layout_get(layout, session, &state->file, diff --git a/daemon/readwrite.c b/daemon/readwrite.c index 580ea63..f412149 100644 --- a/daemon/readwrite.c +++ b/daemon/readwrite.c @@ -148,7 +148,7 @@ static int handle_read(nfs41_upcall *upcall) ULONG pnfs_bytes_read = 0; int status = NO_ERROR; - nfs41_lock_stateid_arg(upcall->state_ref, &stateid); + nfs41_open_stateid_arg(upcall->state_ref, &stateid); #ifdef PNFS_ENABLE_READ status = read_from_pnfs(upcall->root_ref, upcall->state_ref, &stateid, @@ -269,7 +269,7 @@ static int handle_write(nfs41_upcall *upcall) ULONG pnfs_bytes_written = 0; int status; - nfs41_lock_stateid_arg(upcall->state_ref, &stateid); + nfs41_open_stateid_arg(upcall->state_ref, &stateid); #ifdef PNFS_ENABLE_WRITE status = write_to_pnfs(upcall->root_ref, upcall->state_ref, &stateid, diff --git a/daemon/setattr.c b/daemon/setattr.c index ad0c57b..abb5aca 100644 --- a/daemon/setattr.c +++ b/daemon/setattr.c @@ -93,7 +93,7 @@ static int handle_nfs41_setattr(setattr_upcall_args *args) nfs41_file_info info; int status = NO_ERROR; - nfs41_lock_stateid_arg(state, &stateid); + nfs41_open_stateid_arg(state, &stateid); ZeroMemory(&info, sizeof(info)); @@ -343,7 +343,7 @@ static int handle_nfs41_set_size(setattr_upcall_args *args) nfs41_open_state *state = args->state; int status; - nfs41_lock_stateid_arg(state, &stateid); + nfs41_open_stateid_arg(state, &stateid); ZeroMemory(&info, sizeof(info)); info.size = size->QuadPart; @@ -509,7 +509,7 @@ static int handle_setexattr(nfs41_upcall *upcall) stateid_arg stateid; nfs41_file_info info; - nfs41_lock_stateid_arg(state, &stateid); + nfs41_open_stateid_arg(state, &stateid); ZeroMemory(&info, sizeof(info));