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 <cbodley@citi.umich.edu>
This commit is contained in:
parent
02216cbf28
commit
ee71a62af2
7 changed files with 75 additions and 26 deletions
|
|
@ -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);
|
status = nfs41_setattr(state->session, &state->file, &stateid, &info);
|
||||||
if (status) {
|
if (status) {
|
||||||
dprintf(1, "handle_setacl: nfs41_setattr() failed with error %s.\n",
|
dprintf(1, "handle_setacl: nfs41_setattr() failed with error %s.\n",
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "daemon_debug.h"
|
#include "daemon_debug.h"
|
||||||
|
#include "delegation.h"
|
||||||
#include "nfs41_ops.h"
|
#include "nfs41_ops.h"
|
||||||
#include "upcall.h"
|
#include "upcall.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
@ -33,19 +34,26 @@
|
||||||
#define LKLVL 2 /* dprintf level for lock logging */
|
#define LKLVL 2 /* dprintf level for lock logging */
|
||||||
|
|
||||||
|
|
||||||
void nfs41_lock_stateid_arg(
|
static void lock_stateid_arg(
|
||||||
IN nfs41_open_state *state,
|
IN nfs41_open_state *state,
|
||||||
OUT stateid_arg *arg)
|
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);
|
AcquireSRWLockShared(&state->lock);
|
||||||
if (state->locks.stateid.seqid) {
|
if (state->locks.stateid.seqid) {
|
||||||
/* use lock stateid where available */
|
|
||||||
memcpy(&arg->stateid, &state->locks.stateid, sizeof(stateid4));
|
memcpy(&arg->stateid, &state->locks.stateid, sizeof(stateid4));
|
||||||
arg->type = STATEID_LOCK;
|
arg->type = STATEID_LOCK;
|
||||||
arg->open = state;
|
} else if (state->do_close) {
|
||||||
|
memcpy(&arg->stateid, &state->stateid, sizeof(stateid4));
|
||||||
|
arg->type = STATEID_OPEN;
|
||||||
} else {
|
} else {
|
||||||
/* fall back on open stateid */
|
memset(&arg->stateid, 0, sizeof(stateid4));
|
||||||
nfs41_open_stateid_arg(state, arg);
|
arg->type = STATEID_SPECIAL;
|
||||||
}
|
}
|
||||||
ReleaseSRWLockShared(&state->lock);
|
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);
|
const uint32_t type = get_lock_type(args->exclusive, args->blocking);
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(state, &stateid);
|
lock_stateid_arg(state, &stateid);
|
||||||
|
|
||||||
/* 18.10.3. Operation 12: LOCK - Create Lock
|
/* 18.10.3. Operation 12: LOCK - Create Lock
|
||||||
* "To lock the file from a specific offset through the end-of-file
|
* "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)
|
if (upcall->status)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(state, &stateid);
|
lock_stateid_arg(state, &stateid);
|
||||||
|
|
||||||
status = nfs41_unlock(state->session, &state->file,
|
status = nfs41_unlock(state->session, &state->file,
|
||||||
args->offset, args->length, &stateid);
|
args->offset, args->length, &stateid);
|
||||||
|
|
@ -236,7 +244,7 @@ static int handle_unlock(nfs41_upcall *upcall)
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
int status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(state, &stateid);
|
lock_stateid_arg(state, &stateid);
|
||||||
if (stateid.type != STATEID_LOCK) {
|
if (stateid.type != STATEID_LOCK) {
|
||||||
eprintf("attempt to unlock a file with no lock state\n");
|
eprintf("attempt to unlock a file with no lock state\n");
|
||||||
status = ERROR_NOT_LOCKED;
|
status = ERROR_NOT_LOCKED;
|
||||||
|
|
|
||||||
|
|
@ -466,9 +466,4 @@ int nfs41_open(
|
||||||
IN bool_t try_recovery,
|
IN bool_t try_recovery,
|
||||||
OUT OPTIONAL nfs41_file_info *info);
|
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__ */
|
#endif /* __NFS41__ */
|
||||||
|
|
|
||||||
|
|
@ -111,15 +111,57 @@ void nfs41_open_state_deref(
|
||||||
open_state_free(state);
|
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(
|
void nfs41_open_stateid_arg(
|
||||||
IN nfs41_open_state *state,
|
IN nfs41_open_state *state,
|
||||||
OUT stateid_arg *arg)
|
OUT stateid_arg *arg)
|
||||||
{
|
{
|
||||||
AcquireSRWLockShared(&state->lock);
|
|
||||||
memcpy(&arg->stateid, &state->stateid, sizeof(stateid4));
|
|
||||||
ReleaseSRWLockShared(&state->lock);
|
|
||||||
arg->type = STATEID_OPEN;
|
|
||||||
arg->open = state;
|
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 */
|
/* client list of associated open state */
|
||||||
|
|
@ -615,7 +657,9 @@ static void cancel_open(IN nfs41_upcall *upcall)
|
||||||
|
|
||||||
if (state->do_close) {
|
if (state->do_close) {
|
||||||
stateid_arg stateid;
|
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);
|
status = nfs41_close(state->session, &state->file, &stateid);
|
||||||
if (status)
|
if (status)
|
||||||
|
|
@ -689,7 +733,9 @@ static int handle_close(nfs41_upcall *upcall)
|
||||||
|
|
||||||
if (state->do_close) {
|
if (state->do_close) {
|
||||||
stateid_arg stateid;
|
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);
|
status = nfs41_close(state->session, &state->file, &stateid);
|
||||||
if (status) {
|
if (status) {
|
||||||
|
|
|
||||||
|
|
@ -719,7 +719,7 @@ enum pnfs_status pnfs_layout_state_open(
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(state, &stateid);
|
nfs41_open_stateid_arg(state, &stateid);
|
||||||
|
|
||||||
/* make sure the layout can satisfy this request */
|
/* make sure the layout can satisfy this request */
|
||||||
status = file_layout_get(layout, session, &state->file,
|
status = file_layout_get(layout, session, &state->file,
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ static int handle_read(nfs41_upcall *upcall)
|
||||||
ULONG pnfs_bytes_read = 0;
|
ULONG pnfs_bytes_read = 0;
|
||||||
int status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(upcall->state_ref, &stateid);
|
nfs41_open_stateid_arg(upcall->state_ref, &stateid);
|
||||||
|
|
||||||
#ifdef PNFS_ENABLE_READ
|
#ifdef PNFS_ENABLE_READ
|
||||||
status = read_from_pnfs(upcall->root_ref, upcall->state_ref, &stateid,
|
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;
|
ULONG pnfs_bytes_written = 0;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(upcall->state_ref, &stateid);
|
nfs41_open_stateid_arg(upcall->state_ref, &stateid);
|
||||||
|
|
||||||
#ifdef PNFS_ENABLE_WRITE
|
#ifdef PNFS_ENABLE_WRITE
|
||||||
status = write_to_pnfs(upcall->root_ref, upcall->state_ref, &stateid,
|
status = write_to_pnfs(upcall->root_ref, upcall->state_ref, &stateid,
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ static int handle_nfs41_setattr(setattr_upcall_args *args)
|
||||||
nfs41_file_info info;
|
nfs41_file_info info;
|
||||||
int status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(state, &stateid);
|
nfs41_open_stateid_arg(state, &stateid);
|
||||||
|
|
||||||
ZeroMemory(&info, sizeof(info));
|
ZeroMemory(&info, sizeof(info));
|
||||||
|
|
||||||
|
|
@ -343,7 +343,7 @@ static int handle_nfs41_set_size(setattr_upcall_args *args)
|
||||||
nfs41_open_state *state = args->state;
|
nfs41_open_state *state = args->state;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(state, &stateid);
|
nfs41_open_stateid_arg(state, &stateid);
|
||||||
|
|
||||||
ZeroMemory(&info, sizeof(info));
|
ZeroMemory(&info, sizeof(info));
|
||||||
info.size = size->QuadPart;
|
info.size = size->QuadPart;
|
||||||
|
|
@ -509,7 +509,7 @@ static int handle_setexattr(nfs41_upcall *upcall)
|
||||||
stateid_arg stateid;
|
stateid_arg stateid;
|
||||||
nfs41_file_info info;
|
nfs41_file_info info;
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(state, &stateid);
|
nfs41_open_stateid_arg(state, &stateid);
|
||||||
|
|
||||||
ZeroMemory(&info, sizeof(info));
|
ZeroMemory(&info, sizeof(info));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue