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.
This commit is contained in:
Olga Kornievskaia 2011-05-24 12:33:58 -04:00
parent cb54018555
commit 54c11cd84b
6 changed files with 42 additions and 41 deletions

View file

@ -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));

View file

@ -25,6 +25,7 @@
#include <strsafe.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#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;

View file

@ -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;
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,

View file

@ -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;

View file

@ -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 */

View file

@ -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);