[pnfs] [PATCH 4/8] pnfs: split pnfs_update_layout into done routine
Benny Halevy
bhalevy at panasas.com
Wed Mar 12 10:43:42 EDT 2008
On Mar. 10, 2008, 20:39 +0200, andros at umich.edu wrote:
> 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,
> };
Oh, gdata, arg, and res can't be allocated on the stack
and passed to the async rpc! You must dynamically allocated them
and free in the _release rpc method.
It's going to be easier if the args and res will be
embedded in struct nfs4_pnfs_layoutget
How about renaming it and redefining as follows
(so it will be consistent with present rpc callback data structs):
struct pnfs_layoutget_data {
struct nfs4_pnfs_layoutget_arg args;
struct nfs4_pnfs_layoutget_res res;
struct pnfs_layout_segment **lsegpp;
int rpc_status;
};
See nfs4_opendata for example.
Benny
> 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 {
More information about the pNFS
mailing list