Commit 92407e75ce45b41c46944891711fd8faf0714d84

Authored by Peng Tao
Committed by Trond Myklebust
1 parent e20de37757

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 <gusev.vitaliy@nexenta.com>
Signed-off-by: Peng Tao <peng_tao@emc.com>
Signed-off-by: Jim Rees <rees@umich.edu>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 3 changed files with 29 additions and 3 deletions Side-by-side Diff

... ... @@ -5950,6 +5950,7 @@
5950 5950 {
5951 5951 struct nfs4_layoutcommit_data *data = calldata;
5952 5952 struct pnfs_layout_segment *lseg, *tmp;
  5953 + unsigned long *bitlock = &NFS_I(data->args.inode)->flags;
5953 5954  
5954 5955 pnfs_cleanup_layoutcommit(data);
5955 5956 /* Matched by references in pnfs_set_layoutcommit */
... ... @@ -5959,6 +5960,11 @@
5959 5960 &lseg->pls_flags))
5960 5961 put_lseg(lseg);
5961 5962 }
  5963 +
  5964 + clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
  5965 + smp_mb__after_clear_bit();
  5966 + wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
  5967 +
5962 5968 put_rpccred(data->cred);
5963 5969 kfree(data);
5964 5970 }
... ... @@ -1443,17 +1443,31 @@
1443 1443 /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */
1444 1444 data = kzalloc(sizeof(*data), GFP_NOFS);
1445 1445 if (!data) {
1446   - mark_inode_dirty_sync(inode);
1447 1446 status = -ENOMEM;
1448 1447 goto out;
1449 1448 }
1450 1449  
  1450 + if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
  1451 + goto out_free;
  1452 +
  1453 + if (test_and_set_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags)) {
  1454 + if (!sync) {
  1455 + status = -EAGAIN;
  1456 + goto out_free;
  1457 + }
  1458 + status = wait_on_bit_lock(&nfsi->flags, NFS_INO_LAYOUTCOMMITTING,
  1459 + nfs_wait_bit_killable, TASK_KILLABLE);
  1460 + if (status)
  1461 + goto out_free;
  1462 + }
  1463 +
1451 1464 INIT_LIST_HEAD(&data->lseg_list);
1452 1465 spin_lock(&inode->i_lock);
1453 1466 if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
  1467 + clear_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags);
1454 1468 spin_unlock(&inode->i_lock);
1455   - kfree(data);
1456   - goto out;
  1469 + wake_up_bit(&nfsi->flags, NFS_INO_LAYOUTCOMMITTING);
  1470 + goto out_free;
1457 1471 }
1458 1472  
1459 1473 pnfs_list_write_lseg(inode, &data->lseg_list);
1460 1474  
... ... @@ -1475,7 +1489,12 @@
1475 1489  
1476 1490 status = nfs4_proc_layoutcommit(data, sync);
1477 1491 out:
  1492 + if (status)
  1493 + mark_inode_dirty_sync(inode);
1478 1494 dprintk("<-- %s status %d\n", __func__, status);
1479 1495 return status;
  1496 +out_free:
  1497 + kfree(data);
  1498 + goto out;
1480 1499 }
include/linux/nfs_fs.h
... ... @@ -229,6 +229,7 @@
229 229 #define NFS_INO_COMMIT (7) /* inode is committing unstable writes */
230 230 #define NFS_INO_PNFS_COMMIT (8) /* use pnfs code for commit */
231 231 #define NFS_INO_LAYOUTCOMMIT (9) /* layoutcommit required */
  232 +#define NFS_INO_LAYOUTCOMMITTING (10) /* layoutcommit inflight */
232 233  
233 234 static inline struct nfs_inode *NFS_I(const struct inode *inode)
234 235 {