lkml.org 
[lkml]   [2017]   [Nov]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.18 19/67] nfsd: deal with revoked delegations appropriately
    Date
    3.18-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Andrew Elble <aweits@rit.edu>

    commit 95da1b3a5aded124dd1bda1e3cdb876184813140 upstream.

    If a delegation has been revoked by the server, operations using that
    delegation should error out with NFS4ERR_DELEG_REVOKED in the >4.1
    case, and NFS4ERR_BAD_STATEID otherwise.

    The server needs NFSv4.1 clients to explicitly free revoked delegations.
    If the server returns NFS4ERR_DELEG_REVOKED, the client will do that;
    otherwise it may just forget about the delegation and be unable to
    recover when it later sees SEQ4_STATUS_RECALLABLE_STATE_REVOKED set on a
    SEQUENCE reply. That can cause the Linux 4.1 client to loop in its
    stage manager.

    Signed-off-by: Andrew Elble <aweits@rit.edu>
    Reviewed-by: Trond Myklebust <trond.myklebust@primarydata.com>
    Signed-off-by: J. Bruce Fields <bfields@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/nfsd/nfs4state.c | 25 ++++++++++++++++++++++++-
    1 file changed, 24 insertions(+), 1 deletion(-)

    --- a/fs/nfsd/nfs4state.c
    +++ b/fs/nfsd/nfs4state.c
    @@ -3602,7 +3602,8 @@ static struct nfs4_delegation *find_dele
    {
    struct nfs4_stid *ret;

    - ret = find_stateid_by_type(cl, s, NFS4_DELEG_STID);
    + ret = find_stateid_by_type(cl, s,
    + NFS4_DELEG_STID|NFS4_REVOKED_DELEG_STID);
    if (!ret)
    return NULL;
    return delegstateid(ret);
    @@ -3625,6 +3626,12 @@ nfs4_check_deleg(struct nfs4_client *cl,
    deleg = find_deleg_stateid(cl, &open->op_delegate_stateid);
    if (deleg == NULL)
    goto out;
    + if (deleg->dl_stid.sc_type == NFS4_REVOKED_DELEG_STID) {
    + nfs4_put_stid(&deleg->dl_stid);
    + if (cl->cl_minorversion)
    + status = nfserr_deleg_revoked;
    + goto out;
    + }
    flags = share_access_to_flags(open->op_share_access);
    status = nfs4_check_delegmode(deleg, flags);
    if (status) {
    @@ -4451,6 +4458,16 @@ nfsd4_lookup_stateid(struct nfsd4_compou
    struct nfs4_stid **s, struct nfsd_net *nn)
    {
    __be32 status;
    + bool return_revoked = false;
    +
    + /*
    + * only return revoked delegations if explicitly asked.
    + * otherwise we report revoked or bad_stateid status.
    + */
    + if (typemask & NFS4_REVOKED_DELEG_STID)
    + return_revoked = true;
    + else if (typemask & NFS4_DELEG_STID)
    + typemask |= NFS4_REVOKED_DELEG_STID;

    if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
    return nfserr_bad_stateid;
    @@ -4465,6 +4482,12 @@ nfsd4_lookup_stateid(struct nfsd4_compou
    *s = find_stateid_by_type(cstate->clp, stateid, typemask);
    if (!*s)
    return nfserr_bad_stateid;
    + if (((*s)->sc_type == NFS4_REVOKED_DELEG_STID) && !return_revoked) {
    + nfs4_put_stid(*s);
    + if (cstate->minorversion)
    + return nfserr_deleg_revoked;
    + return nfserr_bad_stateid;
    + }
    return nfs_ok;
    }


    \
     
     \ /
      Last update: 2017-11-28 13:41    [W:6.020 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site