forked from Minki/linux
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: Peng Tao <peng_tao@emc.com> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Jim Rees <rees@umich.edu> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
9fa4075878
commit
a9bae5666d
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user