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) {
|
} 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(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 */
|
/* update the stateid arg with the new open->stateid */
|
||||||
memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4));
|
memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4));
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "nfs41_ops.h"
|
#include "nfs41_ops.h"
|
||||||
#include "nfs41_compound.h"
|
#include "nfs41_compound.h"
|
||||||
|
|
@ -302,6 +303,7 @@ int nfs41_open(
|
||||||
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 mode,
|
IN uint32_t mode,
|
||||||
IN bool_t try_recovery,
|
IN bool_t try_recovery,
|
||||||
IN OUT nfs41_open_state *state,
|
IN OUT nfs41_open_state *state,
|
||||||
|
|
@ -324,6 +326,7 @@ 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];
|
||||||
|
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
info = &tmp_info;
|
info = &tmp_info;
|
||||||
|
|
@ -354,12 +357,18 @@ int nfs41_open(
|
||||||
open_args.share_deny = deny;
|
open_args.share_deny = deny;
|
||||||
open_args.owner = &state->owner;
|
open_args.owner = &state->owner;
|
||||||
open_args.openhow.opentype = create;
|
open_args.openhow.opentype = create;
|
||||||
open_args.openhow.how.mode = UNCHECKED4;
|
open_args.openhow.how.mode = how_mode;
|
||||||
open_args.openhow.how.u.createattrs.info.attrmask.count = 2;
|
open_args.openhow.how.createattrs.info.attrmask.count = 2;
|
||||||
open_args.openhow.how.u.createattrs.info.attrmask.arr[0] = FATTR4_WORD0_SIZE;
|
open_args.openhow.how.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.createattrs.info.attrmask.arr[1] = FATTR4_WORD1_MODE;
|
||||||
open_args.openhow.how.u.createattrs.info.mode = mode;
|
open_args.openhow.how.createattrs.info.mode = mode;
|
||||||
open_args.openhow.how.u.createattrs.info.size = 0;
|
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.claim = CLAIM_NULL;
|
||||||
open_args.claim.u.null.filename = &state->file.name;
|
open_args.claim.u.null.filename = &state->file.name;
|
||||||
open_res.resok4.stateid = &state->stateid;
|
open_res.resok4.stateid = &state->stateid;
|
||||||
|
|
|
||||||
|
|
@ -524,21 +524,10 @@ enum createmode4 {
|
||||||
EXCLUSIVE4_1 = 3
|
EXCLUSIVE4_1 = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct __creatverfattr {
|
|
||||||
unsigned char cva_verf[NFS4_VERIFIER_SIZE];
|
|
||||||
fattr4 cva_attrs;
|
|
||||||
} creatverfattr;
|
|
||||||
|
|
||||||
typedef struct __createhow4 {
|
typedef struct __createhow4 {
|
||||||
uint32_t mode;
|
uint32_t mode;
|
||||||
union {
|
|
||||||
/* case UNCHECKED4, GUARDED4: */
|
|
||||||
createattrs4 createattrs;
|
createattrs4 createattrs;
|
||||||
/* case EXCLUSIVE4: */
|
unsigned char *createverf;
|
||||||
unsigned char createverf[NFS4_VERIFIER_SIZE];
|
|
||||||
/* case EXCLUSIVE4_1: */
|
|
||||||
creatverfattr ch_createboth;
|
|
||||||
} u;
|
|
||||||
} createhow4;
|
} createhow4;
|
||||||
|
|
||||||
enum opentype4 {
|
enum opentype4 {
|
||||||
|
|
@ -972,6 +961,7 @@ int nfs41_open(
|
||||||
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 mode,
|
IN uint32_t mode,
|
||||||
IN bool_t try_recovery,
|
IN bool_t try_recovery,
|
||||||
IN OUT nfs41_open_state *state,
|
IN OUT nfs41_open_state *state,
|
||||||
|
|
|
||||||
|
|
@ -1835,16 +1835,6 @@ static bool_t decode_op_getattr(
|
||||||
/*
|
/*
|
||||||
* OP_OPEN
|
* 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(
|
static bool_t encode_createhow4(
|
||||||
XDR *xdr,
|
XDR *xdr,
|
||||||
createhow4 *ch)
|
createhow4 *ch)
|
||||||
|
|
@ -1858,13 +1848,16 @@ static bool_t encode_createhow4(
|
||||||
{
|
{
|
||||||
case UNCHECKED4:
|
case UNCHECKED4:
|
||||||
case GUARDED4:
|
case GUARDED4:
|
||||||
result = encode_createattrs4(xdr, &ch->u.createattrs);
|
result = encode_createattrs4(xdr, &ch->createattrs);
|
||||||
break;
|
break;
|
||||||
case EXCLUSIVE4:
|
case EXCLUSIVE4:
|
||||||
result = xdr_opaque(xdr, (char *)ch->u.createverf, NFS4_VERIFIER_SIZE);
|
result = xdr_opaque(xdr, (char *)ch->createverf, NFS4_VERIFIER_SIZE);
|
||||||
break;
|
break;
|
||||||
case EXCLUSIVE4_1:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
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,
|
static int map_disposition_2_nfsopen(ULONG disposition, int in_status, bool_t persistent,
|
||||||
uint32_t *create, uint32_t *last_error)
|
uint32_t *create, uint32_t *createhowmode,
|
||||||
|
uint32_t *last_error)
|
||||||
{
|
{
|
||||||
int status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
if (disposition == FILE_SUPERSEDE) {
|
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 lookup succeeded which means the file exist, return an error
|
||||||
if (!in_status)
|
if (!in_status)
|
||||||
status = ERROR_FILE_EXISTS;
|
status = ERROR_FILE_EXISTS;
|
||||||
else
|
else {
|
||||||
*create = OPEN4_CREATE;
|
*create = OPEN4_CREATE;
|
||||||
|
if (persistent)
|
||||||
|
*createhowmode = GUARDED4;
|
||||||
|
else
|
||||||
|
*createhowmode = EXCLUSIVE4_1;
|
||||||
|
}
|
||||||
} else if (disposition == FILE_OPEN) {
|
} else if (disposition == FILE_OPEN) {
|
||||||
if (in_status == NFS4ERR_NOENT)
|
if (in_status == NFS4ERR_NOENT)
|
||||||
status = ERROR_FILE_NOT_FOUND;
|
status = ERROR_FILE_NOT_FOUND;
|
||||||
|
|
@ -415,11 +421,13 @@ static int handle_open(nfs41_upcall *upcall)
|
||||||
args->mode = info.mode;
|
args->mode = info.mode;
|
||||||
args->changeattr = info.change;
|
args->changeattr = info.change;
|
||||||
} else {
|
} else {
|
||||||
uint32_t create = 0;
|
uint32_t create = 0, createhowmode = 0;
|
||||||
|
|
||||||
map_access_2_allowdeny(args->access_mask, args->access_mode,
|
map_access_2_allowdeny(args->access_mask, args->access_mode,
|
||||||
&state->share_access, &state->share_deny);
|
&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)
|
if (status)
|
||||||
goto out_free_state;
|
goto out_free_state;
|
||||||
|
|
||||||
|
|
@ -436,7 +444,8 @@ static int handle_open(nfs41_upcall *upcall)
|
||||||
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->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) {
|
if (status == NFS4_OK) {
|
||||||
/* add to the client's list of state for recovery */
|
/* 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,
|
map_access_2_allowdeny(args->access_mask, args->access_mode,
|
||||||
&state->share_access, &state->share_deny);
|
&state->share_access, &state->share_deny);
|
||||||
status = nfs41_open(state->session, state->share_access,
|
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) {
|
if (status) {
|
||||||
dprintf(1, "nfs41_open() failed with %s\n", nfs_error_string(status));
|
dprintf(1, "nfs41_open() failed with %s\n", nfs_error_string(status));
|
||||||
status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
|
status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue