|
@@ -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;
|
|
|
}
|