From 0c874a66ba722e4dd5bb5f444c1193997e34d942 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Tue, 5 Jul 2011 10:23:33 -0400 Subject: [PATCH] open: nfs41_rpc_open() takes open_claim4 and open_delegation4 combined nfs41_open() and nfs41_open_reclaim() into nfs41_rpc_open() by factoring out the open_claim4 argument. new function nfs41_open() in open.c deals with the nfs41_open_state, adding it to the client's list, and handles any delegations granted added xdr for OPEN CLAIM types CLAIM_DELEGATE_CUR, CLAIM_DELEG_CUR_FH, CLAIM_DELEGATE_PREV, CLAIM_DELEG_PREV_FH (the _FH types are new to 4.1, and not supported by linux server) Signed-off-by: Casey Bodley --- daemon/nfs41.h | 11 ++- daemon/nfs41_compound.c | 15 ++-- daemon/nfs41_ops.c | 194 +++++++++++++++------------------------- daemon/nfs41_ops.h | 40 +++++---- daemon/nfs41_types.h | 7 ++ daemon/nfs41_xdr.c | 60 +++++++------ daemon/open.c | 42 +++++++-- 7 files changed, 187 insertions(+), 182 deletions(-) diff --git a/daemon/nfs41.h b/daemon/nfs41.h index 057488f..9dce6cf 100644 --- a/daemon/nfs41.h +++ b/daemon/nfs41.h @@ -442,10 +442,13 @@ void nfs41_open_stateid_arg( IN nfs41_open_state *state, OUT struct __stateid_arg *arg); -void client_state_add( - IN nfs41_open_state *state); -void client_state_remove( - IN nfs41_open_state *state); +int nfs41_open( + IN OUT nfs41_open_state *state, + IN uint32_t create, + IN uint32_t createhow, + IN uint32_t mode, + IN bool_t try_recovery, + OUT OPTIONAL nfs41_file_info *info); /* lock.c */ void nfs41_lock_stateid_arg( diff --git a/daemon/nfs41_compound.c b/daemon/nfs41_compound.c index dbde059..520cfb1 100644 --- a/daemon/nfs41_compound.c +++ b/daemon/nfs41_compound.c @@ -131,14 +131,20 @@ static int recover_open( IN nfs41_session *session, IN nfs41_open_state *open) { + open_claim4 claim; + open_delegation4 delegation; stateid_arg stateid; struct list_entry *entry; nfs41_lock_state *lock; int status; /* reclaim the open stateid */ - status = nfs41_open_reclaim(session, &open->parent, &open->file, - &open->owner, open->share_access, open->share_deny, &stateid.stateid); + claim.claim = CLAIM_PREVIOUS; + claim.u.prev.delegate_type = OPEN_DELEGATE_NONE; + + status = nfs41_rpc_open(session, &open->parent, &open->file, + &open->owner, &claim, open->share_access, open->share_deny, + OPEN4_NOCREATE, 0, 0, FALSE, &stateid.stateid, &delegation, NULL); if (status == NFS4_OK) { /* update the open stateid on success */ @@ -146,8 +152,7 @@ static int recover_open( } else if (status == NFS4ERR_NO_GRACE) { dprintf(1, "not in grace period, retrying a normal open\n"); - status = nfs41_open(session, open->share_access, - open->share_deny, OPEN4_NOCREATE, 0, 0, FALSE, open, NULL); + status = nfs41_open(open, OPEN4_NOCREATE, 0, 0, FALSE, NULL); /* update the stateid arg with the new open->stateid */ memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4)); @@ -610,7 +615,7 @@ restart_recovery: } else if (op == OP_OPEN) { nfs41_op_open_args *oargs = (nfs41_op_open_args *) compound->args.argarray[compound->res.resarray_count-1].arg; - name = oargs->claim.u.null.filename; + name = oargs->claim->u.null.filename; } secinfo_status = nfs41_secinfo(session, file, name, secinfo); if (secinfo_status) { diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c index 3be2a51..64e10ce 100644 --- a/daemon/nfs41_ops.c +++ b/daemon/nfs41_ops.c @@ -302,15 +302,20 @@ out: return status; } -int nfs41_open( +int nfs41_rpc_open( IN nfs41_session *session, + IN nfs41_path_fh *parent, + IN nfs41_path_fh *file, + IN state_owner4 *owner, + IN open_claim4 *claim, IN uint32_t allow, IN uint32_t deny, IN uint32_t create, IN uint32_t how_mode, IN uint32_t mode, IN bool_t try_recovery, - IN OUT nfs41_open_state *state, + OUT stateid4 *stateid, + OUT open_delegation4 *delegation, OUT OPTIONAL nfs41_file_info *info) { int status; @@ -319,8 +324,8 @@ int nfs41_open( nfs_resop4 resops[8]; nfs41_sequence_args sequence_args; nfs41_sequence_res sequence_res; - nfs41_putfh_args putfh_args; - nfs41_putfh_res putfh_res; + nfs41_putfh_args putfh_args[2]; + nfs41_putfh_res putfh_res[2]; nfs41_op_open_args open_args; nfs41_op_open_res open_res; nfs41_getfh_res getfh_res; @@ -330,7 +335,28 @@ int nfs41_open( nfs41_savefh_res savefh_res; nfs41_restorefh_res restorefh_res; nfs41_file_info tmp_info, dir_info; - unsigned char createverf[NFS4_VERIFIER_SIZE]; + bool_t current_fh_is_dir; + + /* depending on the claim type, OPEN expects CURRENT_FH set + * to either the parent directory, or to the file itself */ + switch (claim->claim) { + case CLAIM_NULL: + case CLAIM_DELEGATE_CUR: + case CLAIM_DELEGATE_PREV: + /* CURRENT_FH: directory */ + current_fh_is_dir = TRUE; + /* SEQUENCE; PUTFH(dir); SAVEFH; OPEN; + * GETFH(file); GETATTR(file); RESTOREFH(dir); GETATTR */ + break; + case CLAIM_PREVIOUS: + case CLAIM_FH: + case CLAIM_DELEG_CUR_FH: + case CLAIM_DELEG_PREV_FH: + /* CURRENT_FH: file being opened */ + current_fh_is_dir = FALSE; + /* SEQUENCE; PUTFH(file); OPEN; GETATTR(file); PUTFH(dir); GETATTR */ + break; + } if (info == NULL) info = &tmp_info; @@ -345,11 +371,19 @@ int nfs41_open( if (status) goto out; - compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res); - putfh_args.file = &state->parent; - putfh_args.in_recovery = 0; + if (current_fh_is_dir) { + /* CURRENT_FH: directory */ + compound_add_op(&compound, OP_PUTFH, &putfh_args[0], &putfh_res[0]); + putfh_args[0].file = parent; + putfh_args[0].in_recovery = 0; - compound_add_op(&compound, OP_SAVEFH, NULL, &savefh_res); + compound_add_op(&compound, OP_SAVEFH, NULL, &savefh_res); + } else { + /* CURRENT_FH: file being opened */ + compound_add_op(&compound, OP_PUTFH, &putfh_args[0], &putfh_res[0]); + putfh_args[0].file = file; + putfh_args[0].in_recovery = 0; + } compound_add_op(&compound, OP_OPEN, &open_args, &open_res); open_args.seqid = 0; @@ -359,7 +393,7 @@ int nfs41_open( open_args.share_access = allow; #endif open_args.share_deny = deny; - open_args.owner = &state->owner; + open_args.owner = owner; open_args.openhow.opentype = create; open_args.openhow.how.mode = how_mode; open_args.openhow.how.createattrs.info.attrmask.count = 2; @@ -369,23 +403,30 @@ int nfs41_open( open_args.openhow.how.createattrs.info.size = 0; if (how_mode == EXCLUSIVE4_1) { DWORD tid = GetCurrentThreadId(); - open_args.openhow.how.createverf = createverf; time((time_t*)open_args.openhow.how.createverf); memcpy(open_args.openhow.how.createverf+4, &tid, sizeof(tid)); } - open_args.claim.claim = CLAIM_NULL; - open_args.claim.u.null.filename = &state->file.name; - open_res.resok4.stateid = &state->stateid; + open_args.claim = claim; + open_res.resok4.stateid = stateid; + open_res.resok4.delegation = delegation; - compound_add_op(&compound, OP_GETFH, NULL, &getfh_res); - getfh_res.fh = &state->file.fh; + if (current_fh_is_dir) { + compound_add_op(&compound, OP_GETFH, NULL, &getfh_res); + getfh_res.fh = &file->fh; + } compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res); getattr_args.attr_request = &attr_request; getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; getattr_res.info = info; - compound_add_op(&compound, OP_RESTOREFH, NULL, &restorefh_res); + if (current_fh_is_dir) { + compound_add_op(&compound, OP_RESTOREFH, NULL, &restorefh_res); + } else { + compound_add_op(&compound, OP_PUTFH, &putfh_args[1], &putfh_res[1]); + putfh_args[1].file = parent; + putfh_args[1].in_recovery = 0; + } compound_add_op(&compound, OP_GETATTR, &getattr_args, &pgetattr_res); getattr_args.attr_request = &attr_request; @@ -400,123 +441,28 @@ int nfs41_open( goto out; /* fill in the file handle's fileid and superblock */ - state->file.fh.fileid = info->fileid; - status = nfs41_superblock_for_fh(session, - &info->fsid, &state->parent.fh, &state->file); + file->fh.fileid = info->fileid; + status = nfs41_superblock_for_fh(session, &info->fsid, &parent->fh, file); if (status) goto out; - /* update the attributes of the parent directory */ - memcpy(&dir_info.attrmask, &pgetattr_res.obj_attributes.attrmask, - sizeof(bitmap4)); - nfs41_attr_cache_update(session_name_cache(session), - state->parent.fh.fileid, &dir_info); - - /* add the file handle and attributes to the name cache */ - memcpy(&info->attrmask, &getattr_res.obj_attributes.attrmask, - sizeof(bitmap4)); - AcquireSRWLockShared(&state->path.lock); - nfs41_name_cache_insert(session_name_cache(session), - state->path.path, &state->file.name, &state->file.fh, - info, &open_res.resok4.cinfo); - ReleaseSRWLockShared(&state->path.lock); - -#define RETURN_DELEG_ON_OPEN -#ifdef RETURN_DELEG_ON_OPEN - /* if the server gave us a delegation, return it immediately */ - if (open_res.resok4.delegation_type == OPEN_DELEGATE_READ || - open_res.resok4.delegation_type == OPEN_DELEGATE_WRITE) { - nfs41_delegreturn(session, &state->file, - &open_res.resok4.deleg_stateid); - } -#endif - - if (create == OPEN4_CREATE) - nfs41_superblock_space_changed(state->file.fh.superblock); -out: - return status; -} - -int nfs41_open_reclaim( - IN nfs41_session *session, - IN nfs41_path_fh *parent, - IN nfs41_path_fh *file, - IN state_owner4 *owner, - IN uint32_t allow, - IN uint32_t deny, - OUT stateid4 *stateid) -{ - int status; - nfs41_compound compound; - nfs_argop4 argops[6]; - nfs_resop4 resops[6]; - nfs41_sequence_args sequence_args; - nfs41_sequence_res sequence_res; - nfs41_putfh_args putfh_args[2]; - nfs41_putfh_res putfh_res[2]; - nfs41_op_open_args open_args; - nfs41_op_open_res open_res; - bitmap4 attr_request; - nfs41_getattr_args getattr_args; - nfs41_getattr_res getattr_res, pgetattr_res; - nfs41_file_info info, dir_info; - - init_getattr_request(&attr_request); - - compound_init(&compound, argops, resops, "open reclaim"); - - compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res); - status = nfs41_session_sequence(&sequence_args, session, 1); - if (status) - goto out; - - compound_add_op(&compound, OP_PUTFH, &putfh_args[0], &putfh_res[0]); - putfh_args[0].file = file; - putfh_args[0].in_recovery = 0; - - compound_add_op(&compound, OP_OPEN, &open_args, &open_res); - open_args.seqid = 0; - open_args.share_access = allow | OPEN4_SHARE_ACCESS_WANT_NO_DELEG; - open_args.share_deny = deny; - open_args.owner = owner; - open_args.openhow.opentype = OPEN4_NOCREATE; - open_args.claim.claim = CLAIM_PREVIOUS; - open_args.claim.u.prev.delegate_type = OPEN_DELEGATE_NONE; - open_res.resok4.stateid = stateid; - - compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res); - getattr_args.attr_request = &attr_request; - getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; - getattr_res.info = &info; - - compound_add_op(&compound, OP_PUTFH, &putfh_args[1], &putfh_res[1]); - putfh_args[1].file = parent; - putfh_args[1].in_recovery = 0; - - compound_add_op(&compound, OP_GETATTR, &getattr_args, &pgetattr_res); - getattr_args.attr_request = &attr_request; - pgetattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; - pgetattr_res.info = &dir_info; - - /* don't attempt to recover from BADSESSION errors */ - status = compound_encode_send_decode(session, &compound, FALSE); - if (status) - goto out; - - if (compound_error(status = compound.res.status)) - goto out; - /* update the attributes of the parent directory */ memcpy(&dir_info.attrmask, &pgetattr_res.obj_attributes.attrmask, sizeof(bitmap4)); nfs41_attr_cache_update(session_name_cache(session), parent->fh.fileid, &dir_info); - /* update the attributes of the file */ - memcpy(&info.attrmask, &getattr_res.obj_attributes.attrmask, + /* add the file handle and attributes to the name cache */ + memcpy(&info->attrmask, &getattr_res.obj_attributes.attrmask, sizeof(bitmap4)); - nfs41_attr_cache_update(session_name_cache(session), - file->fh.fileid, &info); + AcquireSRWLockShared(&file->path->lock); + nfs41_name_cache_insert(session_name_cache(session), + file->path->path, &file->name, &file->fh, + info, &open_res.resok4.cinfo); + ReleaseSRWLockShared(&file->path->lock); + + if (create == OPEN4_CREATE) + nfs41_superblock_space_changed(file->fh.superblock); out: return status; } diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h index 0bad64d..2ef876d 100644 --- a/daemon/nfs41_ops.h +++ b/daemon/nfs41_ops.h @@ -546,7 +546,7 @@ enum createmode4 { typedef struct __createhow4 { uint32_t mode; createattrs4 createattrs; - unsigned char *createverf; + unsigned char createverf[NFS4_VERIFIER_SIZE]; } createhow4; enum opentype4 { @@ -620,8 +620,21 @@ typedef struct __open_claim4 { } null; /* case CLAIM_PREVIOUS: */ struct __open_claim_prev { - uint32_t delegate_type; + uint32_t delegate_type; } prev; + /* case CLAIM_DELEGATE_CUR: */ + struct __open_claim_deleg_cur { + stateid4 *delegate_stateid; + nfs41_component *name; + } deleg_cur; + /* case CLAIM_DELEG_CUR_FH: */ + struct __open_claim_deleg_cur_fh { + stateid4 *delegate_stateid; + } deleg_cur_fh; + /* case CLAIM_DELEGATE_PREV: */ + struct __open_claim_deleg_prev { + const nfs41_component *filename; + } deleg_prev; } u; } open_claim4; @@ -631,7 +644,7 @@ typedef struct __nfs41_op_open_args { uint32_t share_deny; state_owner4 *owner; openflag4 openhow; - open_claim4 claim; + open_claim4 *claim; } nfs41_op_open_args; enum { @@ -646,8 +659,7 @@ typedef struct __nfs41_op_open_res_ok { change_info4 cinfo; uint32_t rflags; bitmap4 attrset; - uint32_t delegation_type; - stateid4 deleg_stateid; + open_delegation4 *delegation; uint32_t why_no_deleg; uint32_t why_none_flag; } nfs41_op_open_res_ok; @@ -985,26 +997,22 @@ int nfs41_lookup( OUT OPTIONAL nfs41_file_info *info_out, OUT nfs41_session **session_out); -int nfs41_open( +int nfs41_rpc_open( IN nfs41_session *session, + IN nfs41_path_fh *parent, + IN nfs41_path_fh *file, + IN state_owner4 *owner, + IN open_claim4 *claim, IN uint32_t allow, IN uint32_t deny, IN uint32_t create, IN uint32_t how_mode, IN uint32_t mode, IN bool_t try_recovery, - IN OUT nfs41_open_state *state, + OUT stateid4 *stateid, + OUT open_delegation4 *delegation, OUT OPTIONAL nfs41_file_info *info); -int nfs41_open_reclaim( - IN nfs41_session *session, - IN nfs41_path_fh *parent, - IN nfs41_path_fh *file, - IN state_owner4 *owner, - IN uint32_t allow, - IN uint32_t deny, - OUT stateid4 *stateid); - int nfs41_create( IN nfs41_session *session, IN uint32_t type, diff --git a/daemon/nfs41_types.h b/daemon/nfs41_types.h index 88c0abf..57851fd 100644 --- a/daemon/nfs41_types.h +++ b/daemon/nfs41_types.h @@ -137,6 +137,13 @@ typedef struct __stateid4 { unsigned char other[NFS4_STATEID_OTHER]; } stateid4; +typedef struct __open_delegation4 { + stateid4 stateid; + nfsace4 permissions; + enum open_delegation_type4 type; + bool_t recalled; +} open_delegation4; + typedef struct __fattr4 { bitmap4 attrmask; uint32_t attr_vals_len; diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c index 5284ea8..9857586 100644 --- a/daemon/nfs41_xdr.c +++ b/daemon/nfs41_xdr.c @@ -1899,33 +1899,45 @@ static bool_t encode_openflag4( return result; } +static bool_t encode_claim_deleg_cur( + XDR *xdr, + stateid4 *stateid, + nfs41_component *name) +{ + if (!xdr_stateid4(xdr, stateid)) + return FALSE; + return encode_component(xdr, name); +} + static bool_t encode_open_claim4( XDR *xdr, open_claim4 *oc) { - bool_t result = TRUE; - if (!xdr_u_int32_t(xdr, &oc->claim)) return FALSE; switch (oc->claim) { case CLAIM_NULL: - result = encode_component(xdr, oc->u.null.filename); - break; + return encode_component(xdr, oc->u.null.filename); case CLAIM_PREVIOUS: - result = xdr_u_int32_t(xdr, &oc->u.prev.delegate_type); - break; + return xdr_u_int32_t(xdr, &oc->u.prev.delegate_type); case CLAIM_FH: - /* use current file handle */ - break; + return TRUE; /* use current file handle */ + case CLAIM_DELEGATE_CUR: + return encode_claim_deleg_cur(xdr, + oc->u.deleg_cur.delegate_stateid, oc->u.deleg_cur.name); + case CLAIM_DELEG_CUR_FH: + return xdr_stateid4(xdr, oc->u.deleg_cur_fh.delegate_stateid); + case CLAIM_DELEGATE_PREV: + return encode_component(xdr, oc->u.deleg_prev.filename); + case CLAIM_DELEG_PREV_FH: + return TRUE; /* use current file handle */ default: eprintf("encode_open_claim4: unsupported claim %d.\n", oc->claim); - result = FALSE; - break; + return FALSE; } - return result; } static bool_t encode_op_open( @@ -1952,7 +1964,7 @@ static bool_t encode_op_open( if (!encode_openflag4(xdr, &args->openhow)) return FALSE; - return encode_open_claim4(xdr, &args->claim); + return encode_open_claim4(xdr, args->claim); } static bool_t decode_open_none_delegation4( @@ -1977,18 +1989,17 @@ static bool_t decode_open_none_delegation4( static bool_t decode_open_read_delegation4( XDR *xdr, - nfs41_op_open_res_ok *res) + open_delegation4 *delegation) { bool_t tmp_bool; - nfsace4 tmp_nfsace; - if (!xdr_stateid4(xdr, &res->deleg_stateid)) + if (!xdr_stateid4(xdr, &delegation->stateid)) return FALSE; if (!xdr_bool(xdr, &tmp_bool)) return FALSE; - return xdr_nfsace4(xdr, &tmp_nfsace); + return xdr_nfsace4(xdr, &delegation->permissions); } static bool_t decode_modified_limit4( @@ -2034,12 +2045,11 @@ static bool_t decode_space_limit4( static bool_t decode_open_write_delegation4( XDR *xdr, - nfs41_op_open_res_ok *res) + open_delegation4 *delegation) { bool_t tmp_bool; - nfsace4 tmp_nfsace; - if (!xdr_stateid4(xdr, &res->deleg_stateid)) + if (!xdr_stateid4(xdr, &delegation->stateid)) return FALSE; if (!xdr_bool(xdr, &tmp_bool)) @@ -2048,7 +2058,7 @@ static bool_t decode_open_write_delegation4( if (!decode_space_limit4(xdr)) return FALSE; - return xdr_nfsace4(xdr, &tmp_nfsace); + return xdr_nfsace4(xdr, &delegation->permissions); } static bool_t decode_open_res_ok( @@ -2069,10 +2079,10 @@ static bool_t decode_open_res_ok( if (!xdr_bitmap4(xdr, &res->attrset)) return FALSE; - if (!xdr_u_int32_t(xdr, &res->delegation_type)) + if (!xdr_enum(xdr, (enum_t*)&res->delegation->type)) return FALSE; - switch (res->delegation_type) + switch (res->delegation->type) { case OPEN_DELEGATE_NONE: break; @@ -2080,14 +2090,14 @@ static bool_t decode_open_res_ok( result = decode_open_none_delegation4(xdr, res); break; case OPEN_DELEGATE_READ: - result = decode_open_read_delegation4(xdr, res); + result = decode_open_read_delegation4(xdr, res->delegation); break; case OPEN_DELEGATE_WRITE: - result = decode_open_write_delegation4(xdr, res); + result = decode_open_write_delegation4(xdr, res->delegation); break; default: eprintf("decode_open_res_ok: delegation type %d not " - "supported.\n", res->delegation_type); + "supported.\n", res->delegation->type); result = FALSE; break; } diff --git a/daemon/open.c b/daemon/open.c index da1d834..f207726 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -139,6 +139,38 @@ void client_state_remove( LeaveCriticalSection(&client->state.lock); } +int nfs41_open( + IN OUT nfs41_open_state *state, + IN uint32_t create, + IN uint32_t createhow, + IN uint32_t mode, + IN bool_t try_recovery, + OUT OPTIONAL nfs41_file_info *info) +{ + open_claim4 claim; + open_delegation4 delegation = { 0 }; + int status; + + claim.claim = CLAIM_NULL; + claim.u.null.filename = &state->file.name; + + status = nfs41_rpc_open(state->session, &state->parent, &state->file, + &state->owner, &claim, state->share_access, state->share_deny, + create, createhow, mode, TRUE, &state->stateid, &delegation, info); + if (status) + goto out; + + if (delegation.type == OPEN_DELEGATE_READ || + delegation.type == OPEN_DELEGATE_WRITE) + nfs41_delegreturn(state->session, &state->file, &delegation.stateid); + + /* register the client's open state on success */ + client_state_add(state); + state->do_close = 1; +out: + return status; +} + /* NFS41_OPEN */ static int parse_open(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall) @@ -477,17 +509,11 @@ static int handle_open(nfs41_upcall *upcall) args->std_info.Directory = 1; args->created = status == NFS4_OK ? TRUE : FALSE; } else { - status = nfs41_open(state->session, state->share_access, - state->share_deny, create, createhowmode, args->mode, - TRUE, state, &info); - + status = nfs41_open(state, create, createhowmode, + args->mode, TRUE, &info); if (status == NFS4_OK) { - /* add to the client's list of state for recovery */ - client_state_add(state); - nfs_to_basic_info(&info, &args->basic_info); nfs_to_standard_info(&info, &args->std_info); - state->do_close = 1; args->mode = info.mode; } }