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 <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2011-07-05 10:23:33 -04:00 committed by unknown
parent 2b5a5fb071
commit 0c874a66ba
7 changed files with 187 additions and 182 deletions

View file

@ -442,10 +442,13 @@ void nfs41_open_stateid_arg(
IN nfs41_open_state *state, IN nfs41_open_state *state,
OUT struct __stateid_arg *arg); OUT struct __stateid_arg *arg);
void client_state_add( int nfs41_open(
IN nfs41_open_state *state); IN OUT nfs41_open_state *state,
void client_state_remove( IN uint32_t create,
IN nfs41_open_state *state); IN uint32_t createhow,
IN uint32_t mode,
IN bool_t try_recovery,
OUT OPTIONAL nfs41_file_info *info);
/* lock.c */ /* lock.c */
void nfs41_lock_stateid_arg( void nfs41_lock_stateid_arg(

View file

@ -131,14 +131,20 @@ static int recover_open(
IN nfs41_session *session, IN nfs41_session *session,
IN nfs41_open_state *open) IN nfs41_open_state *open)
{ {
open_claim4 claim;
open_delegation4 delegation;
stateid_arg stateid; stateid_arg stateid;
struct list_entry *entry; struct list_entry *entry;
nfs41_lock_state *lock; nfs41_lock_state *lock;
int status; int status;
/* reclaim the open stateid */ /* reclaim the open stateid */
status = nfs41_open_reclaim(session, &open->parent, &open->file, claim.claim = CLAIM_PREVIOUS;
&open->owner, open->share_access, open->share_deny, &stateid.stateid); 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) { if (status == NFS4_OK) {
/* update the open stateid on success */ /* update the open stateid on success */
@ -146,8 +152,7 @@ static int recover_open(
} else if (status == NFS4ERR_NO_GRACE) { } else if (status == NFS4ERR_NO_GRACE) {
dprintf(1, "not in grace period, retrying a normal open\n"); dprintf(1, "not in grace period, retrying a normal open\n");
status = nfs41_open(session, open->share_access, status = nfs41_open(open, OPEN4_NOCREATE, 0, 0, FALSE, NULL);
open->share_deny, OPEN4_NOCREATE, 0, 0, FALSE, open, NULL);
/* update the stateid arg with the new open->stateid */ /* update the stateid arg with the new open->stateid */
memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4)); memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4));
@ -610,7 +615,7 @@ restart_recovery:
} else if (op == OP_OPEN) { } else if (op == OP_OPEN) {
nfs41_op_open_args *oargs = (nfs41_op_open_args *) nfs41_op_open_args *oargs = (nfs41_op_open_args *)
compound->args.argarray[compound->res.resarray_count-1].arg; 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); secinfo_status = nfs41_secinfo(session, file, name, secinfo);
if (secinfo_status) { if (secinfo_status) {

View file

@ -302,15 +302,20 @@ out:
return status; return status;
} }
int nfs41_open( int nfs41_rpc_open(
IN nfs41_session *session, 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 allow,
IN uint32_t deny, IN uint32_t deny,
IN uint32_t create, IN uint32_t create,
IN uint32_t how_mode, IN uint32_t how_mode,
IN uint32_t mode, IN uint32_t mode,
IN bool_t try_recovery, IN bool_t try_recovery,
IN OUT nfs41_open_state *state, OUT stateid4 *stateid,
OUT open_delegation4 *delegation,
OUT OPTIONAL nfs41_file_info *info) OUT OPTIONAL nfs41_file_info *info)
{ {
int status; int status;
@ -319,8 +324,8 @@ int nfs41_open(
nfs_resop4 resops[8]; nfs_resop4 resops[8];
nfs41_sequence_args sequence_args; nfs41_sequence_args sequence_args;
nfs41_sequence_res sequence_res; nfs41_sequence_res sequence_res;
nfs41_putfh_args putfh_args; nfs41_putfh_args putfh_args[2];
nfs41_putfh_res putfh_res; nfs41_putfh_res putfh_res[2];
nfs41_op_open_args open_args; nfs41_op_open_args open_args;
nfs41_op_open_res open_res; nfs41_op_open_res open_res;
nfs41_getfh_res getfh_res; nfs41_getfh_res getfh_res;
@ -330,7 +335,28 @@ int nfs41_open(
nfs41_savefh_res savefh_res; nfs41_savefh_res savefh_res;
nfs41_restorefh_res restorefh_res; nfs41_restorefh_res restorefh_res;
nfs41_file_info tmp_info, dir_info; 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) if (info == NULL)
info = &tmp_info; info = &tmp_info;
@ -345,11 +371,19 @@ int nfs41_open(
if (status) if (status)
goto out; goto out;
compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res); if (current_fh_is_dir) {
putfh_args.file = &state->parent; /* CURRENT_FH: directory */
putfh_args.in_recovery = 0; 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); compound_add_op(&compound, OP_OPEN, &open_args, &open_res);
open_args.seqid = 0; open_args.seqid = 0;
@ -359,7 +393,7 @@ int nfs41_open(
open_args.share_access = allow; open_args.share_access = allow;
#endif #endif
open_args.share_deny = deny; open_args.share_deny = deny;
open_args.owner = &state->owner; open_args.owner = owner;
open_args.openhow.opentype = create; open_args.openhow.opentype = create;
open_args.openhow.how.mode = how_mode; open_args.openhow.how.mode = how_mode;
open_args.openhow.how.createattrs.info.attrmask.count = 2; open_args.openhow.how.createattrs.info.attrmask.count = 2;
@ -369,23 +403,30 @@ int nfs41_open(
open_args.openhow.how.createattrs.info.size = 0; open_args.openhow.how.createattrs.info.size = 0;
if (how_mode == EXCLUSIVE4_1) { if (how_mode == EXCLUSIVE4_1) {
DWORD tid = GetCurrentThreadId(); DWORD tid = GetCurrentThreadId();
open_args.openhow.how.createverf = createverf;
time((time_t*)open_args.openhow.how.createverf); time((time_t*)open_args.openhow.how.createverf);
memcpy(open_args.openhow.how.createverf+4, &tid, sizeof(tid)); memcpy(open_args.openhow.how.createverf+4, &tid, sizeof(tid));
} }
open_args.claim.claim = CLAIM_NULL; open_args.claim = claim;
open_args.claim.u.null.filename = &state->file.name; open_res.resok4.stateid = stateid;
open_res.resok4.stateid = &state->stateid; open_res.resok4.delegation = delegation;
compound_add_op(&compound, OP_GETFH, NULL, &getfh_res); if (current_fh_is_dir) {
getfh_res.fh = &state->file.fh; compound_add_op(&compound, OP_GETFH, NULL, &getfh_res);
getfh_res.fh = &file->fh;
}
compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res); compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
getattr_args.attr_request = &attr_request; getattr_args.attr_request = &attr_request;
getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
getattr_res.info = info; 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); compound_add_op(&compound, OP_GETATTR, &getattr_args, &pgetattr_res);
getattr_args.attr_request = &attr_request; getattr_args.attr_request = &attr_request;
@ -400,123 +441,28 @@ int nfs41_open(
goto out; goto out;
/* fill in the file handle's fileid and superblock */ /* fill in the file handle's fileid and superblock */
state->file.fh.fileid = info->fileid; file->fh.fileid = info->fileid;
status = nfs41_superblock_for_fh(session, status = nfs41_superblock_for_fh(session, &info->fsid, &parent->fh, file);
&info->fsid, &state->parent.fh, &state->file);
if (status) if (status)
goto out; 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 */ /* update the attributes of the parent directory */
memcpy(&dir_info.attrmask, &pgetattr_res.obj_attributes.attrmask, memcpy(&dir_info.attrmask, &pgetattr_res.obj_attributes.attrmask,
sizeof(bitmap4)); sizeof(bitmap4));
nfs41_attr_cache_update(session_name_cache(session), nfs41_attr_cache_update(session_name_cache(session),
parent->fh.fileid, &dir_info); parent->fh.fileid, &dir_info);
/* update the attributes of the file */ /* add the file handle and attributes to the name cache */
memcpy(&info.attrmask, &getattr_res.obj_attributes.attrmask, memcpy(&info->attrmask, &getattr_res.obj_attributes.attrmask,
sizeof(bitmap4)); sizeof(bitmap4));
nfs41_attr_cache_update(session_name_cache(session), AcquireSRWLockShared(&file->path->lock);
file->fh.fileid, &info); 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: out:
return status; return status;
} }

View file

@ -546,7 +546,7 @@ enum createmode4 {
typedef struct __createhow4 { typedef struct __createhow4 {
uint32_t mode; uint32_t mode;
createattrs4 createattrs; createattrs4 createattrs;
unsigned char *createverf; unsigned char createverf[NFS4_VERIFIER_SIZE];
} createhow4; } createhow4;
enum opentype4 { enum opentype4 {
@ -620,8 +620,21 @@ typedef struct __open_claim4 {
} null; } null;
/* case CLAIM_PREVIOUS: */ /* case CLAIM_PREVIOUS: */
struct __open_claim_prev { struct __open_claim_prev {
uint32_t delegate_type; uint32_t delegate_type;
} prev; } 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; } u;
} open_claim4; } open_claim4;
@ -631,7 +644,7 @@ typedef struct __nfs41_op_open_args {
uint32_t share_deny; uint32_t share_deny;
state_owner4 *owner; state_owner4 *owner;
openflag4 openhow; openflag4 openhow;
open_claim4 claim; open_claim4 *claim;
} nfs41_op_open_args; } nfs41_op_open_args;
enum { enum {
@ -646,8 +659,7 @@ typedef struct __nfs41_op_open_res_ok {
change_info4 cinfo; change_info4 cinfo;
uint32_t rflags; uint32_t rflags;
bitmap4 attrset; bitmap4 attrset;
uint32_t delegation_type; open_delegation4 *delegation;
stateid4 deleg_stateid;
uint32_t why_no_deleg; uint32_t why_no_deleg;
uint32_t why_none_flag; uint32_t why_none_flag;
} nfs41_op_open_res_ok; } nfs41_op_open_res_ok;
@ -985,26 +997,22 @@ int nfs41_lookup(
OUT OPTIONAL nfs41_file_info *info_out, OUT OPTIONAL nfs41_file_info *info_out,
OUT nfs41_session **session_out); OUT nfs41_session **session_out);
int nfs41_open( int nfs41_rpc_open(
IN nfs41_session *session, 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 allow,
IN uint32_t deny, IN uint32_t deny,
IN uint32_t create, IN uint32_t create,
IN uint32_t how_mode, IN uint32_t how_mode,
IN uint32_t mode, IN uint32_t mode,
IN bool_t try_recovery, IN bool_t try_recovery,
IN OUT nfs41_open_state *state, OUT stateid4 *stateid,
OUT open_delegation4 *delegation,
OUT OPTIONAL nfs41_file_info *info); 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( int nfs41_create(
IN nfs41_session *session, IN nfs41_session *session,
IN uint32_t type, IN uint32_t type,

View file

@ -137,6 +137,13 @@ typedef struct __stateid4 {
unsigned char other[NFS4_STATEID_OTHER]; unsigned char other[NFS4_STATEID_OTHER];
} stateid4; } stateid4;
typedef struct __open_delegation4 {
stateid4 stateid;
nfsace4 permissions;
enum open_delegation_type4 type;
bool_t recalled;
} open_delegation4;
typedef struct __fattr4 { typedef struct __fattr4 {
bitmap4 attrmask; bitmap4 attrmask;
uint32_t attr_vals_len; uint32_t attr_vals_len;

View file

@ -1899,33 +1899,45 @@ static bool_t encode_openflag4(
return result; 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( static bool_t encode_open_claim4(
XDR *xdr, XDR *xdr,
open_claim4 *oc) open_claim4 *oc)
{ {
bool_t result = TRUE;
if (!xdr_u_int32_t(xdr, &oc->claim)) if (!xdr_u_int32_t(xdr, &oc->claim))
return FALSE; return FALSE;
switch (oc->claim) switch (oc->claim)
{ {
case CLAIM_NULL: case CLAIM_NULL:
result = encode_component(xdr, oc->u.null.filename); return encode_component(xdr, oc->u.null.filename);
break;
case CLAIM_PREVIOUS: case CLAIM_PREVIOUS:
result = xdr_u_int32_t(xdr, &oc->u.prev.delegate_type); return xdr_u_int32_t(xdr, &oc->u.prev.delegate_type);
break;
case CLAIM_FH: case CLAIM_FH:
/* use current file handle */ return TRUE; /* use current file handle */
break; 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: default:
eprintf("encode_open_claim4: unsupported claim %d.\n", eprintf("encode_open_claim4: unsupported claim %d.\n",
oc->claim); oc->claim);
result = FALSE; return FALSE;
break;
} }
return result;
} }
static bool_t encode_op_open( static bool_t encode_op_open(
@ -1952,7 +1964,7 @@ static bool_t encode_op_open(
if (!encode_openflag4(xdr, &args->openhow)) if (!encode_openflag4(xdr, &args->openhow))
return FALSE; return FALSE;
return encode_open_claim4(xdr, &args->claim); return encode_open_claim4(xdr, args->claim);
} }
static bool_t decode_open_none_delegation4( 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( static bool_t decode_open_read_delegation4(
XDR *xdr, XDR *xdr,
nfs41_op_open_res_ok *res) open_delegation4 *delegation)
{ {
bool_t tmp_bool; bool_t tmp_bool;
nfsace4 tmp_nfsace;
if (!xdr_stateid4(xdr, &res->deleg_stateid)) if (!xdr_stateid4(xdr, &delegation->stateid))
return FALSE; return FALSE;
if (!xdr_bool(xdr, &tmp_bool)) if (!xdr_bool(xdr, &tmp_bool))
return FALSE; return FALSE;
return xdr_nfsace4(xdr, &tmp_nfsace); return xdr_nfsace4(xdr, &delegation->permissions);
} }
static bool_t decode_modified_limit4( static bool_t decode_modified_limit4(
@ -2034,12 +2045,11 @@ static bool_t decode_space_limit4(
static bool_t decode_open_write_delegation4( static bool_t decode_open_write_delegation4(
XDR *xdr, XDR *xdr,
nfs41_op_open_res_ok *res) open_delegation4 *delegation)
{ {
bool_t tmp_bool; bool_t tmp_bool;
nfsace4 tmp_nfsace;
if (!xdr_stateid4(xdr, &res->deleg_stateid)) if (!xdr_stateid4(xdr, &delegation->stateid))
return FALSE; return FALSE;
if (!xdr_bool(xdr, &tmp_bool)) if (!xdr_bool(xdr, &tmp_bool))
@ -2048,7 +2058,7 @@ static bool_t decode_open_write_delegation4(
if (!decode_space_limit4(xdr)) if (!decode_space_limit4(xdr))
return FALSE; return FALSE;
return xdr_nfsace4(xdr, &tmp_nfsace); return xdr_nfsace4(xdr, &delegation->permissions);
} }
static bool_t decode_open_res_ok( static bool_t decode_open_res_ok(
@ -2069,10 +2079,10 @@ static bool_t decode_open_res_ok(
if (!xdr_bitmap4(xdr, &res->attrset)) if (!xdr_bitmap4(xdr, &res->attrset))
return FALSE; return FALSE;
if (!xdr_u_int32_t(xdr, &res->delegation_type)) if (!xdr_enum(xdr, (enum_t*)&res->delegation->type))
return FALSE; return FALSE;
switch (res->delegation_type) switch (res->delegation->type)
{ {
case OPEN_DELEGATE_NONE: case OPEN_DELEGATE_NONE:
break; break;
@ -2080,14 +2090,14 @@ static bool_t decode_open_res_ok(
result = decode_open_none_delegation4(xdr, res); result = decode_open_none_delegation4(xdr, res);
break; break;
case OPEN_DELEGATE_READ: case OPEN_DELEGATE_READ:
result = decode_open_read_delegation4(xdr, res); result = decode_open_read_delegation4(xdr, res->delegation);
break; break;
case OPEN_DELEGATE_WRITE: case OPEN_DELEGATE_WRITE:
result = decode_open_write_delegation4(xdr, res); result = decode_open_write_delegation4(xdr, res->delegation);
break; break;
default: default:
eprintf("decode_open_res_ok: delegation type %d not " eprintf("decode_open_res_ok: delegation type %d not "
"supported.\n", res->delegation_type); "supported.\n", res->delegation->type);
result = FALSE; result = FALSE;
break; break;
} }

View file

@ -139,6 +139,38 @@ void client_state_remove(
LeaveCriticalSection(&client->state.lock); 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 */ /* NFS41_OPEN */
static int parse_open(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall) 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->std_info.Directory = 1;
args->created = status == NFS4_OK ? TRUE : FALSE; args->created = status == NFS4_OK ? TRUE : FALSE;
} else { } else {
status = nfs41_open(state->session, state->share_access, status = nfs41_open(state, create, createhowmode,
state->share_deny, create, createhowmode, args->mode, args->mode, TRUE, &info);
TRUE, state, &info);
if (status == NFS4_OK) { 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_basic_info(&info, &args->basic_info);
nfs_to_standard_info(&info, &args->std_info); nfs_to_standard_info(&info, &args->std_info);
state->do_close = 1;
args->mode = info.mode; args->mode = info.mode;
} }
} }