nfs4: serialize layoutcommit
Subsystems (2)
PATCH v2 1/1 nfs4: serialize layoutcommit
Current pnfs_layoutcommit_inode can not handle parallel layoutcommit. And as Trond suggested , there is no need for client to optimize for parallel layoutcommit. So add NFS_INO_LAYOUTCOMMITTING flag to mark inflight layoutcommit and serialize lalyoutcommit with it. Also mark_inode_dirty_sync if pnfs_layoutcommit_inode fails to issue layoutcommit.
Reported-by Vitaliy Gusev <[email protected]>
Signed-off-by Peng Tao <[email protected]>
Signed-off-by Jim Rees <[email protected]>
---
change from v1:
remove else if after goto.
fs/nfs/nfs4proc.c | 6 ++++++ fs/nfs/pnfs.c | 25 ++++++++++++++++++++++--- include/linux/nfs_fs.h | 1 + 3 files changed, 29 insertions(+), 3 deletions(-)
fs/nfs/nfs4proc.c +6 -0
@@ -5950,6 +5950,7 @@ static void nfs4_layoutcommit_release(void *calldata) {struct nfs4_layoutcommit_data *data = calldata;struct pnfs_layout_segment *lseg, *tmp; +unsigned long *bitlock = &NFS_I (data->args.inode)->flags;pnfs_cleanup_layoutcommit (data);/* Matched by references in pnfs_set_layoutcommit */
@@ -5959,6 +5960,11 @@ static void nfs4_layoutcommit_release(void *calldata) &lseg->pls_flags))put_lseg (lseg); } + +clear_bit_unlock (NFS_INO_LAYOUTCOMMITTING , bitlock); +smp_mb__after_clear_bit (); +wake_up_bit (bitlock,NFS_INO_LAYOUTCOMMITTING ); +put_rpccred (data->cred);kfree (data); }
fs/nfs/pnfs.c +22 -3
@@ -1443,17 +1443,31 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)/* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ data =kzalloc (sizeof (*data),GFP_NOFS );if (!data) { -mark_inode_dirty_sync (inode); status = -ENOMEM ; goto out; } +if (!test_bit (NFS_INO_LAYOUTCOMMIT , &nfsi->flags)) + goto out_free; + +if (test_and_set_bit (NFS_INO_LAYOUTCOMMITTING , &nfsi->flags)) { +if (!sync) { + status = -EAGAIN ; + goto out_free; + } + status =wait_on_bit_lock (&nfsi->flags,NFS_INO_LAYOUTCOMMITTING , + nfs_wait_bit_killable,TASK_KILLABLE ); +if (status) + goto out_free; + } +INIT_LIST_HEAD (&data->lseg_list);spin_lock (&inode->i_lock);if (!test_and_clear_bit (NFS_INO_LAYOUTCOMMIT , &nfsi->flags)) { +clear_bit (NFS_INO_LAYOUTCOMMITTING , &nfsi->flags);spin_unlock (&inode->i_lock); -kfree (data); - goto out; +wake_up_bit (&nfsi->flags,NFS_INO_LAYOUTCOMMITTING ); + goto out_free; }pnfs_list_write_lseg (inode, &data->lseg_list);
@@ -1475,6 +1489,11 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) status =nfs4_proc_layoutcommit (data, sync); out: +if (status) +mark_inode_dirty_sync (inode);dprintk ("<-- %s status %d\n" , __func__, status);return status; +out_free: +kfree (data); + goto out; }
include/linux/nfs_fs.h +1 -0
@@ -229,6 +229,7 @@ struct nfs_inode {#define NFS_INO_COMMIT (7)/* inode is committing unstable writes */ #define NFS_INO_PNFS_COMMIT (8)/* use pnfs code for commit */ #define NFS_INO_LAYOUTCOMMIT (9)/* layoutcommit required */ +#define NFS_INO_LAYOUTCOMMITTING (10)/* layoutcommit inflight */ static inline struct nfs_inode *NFS_I (const struct inode *inode) {
Signature · 1 line
1.7.1.262.g5ef3d