[pnfs] [PATCH 1/6] pnfs: fix commit lseg reference counting

Andy Adamson andros at netapp.com
Mon Jul 28 09:42:03 EDT 2008


On Sun, 2008-07-27 at 19:50 +0300, Benny Halevy wrote:
> On Wed, 23 Jul 2008 15:05:09 -0400 andros at netapp.com wrote:
> > From: Andy Adamson <andros at localhost.localdomain>
> 
> Also, Andy, this looks like a bogus author address...

Sorry. I saw this and don't know what happened.

-->Andy

> 
> Benny
> 
> > 
> > This fixes a bug where destroy_lseg was not called at umount for the
> > filelayout driver.
> > 
> > The commit lseg kref is incremented by pnfs_has_layout in pnfs_update_layout
> > called in the COMMIT path. Refactor nfs_initiate_commit to match the read and
> > write code by adding an rpc_call_ops parameter. This allows the filelayout
> > driver (as the non-RPC drivers do) to call pnfs_commit_done->pnfs_call_done->
> > put_lseg, and then call the nfs_commit_ops rpc_call_done and rpc_release
> > routines.
> > 
> > An lseg reference is already taken for a COMMIT to the MDS, or a COMMIT to the
> > first data server.  Add a kref_get on the commit lseg for the remaining data
> > servers.
> > 
> > Signed-off-by: Andy Adamson<andros at netapp.com>
> > ---
> >  fs/nfs/internal.h       |    4 +++-
> >  fs/nfs/nfs4filelayout.c |   24 ++++++++++++++++++++++--
> >  fs/nfs/nfs4proc.c       |    2 +-
> >  fs/nfs/pnfs.c           |    3 ++-
> >  fs/nfs/write.c          |    6 ++++--
> >  5 files changed, 32 insertions(+), 7 deletions(-)
> > 
> > diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
> > index 1db3d4b..f6308d1 100644
> > --- a/fs/nfs/internal.h
> > +++ b/fs/nfs/internal.h
> > @@ -212,7 +212,9 @@ extern int nfs_initiate_write(struct nfs_write_data *data,
> >  			      int how);
> >  extern int nfs_write_validate(struct rpc_task *task, void *calldata);
> >  extern int nfs_initiate_commit(struct nfs_write_data *data,
> > -			       struct rpc_clnt *clnt, int how);
> > +			       struct rpc_clnt *clnt,
> > +			       const struct rpc_call_ops *call_ops,
> > +			       int how);
> >  extern int nfs_flush_one(struct inode *inode, struct list_head *head,
> >  			 unsigned int npages, size_t count, int how);
> >  
> > diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
> > index 7ed06ac..6d0ae53 100644
> > --- a/fs/nfs/nfs4filelayout.c
> > +++ b/fs/nfs/nfs4filelayout.c
> > @@ -558,12 +558,25 @@ filelayout_clone_write_data(struct nfs_write_data *old)
> >  	nfs_fattr_init(&new->fattr);
> >  	new->res.verf    = &new->verf;
> >  	new->args.context = old->args.context;
> > +	new->pdata.lseg = old->pdata.lseg;
> >  	new->pdata.call_ops = old->pdata.call_ops;
> >  	new->pdata.how = old->pdata.how;
> >  out:
> >  	return new;
> >  }
> >  
> > +static void filelayout_commit_call_done(struct rpc_task *task, void *data)
> > +{
> > +	struct nfs_write_data *wdata = (struct nfs_write_data *)data;
> > +
> > +	pnfs_callback_ops->nfs_commit_complete(wdata);
> > +}
> > +
> > +struct rpc_call_ops filelayout_commit_call_ops = {
> > +	.rpc_call_validate_args = nfs_write_validate,
> > +	.rpc_call_done = filelayout_commit_call_done,
> > +};
> > +
> >  /*
> >   * Execute a COMMIT op to the MDS or to each data server on which a page
> >   * in 'pages' exists.
> > @@ -630,8 +643,14 @@ filelayout_commit(struct pnfs_layout_type *layoutid, int sync,
> >  			data->pdata.pnfs_error = -ENOMEM;
> >  			goto out;
> >  		}
> > -		if (count != 0)
> > +		if (count != 0) {
> > +			/* The open context and layout segment have
> > +			 * have been referenced for the call to the first
> > +			 * data server. Do the same for any other data servers.
> > +			 */
> >  			atomic_inc(&dsdata->args.context->count);
> > +			kref_get(&data->pdata.lseg->kref);
> > +		}
> >  
> >  		/* Just try the first multipath data server */
> >  		ds = dserver.dev->ds_list[0];
> > @@ -661,7 +680,8 @@ filelayout_commit(struct pnfs_layout_type *layoutid, int sync,
> >  		print_ds(ds);
> >  
> >  		/* Send COMMIT to data server */
> > -		nfs_initiate_commit(dsdata, dsdata->fldata.pnfs_client, sync);
> > +		nfs_initiate_commit(dsdata, dsdata->fldata.pnfs_client,
> > +				    &filelayout_commit_call_ops, sync);
> >  		count++;
> >  	}
> >  
> > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> > index 540a3b8..379f98c 100644
> > --- a/fs/nfs/nfs4proc.c
> > +++ b/fs/nfs/nfs4proc.c
> > @@ -3067,7 +3067,7 @@ static int pnfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
> >  }
> >  
> >  /*
> > - * rpc_call_done callback for a write to the MDS or to a filelayout Data Server
> > + * rpc_call_done callback for a commit to the MDS or to a filelayout Data Server
> >   */
> >  static int pnfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
> >  {
> > diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
> > index 21c5c8d..47e00ea 100644
> > --- a/fs/nfs/pnfs.c
> > +++ b/fs/nfs/pnfs.c
> > @@ -392,6 +392,7 @@ destroy_lseg(struct kref *kref)
> >  	struct pnfs_layout_segment *lseg =
> >  		container_of(kref, struct pnfs_layout_segment, kref);
> >  
> > +	dprintk("--> %s\n", __func__);
> >  	PNFS_LD_IO_OPS(lseg->layout)->free_lseg(lseg);
> >  }
> >  
> > @@ -1738,7 +1739,7 @@ _pnfs_try_to_commit(struct nfs_write_data *data,
> >  	}
> >  }
> >  
> > -/* pNFS Commit callback function for non-file layout drivers */
> > +/* pNFS Commit callback function */
> >  static void
> >  pnfs_commit_done(struct nfs_write_data *data)
> >  {
> > diff --git a/fs/nfs/write.c b/fs/nfs/write.c
> > index 71a9dcc..b62aee7 100644
> > --- a/fs/nfs/write.c
> > +++ b/fs/nfs/write.c
> > @@ -1245,6 +1245,7 @@ void nfs_commitdata_release(void *data)
> >  
> >  int nfs_initiate_commit(struct nfs_write_data *data,
> >  			struct rpc_clnt *clnt,
> > +			const struct rpc_call_ops *call_ops,
> >  			int how)
> >  {
> >  	struct inode *inode = data->inode;
> > @@ -1260,7 +1261,7 @@ int nfs_initiate_commit(struct nfs_write_data *data,
> >  		.task = &data->task,
> >  		.rpc_client = clnt,
> >  		.rpc_message = &msg,
> > -		.callback_ops = &nfs_commit_ops,
> > +		.callback_ops = call_ops,
> >  		.callback_data = data,
> >  		.workqueue = nfsiod_workqueue,
> >  		.flags = flags,
> > @@ -1315,7 +1316,8 @@ static int nfs_commit_rpcsetup(struct list_head *head,
> >  	if (ret == PNFS_ATTEMPTED)
> >  		return pnfs_get_write_status(data);
> >  
> > -	return nfs_initiate_commit(data, NFS_CLIENT(inode), how);
> > +	return nfs_initiate_commit(data, NFS_CLIENT(inode), &nfs_commit_ops,
> > +				   how);
> >  }
> >  
> >  /*


More information about the pNFS mailing list