deleg: use SETATTR for OPEN4_CREATE
prevent an OPEN with OPEN4_CREATE from breaking a write delegation by sending a SETATTR instead moved static function remove_unsupported_attrs() from setattr.c to nfs41_superblock_supported_attrs() in nfs41_superblock.c, now used by both setattr.c and delegation.c Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
bc6471d981
commit
83d17fcb69
6 changed files with 69 additions and 30 deletions
|
|
@ -215,10 +215,6 @@ static bool_t delegation_compatible(
|
||||||
IN uint32_t access,
|
IN uint32_t access,
|
||||||
IN uint32_t deny)
|
IN uint32_t deny)
|
||||||
{
|
{
|
||||||
/* TODO: allow write delegation to handle OPEN4_CREATE */
|
|
||||||
if (create == OPEN4_CREATE)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case OPEN_DELEGATE_WRITE:
|
case OPEN_DELEGATE_WRITE:
|
||||||
/* An OPEN_DELEGATE_WRITE delegation allows the client to handle,
|
/* An OPEN_DELEGATE_WRITE delegation allows the client to handle,
|
||||||
|
|
@ -229,6 +225,8 @@ static bool_t delegation_compatible(
|
||||||
/* An OPEN_DELEGATE_READ delegation allows a client to handle,
|
/* An OPEN_DELEGATE_READ delegation allows a client to handle,
|
||||||
* on its own, requests to open a file for reading that do not
|
* on its own, requests to open a file for reading that do not
|
||||||
* deny OPEN4_SHARE_ACCESS_READ access to others. */
|
* deny OPEN4_SHARE_ACCESS_READ access to others. */
|
||||||
|
if (create == OPEN4_CREATE)
|
||||||
|
return FALSE;
|
||||||
if (access & OPEN4_SHARE_ACCESS_WRITE || deny & OPEN4_SHARE_DENY_READ)
|
if (access & OPEN4_SHARE_ACCESS_WRITE || deny & OPEN4_SHARE_DENY_READ)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
@ -258,16 +256,45 @@ static int delegation_find(
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int delegation_truncate(
|
||||||
|
IN nfs41_delegation_state *deleg,
|
||||||
|
IN nfs41_client *client,
|
||||||
|
IN stateid_arg *stateid,
|
||||||
|
IN uint32_t mode,
|
||||||
|
IN nfs41_file_info *info)
|
||||||
|
{
|
||||||
|
nfs41_superblock *superblock = deleg->file.fh.superblock;
|
||||||
|
|
||||||
|
/* use SETATTR to truncate the file */
|
||||||
|
info->attrmask.arr[0] = FATTR4_WORD0_SIZE;
|
||||||
|
info->attrmask.arr[1] = FATTR4_WORD1_MODE |
|
||||||
|
FATTR4_WORD1_TIME_CREATE | FATTR4_WORD1_TIME_MODIFY_SET;
|
||||||
|
info->attrmask.count = 2;
|
||||||
|
|
||||||
|
info->size = 0;
|
||||||
|
info->mode = mode;
|
||||||
|
get_nfs_time(&info->time_create);
|
||||||
|
get_nfs_time(&info->time_modify);
|
||||||
|
info->time_delta = &superblock->time_delta;
|
||||||
|
|
||||||
|
/* mask out unsupported attributes */
|
||||||
|
nfs41_superblock_supported_attrs(superblock, &info->attrmask);
|
||||||
|
|
||||||
|
return nfs41_setattr(client->session, &deleg->file, stateid, info);
|
||||||
|
}
|
||||||
|
|
||||||
int nfs41_delegate_open(
|
int nfs41_delegate_open(
|
||||||
IN nfs41_client *client,
|
IN nfs41_client *client,
|
||||||
IN nfs41_path_fh *file,
|
IN nfs41_path_fh *file,
|
||||||
IN uint32_t create,
|
IN uint32_t create,
|
||||||
|
IN uint32_t mode,
|
||||||
IN uint32_t access,
|
IN uint32_t access,
|
||||||
IN uint32_t deny,
|
IN uint32_t deny,
|
||||||
OUT nfs41_delegation_state **deleg_out,
|
OUT nfs41_delegation_state **deleg_out,
|
||||||
OUT nfs41_file_info *info)
|
OUT nfs41_file_info *info)
|
||||||
{
|
{
|
||||||
nfs41_delegation_state *deleg;
|
nfs41_delegation_state *deleg;
|
||||||
|
stateid_arg stateid;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* search for a delegation with this filehandle */
|
/* search for a delegation with this filehandle */
|
||||||
|
|
@ -290,6 +317,11 @@ int nfs41_delegate_open(
|
||||||
#else
|
#else
|
||||||
status = NFS4ERR_BADHANDLE;
|
status = NFS4ERR_BADHANDLE;
|
||||||
#endif
|
#endif
|
||||||
|
} else if (create == OPEN4_CREATE) {
|
||||||
|
/* copy the stateid for SETATTR */
|
||||||
|
stateid.open = NULL;
|
||||||
|
stateid.type = STATEID_DELEG_FILE;
|
||||||
|
memcpy(&stateid.stateid, &deleg->state.stateid, sizeof(stateid4));
|
||||||
}
|
}
|
||||||
ReleaseSRWLockExclusive(&deleg->lock);
|
ReleaseSRWLockExclusive(&deleg->lock);
|
||||||
|
|
||||||
|
|
@ -298,6 +330,13 @@ int nfs41_delegate_open(
|
||||||
if (status)
|
if (status)
|
||||||
goto out_deleg;
|
goto out_deleg;
|
||||||
|
|
||||||
|
if (create == OPEN4_CREATE) {
|
||||||
|
/* write delegations allow us to simulate OPEN4_CREATE with SETATTR */
|
||||||
|
status = delegation_truncate(deleg, client, &stateid, mode, info);
|
||||||
|
if (status)
|
||||||
|
goto out_deleg;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: check access against deleg->state.permissions or send ACCESS */
|
/* TODO: check access against deleg->state.permissions or send ACCESS */
|
||||||
|
|
||||||
*deleg_out = deleg;
|
*deleg_out = deleg;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ int nfs41_delegate_open(
|
||||||
IN nfs41_client *client,
|
IN nfs41_client *client,
|
||||||
IN nfs41_path_fh *file,
|
IN nfs41_path_fh *file,
|
||||||
IN uint32_t create,
|
IN uint32_t create,
|
||||||
|
IN uint32_t mode,
|
||||||
IN uint32_t access,
|
IN uint32_t access,
|
||||||
IN uint32_t deny,
|
IN uint32_t deny,
|
||||||
OUT nfs41_delegation_state **deleg_out,
|
OUT nfs41_delegation_state **deleg_out,
|
||||||
|
|
|
||||||
|
|
@ -412,6 +412,10 @@ int nfs41_superblock_for_fh(
|
||||||
IN const nfs41_fh *parent OPTIONAL,
|
IN const nfs41_fh *parent OPTIONAL,
|
||||||
OUT nfs41_path_fh *file);
|
OUT nfs41_path_fh *file);
|
||||||
|
|
||||||
|
void nfs41_superblock_supported_attrs(
|
||||||
|
IN nfs41_superblock *superblock,
|
||||||
|
IN OUT bitmap4 *attrs);
|
||||||
|
|
||||||
void nfs41_superblock_space_changed(
|
void nfs41_superblock_space_changed(
|
||||||
IN nfs41_superblock *superblock);
|
IN nfs41_superblock *superblock);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,22 @@ out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nfs41_superblock_supported_attrs(
|
||||||
|
IN nfs41_superblock *superblock,
|
||||||
|
IN OUT bitmap4 *attrs)
|
||||||
|
{
|
||||||
|
uint32_t i, count = 0;
|
||||||
|
|
||||||
|
AcquireSRWLockShared(&superblock->lock);
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
attrs->arr[i] &= superblock->supported_attrs.arr[i];
|
||||||
|
if (attrs->arr[i])
|
||||||
|
count = i+1;
|
||||||
|
}
|
||||||
|
attrs->count = min(attrs->count, count);
|
||||||
|
ReleaseSRWLockShared(&superblock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
void nfs41_superblock_space_changed(
|
void nfs41_superblock_space_changed(
|
||||||
IN nfs41_superblock *superblock)
|
IN nfs41_superblock *superblock)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -233,8 +233,9 @@ static int open_or_delegate(
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* check for existing delegation */
|
/* check for existing delegation */
|
||||||
status = nfs41_delegate_open(state->session->client, &state->file, create,
|
status = nfs41_delegate_open(state->session->client, &state->file,
|
||||||
state->share_access, state->share_deny, &state->delegation.state, info);
|
create, mode, state->share_access, state->share_deny,
|
||||||
|
&state->delegation.state, info);
|
||||||
|
|
||||||
/* get an open stateid if we have no delegation stateid */
|
/* get an open stateid if we have no delegation stateid */
|
||||||
if (status)
|
if (status)
|
||||||
|
|
|
||||||
|
|
@ -65,26 +65,6 @@ out_free:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_unsupported_attrs(
|
|
||||||
IN const bitmap4 *supported_attrs,
|
|
||||||
IN OUT bitmap4 *attrs)
|
|
||||||
{
|
|
||||||
uint32_t i, count = 0;
|
|
||||||
dprintf(3, "remove_unsupported_attrs\n");
|
|
||||||
for (i = 0; i < 3; i++) {
|
|
||||||
dprintf(3, "\tmask[%d] = %12u", i, attrs->arr[i]);
|
|
||||||
dprintf(3, " & %12u", supported_attrs->arr[i]);
|
|
||||||
|
|
||||||
attrs->arr[i] &= supported_attrs->arr[i];
|
|
||||||
if (attrs->arr[i])
|
|
||||||
count = i+1;
|
|
||||||
|
|
||||||
dprintf(3, " = %12d\n", attrs->arr[i]);
|
|
||||||
}
|
|
||||||
attrs->count = min(attrs->count, count);
|
|
||||||
dprintf(3, "\tcount = %d\n", attrs->count);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_nfs41_setattr(setattr_upcall_args *args)
|
static int handle_nfs41_setattr(setattr_upcall_args *args)
|
||||||
{
|
{
|
||||||
PFILE_BASIC_INFO basic_info = (PFILE_BASIC_INFO)args->buf;
|
PFILE_BASIC_INFO basic_info = (PFILE_BASIC_INFO)args->buf;
|
||||||
|
|
@ -136,10 +116,8 @@ static int handle_nfs41_setattr(setattr_upcall_args *args)
|
||||||
info.attrmask.count = 2;
|
info.attrmask.count = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only ask for attributes that are supported by the filesystem */
|
/* mask out unsupported attributes */
|
||||||
AcquireSRWLockShared(&superblock->lock);
|
nfs41_superblock_supported_attrs(superblock, &info.attrmask);
|
||||||
remove_unsupported_attrs(&superblock->supported_attrs, &info.attrmask);
|
|
||||||
ReleaseSRWLockShared(&superblock->lock);
|
|
||||||
|
|
||||||
if (!info.attrmask.count)
|
if (!info.attrmask.count)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue