lkml.org 
[lkml]   [2019]   [Aug]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 101/158] NFSv4: Fix open create exclusive when the server reboots
    Date
    [ Upstream commit 8fd1ab747d2b1ec7ec663ad0b41a32eaa35117a8 ]

    If the server that does not implement NFSv4.1 persistent session
    semantics reboots while we are performing an exclusive create,
    then the return value of NFS4ERR_DELAY when we replay the open
    during the grace period causes us to lose the verifier.
    When the grace period expires, and we present a new verifier,
    the server will then correctly reply NFS4ERR_EXIST.

    This commit ensures that we always present the same verifier when
    replaying the OPEN.

    Reported-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
    Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
    Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/nfs/nfs4proc.c | 41 ++++++++++++++++++++++++++---------------
    1 file changed, 26 insertions(+), 15 deletions(-)

    diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
    index 41c8ddbc80dc..d1816ee0c11b 100644
    --- a/fs/nfs/nfs4proc.c
    +++ b/fs/nfs/nfs4proc.c
    @@ -997,6 +997,12 @@ struct nfs4_opendata {
    int cancelled;
    };

    +struct nfs4_open_createattrs {
    + struct nfs4_label *label;
    + struct iattr *sattr;
    + const __u32 verf[2];
    +};
    +
    static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server,
    int err, struct nfs4_exception *exception)
    {
    @@ -1066,8 +1072,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)

    static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
    struct nfs4_state_owner *sp, fmode_t fmode, int flags,
    - const struct iattr *attrs,
    - struct nfs4_label *label,
    + const struct nfs4_open_createattrs *c,
    enum open_claim_type4 claim,
    gfp_t gfp_mask)
    {
    @@ -1075,6 +1080,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
    struct inode *dir = d_inode(parent);
    struct nfs_server *server = NFS_SERVER(dir);
    struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
    + struct nfs4_label *label = (c != NULL) ? c->label : NULL;
    struct nfs4_opendata *p;

    p = kzalloc(sizeof(*p), gfp_mask);
    @@ -1131,15 +1137,11 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
    case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
    p->o_arg.fh = NFS_FH(d_inode(dentry));
    }
    - if (attrs != NULL && attrs->ia_valid != 0) {
    - __u32 verf[2];
    -
    + if (c != NULL && c->sattr != NULL && c->sattr->ia_valid != 0) {
    p->o_arg.u.attrs = &p->attrs;
    - memcpy(&p->attrs, attrs, sizeof(p->attrs));
    + memcpy(&p->attrs, c->sattr, sizeof(p->attrs));

    - verf[0] = jiffies;
    - verf[1] = current->pid;
    - memcpy(p->o_arg.u.verifier.data, verf,
    + memcpy(p->o_arg.u.verifier.data, c->verf,
    sizeof(p->o_arg.u.verifier.data));
    }
    p->c_arg.fh = &p->o_res.fh;
    @@ -1653,7 +1655,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
    struct nfs4_opendata *opendata;

    opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0,
    - NULL, NULL, claim, GFP_NOFS);
    + NULL, claim, GFP_NOFS);
    if (opendata == NULL)
    return ERR_PTR(-ENOMEM);
    opendata->state = state;
    @@ -2488,8 +2490,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
    static int _nfs4_do_open(struct inode *dir,
    struct nfs_open_context *ctx,
    int flags,
    - struct iattr *sattr,
    - struct nfs4_label *label,
    + const struct nfs4_open_createattrs *c,
    int *opened)
    {
    struct nfs4_state_owner *sp;
    @@ -2501,6 +2502,8 @@ static int _nfs4_do_open(struct inode *dir,
    struct nfs4_threshold **ctx_th = &ctx->mdsthreshold;
    fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC);
    enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL;
    + struct iattr *sattr = c->sattr;
    + struct nfs4_label *label = c->label;
    struct nfs4_label *olabel = NULL;
    int status;

    @@ -2519,8 +2522,8 @@ static int _nfs4_do_open(struct inode *dir,
    status = -ENOMEM;
    if (d_really_is_positive(dentry))
    claim = NFS4_OPEN_CLAIM_FH;
    - opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr,
    - label, claim, GFP_KERNEL);
    + opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags,
    + c, claim, GFP_KERNEL);
    if (opendata == NULL)
    goto err_put_state_owner;

    @@ -2596,10 +2599,18 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
    struct nfs_server *server = NFS_SERVER(dir);
    struct nfs4_exception exception = { };
    struct nfs4_state *res;
    + struct nfs4_open_createattrs c = {
    + .label = label,
    + .sattr = sattr,
    + .verf = {
    + [0] = (__u32)jiffies,
    + [1] = (__u32)current->pid,
    + },
    + };
    int status;

    do {
    - status = _nfs4_do_open(dir, ctx, flags, sattr, label, opened);
    + status = _nfs4_do_open(dir, ctx, flags, &c, opened);
    res = ctx->state;
    trace_nfs4_open_file(ctx, flags, status);
    if (status == 0)
    --
    2.20.1


    \
     
     \ /
      Last update: 2019-08-02 11:39    [W:4.044 / U:1.384 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site