[pnfs] [PATCH 4/8] pnfs: split pnfs_update_layout into done routine
andros at umich.edu
andros at umich.edu
Mon Mar 10 14:39:16 EDT 2008
From: Andy Adamson <andros at umich.edu>
The new async nfs4_pnfs_layoutget_done() calls the bottom half of
pnfs_update_layout() now called pnfs_update_layout_done().
Replace the call to put_unlock_current_layout(), which will go into the rpc
release call, with spin_unlock().
Signed-off-by: Andy Adamson<andros at umich.edu>
---
fs/nfs/nfs4proc.c | 9 ++++-
fs/nfs/pnfs.c | 99 +++++++++++++++++++++++++++++-----------------
fs/nfs/pnfs.h | 3 +
include/linux/pnfs_xdr.h | 2 +
4 files changed, 76 insertions(+), 37 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index bcf9ea6..ef77a89 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5253,12 +5253,19 @@ static void nfs4_pnfs_layoutget_done(struct rpc_task *task, void *calldata)
struct nfs4_pnfs_layoutget *lgp = calldata;
struct inode *ino = lgp->args->inode;
struct nfs_server *server = NFS_SERVER(ino);
+ struct nfs_inode *nfsi = NFS_I(ino);
+ struct pnfs_layout_type *lo;
dprintk("--> %s\n", __func__);
if (RPC_ASSASSINATED(task))
return;
nfs4_sequence_done(server, &lgp->res->seq_res, task->tk_status);
+
+ lo = nfsi->current_layout;
+ BUG_ON(!lo);
+
+ pnfs_get_layout_done(lo, lgp, task->tk_status);
dprintk("<-- %s\n", __func__);
}
@@ -5294,7 +5301,7 @@ static int nfs4_proc_pnfs_layoutget(struct nfs4_pnfs_layoutget *lgp)
if (status != 0) {
smp_wmb();
} else
- status = task->tk_status;
+ status = lgp->status;
rpc_put_task(task);
dprintk("<-- %s\n", __func__);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 31158b6..7665188 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -825,6 +825,7 @@ pnfs_update_layout(struct inode *ino,
struct nfs4_pnfs_layoutget gdata = {
.args = &arg,
.res = &res,
+ .lsegpp = lsegpp,
};
struct nfs_inode *nfsi = NFS_I(ino);
struct nfs_server *nfss = NFS_SERVER(ino);
@@ -834,8 +835,9 @@ pnfs_update_layout(struct inode *ino,
lo = get_lock_alloc_layout(ino, nfss->pnfs_curr_ld->ld_io_ops);
if (IS_ERR(lo)) {
+ dprintk("%s ERROR: can't get pnfs_layout_type\n", __func__);
result = PTR_ERR(lo);
- goto ret;
+ goto out;
}
arg.lseg.iomode = iomode;
@@ -845,110 +847,135 @@ pnfs_update_layout(struct inode *ino,
lseg = pnfs_has_layout(lo, &arg.lseg, lsegpp != NULL);
if (lseg) {
dprintk("%s: Using cached layout %p for %llu@%llu iomode %d)\n",
- __FUNCTION__,
+ __func__,
nfsi->current_layout,
arg.lseg.length,
arg.lseg.offset,
arg.lseg.iomode);
result = 0;
- goto out;
+ goto out_put;
}
/* if get layout already failed once goto out */
if (nfsi->pnfs_layout_state & NFS_INO_LAYOUT_FAILED) {
if (unlikely(nfsi->pnfs_layout_suspend &&
get_seconds() >= nfsi->pnfs_layout_suspend)) {
- dprintk("%s: layout_get resumed\n", __FUNCTION__);
+ dprintk("%s: layout_get resumed\n", __func__);
nfsi->pnfs_layout_state &= ~NFS_INO_LAYOUT_FAILED;
nfsi->pnfs_layout_suspend = 0;
} else {
result = 1;
- goto out;
+ goto out_put;
}
}
res.layout.buf = NULL;
memcpy(&lo->stateid.data, &arg.stateid.data, NFS4_STATEID_SIZE);
spin_unlock(&nfsi->lo_lock);
+
result = get_layout(ino, ctx, &gdata);
+out:
+ dprintk("%s end (err:%d) state 0x%lx lseg %p\n",
+ __func__, result, nfsi->pnfs_layout_state, lseg);
+ return result;
+out_put:
+ if (lseg && lsegpp)
+ *lsegpp = lseg;
+ put_unlock_current_layout(nfsi, lo);
+ goto out;
+}
+
+void
+pnfs_get_layout_done(struct pnfs_layout_type *lo,
+ struct nfs4_pnfs_layoutget *lgp,
+ int rpc_status)
+{
+ struct nfs4_pnfs_layoutget_res *res = lgp->res;
+ struct pnfs_layout_segment *lseg = NULL;
+ struct nfs_inode *nfsi = NFS_I(lo->inode);
+
+ dprintk("-->%s \n", __func__);
+
spin_lock(&nfsi->lo_lock);
- /* FIXME: check for reordering using the returned sequence id */
- memcpy(&res.stateid.data, &lo->stateid.data, NFS4_STATEID_SIZE);
- /* we got a reference on nfsi->current_layout hence it must never
- * change, even while nfsi->lo_lock was not held.
- */
BUG_ON(nfsi->current_layout != lo);
- if (result) {
+ /* FIXME: check for reordering using the returned sequence id */
+ memcpy(&res->stateid.data, &lo->stateid.data, NFS4_STATEID_SIZE);
+
+ if (rpc_status) {
dprintk("%s: ERROR retrieving layout %d\n",
- __FUNCTION__, result);
+ __func__, rpc_status);
- switch (result) {
+ switch (rpc_status) {
case -ENOENT: /* NFS4ERR_BADLAYOUT */
/* transient error, don't mark with NFS_INO_LAYOUT_FAILED */
- result = 1;
+ lgp->status = 1;
break;
- case -EAGAIN: /* NFS4ERR_LAYOUTTRYLATER, NFS4ERR_RECALLCONFLICT, NFS4ERR_LOCKED */
+ case -EAGAIN: /* NFS4ERR_LAYOUTTRYLATER,
+ * NFS4ERR_RECALLCONFLICT, NFS4ERR_LOCKED
+ */
nfsi->pnfs_layout_suspend = get_seconds() + 1;
dprintk("%s: layout_get suspended until %ld\n",
- __FUNCTION__, nfsi->pnfs_layout_suspend);
+ __func__, nfsi->pnfs_layout_suspend);
break;
- case -EINVAL: /* NFS4ERR_INVAL, NFSERR_BADIOMODE, NFS4ERR_UNKNOWN_LAYOUTTYPE */
+ case -EINVAL: /* NFS4ERR_INVAL, NFSERR_BADIOMODE,
+ * NFS4ERR_UNKNOWN_LAYOUTTYPE
+ */
case -ENOTSUPP: /* NFS4ERR_LAYOUTUNAVAILABLE */
case -ETOOSMALL:/* NFS4ERR_TOOSMALL */
default:
/* suspend layout get for ever for this file */
nfsi->pnfs_layout_suspend = 0;
dprintk("%s: no layout_get until %ld\n",
- __FUNCTION__, nfsi->pnfs_layout_suspend);
+ __func__, nfsi->pnfs_layout_suspend);
/* mark with NFS_INO_LAYOUT_FAILED */
+ lgp->status = rpc_status;
break;
}
goto get_out;
}
- if (res.layout.len <= 0) {
+ if (res->layout.len <= 0) {
printk(KERN_ERR
"%s: ERROR! Layout size is ZERO!\n", __FUNCTION__);
- result = -EIO;
+ lgp->status = -EIO;
goto get_out;
}
/* Inject layout blob into I/O device driver */
- lseg = pnfs_inject_layout(lo, &res, lsegpp != NULL);
+ lseg = pnfs_inject_layout(lo, res, lgp->lsegpp != NULL);
if (IS_ERR(lseg)) {
- result = PTR_ERR(lseg);
+ lgp->status = PTR_ERR(lseg);
lseg = NULL;
printk(KERN_ERR "%s: ERROR! Could not inject layout (%d)\n",
- __FUNCTION__, result);
+ __func__, lgp->status);
goto get_out;
}
- if (res.return_on_close) {
- lo->roc_iomode |= res.lseg.iomode;
+ if (res->return_on_close) {
+ lo->roc_iomode |= res->lseg.iomode;
if (!lo->roc_iomode)
lo->roc_iomode = IOMODE_ANY;
}
+ lgp->status = 0;
- result = 0;
get_out:
+ spin_unlock(&nfsi->lo_lock);
/* remember that get layout failed and don't try again */
- if (result < 0)
+ if (lgp->status < 0)
nfsi->pnfs_layout_state |= NFS_INO_LAYOUT_FAILED;
- /* res.layout.buf kalloc'ed by the xdr decoder? */
- kfree(res.layout.buf);
-out:
- put_unlock_current_layout(nfsi, lo);
-ret:
+ /* res->layout.buf kalloc'ed by the xdr decoder? */
+ kfree(res->layout.buf);
+
dprintk("%s end (err:%d) state 0x%lx lseg %p\n",
- __FUNCTION__, result, nfsi->pnfs_layout_state, lseg);
- if (lsegpp)
- *lsegpp = lseg;
- return result;
+ __func__, lgp->status, nfsi->pnfs_layout_state, lseg);
+ if (lgp->lsegpp)
+ *lgp->lsegpp = lseg;
+ return;
}
/* Return true if a layout driver is being used for this mountpoint */
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 8e11489..c458b18 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -47,6 +47,9 @@ void pnfs_update_layout_commit(struct inode *, struct list_head *, pgoff_t, unsi
int pnfs_flush_one(struct inode *, struct list_head *, unsigned int, size_t, int);
void pnfs_free_request_data(struct nfs_page *req);
ssize_t pnfs_file_write(struct file *, const char __user *, size_t, loff_t *);
+void pnfs_get_layout_done(struct pnfs_layout_type *,
+ struct nfs4_pnfs_layoutget *, int);
+
#endif /* CONFIG_PNFS */
diff --git a/include/linux/pnfs_xdr.h b/include/linux/pnfs_xdr.h
index c6a4e3a..039c271 100644
--- a/include/linux/pnfs_xdr.h
+++ b/include/linux/pnfs_xdr.h
@@ -56,6 +56,8 @@ struct nfs4_pnfs_layoutget_res {
struct nfs4_pnfs_layoutget {
struct nfs4_pnfs_layoutget_arg *args;
struct nfs4_pnfs_layoutget_res *res;
+ struct pnfs_layout_segment **lsegpp;
+ int status;
};
struct pnfs_layoutcommit_arg {
--
1.5.0.2
More information about the pNFS
mailing list