Commit 892cd4a3 authored by Peng Tao's avatar Peng Tao Committed by Greg Kroah-Hartman

pnfs: let layoutcommit handle a list of lseg

commit a9bae566 upstream.

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

[Needed in v3.0]
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>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent f45c1d46
...@@ -5850,9 +5850,15 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) ...@@ -5850,9 +5850,15 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
static void nfs4_layoutcommit_release(void *calldata) static void nfs4_layoutcommit_release(void *calldata)
{ {
struct nfs4_layoutcommit_data *data = calldata; struct nfs4_layoutcommit_data *data = calldata;
struct pnfs_layout_segment *lseg, *tmp;
/* Matched by references in pnfs_set_layoutcommit */ /* 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); put_rpccred(data->cred);
kfree(data); kfree(data);
} }
......
...@@ -224,6 +224,7 @@ static void ...@@ -224,6 +224,7 @@ static void
init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg) init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg)
{ {
INIT_LIST_HEAD(&lseg->pls_list); INIT_LIST_HEAD(&lseg->pls_list);
INIT_LIST_HEAD(&lseg->pls_lc_list);
atomic_set(&lseg->pls_refcount, 1); atomic_set(&lseg->pls_refcount, 1);
smp_mb(); smp_mb();
set_bit(NFS_LSEG_VALID, &lseg->pls_flags); set_bit(NFS_LSEG_VALID, &lseg->pls_flags);
...@@ -1201,16 +1202,17 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata, ...@@ -1201,16 +1202,17 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata,
} }
/* /*
* 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) list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) {
if (lseg->pls_range.iomode == IOMODE_RW) if (lseg->pls_range.iomode == IOMODE_RW &&
rv = lseg; test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
return rv; list_add(&lseg->pls_lc_list, listp);
}
} }
void void
...@@ -1222,12 +1224,14 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) ...@@ -1222,12 +1224,14 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
spin_lock(&nfsi->vfs_inode.i_lock); spin_lock(&nfsi->vfs_inode.i_lock);
if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
/* references matched in nfs4_layoutcommit_release */
get_lseg(wdata->lseg);
mark_as_dirty = true; mark_as_dirty = true;
dprintk("%s: Set layoutcommit for inode %lu ", dprintk("%s: Set layoutcommit for inode %lu ",
__func__, wdata->inode->i_ino); __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) if (end_pos > nfsi->layout->plh_lwb)
nfsi->layout->plh_lwb = end_pos; nfsi->layout->plh_lwb = end_pos;
spin_unlock(&nfsi->vfs_inode.i_lock); spin_unlock(&nfsi->vfs_inode.i_lock);
...@@ -1254,7 +1258,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) ...@@ -1254,7 +1258,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
{ {
struct nfs4_layoutcommit_data *data; struct nfs4_layoutcommit_data *data;
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
struct pnfs_layout_segment *lseg;
loff_t end_pos; loff_t end_pos;
int status = 0; int status = 0;
...@@ -1271,17 +1274,15 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) ...@@ -1271,17 +1274,15 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
goto out; goto out;
} }
INIT_LIST_HEAD(&data->lseg_list);
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
kfree(data); kfree(data);
goto out; goto out;
} }
/*
* Currently only one (whole file) write lseg which is referenced pnfs_list_write_lseg(inode, &data->lseg_list);
* in pnfs_set_layoutcommit and will be found.
*/
lseg = pnfs_list_write_lseg(inode);
end_pos = nfsi->layout->plh_lwb; end_pos = nfsi->layout->plh_lwb;
nfsi->layout->plh_lwb = 0; nfsi->layout->plh_lwb = 0;
...@@ -1291,7 +1292,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) ...@@ -1291,7 +1292,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
data->args.inode = inode; data->args.inode = inode;
data->lseg = lseg;
data->cred = get_rpccred(nfsi->layout->plh_lc_cred); data->cred = get_rpccred(nfsi->layout->plh_lc_cred);
nfs_fattr_init(&data->fattr); nfs_fattr_init(&data->fattr);
data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
......
...@@ -36,10 +36,12 @@ ...@@ -36,10 +36,12 @@
enum { enum {
NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */ NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */
NFS_LSEG_ROC, /* roc bit received from server */ NFS_LSEG_ROC, /* roc bit received from server */
NFS_LSEG_LAYOUTCOMMIT, /* layoutcommit bit set for layoutcommit */
}; };
struct pnfs_layout_segment { struct pnfs_layout_segment {
struct list_head pls_list; struct list_head pls_list;
struct list_head pls_lc_list;
struct pnfs_layout_range pls_range; struct pnfs_layout_range pls_range;
atomic_t pls_refcount; atomic_t pls_refcount;
unsigned long pls_flags; unsigned long pls_flags;
......
...@@ -262,7 +262,7 @@ struct nfs4_layoutcommit_res { ...@@ -262,7 +262,7 @@ struct nfs4_layoutcommit_res {
struct nfs4_layoutcommit_data { struct nfs4_layoutcommit_data {
struct rpc_task task; struct rpc_task task;
struct nfs_fattr fattr; struct nfs_fattr fattr;
struct pnfs_layout_segment *lseg; struct list_head lseg_list;
struct rpc_cred *cred; struct rpc_cred *cred;
struct nfs4_layoutcommit_args args; struct nfs4_layoutcommit_args args;
struct nfs4_layoutcommit_res res; struct nfs4_layoutcommit_res res;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment