[PATCH] draft patches to fixes LAYOUTCOMMIT related issues

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



1, fix an issue that client may send LAYOUTRETURN before LAYOUTCOMMIT
2, update layout stateid when layoutcommit receiving NFS4ERR_OLD_STATEID
---
 fs/nfs/nfs4proc.c | 19 ++++++++++++++++++-
 fs/nfs/pnfs.c     | 15 ++++++++++++---
 fs/nfs/pnfs.h     |  6 ++++--
 3 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 7d2b67e06cc3..448a13f2537b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -10081,7 +10081,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
 	case -NFS4ERR_OLD_STATEID:
 		if (nfs4_layout_refresh_old_stateid(&lrp->args.stateid,
 					&lrp->args.range,
-					lrp->args.inode))
+					lrp->args.inode,
+					false))
 			goto out_restart;
 		fallthrough;
 	default:
@@ -10255,6 +10256,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
 {
 	struct nfs4_layoutcommit_data *data = calldata;
 	struct nfs_server *server = NFS_SERVER(data->args.inode);
+	struct pnfs_layout_range dst_range;
 
 	if (!nfs41_sequence_done(task, &data->res.seq_res))
 		return;
@@ -10268,6 +10270,14 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
 		break;
 	case 0:
 		break;
+	case -NFS4ERR_OLD_STATEID:
+		if (data->inode) {
+			nfs4_layout_refresh_old_stateid(&data->args.stateid,
+					&dst_range,
+					data->args.inode,
+					true);
+		}
+		fallthrough;
 	default:
 		if (nfs4_async_handle_error(task, server, NULL, NULL) == -EAGAIN) {
 			rpc_restart_call_prepare(task);
@@ -10279,10 +10289,17 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
 static void nfs4_layoutcommit_release(void *calldata)
 {
 	struct nfs4_layoutcommit_data *data = calldata;
+	struct inode *inode = data->args.inode;
 
 	pnfs_cleanup_layoutcommit(data);
 	nfs_post_op_update_inode_force_wcc(data->args.inode,
 					   data->res.fattr);
+	struct pnfs_layout_hdr *lo;
+	spin_lock(&inode->i_lock);
+	lo = NFS_I(inode)->layout;
+	spin_unlock(&inode->i_lock);
+	pnfs_put_layout_hdr(lo);
+
 	put_cred(data->cred);
 	nfs_iput_and_deactive(data->inode);
 	kfree(data);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index a3135b5af7ee..defc0a84e6c7 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -409,7 +409,8 @@ pnfs_clear_lseg_state(struct pnfs_layout_segment *lseg,
  */
 bool nfs4_layout_refresh_old_stateid(nfs4_stateid *dst,
 		struct pnfs_layout_range *dst_range,
-		struct inode *inode)
+		struct inode *inode,
+		bool force_update)
 {
 	struct pnfs_layout_hdr *lo;
 	struct pnfs_layout_range range = {
@@ -433,7 +434,7 @@ bool nfs4_layout_refresh_old_stateid(nfs4_stateid *dst,
 		}
 		/* Try to update the seqid to the most recent */
 		err = pnfs_mark_matching_lsegs_return(lo, &head, &range, 0);
-		if (err != -EBUSY) {
+		if (force_update || err != -EBUSY) {
 			dst->seqid = lo->plh_stateid.seqid;
 			*dst_range = range;
 			ret = true;
@@ -1306,6 +1307,9 @@ pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo,
 	/* Serialise LAYOUTGET/LAYOUTRETURN */
 	if (atomic_read(&lo->plh_outstanding) != 0 && lo->plh_return_seq == 0)
 		return false;
+	/* Serialise LAYOUTCOMMIT/LAYOUTRETURN */
+	if (pnfs_layoutcommit_outstanding(lo->plh_inode))
+		return false;
 	if (test_and_set_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags))
 		return false;
 	set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
@@ -1686,7 +1690,8 @@ int pnfs_roc_done(struct rpc_task *task, struct nfs4_layoutreturn_args **argpp,
 		return 0;
 	case -NFS4ERR_OLD_STATEID:
 		if (!nfs4_layout_refresh_old_stateid(&arg->stateid,
-						     &arg->range, arg->inode))
+						     &arg->range, arg->inode,
+						     false))
 			break;
 		*ret = -NFS4ERR_NOMATCHING_LAYOUT;
 		return -EAGAIN;
@@ -3397,6 +3402,10 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
 		}
 	}
 
+	/* the ref will be free on nfs4_layoutcommit_release, and trigger
+	 * LAYOUTRETURN
+	 */
+	pnfs_get_layout_hdr(nfsi->layout);
 
 	status = nfs4_proc_layoutcommit(data, sync);
 out:
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 91ff877185c8..c6788f1423a3 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -287,7 +287,8 @@ int pnfs_layout_destroy_byclid(struct nfs_client *clp,
 			       enum pnfs_layout_destroy_mode mode);
 bool nfs4_layout_refresh_old_stateid(nfs4_stateid *dst,
 		struct pnfs_layout_range *dst_range,
-		struct inode *inode);
+		struct inode *inode,
+		bool force_update);
 void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo);
 void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
 			     const nfs4_stateid *new,
@@ -891,7 +892,8 @@ static inline void nfs4_pnfs_v3_ds_connect_unload(void)
 
 static inline bool nfs4_layout_refresh_old_stateid(nfs4_stateid *dst,
 		struct pnfs_layout_range *dst_range,
-		struct inode *inode)
+		struct inode *inode,
+		bool force_update)
 {
 	return false;
 }
-- 
2.51.0.87.g1fa68948c3.dirty





[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux