From 54c11cd84bcb59f6b05b05d65e9c081e52b53400 Mon Sep 17 00:00:00 2001 From: Olga Kornievskaia Date: Tue, 24 May 2011 12:33:58 -0400 Subject: [PATCH] ensuring exactly once semantics for open if we are doing CREATE_NEW file creation, then based on whether or not we have a persistent session, we'll send either GUARDED4 create for persistent session and EXCLUSIVE4_1 create otherwise. --- daemon/nfs41_compound.c | 2 +- daemon/nfs41_ops.c | 21 +++++++++++++++------ daemon/nfs41_ops.h | 18 ++++-------------- daemon/nfs41_xdr.c | 19 ++++++------------- daemon/open.c | 21 +++++++++++++++------ daemon/setattr.c | 2 +- 6 files changed, 42 insertions(+), 41 deletions(-) diff --git a/daemon/nfs41_compound.c b/daemon/nfs41_compound.c index d3dcedb..236a437 100644 --- a/daemon/nfs41_compound.c +++ b/daemon/nfs41_compound.c @@ -145,7 +145,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, FALSE, open, NULL); + open->share_deny, OPEN4_NOCREATE, 0, 0, FALSE, open, NULL); /* update the stateid arg with the new open->stateid */ memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4)); diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c index 94bab01..d1a6a90 100644 --- a/daemon/nfs41_ops.c +++ b/daemon/nfs41_ops.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "nfs41_ops.h" #include "nfs41_compound.h" @@ -302,6 +303,7 @@ int nfs41_open( 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, @@ -324,6 +326,7 @@ 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]; if (info == NULL) info = &tmp_info; @@ -354,12 +357,18 @@ int nfs41_open( open_args.share_deny = deny; open_args.owner = &state->owner; open_args.openhow.opentype = create; - open_args.openhow.how.mode = UNCHECKED4; - open_args.openhow.how.u.createattrs.info.attrmask.count = 2; - open_args.openhow.how.u.createattrs.info.attrmask.arr[0] = FATTR4_WORD0_SIZE; - open_args.openhow.how.u.createattrs.info.attrmask.arr[1] = FATTR4_WORD1_MODE; - open_args.openhow.how.u.createattrs.info.mode = mode; - open_args.openhow.how.u.createattrs.info.size = 0; + open_args.openhow.how.mode = how_mode; + open_args.openhow.how.createattrs.info.attrmask.count = 2; + open_args.openhow.how.createattrs.info.attrmask.arr[0] = FATTR4_WORD0_SIZE; + open_args.openhow.how.createattrs.info.attrmask.arr[1] = FATTR4_WORD1_MODE; + open_args.openhow.how.createattrs.info.mode = mode; + 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; diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h index 7936cc1..3b296f8 100644 --- a/daemon/nfs41_ops.h +++ b/daemon/nfs41_ops.h @@ -524,21 +524,10 @@ enum createmode4 { EXCLUSIVE4_1 = 3 }; -typedef struct __creatverfattr { - unsigned char cva_verf[NFS4_VERIFIER_SIZE]; - fattr4 cva_attrs; -} creatverfattr; - typedef struct __createhow4 { - uint32_t mode; - union { - /* case UNCHECKED4, GUARDED4: */ - createattrs4 createattrs; - /* case EXCLUSIVE4: */ - unsigned char createverf[NFS4_VERIFIER_SIZE]; - /* case EXCLUSIVE4_1: */ - creatverfattr ch_createboth; - } u; + uint32_t mode; + createattrs4 createattrs; + unsigned char *createverf; } createhow4; enum opentype4 { @@ -972,6 +961,7 @@ int nfs41_open( 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, diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c index d52ba42..4e84ee3 100644 --- a/daemon/nfs41_xdr.c +++ b/daemon/nfs41_xdr.c @@ -1835,16 +1835,6 @@ static bool_t decode_op_getattr( /* * OP_OPEN */ -static bool_t encode_creatverfattr( - XDR *xdr, - creatverfattr *cva) -{ - if (!xdr_opaque(xdr, (char *)cva->cva_verf, NFS4_VERIFIER_SIZE)) - return FALSE; - - return xdr_fattr4(xdr, &cva->cva_attrs); -} - static bool_t encode_createhow4( XDR *xdr, createhow4 *ch) @@ -1858,13 +1848,16 @@ static bool_t encode_createhow4( { case UNCHECKED4: case GUARDED4: - result = encode_createattrs4(xdr, &ch->u.createattrs); + result = encode_createattrs4(xdr, &ch->createattrs); break; case EXCLUSIVE4: - result = xdr_opaque(xdr, (char *)ch->u.createverf, NFS4_VERIFIER_SIZE); + result = xdr_opaque(xdr, (char *)ch->createverf, NFS4_VERIFIER_SIZE); break; case EXCLUSIVE4_1: - result = encode_creatverfattr(xdr, &ch->u.ch_createboth); + if (!xdr_opaque(xdr, (char *)ch->createverf, NFS4_VERIFIER_SIZE)) + return FALSE; + if (!encode_createattrs4(xdr, &ch->createattrs)) + return FALSE; break; } return result; diff --git a/daemon/open.c b/daemon/open.c index 5bcf7c1..b058613 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -199,8 +199,9 @@ static BOOLEAN do_lookup(uint32_t type, ULONG access_mask, ULONG disposition) } } -static int map_disposition_2_nfsopen(ULONG disposition, int in_status, - uint32_t *create, uint32_t *last_error) +static int map_disposition_2_nfsopen(ULONG disposition, int in_status, bool_t persistent, + uint32_t *create, uint32_t *createhowmode, + uint32_t *last_error) { int status = NO_ERROR; if (disposition == FILE_SUPERSEDE) { @@ -214,8 +215,13 @@ static int map_disposition_2_nfsopen(ULONG disposition, int in_status, // if lookup succeeded which means the file exist, return an error if (!in_status) status = ERROR_FILE_EXISTS; - else + else { *create = OPEN4_CREATE; + if (persistent) + *createhowmode = GUARDED4; + else + *createhowmode = EXCLUSIVE4_1; + } } else if (disposition == FILE_OPEN) { if (in_status == NFS4ERR_NOENT) status = ERROR_FILE_NOT_FOUND; @@ -415,11 +421,13 @@ static int handle_open(nfs41_upcall *upcall) args->mode = info.mode; args->changeattr = info.change; } else { - uint32_t create = 0; + uint32_t create = 0, createhowmode = 0; map_access_2_allowdeny(args->access_mask, args->access_mode, &state->share_access, &state->share_deny); - status = map_disposition_2_nfsopen(args->disposition, status, &create, &upcall->last_error); + status = map_disposition_2_nfsopen(args->disposition, status, + state->session->flags & CREATE_SESSION4_FLAG_PERSIST, + &create, &createhowmode, &upcall->last_error); if (status) goto out_free_state; @@ -436,7 +444,8 @@ static int handle_open(nfs41_upcall *upcall) args->created = status == NFS4_OK ? TRUE : FALSE; } else { status = nfs41_open(state->session, state->share_access, - state->share_deny, create, args->mode, TRUE, state, &info); + state->share_deny, create, createhowmode, args->mode, + TRUE, state, &info); if (status == NFS4_OK) { /* add to the client's list of state for recovery */ diff --git a/daemon/setattr.c b/daemon/setattr.c index e0ec5f5..724b618 100644 --- a/daemon/setattr.c +++ b/daemon/setattr.c @@ -479,7 +479,7 @@ static int handle_setattr(nfs41_upcall *upcall) map_access_2_allowdeny(args->access_mask, args->access_mode, &state->share_access, &state->share_deny); status = nfs41_open(state->session, state->share_access, - state->share_deny, OPEN4_NOCREATE, 0, TRUE, state, NULL); + state->share_deny, OPEN4_NOCREATE, 0, 0, TRUE, state, NULL); if (status) { dprintf(1, "nfs41_open() failed with %s\n", nfs_error_string(status)); status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);