lkml.org 
[lkml]   [2019]   [Nov]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.3 183/193] NFSv4: Dont allow a cached open with a revoked delegation
    Date
    From: Trond Myklebust <trondmy@gmail.com>

    [ Upstream commit be3df3dd4c70ee020587a943a31b98a0fb4b6424 ]

    If the delegation is marked as being revoked, we must not use it
    for cached opens.

    Fixes: 869f9dfa4d6d ("NFSv4: Fix races between nfs_remove_bad_delegation() and delegation return")
    Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
    Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/nfs/delegation.c | 10 ++++++++++
    fs/nfs/delegation.h | 1 +
    fs/nfs/nfs4proc.c | 7 ++-----
    3 files changed, 13 insertions(+), 5 deletions(-)

    diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
    index ad7a771014714..af549d70ec507 100644
    --- a/fs/nfs/delegation.c
    +++ b/fs/nfs/delegation.c
    @@ -53,6 +53,16 @@ nfs4_is_valid_delegation(const struct nfs_delegation *delegation,
    return false;
    }

    +struct nfs_delegation *nfs4_get_valid_delegation(const struct inode *inode)
    +{
    + struct nfs_delegation *delegation;
    +
    + delegation = rcu_dereference(NFS_I(inode)->delegation);
    + if (nfs4_is_valid_delegation(delegation, 0))
    + return delegation;
    + return NULL;
    +}
    +
    static int
    nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark)
    {
    diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
    index 9eb87ae4c9827..8b14d441e699b 100644
    --- a/fs/nfs/delegation.h
    +++ b/fs/nfs/delegation.h
    @@ -68,6 +68,7 @@ int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state,
    bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred);
    bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode);

    +struct nfs_delegation *nfs4_get_valid_delegation(const struct inode *inode);
    void nfs_mark_delegation_referenced(struct nfs_delegation *delegation);
    int nfs4_have_delegation(struct inode *inode, fmode_t flags);
    int nfs4_check_delegation(struct inode *inode, fmode_t flags);
    diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
    index e1e7d2724b971..e600f28b1ddb9 100644
    --- a/fs/nfs/nfs4proc.c
    +++ b/fs/nfs/nfs4proc.c
    @@ -1435,8 +1435,6 @@ static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode,
    return 0;
    if ((delegation->type & fmode) != fmode)
    return 0;
    - if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
    - return 0;
    switch (claim) {
    case NFS4_OPEN_CLAIM_NULL:
    case NFS4_OPEN_CLAIM_FH:
    @@ -1805,7 +1803,6 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo
    static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
    {
    struct nfs4_state *state = opendata->state;
    - struct nfs_inode *nfsi = NFS_I(state->inode);
    struct nfs_delegation *delegation;
    int open_mode = opendata->o_arg.open_flags;
    fmode_t fmode = opendata->o_arg.fmode;
    @@ -1822,7 +1819,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
    }
    spin_unlock(&state->owner->so_lock);
    rcu_read_lock();
    - delegation = rcu_dereference(nfsi->delegation);
    + delegation = nfs4_get_valid_delegation(state->inode);
    if (!can_open_delegated(delegation, fmode, claim)) {
    rcu_read_unlock();
    break;
    @@ -2366,7 +2363,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
    data->o_arg.open_flags, claim))
    goto out_no_action;
    rcu_read_lock();
    - delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
    + delegation = nfs4_get_valid_delegation(data->state->inode);
    if (can_open_delegated(delegation, data->o_arg.fmode, claim))
    goto unlock_no_action;
    rcu_read_unlock();
    --
    2.20.1


    \
     
     \ /
      Last update: 2019-11-11 19:58    [W:4.404 / U:0.476 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site