pnfs: Fix handling of NFS4ERR_OLD_STATEID replies to layoutreturn
authorTrond Myklebust <trondmy@gmail.com>
Mon, 30 Jul 2018 02:39:15 +0000 (22:39 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Wed, 8 Aug 2018 20:50:01 +0000 (16:50 -0400)
If the server tells us that out layoutreturn raced with another layout
update, then we must ensure that the new layout segments are not in use
before we resend with an updated layout stateid.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h

index bddba460643a1cce12c5cff0e4b5079277ef3651..914f52f4ab0853fa36e7ae2167498277251a9b64 100644 (file)
@@ -3232,7 +3232,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                        calldata->res.lr_res = NULL;
                        break;
                case -NFS4ERR_OLD_STATEID:
-                       if (nfs4_refresh_layout_stateid(&calldata->arg.lr_args->stateid,
+                       if (nfs4_layoutreturn_refresh_stateid(&calldata->arg.lr_args->stateid,
                                                calldata->inode))
                                goto lr_restart;
                        /* Fallthrough */
@@ -5914,7 +5914,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
                        data->res.lr_res = NULL;
                        break;
                case -NFS4ERR_OLD_STATEID:
-                       if (nfs4_refresh_layout_stateid(&data->args.lr_args->stateid,
+                       if (nfs4_layoutreturn_refresh_stateid(&data->args.lr_args->stateid,
                                                data->inode))
                                goto lr_restart;
                        /* Fallthrough */
@@ -8863,7 +8863,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
        server = NFS_SERVER(lrp->args.inode);
        switch (task->tk_status) {
        case -NFS4ERR_OLD_STATEID:
-               if (nfs4_refresh_layout_stateid(&lrp->args.stateid,
+               if (nfs4_layoutreturn_refresh_stateid(&lrp->args.stateid,
                                        lrp->args.inode))
                        goto out_restart;
                /* Fallthrough */
index 7fdac8b504dd231438ca5dbd1d6e475c893fd21c..7020f726275cd3ff292d61cc4aca7a95151656a8 100644 (file)
@@ -361,18 +361,29 @@ pnfs_clear_lseg_state(struct pnfs_layout_segment *lseg,
 /*
  * Update the seqid of a layout stateid
  */
-bool nfs4_refresh_layout_stateid(nfs4_stateid *dst, struct inode *inode)
+bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst, struct inode *inode)
 {
        struct pnfs_layout_hdr *lo;
+       struct pnfs_layout_range range = {
+               .iomode = IOMODE_ANY,
+               .offset = 0,
+               .length = NFS4_MAX_UINT64,
+       };
        bool ret = false;
+       LIST_HEAD(head);
+       int err;
 
        spin_lock(&inode->i_lock);
        lo = NFS_I(inode)->layout;
        if (lo && nfs4_stateid_match_other(dst, &lo->plh_stateid)) {
-               dst->seqid = lo->plh_stateid.seqid;
-               ret = true;
+               err = pnfs_mark_matching_lsegs_return(lo, &head, &range, 0);
+               if (err != -EBUSY) {
+                       dst->seqid = lo->plh_stateid.seqid;
+                       ret = true;
+               }
        }
        spin_unlock(&inode->i_lock);
+       pnfs_free_lseg_list(&head);
        return ret;
 }
 
index 3fe81424337d07b5b19ab77d08825fb27bf523b0..1a38a3b533b5625c04c8916dc5c02f05c2ed1a63 100644 (file)
@@ -259,7 +259,7 @@ int pnfs_destroy_layouts_byfsid(struct nfs_client *clp,
                bool is_recall);
 int pnfs_destroy_layouts_byclid(struct nfs_client *clp,
                bool is_recall);
-bool nfs4_refresh_layout_stateid(nfs4_stateid *dst, struct inode *inode);
+bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst, struct inode *inode);
 void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo);
 void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
                             const nfs4_stateid *new,
@@ -780,7 +780,7 @@ static inline void nfs4_pnfs_v3_ds_connect_unload(void)
 {
 }
 
-static inline bool nfs4_refresh_layout_stateid(nfs4_stateid *dst,
+static inline bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst,
                struct inode *inode)
 {
        return false;