pNFS: Retry NFS4ERR_OLD_STATEID errors in layoutreturn-on-close
authorTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 6 Nov 2017 20:28:07 +0000 (15:28 -0500)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Fri, 17 Nov 2017 21:43:47 +0000 (16:43 -0500)
If our layoutreturn on close operation returns an NFS4ERR_OLD_STATEID,
then try to update the stateid and retry. We know that there should
be no further LAYOUTGET requests being launched.

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

index ef313d602a85746b9545e271cf81e505c5bda2b1..7ff9c43f79ebe3d8b6e578146d4d6001c6482290 100644 (file)
@@ -3166,11 +3166,18 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                        calldata->arg.lr_args = NULL;
                        calldata->res.lr_res = NULL;
                        break;
+               case -NFS4ERR_OLD_STATEID:
+                       if (nfs4_refresh_layout_stateid(&calldata->arg.lr_args->stateid,
+                                               calldata->inode)) {
+                               calldata->res.lr_ret = 0;
+                               rpc_restart_call_prepare(task);
+                               return;
+                       }
+                       /* Fallthrough */
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_DELEG_REVOKED:
                case -NFS4ERR_EXPIRED:
                case -NFS4ERR_BAD_STATEID:
-               case -NFS4ERR_OLD_STATEID:
                case -NFS4ERR_UNKNOWN_LAYOUTTYPE:
                case -NFS4ERR_WRONG_CRED:
                        calldata->arg.lr_args = NULL;
@@ -5771,11 +5778,18 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
                        data->args.lr_args = NULL;
                        data->res.lr_res = NULL;
                        break;
+               case -NFS4ERR_OLD_STATEID:
+                       if (nfs4_refresh_layout_stateid(&data->args.lr_args->stateid,
+                                               data->inode)) {
+                               data->res.lr_ret = 0;
+                               rpc_restart_call_prepare(task);
+                               return;
+                       }
+                       /* Fallthrough */
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_DELEG_REVOKED:
                case -NFS4ERR_EXPIRED:
                case -NFS4ERR_BAD_STATEID:
-               case -NFS4ERR_OLD_STATEID:
                case -NFS4ERR_UNKNOWN_LAYOUTTYPE:
                case -NFS4ERR_WRONG_CRED:
                        data->args.lr_args = NULL;
index ec30dacf1a24acf148c9909f45472f73734ba84d..d602fe9e1ac89e27c7139d4bf43067603a59b1de 100644 (file)
@@ -354,6 +354,24 @@ pnfs_clear_lseg_state(struct pnfs_layout_segment *lseg,
                pnfs_lseg_dec_and_remove_zero(lseg, free_me);
 }
 
+/*
+ * Update the seqid of a layout stateid
+ */
+bool nfs4_refresh_layout_stateid(nfs4_stateid *dst, struct inode *inode)
+{
+       struct pnfs_layout_hdr *lo;
+       bool ret = false;
+
+       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;
+       }
+       spin_unlock(&inode->i_lock);
+       return ret;
+}
+
 /*
  * Mark a pnfs_layout_hdr and all associated layout segments as invalid
  *
index 78de7a2052f7d51148df4fa8e8ae188bc3a8b282..8d507c361d980dad0a0aed52bf5a5ed02203634b 100644 (file)
@@ -252,6 +252,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);
 void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo);
 void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
                             const nfs4_stateid *new,
@@ -765,6 +766,11 @@ static inline void nfs4_pnfs_v3_ds_connect_unload(void)
 {
 }
 
+static inline bool nfs4_refresh_layout_stateid(nfs4_stateid *dst,
+               struct inode *inode)
+{
+       return false;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 #if IS_ENABLED(CONFIG_NFS_V4_2)