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:
parent
cb54018555
commit
54c11cd84b
6 changed files with 42 additions and 41 deletions
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue