From 3ecd38e41424eb62c5c3662550155f923054929d Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Mon, 15 Nov 2010 14:59:49 -0500 Subject: [PATCH] recovery: operations take stateid_arg instead of stateid4 operations that require a stateid now take stateid_arg for recovery information. these operations include close, setattr, lock/unlock, layoutget, and read/write (including pnfs) nfs41_open_stateid_arg() locks nfs41_open_state and copies its stateid into a stateid_arg nfs41_lock_stateid_arg() locks nfs41_open_state.last_lock and copies its stateid into a stateid_arg; if there is no lock state, it falls back to nfs41_open_stateid_arg() pnfs_read/write() now take nfs41_open_state so they can generate stateid_args Signed-off-by: Casey Bodley --- daemon/lock.c | 61 ++++++++++++++-------------- daemon/nfs41.h | 10 +++++ daemon/nfs41_ops.c | 94 ++++++++++++-------------------------------- daemon/nfs41_ops.h | 64 +++++++++++++++++------------- daemon/nfs41_xdr.c | 19 ++++----- daemon/open.c | 21 +++++++++- daemon/pnfs.h | 9 ++--- daemon/pnfs_device.c | 2 +- daemon/pnfs_io.c | 42 ++++++++++---------- daemon/pnfs_layout.c | 26 +++++++----- daemon/readwrite.c | 53 +++++++++++-------------- daemon/setattr.c | 31 ++++++--------- 12 files changed, 205 insertions(+), 227 deletions(-) diff --git a/daemon/lock.c b/daemon/lock.c index c7461fc..16fc3ed 100644 --- a/daemon/lock.c +++ b/daemon/lock.c @@ -33,23 +33,22 @@ #define LKLVL 2 /* dprintf level for lock logging */ -stateid4* nfs41_lock_stateid_copy( - IN nfs41_lock_state *lock_state, - IN OUT stateid4 *dest) +void nfs41_lock_stateid_arg( + IN nfs41_open_state *state, + OUT stateid_arg *arg) { - stateid4 *result; - AcquireSRWLockShared(&lock_state->lock); - if (lock_state->initialized) { - memcpy(dest, &lock_state->stateid, sizeof(stateid4)); - result = dest; - dprintf(LKLVL, "nfs41_lock_stateid_copy: copying existing stateid " - "with seqid=%u\n", result->seqid); + AcquireSRWLockShared(&state->last_lock.lock); + if (state->last_lock.initialized) { + /* use lock stateid where available */ + memcpy(&arg->stateid, &state->last_lock.stateid, sizeof(stateid4)); + arg->type = STATEID_LOCK; + ReleaseSRWLockShared(&state->last_lock.lock); } else { - result = NULL; - dprintf(LKLVL, "nfs41_lock_stateid_copy: no existing lock state\n"); + ReleaseSRWLockShared(&state->last_lock.lock); + + /* fall back on open stateid */ + nfs41_open_stateid_arg(state, arg); } - ReleaseSRWLockShared(&lock_state->lock); - return result; } static void update_last_lock_state( @@ -124,15 +123,15 @@ static __inline uint32_t get_lock_type(BOOLEAN exclusive, BOOLEAN blocking) static int handle_lock(nfs41_upcall *upcall) { - int status; + stateid_arg stateid; lock_upcall_args *args = &upcall->args.lock; nfs41_open_state *state = args->state; const uint32_t type = get_lock_type(args->exclusive, args->blocking); - stateid4 stateid, *prev_stateid; + int status; - prev_stateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid); + nfs41_lock_stateid_arg(state, &stateid); - status = nfs41_lock(state->session, state, prev_stateid, + status = nfs41_lock(state->session, &state->file, &state->owner, type, args->offset, args->length, &stateid); if (status) { dprintf(LKLVL, "nfs41_lock failed with %s\n", @@ -141,27 +140,27 @@ static int handle_lock(nfs41_upcall *upcall) goto out; } - update_last_lock_state(&state->last_lock, &stateid); + update_last_lock_state(&state->last_lock, &stateid.stateid); out: return status; } static void cancel_lock(IN nfs41_upcall *upcall) { - int status = NO_ERROR; + stateid_arg stateid; lock_upcall_args *args = &upcall->args.lock; nfs41_open_state *state = args->state; - stateid4 stateid, *prev_stateid; + int status = NO_ERROR; dprintf(1, "--> cancel_lock()\n"); if (upcall->status) goto out; - prev_stateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid); + nfs41_lock_stateid_arg(state, &stateid); - status = nfs41_unlock(state->session, state, - prev_stateid, args->offset, args->length); + status = nfs41_unlock(state->session, &state->file, + args->offset, args->length, &stateid); if (status) { dprintf(LKLVL, "cancel_lock: nfs41_unlock() failed with %s\n", nfs_error_string(status)); @@ -169,7 +168,7 @@ static void cancel_lock(IN nfs41_upcall *upcall) goto out; } - update_last_lock_state(&state->last_lock, &stateid); + update_last_lock_state(&state->last_lock, &stateid.stateid); out: dprintf(1, "<-- cancel_lock() returning %d\n", status); } @@ -201,17 +200,18 @@ out: static int handle_unlock(nfs41_upcall *upcall) { - int status; + stateid_arg stateid; unlock_upcall_args *args = &upcall->args.unlock; nfs41_open_state *state = args->state; - stateid4 stateid; uint32_t i, nsuccess = 0; unsigned char *buf = args->buf; uint32_t buf_len = args->buf_len; uint64_t offset; uint64_t length; + int status; - if (nfs41_lock_stateid_copy(&state->last_lock, &stateid) == NULL) { + nfs41_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; goto out; @@ -222,7 +222,8 @@ static int handle_unlock(nfs41_upcall *upcall) if (safe_read(&buf, &buf_len, &offset, sizeof(LONGLONG))) break; if (safe_read(&buf, &buf_len, &length, sizeof(LONGLONG))) break; - status = nfs41_unlock(state->session, state, &stateid, offset, length); + status = nfs41_unlock(state->session, + &state->file, offset, length, &stateid); if (status == NFS4_OK) { nsuccess++; } else { @@ -233,7 +234,7 @@ static int handle_unlock(nfs41_upcall *upcall) } if (nsuccess) { - update_last_lock_state(&state->last_lock, &stateid); + update_last_lock_state(&state->last_lock, &stateid.stateid); status = NO_ERROR; } out: diff --git a/daemon/nfs41.h b/daemon/nfs41.h index 2294cf6..61ae61d 100644 --- a/daemon/nfs41.h +++ b/daemon/nfs41.h @@ -400,4 +400,14 @@ void nfs41_open_state_ref( void nfs41_open_state_deref( IN nfs41_open_state *state); +struct __stateid_arg; +void nfs41_open_stateid_arg( + IN nfs41_open_state *state, + OUT struct __stateid_arg *arg); + +/* lock.c */ +void nfs41_lock_stateid_arg( + IN nfs41_open_state *state, + OUT struct __stateid_arg *arg); + #endif /* __NFS41__ */ diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c index 28c9b0d..8baa1f0 100644 --- a/daemon/nfs41_ops.c +++ b/daemon/nfs41_ops.c @@ -590,7 +590,8 @@ out: int nfs41_close( IN nfs41_session *session, - IN nfs41_open_state *state) + IN nfs41_path_fh *file, + IN stateid_arg *stateid) { int status; nfs41_compound compound; @@ -617,11 +618,11 @@ int nfs41_close( goto out; compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res); - putfh_args.file = &state->file; + putfh_args.file = file; putfh_args.in_recovery = 0; compound_add_op(&compound, OP_CLOSE, &close_args, &close_res); - close_args.open_stateid = &state->stateid; + close_args.stateid = stateid; compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res); getattr_args.attr_request = &attr_request; @@ -639,7 +640,7 @@ int nfs41_close( memcpy(&info.attrmask, &getattr_res.obj_attributes.attrmask, sizeof(bitmap4)); nfs41_attr_cache_update(session_name_cache(session), - state->file.fh.fileid, &info); + file->fh.fileid, &info); out: return status; @@ -648,7 +649,7 @@ out: int nfs41_write( IN nfs41_session *session, IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN stateid_arg *stateid, IN unsigned char *data, IN uint32_t data_len, IN uint64_t offset, @@ -732,7 +733,7 @@ out: int nfs41_read( IN nfs41_session *session, IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN stateid_arg *stateid, IN uint64_t offset, IN uint32_t count, OUT unsigned char *data_out, @@ -857,12 +858,12 @@ out: int nfs41_lock( IN nfs41_session *session, - IN nfs41_open_state *open_state, - IN stateid4 *lock_state OPTIONAL, + IN nfs41_path_fh *file, + IN state_owner4 *owner, IN uint32_t type, IN uint64_t offset, IN uint64_t length, - OUT stateid4 *stateid_out) + IN OUT stateid_arg *stateid) { int status; nfs41_compound compound; @@ -883,7 +884,7 @@ int nfs41_lock( goto out; compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res); - putfh_args.file = &open_state->file; + putfh_args.file = file; putfh_args.in_recovery = 0; compound_add_op(&compound, OP_LOCK, &lock_args, &lock_res); @@ -891,18 +892,18 @@ int nfs41_lock( lock_args.reclaim = 0; lock_args.offset = offset; lock_args.length = length; - if (lock_state) { + if (stateid->type == STATEID_LOCK) { lock_args.locker.new_lock_owner = 0; - lock_args.locker.u.lock_owner.lock_stateid = lock_state; + lock_args.locker.u.lock_owner.lock_stateid = stateid; lock_args.locker.u.lock_owner.lock_seqid = 0; /* ignored */ } else { lock_args.locker.new_lock_owner = 1; lock_args.locker.u.open_owner.open_seqid = 0; /* ignored */ - lock_args.locker.u.open_owner.open_stateid = &open_state->stateid; + lock_args.locker.u.open_owner.open_stateid = stateid; lock_args.locker.u.open_owner.lock_seqid = 0; /* ignored */ - lock_args.locker.u.open_owner.lock_owner = &open_state->owner; + lock_args.locker.u.open_owner.lock_owner = owner; } - lock_res.u.resok4.lock_stateid = stateid_out; + lock_res.u.resok4.lock_stateid = &stateid->stateid; lock_res.u.denied.owner.owner_len = NFS4_OPAQUE_LIMIT; status = compound_encode_send_decode(session, &compound, 0, 0); @@ -914,57 +915,12 @@ out: return status; } -int nfs41_test_lock( - IN nfs41_session *session, - IN nfs41_open_state *state, - IN uint32_t type, - IN uint64_t offset, - IN uint64_t length) -{ - int status; - nfs41_compound compound; - nfs_argop4 argops[3]; - nfs_resop4 resops[3]; - nfs41_sequence_args sequence_args; - nfs41_sequence_res sequence_res; - nfs41_putfh_args putfh_args; - nfs41_putfh_res putfh_res; - nfs41_lockt_args lockt_args; - nfs41_lockt_res lockt_res; - - compound_init(&compound, argops, resops, "test_lock"); - - compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res); - status = nfs41_session_sequence(&sequence_args, session, 0); - if (status) - goto out; - - compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res); - putfh_args.file = &state->file; - putfh_args.in_recovery = 0; - - compound_add_op(&compound, OP_LOCKT, &lockt_args, &lockt_res); - lockt_args.locktype = type; - lockt_args.offset = offset; - lockt_args.length = length; - lockt_args.owner = &state->owner; - lockt_res.denied.owner.owner_len = NFS4_OPAQUE_LIMIT; - - status = compound_encode_send_decode(session, &compound, 0, 0); - if (status) - goto out; - - compound_error(status = compound.res.status); -out: - return status; -} - int nfs41_unlock( IN nfs41_session *session, - IN nfs41_open_state *open_state, - IN OUT stateid4 *lock_state, + IN nfs41_path_fh *file, IN uint64_t offset, - IN uint64_t length) + IN uint64_t length, + IN OUT stateid_arg *stateid) { int status; nfs41_compound compound; @@ -985,7 +941,7 @@ int nfs41_unlock( goto out; compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res); - putfh_args.file = &open_state->file; + putfh_args.file = file; putfh_args.in_recovery = 0; compound_add_op(&compound, OP_LOCKU, &locku_args, &locku_res); @@ -993,8 +949,8 @@ int nfs41_unlock( locku_args.locktype = READ_LT; locku_args.offset = offset; locku_args.length = length; - locku_args.lock_stateid = lock_state; - locku_res.lock_stateid = lock_state; + locku_args.lock_stateid = stateid; + locku_res.lock_stateid = &stateid->stateid; status = compound_encode_send_decode(session, &compound, 0, 0); if (status) @@ -1299,7 +1255,7 @@ out: int nfs41_setattr( IN nfs41_session *session, IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN stateid_arg *stateid, IN nfs41_file_info *info) { int status; @@ -1662,7 +1618,7 @@ out: enum nfsstat4 pnfs_rpc_layoutget( IN nfs41_session *session, IN nfs41_path_fh *file, - IN stateid4 *state, + IN stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length, @@ -1697,7 +1653,7 @@ enum nfsstat4 pnfs_rpc_layoutget( layoutget_args.iomode = iomode; layoutget_args.offset = offset; layoutget_args.minlength = layoutget_args.length = length; - layoutget_args.stateid = state; + layoutget_args.stateid = stateid; layoutget_args.maxcount = session->fore_chan_attrs.ca_maxresponsesize - READ_OVERHEAD; layoutget_res.u.res_ok.layout = layout; diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h index 4bbb256..6048817 100644 --- a/daemon/nfs41_ops.h +++ b/daemon/nfs41_ops.h @@ -244,6 +244,22 @@ typedef struct __nfs41_reclaim_complete_res { } nfs41_reclaim_complete_res; +/* recoverable stateid argument */ +enum stateid_type { + STATEID_OPEN, + STATEID_LOCK, + STATEID_DELEG_FILE, + STATEID_DELEG_DIR, + STATEID_LAYOUT, + STATEID_SPECIAL +}; +typedef struct __stateid_arg { + stateid4 stateid; + enum stateid_type type; + nfs41_open_state *open; +} stateid_arg; + + /* OP_ACCESS */ enum { ACCESS4_READ = 0x00000001, @@ -269,13 +285,11 @@ typedef struct __nfs41_access_res { /* OP_CLOSE */ typedef struct __nfs41_op_close_args { // uint32_t seqid; // not used, always 0 - stateid4 *open_stateid; /* -> nfs41_op_open_res_ok.stateid */ + stateid_arg *stateid; } nfs41_op_close_args; typedef struct __nfs41_op_close_res { uint32_t status; - /* case NFS4_OK: */ - stateid4 open_stateid; } nfs41_op_close_res; @@ -360,13 +374,13 @@ enum { typedef struct __open_to_lock_owner4 { uint32_t open_seqid; - stateid4 *open_stateid; + stateid_arg *open_stateid; uint32_t lock_seqid; state_owner4 *lock_owner; } open_to_lock_owner4; typedef struct __exist_lock_owner4 { - stateid4 *lock_stateid; + stateid_arg *lock_stateid; uint32_t lock_seqid; } exist_lock_owner4; @@ -431,7 +445,7 @@ typedef struct __nfs41_lockt_res { typedef struct __nfs41_locku_args { uint32_t locktype; uint32_t seqid; - stateid4 *lock_stateid; + stateid_arg *lock_stateid; uint64_t offset; uint64_t length; } nfs41_locku_args; @@ -628,7 +642,7 @@ typedef struct __nfs41_op_open_res { /* OP_READ */ typedef struct __nfs41_read_args { - stateid4 *stateid; /* -> nfs41_op_open_res_ok.stateid */ + stateid_arg *stateid; /* -> nfs41_op_open_res_ok.stateid */ uint64_t offset; uint32_t count; } nfs41_read_args; @@ -726,7 +740,7 @@ enum time_how4 { }; typedef struct __nfs41_setattr_args { - stateid4 *stateid; + stateid_arg *stateid; nfs41_file_info *info; } nfs41_setattr_args; @@ -750,7 +764,7 @@ typedef struct __nfs41_write_verf { } nfs41_write_verf; typedef struct __nfs41_write_args { - stateid4 *stateid; /* -> nfs41_op_open_res_ok.stateid */ + stateid_arg *stateid; /* -> nfs41_op_open_res_ok.stateid */ uint64_t offset; uint32_t stable; /* stable_how4 */ uint32_t data_len; @@ -777,7 +791,7 @@ typedef struct __pnfs_layoutget_args { uint64_t offset; uint64_t length; uint64_t minlength; - stateid4 *stateid; + stateid_arg *stateid; uint32_t maxcount; } pnfs_layoutget_args; @@ -923,12 +937,13 @@ int nfs41_create( int nfs41_close( IN nfs41_session *session, - IN nfs41_open_state *state); + IN nfs41_path_fh *file, + IN stateid_arg *stateid); int nfs41_write( IN nfs41_session *session, IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN stateid_arg *stateid, IN unsigned char *data, IN uint32_t data_len, IN uint64_t offset, @@ -939,7 +954,7 @@ int nfs41_write( int nfs41_read( IN nfs41_session *session, IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN stateid_arg *stateid, IN uint64_t offset, IN uint32_t count, OUT unsigned char *data_out, @@ -955,26 +970,19 @@ int nfs41_commit( int nfs41_lock( IN nfs41_session *session, - IN nfs41_open_state *open_state, - IN stateid4 *lock_state OPTIONAL, + IN nfs41_path_fh *file, + IN state_owner4 *owner, IN uint32_t type, IN uint64_t offset, IN uint64_t length, - OUT stateid4 *stateid_out); - -int nfs41_test_lock( - IN nfs41_session *session, - IN nfs41_open_state *state, - IN uint32_t type, - IN uint64_t offset, - IN uint64_t length); + IN OUT stateid_arg *stateid); int nfs41_unlock( IN nfs41_session *session, - IN nfs41_open_state *open_state, - IN OUT stateid4 *lock_state, + IN nfs41_path_fh *file, IN uint64_t offset, - IN uint64_t length); + IN uint64_t length, + IN OUT stateid_arg *stateid); stateid4* nfs41_lock_stateid_copy( IN nfs41_lock_state *lock_state, @@ -1019,7 +1027,7 @@ int nfs41_rename( int nfs41_setattr( IN nfs41_session *session, IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN stateid_arg *stateid, IN nfs41_file_info *info); int nfs41_link( @@ -1070,7 +1078,7 @@ enum nfsstat4 nfs41_fs_locations( enum nfsstat4 pnfs_rpc_layoutget( IN nfs41_session *session, IN nfs41_path_fh *file, - IN stateid4 *state, + IN stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length, diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c index 9fcab60..081c623 100644 --- a/daemon/nfs41_xdr.c +++ b/daemon/nfs41_xdr.c @@ -1101,13 +1101,14 @@ static bool_t encode_op_close( if (!xdr_u_int32_t(xdr, &zero)) // This should be ignored by server return FALSE; - return xdr_stateid4(xdr, args->open_stateid); + return xdr_stateid4(xdr, &args->stateid->stateid); } static bool_t decode_op_close( XDR *xdr, nfs_resop4 *resop) { + stateid4 ignored; nfs41_op_close_res *res = (nfs41_op_close_res*)resop->res; if (unexpected_op(resop->op, OP_CLOSE)) @@ -1117,7 +1118,7 @@ static bool_t decode_op_close( return FALSE; if (res->status == NFS4_OK) - return xdr_stateid4(xdr, &res->open_stateid); + return xdr_stateid4(xdr, &ignored); return TRUE; } @@ -1315,7 +1316,7 @@ static bool_t xdr_locker4( if (!xdr_u_int32_t(xdr, &locker->u.open_owner.open_seqid)) return FALSE; - if (!xdr_stateid4(xdr, locker->u.open_owner.open_stateid)) + if (!xdr_stateid4(xdr, &locker->u.open_owner.open_stateid->stateid)) return FALSE; if (!xdr_u_int32_t(xdr, &locker->u.open_owner.lock_seqid)) @@ -1324,7 +1325,7 @@ static bool_t xdr_locker4( return xdr_state_owner4(xdr, locker->u.open_owner.lock_owner); } else { /* exist_lock_owner4 lock_owner */ - if (!xdr_stateid4(xdr, locker->u.lock_owner.lock_stateid)) + if (!xdr_stateid4(xdr, &locker->u.lock_owner.lock_stateid->stateid)) return FALSE; return xdr_u_int32_t(xdr, &locker->u.lock_owner.lock_seqid); @@ -1459,7 +1460,7 @@ static bool_t encode_op_locku( if (!xdr_u_int32_t(xdr, &args->seqid)) return FALSE; - if (!xdr_stateid4(xdr, args->lock_stateid)) + if (!xdr_stateid4(xdr, &args->lock_stateid->stateid)) return FALSE; if (!xdr_u_hyper(xdr, &args->offset)) @@ -1974,7 +1975,7 @@ static bool_t encode_op_read( if (unexpected_op(argop->op, OP_READ)) return FALSE; - if (!xdr_stateid4(xdr, args->stateid)) + if (!xdr_stateid4(xdr, &args->stateid->stateid)) return FALSE; if (!xdr_u_hyper(xdr, &args->offset)) @@ -2409,7 +2410,7 @@ static bool_t encode_op_setattr( if (unexpected_op(argop->op, OP_SETATTR)) return FALSE; - if (!xdr_stateid4(xdr, args->stateid)) + if (!xdr_stateid4(xdr, &args->stateid->stateid)) return FALSE; /* encode attribute values from args->info into attrs.attr_vals */ @@ -2452,7 +2453,7 @@ static bool_t encode_op_write( if (unexpected_op(argop->op, OP_WRITE)) return FALSE; - if (!xdr_stateid4(xdr, args->stateid)) + if (!xdr_stateid4(xdr, &args->stateid->stateid)) return FALSE; if (!xdr_u_hyper(xdr, &args->offset)) @@ -2811,7 +2812,7 @@ static bool_t encode_op_layoutget( if (!xdr_u_hyper(xdr, &args->minlength)) return FALSE; - if (!xdr_stateid4(xdr, args->stateid)) + if (!xdr_stateid4(xdr, &args->stateid->stateid)) return FALSE; return xdr_u_int32_t(xdr, &args->maxcount); diff --git a/daemon/open.c b/daemon/open.c index 96798aa..2e38bc2 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -94,6 +94,17 @@ void nfs41_open_state_deref( free(state); } +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; +} + /* client list of associated open state */ static void client_state_add( @@ -491,7 +502,10 @@ static void cancel_open(IN nfs41_upcall *upcall) goto out; /* if handle_open() failed, the state was already freed */ if (state->do_close) { - status = nfs41_close(state->session, state); + stateid_arg stateid; + nfs41_open_stateid_arg(state, &stateid); + + status = nfs41_close(state->session, &state->file, &stateid); if (status) dprintf(1, "cancel_open: nfs41_close() failed with %s\n", nfs_error_string(status)); @@ -569,7 +583,10 @@ static int handle_close(nfs41_upcall *upcall) } if (state->do_close) { - status = nfs41_close(state->session, state); + stateid_arg stateid; + nfs41_open_stateid_arg(state, &stateid); + + status = nfs41_close(state->session, &state->file, &stateid); if (status) { dprintf(1, "nfs41_close() failed with error %s.\n", nfs_error_string(status)); diff --git a/daemon/pnfs.h b/daemon/pnfs.h index d136db5..cd56258 100644 --- a/daemon/pnfs.h +++ b/daemon/pnfs.h @@ -194,8 +194,7 @@ typedef struct __pnfs_layout_recall { typedef struct __pnfs_io_pattern { struct __pnfs_io_thread *threads; struct __nfs41_root *root; - nfs41_path_fh *meta_file; - stateid4 stateid; + struct __nfs41_open_state *state; pnfs_file_layout *layout; unsigned char *buffer; uint64_t offset_start; @@ -330,8 +329,7 @@ __inline uint32_t data_server_index( enum pnfs_status pnfs_read( IN struct __nfs41_root *root, IN struct __nfs41_session *session, - IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN struct __nfs41_open_state *state, IN pnfs_file_layout *layout, IN uint64_t offset, IN uint64_t length, @@ -341,8 +339,7 @@ enum pnfs_status pnfs_read( enum pnfs_status pnfs_write( IN struct __nfs41_root *root, IN struct __nfs41_session *session, - IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN struct __nfs41_open_state *state, IN pnfs_file_layout *layout, IN uint64_t offset, IN uint64_t length, diff --git a/daemon/pnfs_device.c b/daemon/pnfs_device.c index cc731a7..5f6b6ea 100644 --- a/daemon/pnfs_device.c +++ b/daemon/pnfs_device.c @@ -281,7 +281,7 @@ static enum pnfs_status get_sparse_fh( } else if (filehandle_count == 1) { *file_out = &layout->filehandles.arr[0]; } else if (filehandle_count == 0) { - *file_out = pattern->meta_file; + *file_out = &pattern->state->file; } else { eprintf("invalid sparse layout! has %u file handles " "and %u servers\n", filehandle_count, server_count); diff --git a/daemon/pnfs_io.c b/daemon/pnfs_io.c index 70b49a3..a02df08 100644 --- a/daemon/pnfs_io.c +++ b/daemon/pnfs_io.c @@ -43,8 +43,7 @@ static uint32_t io_unit_count( static enum pnfs_status pattern_init( IN pnfs_io_pattern *pattern, IN nfs41_root *root, - IN nfs41_path_fh *meta_file, - IN stateid4 *stateid, + IN nfs41_open_state *state, IN pnfs_file_layout *layout, IN unsigned char *buffer, IN uint64_t offset, @@ -76,12 +75,7 @@ static enum pnfs_status pattern_init( } pattern->root = root; - pattern->meta_file = meta_file; - /* 13.9.1. Global Stateid Requirements - * "The stateid sent to the data server MUST be sent - * with the seqid set to zero" */ - memcpy(&pattern->stateid, stateid, sizeof(stateid4)); - pattern->stateid.seqid = 0; + pattern->state = state; pattern->layout = layout; pattern->buffer = buffer; pattern->offset_start = offset; @@ -301,9 +295,9 @@ static enum pnfs_status map_ds_error( static uint32_t WINAPI file_layout_read_thread(void *args) { pnfs_io_unit io; + stateid_arg stateid; pnfs_io_thread *thread = (pnfs_io_thread*)args; pnfs_io_pattern *pattern = thread->pattern; - stateid4 *state = &pattern->stateid; pnfs_data_server *server; nfs41_client *client; uint32_t maxreadsize, bytes_read, total_read; @@ -329,13 +323,16 @@ static uint32_t WINAPI file_layout_read_thread(void *args) goto out; } + nfs41_lock_stateid_arg(pattern->state, &stateid); + stateid.stateid.seqid = 0; + total_read = 0; while ((status = thread_next_unit(thread, &io)) == PNFS_PENDING) { maxreadsize = max_read_size(client->session, &io.file->fh); if (io.length > maxreadsize) io.length = maxreadsize; - nfsstat = nfs41_read(client->session, io.file, state, io.offset, + nfsstat = nfs41_read(client->session, io.file, &stateid, io.offset, (uint32_t)io.length, io.buffer, &bytes_read, &eof); if (nfsstat) { eprintf("nfs41_read() failed with %s\n", @@ -363,10 +360,10 @@ out: static uint32_t WINAPI file_layout_write_thread(void *args) { pnfs_io_unit io; + stateid_arg stateid; nfs41_write_verf verf; pnfs_io_thread *thread = (pnfs_io_thread*)args; pnfs_io_pattern *pattern = thread->pattern; - stateid4 *state = &pattern->stateid; pnfs_data_server *server; pnfs_file_layout *layout = pattern->layout; nfs41_client *client; @@ -395,6 +392,9 @@ static uint32_t WINAPI file_layout_write_thread(void *args) goto out; } + nfs41_lock_stateid_arg(pattern->state, &stateid); + stateid.stateid.seqid = 0; + retry_write: thread->offset = offset_start; thread->stable = DATA_SYNC4; @@ -406,7 +406,7 @@ retry_write: if (io.length > maxwritesize) io.length = maxwritesize; - nfsstat = nfs41_write(client->session, io.file, state, io.buffer, + nfsstat = nfs41_write(client->session, io.file, &stateid, io.buffer, (uint32_t)io.length, io.offset, UNSTABLE4, &bytes_written, &verf); if (nfsstat) { eprintf("nfs41_write() failed with %s\n", @@ -460,8 +460,7 @@ out: enum pnfs_status pnfs_read( IN nfs41_root *root, IN nfs41_session *session, - IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN nfs41_open_state *state, IN pnfs_file_layout *layout, IN uint64_t offset, IN uint64_t length, @@ -475,8 +474,8 @@ enum pnfs_status pnfs_read( *len_out = 0; - status = pattern_init(&pattern, root, file, stateid, - layout, buffer_out, offset, length, session->lease_time); + status = pattern_init(&pattern, root, state, layout, + buffer_out, offset, length, session->lease_time); if (status) { eprintf("pattern_init() failed with %s\n", pnfs_error_string(status)); @@ -500,8 +499,7 @@ out: enum pnfs_status pnfs_write( IN nfs41_root *root, IN nfs41_session *session, - IN nfs41_path_fh *file, - IN stateid4 *stateid, + IN nfs41_open_state *state, IN pnfs_file_layout *layout, IN uint64_t offset, IN uint64_t length, @@ -518,8 +516,8 @@ enum pnfs_status pnfs_write( *len_out = 0; - status = pattern_init(&pattern, root, file, stateid, - layout, buffer, offset, length, session->lease_time); + status = pattern_init(&pattern, root, state, layout, + buffer, offset, length, session->lease_time); if (status) { eprintf("pattern_init() failed with %s\n", pnfs_error_string(status)); @@ -541,7 +539,7 @@ enum pnfs_status pnfs_write( * after LAYOUTCOMMIT */ dprintf(1, "sending COMMIT to meta server for offset=%d and len=%d\n", offset, *len_out); - nfsstat = nfs41_commit(session, pattern.meta_file, offset, *len_out, 0); + nfsstat = nfs41_commit(session, &state->file, offset, *len_out, 0); if (nfsstat) { dprintf(IOLVL, "nfs41_commit() failed with %s\n", nfs_error_string(nfsstat)); @@ -553,7 +551,7 @@ enum pnfs_status pnfs_write( /* send LAYOUTCOMMIT */ new_last_offset = offset + *len_out - 1; - nfsstat = pnfs_rpc_layoutcommit(session, pattern.meta_file, + nfsstat = pnfs_rpc_layoutcommit(session, &state->file, &pattern.layout->layout.state, offset, *len_out, &new_last_offset, NULL); if (nfsstat) { diff --git a/daemon/pnfs_layout.c b/daemon/pnfs_layout.c index f19a281..bce3a21 100644 --- a/daemon/pnfs_layout.c +++ b/daemon/pnfs_layout.c @@ -192,7 +192,7 @@ static enum pnfs_status file_layout_fetch( IN OUT pnfs_file_layout *layout, IN nfs41_session *session, IN nfs41_path_fh *meta_file, - IN stateid4 *state, + IN stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length) @@ -204,7 +204,7 @@ static enum pnfs_status file_layout_fetch( pnfs_iomode_string(iomode), layout->layout.state.seqid); nfsstat = pnfs_rpc_layoutget(session, meta_file, - state, iomode, offset, length, layout); + stateid, iomode, offset, length, layout); if (nfsstat) { dprintf(FLLVL, "pnfs_rpc_layoutget() failed with %s\n", nfs_error_string(nfsstat)); @@ -264,7 +264,7 @@ static enum pnfs_status file_layout_cache( IN OUT pnfs_file_layout *layout, IN nfs41_session *session, IN nfs41_path_fh *meta_file, - IN stateid4 *state, + IN stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length) @@ -283,19 +283,22 @@ static enum pnfs_status file_layout_cache( status = layout_grant_status(&layout->layout, iomode); if (status == PNFS_PENDING) { /* if there's an existing layout stateid, use it */ - if (layout->layout.state.seqid) - state = &layout->layout.state; + if (layout->layout.state.seqid) { + memcpy(&stateid->stateid, &layout->layout.state, + sizeof(stateid4)); + stateid->type = STATEID_LAYOUT; + } if ((layout->layout.status & PNFS_LAYOUT_NOT_RW) == 0) { /* try to get a RW layout first */ status = file_layout_fetch(layout, session, - meta_file, state, PNFS_IOMODE_RW, offset, length); + meta_file, stateid, PNFS_IOMODE_RW, offset, length); } if (status && iomode == PNFS_IOMODE_READ) { /* fall back on READ if necessary */ status = file_layout_fetch(layout, session, - meta_file, state, iomode, offset, length); + meta_file, stateid, iomode, offset, length); } } @@ -375,7 +378,7 @@ static enum pnfs_status file_layout_get( IN OUT pnfs_file_layout *layout, IN nfs41_session *session, IN nfs41_path_fh *meta_file, - IN stateid4 *state, + IN stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length) @@ -384,7 +387,7 @@ static enum pnfs_status file_layout_get( /* request a range for the entire file */ status = file_layout_cache(layout, session, - meta_file, state, iomode, 0, NFS4_UINT64_MAX); + meta_file, stateid, iomode, 0, NFS4_UINT64_MAX); if (status) { dprintf(FLLVL, "file_layout_cache() failed with %s\n", pnfs_error_string(status)); @@ -509,6 +512,7 @@ enum pnfs_status pnfs_open_state_layout( IN uint64_t length, OUT pnfs_file_layout **layout_out) { + stateid_arg stateid; pnfs_file_layout *layout; enum pnfs_status status; @@ -547,9 +551,11 @@ enum pnfs_status pnfs_open_state_layout( goto out; } + nfs41_open_stateid_arg(state, &stateid); + /* make sure the layout can satisfy this request */ status = file_layout_get(layout, session, &state->file, - &state->stateid, iomode, offset, length); + &stateid, iomode, offset, length); if (status) { dprintf(FLLVL, "file_layout_get() failed with %s\n", pnfs_error_string(status)); diff --git a/daemon/readwrite.c b/daemon/readwrite.c index efde36f..2051420 100644 --- a/daemon/readwrite.c +++ b/daemon/readwrite.c @@ -31,7 +31,7 @@ #include "util.h" -stateid4 special_read_stateid = {0xffffffff, +const stateid4 special_read_stateid = {0xffffffff, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; static int parse_rw(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall) @@ -62,18 +62,20 @@ out: /* NFS41_READ */ static int read_from_mds( IN nfs41_session *session, - IN stateid4 *stateid, - IN nfs41_path_fh *file, + IN nfs41_open_state *state, IN uint64_t offset, IN uint32_t length, OUT unsigned char *buffer, OUT ULONG *len_out) { + stateid_arg stateid; int status = 0; bool_t eof; unsigned char *p = buffer; ULONG to_rcv = length, reloffset = 0, len = 0; - const uint32_t maxreadsize = max_read_size(session, &file->fh); + const uint32_t maxreadsize = max_read_size(session, &state->file.fh); + + nfs41_lock_stateid_arg(state, &stateid); if (to_rcv > maxreadsize) dprintf(1, "handle_nfs41_read: reading %d in chunks of %d\n", @@ -82,10 +84,11 @@ static int read_from_mds( while(to_rcv > 0) { uint32_t bytes_read = 0, chunk = min(to_rcv, maxreadsize); - status = nfs41_read(session, file, stateid, + status = nfs41_read(session, &state->file, &stateid, offset + reloffset, chunk, p, &bytes_read, &eof); if (status == NFS4ERR_OPENMODE && !len) { - stateid = &special_read_stateid; + stateid.type = STATEID_SPECIAL; + memcpy(&stateid.stateid, &special_read_stateid, sizeof(stateid4)); continue; } else if (status && !len) { status = nfs_to_windows_error(status, ERROR_NET_WRITE_FAULT); @@ -114,7 +117,6 @@ out: static int read_from_pnfs( IN nfs41_root *root, IN nfs41_open_state *state, - IN stateid4 *stateid, IN uint64_t offset, IN uint32_t length, OUT unsigned char *buffer, @@ -131,7 +133,7 @@ static int read_from_pnfs( goto out; } - pnfsstat = pnfs_read(root, state->session, &state->file, stateid, + pnfsstat = pnfs_read(root, state->session, state, layout, offset, length, buffer, len_out); switch (pnfsstat) { case PNFS_SUCCESS: @@ -149,18 +151,12 @@ out: static int handle_read(nfs41_upcall *upcall) { - stateid4 stateid, *pstateid; readwrite_upcall_args *args = &upcall->args.rw; - nfs41_open_state *state = args->state; ULONG pnfs_bytes_read = 0; int status = NO_ERROR; - pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid); - if (pstateid == NULL) - pstateid = &state->stateid; - #ifdef PNFS_ENABLE_READ - status = read_from_pnfs(args->root, state, pstateid, + status = read_from_pnfs(args->root, args->state, args->offset, args->len, args->buffer, &args->out_len); if (status == NO_ERROR || status == ERROR_HANDLE_EOF) @@ -176,7 +172,7 @@ static int handle_read(nfs41_upcall *upcall) } #endif - status = read_from_mds(state->session, pstateid, &state->file, + status = read_from_mds(args->state->session, args->state, args->offset, args->len, args->buffer, &args->out_len); args->out_len += pnfs_bytes_read; @@ -188,20 +184,22 @@ out: /* NFS41_WRITE */ static int write_to_mds( IN nfs41_session *session, - IN stateid4 *stateid, - IN nfs41_path_fh *file, + IN nfs41_open_state *state, IN uint64_t offset, IN uint32_t length, IN unsigned char *buffer, OUT ULONG *len_out) { + stateid_arg stateid; nfs41_write_verf verf; enum stable_how4 stable, committed; unsigned char *p; - const uint32_t maxwritesize = max_write_size(session, &file->fh); + const uint32_t maxwritesize = max_write_size(session, &state->file.fh); uint32_t to_send, reloffset, len; int status = 0; + nfs41_lock_stateid_arg(state, &stateid); + retry_write: p = buffer; to_send = length; @@ -217,7 +215,7 @@ retry_write: while(to_send > 0) { uint32_t bytes_written = 0, chunk = min(to_send, maxwritesize); - status = nfs41_write(session, file, stateid, p, chunk, + status = nfs41_write(session, &state->file, &stateid, p, chunk, offset + reloffset, stable, &bytes_written, &verf); if (status && !len) goto out; @@ -234,7 +232,7 @@ retry_write: } if (committed == UNSTABLE4) { dprintf(1, "sending COMMIT for offset=%d and len=%d\n", offset, len); - status = nfs41_commit(session, file, offset, len, 1); + status = nfs41_commit(session, &state->file, offset, len, 1); } out: *len_out = len; @@ -244,7 +242,6 @@ out: static int write_to_pnfs( IN nfs41_root *root, IN nfs41_open_state *state, - IN stateid4 *stateid, IN uint64_t offset, IN uint32_t length, IN unsigned char *buffer, @@ -261,7 +258,7 @@ static int write_to_pnfs( goto out; } - pnfsstat = pnfs_write(root, state->session, &state->file, stateid, + pnfsstat = pnfs_write(root, state->session, state, layout, offset, length, buffer, len_out); if (pnfsstat) { status = ERROR_WRITE_FAULT; @@ -273,18 +270,12 @@ out: static int handle_write(nfs41_upcall *upcall) { - stateid4 stateid, *pstateid = NULL; readwrite_upcall_args *args = &upcall->args.rw; - nfs41_open_state *state = args->state; ULONG pnfs_bytes_written = 0; int status; - pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid); - if (pstateid == NULL) - pstateid = &state->stateid; - #ifdef PNFS_ENABLE_WRITE - status = write_to_pnfs(args->root, args->state, pstateid, + status = write_to_pnfs(args->root, args->state, args->offset, args->len, args->buffer, &args->out_len); if (status == NO_ERROR) @@ -300,7 +291,7 @@ static int handle_write(nfs41_upcall *upcall) } #endif - status = write_to_mds(state->session, pstateid, &state->file, + status = write_to_mds(args->state->session, args->state, args->offset, args->len, args->buffer, &args->out_len); args->out_len += pnfs_bytes_written; diff --git a/daemon/setattr.c b/daemon/setattr.c index adb5f37..82ed115 100644 --- a/daemon/setattr.c +++ b/daemon/setattr.c @@ -101,13 +101,11 @@ static int handle_nfs41_setattr(setattr_upcall_args *args) PFILE_BASIC_INFO basic_info = (PFILE_BASIC_INFO)args->buf; nfs41_open_state *state = args->state; nfs41_superblock *superblock = state->file.fh.superblock; - stateid4 stateid, *pstateid; + stateid_arg stateid; nfs41_file_info info; int status = NO_ERROR; - pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid); - if (pstateid == NULL) - pstateid = &state->stateid; + nfs41_lock_stateid_arg(state, &stateid); ZeroMemory(&info, sizeof(info)); @@ -159,7 +157,7 @@ static int handle_nfs41_setattr(setattr_upcall_args *args) if (!info.attrmask.count) goto out; - status = nfs41_setattr(state->session, &state->file, pstateid, &info); + status = nfs41_setattr(state->session, &state->file, &stateid, &info); if (status) { dprintf(1, "nfs41_setattr() failed with error %s.\n", nfs_error_string(status)); @@ -313,18 +311,15 @@ out: static int handle_nfs41_set_size(setattr_upcall_args *args) { - nfs41_open_state *state = args->state; - int status; - + nfs41_file_info info; + stateid_arg stateid; /* note: this is called with either FILE_END_OF_FILE_INFO or * FILE_ALLOCATION_INFO, both of which contain a single LARGE_INTEGER */ PLARGE_INTEGER size = (PLARGE_INTEGER)args->buf; - stateid4 stateid, *pstateid; - nfs41_file_info info; + nfs41_open_state *state = args->state; + int status; - pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid); - if (pstateid == NULL) - pstateid = &state->stateid; + nfs41_lock_stateid_arg(state, &stateid); ZeroMemory(&info, sizeof(info)); info.size = size->QuadPart; @@ -333,7 +328,7 @@ static int handle_nfs41_set_size(setattr_upcall_args *args) info.attrmask.arr[0] = FATTR4_WORD0_SIZE; dprintf(2, "calling setattr() with size=%lld\n", info.size); - status = nfs41_setattr(state->session, &state->file, pstateid, &info); + status = nfs41_setattr(state->session, &state->file, &stateid, &info); if (status) dprintf(1, "nfs41_setattr() failed with error %s.\n", nfs_error_string(status)); @@ -518,12 +513,10 @@ static int handle_setexattr(nfs41_upcall *upcall) int status; setexattr_upcall_args *args = &upcall->args.setexattr; nfs41_open_state *state = args->state; - stateid4 stateid, *pstateid; + stateid_arg stateid; nfs41_file_info info; - pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid); - if (pstateid == NULL) - pstateid = &state->stateid; + nfs41_lock_stateid_arg(state, &stateid); ZeroMemory(&info, sizeof(info)); @@ -532,7 +525,7 @@ static int handle_setexattr(nfs41_upcall *upcall) info.attrmask.arr[1] |= FATTR4_WORD1_MODE; info.attrmask.count = 2; - status = nfs41_setattr(state->session, &state->file, pstateid, &info); + status = nfs41_setattr(state->session, &state->file, &stateid, &info); if (status) dprintf(1, "nfs41_setattr() failed with error %s.\n", nfs_error_string(status));