|
@@ -225,6 +225,7 @@ static void
|
|
|
init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg)
|
|
|
{
|
|
|
INIT_LIST_HEAD(&lseg->pls_list);
|
|
|
+ INIT_LIST_HEAD(&lseg->pls_lc_list);
|
|
|
atomic_set(&lseg->pls_refcount, 1);
|
|
|
smp_mb();
|
|
|
set_bit(NFS_LSEG_VALID, &lseg->pls_flags);
|
|
@@ -1356,16 +1357,17 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
|
|
|
EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages);
|
|
|
|
|
|
/*
|
|
|
- * Currently there is only one (whole file) write lseg.
|
|
|
+ * There can be multiple RW segments.
|
|
|
*/
|
|
|
-static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode)
|
|
|
+static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp)
|
|
|
{
|
|
|
- struct pnfs_layout_segment *lseg, *rv = NULL;
|
|
|
+ struct pnfs_layout_segment *lseg;
|
|
|
|
|
|
- list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list)
|
|
|
- if (lseg->pls_range.iomode == IOMODE_RW)
|
|
|
- rv = lseg;
|
|
|
- return rv;
|
|
|
+ list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) {
|
|
|
+ if (lseg->pls_range.iomode == IOMODE_RW &&
|
|
|
+ test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
|
|
|
+ list_add(&lseg->pls_lc_list, listp);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void
|
|
@@ -1377,12 +1379,14 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
|
|
|
|
|
|
spin_lock(&nfsi->vfs_inode.i_lock);
|
|
|
if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
|
|
|
- /* references matched in nfs4_layoutcommit_release */
|
|
|
- get_lseg(wdata->lseg);
|
|
|
mark_as_dirty = true;
|
|
|
dprintk("%s: Set layoutcommit for inode %lu ",
|
|
|
__func__, wdata->inode->i_ino);
|
|
|
}
|
|
|
+ if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &wdata->lseg->pls_flags)) {
|
|
|
+ /* references matched in nfs4_layoutcommit_release */
|
|
|
+ get_lseg(wdata->lseg);
|
|
|
+ }
|
|
|
if (end_pos > nfsi->layout->plh_lwb)
|
|
|
nfsi->layout->plh_lwb = end_pos;
|
|
|
spin_unlock(&nfsi->vfs_inode.i_lock);
|
|
@@ -1409,7 +1413,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
|
|
|
{
|
|
|
struct nfs4_layoutcommit_data *data;
|
|
|
struct nfs_inode *nfsi = NFS_I(inode);
|
|
|
- struct pnfs_layout_segment *lseg;
|
|
|
loff_t end_pos;
|
|
|
int status = 0;
|
|
|
|
|
@@ -1426,17 +1429,15 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
+ INIT_LIST_HEAD(&data->lseg_list);
|
|
|
spin_lock(&inode->i_lock);
|
|
|
if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
kfree(data);
|
|
|
goto out;
|
|
|
}
|
|
|
- /*
|
|
|
- * Currently only one (whole file) write lseg which is referenced
|
|
|
- * in pnfs_set_layoutcommit and will be found.
|
|
|
- */
|
|
|
- lseg = pnfs_list_write_lseg(inode);
|
|
|
+
|
|
|
+ pnfs_list_write_lseg(inode, &data->lseg_list);
|
|
|
|
|
|
end_pos = nfsi->layout->plh_lwb;
|
|
|
nfsi->layout->plh_lwb = 0;
|
|
@@ -1446,7 +1447,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
|
|
data->args.inode = inode;
|
|
|
- data->lseg = lseg;
|
|
|
data->cred = get_rpccred(nfsi->layout->plh_lc_cred);
|
|
|
nfs_fattr_init(&data->fattr);
|
|
|
data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
|