Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7380020e authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker
Browse files

pNFS: Retry NFS4ERR_OLD_STATEID errors in layoutreturn-on-close



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: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent c82bac6f
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -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;
+18 −0
Original line number Diff line number Diff line
@@ -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
 *
+6 −0
Original line number Diff line number Diff line
@@ -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)