NFSv4: Fix problem with OPEN_DOWNGRADE
RFC 3530 states that for OPEN_DOWNGRADE "The share_access and share_deny bits specified must be exactly equal to the union of the share_access and share_deny bits specified for some subset of the OPENs in effect for current openowner on the current file. Setattr is currently violating the NFSv4 rules for OPEN_DOWNGRADE in that it may cause a downgrade from OPEN4_SHARE_ACCESS_BOTH to OPEN4_SHARE_ACCESS_WRITE despite the fact that there exists no open file with O_WRONLY access mode. Fix the problem by replacing nfs4_find_state() with a modified version of nfs_find_open_context(). Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
@@ -383,28 +383,6 @@ nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode)
|
||||
state->state = mode;
|
||||
}
|
||||
|
||||
static struct nfs4_state *
|
||||
__nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode)
|
||||
{
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
struct nfs4_state *state;
|
||||
|
||||
mode &= (FMODE_READ|FMODE_WRITE);
|
||||
list_for_each_entry(state, &nfsi->open_states, inode_states) {
|
||||
if (state->owner->so_cred != cred)
|
||||
continue;
|
||||
if ((state->state & mode) != mode)
|
||||
continue;
|
||||
atomic_inc(&state->count);
|
||||
if (mode & FMODE_READ)
|
||||
state->nreaders++;
|
||||
if (mode & FMODE_WRITE)
|
||||
state->nwriters++;
|
||||
return state;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct nfs4_state *
|
||||
__nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
|
||||
{
|
||||
@@ -423,17 +401,6 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct nfs4_state *
|
||||
nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode)
|
||||
{
|
||||
struct nfs4_state *state;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
state = __nfs4_find_state(inode, cred, mode);
|
||||
spin_unlock(&inode->i_lock);
|
||||
return state;
|
||||
}
|
||||
|
||||
static void
|
||||
nfs4_free_open_state(struct nfs4_state *state)
|
||||
{
|
||||
|
Reference in New Issue
Block a user