Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9bae566 authored by Peng Tao's avatar Peng Tao Committed by Trond Myklebust
Browse files

pnfs: let layoutcommit handle a list of lseg



There can be multiple lseg per file, so layoutcommit should be
able to handle it.

[Needed in v3.0]
CC: Stable Tree <stable@kernel.org>
Signed-off-by: default avatarPeng Tao <peng_tao@emc.com>
Signed-off-by: default avatarBoaz Harrosh <bharrosh@panasas.com>
Signed-off-by: default avatarJim Rees <rees@umich.edu>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 9fa40758
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -5912,9 +5912,15 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
static void nfs4_layoutcommit_release(void *calldata)
{
	struct nfs4_layoutcommit_data *data = calldata;
	struct pnfs_layout_segment *lseg, *tmp;

	/* Matched by references in pnfs_set_layoutcommit */
	put_lseg(data->lseg);
	list_for_each_entry_safe(lseg, tmp, &data->lseg_list, pls_lc_list) {
		list_del_init(&lseg->pls_lc_list);
		if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT,
				       &lseg->pls_flags))
			put_lseg(lseg);
	}
	put_rpccred(data->cred);
	kfree(data);
}
+16 −16
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -36,10 +36,12 @@
enum {
	NFS_LSEG_VALID = 0,	/* cleared when lseg is recalled/returned */
	NFS_LSEG_ROC,		/* roc bit received from server */
	NFS_LSEG_LAYOUTCOMMIT,	/* layoutcommit bit set for layoutcommit */
};

struct pnfs_layout_segment {
	struct list_head pls_list;
	struct list_head pls_lc_list;
	struct pnfs_layout_range pls_range;
	atomic_t pls_refcount;
	unsigned long pls_flags;
+1 −1
Original line number Diff line number Diff line
@@ -262,7 +262,7 @@ struct nfs4_layoutcommit_res {
struct nfs4_layoutcommit_data {
	struct rpc_task task;
	struct nfs_fattr fattr;
	struct pnfs_layout_segment *lseg;
	struct list_head lseg_list;
	struct rpc_cred *cred;
	struct nfs4_layoutcommit_args args;
	struct nfs4_layoutcommit_res res;