From: Trond Myklebust <trond.myklebust@fys.uio.no>
To: Chuck Lever <chucklever@gmail.com>
Cc: nfs@lists.sourceforge.net
Subject: Re: [PATCH 23/25] NFS: Fix double d_drop in nfs_instantiate() error path
Date: Wed, 09 Aug 2006 11:34:27 -0400 [thread overview]
Message-ID: <1155137667.5731.90.camel@localhost> (raw)
In-Reply-To: <20060809145946.3914.34497.stgit@picasso.dsl.sfldmi.ameritech.net>
On Wed, 2006-08-09 at 10:59 -0400, Chuck Lever wrote:
> If the LOOKUP or GETATTR in nfs_instantiate fail, nfs_instantiate will do a
> d_drop before returning. But some callers already do a d_drop in the case
> of an error return. Make certain we do only one d_drop in all error paths.
Hmm... Calling d_drop() twice is at worst an inefficiency. It is not
strictly speaking a bug.
> This bug was introduced because over time, the symlink proc API diverged
> slightly from the create/mkdir/mknod proc API. To prevent other bugs of
> this type, change the symlink proc API to be more like create/mkdir/mknod
> and move the nfs_instantiate call into the symlink proc routines so it is
> used in exactly the same way for create, mkdir, mknod, and symlink.
>
> Test plan:
> Connectathon, all versions of NFS.
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
>
> fs/nfs/dir.c | 16 ++++------------
> fs/nfs/nfs3proc.c | 26 ++++++++++++++++----------
> fs/nfs/nfs4proc.c | 31 ++++++++++++++++---------------
> fs/nfs/proc.c | 29 +++++++++++++++++++++--------
> include/linux/nfs_xdr.h | 5 ++---
> 5 files changed, 59 insertions(+), 48 deletions(-)
>
> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> index 428d963..ff4e852 100644
> --- a/fs/nfs/dir.c
> +++ b/fs/nfs/dir.c
> @@ -1143,23 +1143,20 @@ int nfs_instantiate(struct dentry *dentr
> struct inode *dir = dentry->d_parent->d_inode;
> error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
> if (error)
> - goto out_err;
> + return error;
> }
> if (!(fattr->valid & NFS_ATTR_FATTR)) {
> struct nfs_server *server = NFS_SB(dentry->d_sb);
> error = server->rpc_ops->getattr(server, fhandle, fattr);
> if (error < 0)
> - goto out_err;
> + return error;
> }
> inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
> error = PTR_ERR(inode);
> if (IS_ERR(inode))
> - goto out_err;
> + return error;
> d_instantiate(dentry, inode);
> return 0;
> -out_err:
> - d_drop(dentry);
> - return error;
> }
>
> /*
> @@ -1444,8 +1441,6 @@ static int
> nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
> {
> struct iattr attr;
> - struct nfs_fattr sym_attr;
> - struct nfs_fh sym_fh;
> struct qstr qsymname;
> int error;
>
> @@ -1469,12 +1464,9 @@ #endif
>
> lock_kernel();
> nfs_begin_data_update(dir);
> - error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname,
> - &attr, &sym_fh, &sym_attr);
> + error = NFS_PROTO(dir)->symlink(dir, dentry, &qsymname, &attr);
> nfs_end_data_update(dir);
> if (!error)
> - error = nfs_instantiate(dentry, &sym_fh, &sym_attr);
> - else
> d_drop(dentry);
> unlock_kernel();
> return error;
> diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
> index 7143b1f..15eac8d 100644
> --- a/fs/nfs/nfs3proc.c
> +++ b/fs/nfs/nfs3proc.c
> @@ -544,23 +544,23 @@ nfs3_proc_link(struct inode *inode, stru
> }
>
> static int
> -nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
> - struct iattr *sattr, struct nfs_fh *fhandle,
> - struct nfs_fattr *fattr)
> +nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct qstr *path,
> + struct iattr *sattr)
> {
> - struct nfs_fattr dir_attr;
> + struct nfs_fh fhandle;
> + struct nfs_fattr fattr, dir_attr;
> struct nfs3_symlinkargs arg = {
> .fromfh = NFS_FH(dir),
> - .fromname = name->name,
> - .fromlen = name->len,
> + .fromname = dentry->d_name.name,
> + .fromlen = dentry->d_name.len,
> .topath = path->name,
> .tolen = path->len,
> .sattr = sattr
> };
> struct nfs3_diropres res = {
> .dir_attr = &dir_attr,
> - .fh = fhandle,
> - .fattr = fattr
> + .fh = &fhandle,
> + .fattr = &fattr
> };
> struct rpc_message msg = {
> .rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK],
> @@ -571,11 +571,17 @@ nfs3_proc_symlink(struct inode *dir, str
>
> if (path->len > NFS3_MAXPATHLEN)
> return -ENAMETOOLONG;
> - dprintk("NFS call symlink %s -> %s\n", name->name, path->name);
> +
> + dprintk("NFS call symlink %s -> %s\n", dentry->d_name.name,
> + path->name);
> nfs_fattr_init(&dir_attr);
> - nfs_fattr_init(fattr);
> + nfs_fattr_init(&fattr);
> status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
> nfs_post_op_update_inode(dir, &dir_attr);
> + if (status != 0)
> + goto out;
> + status = nfs_instantiate(dentry, &fhandle, &fattr);
> +out:
> dprintk("NFS reply symlink: %d\n", status);
> return status;
> }
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index e6ee97f..370b5ab 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -2089,24 +2089,24 @@ static int nfs4_proc_link(struct inode *
> return err;
> }
>
> -static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
> - struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
> - struct nfs_fattr *fattr)
> +static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
> + struct qstr *path, struct iattr *sattr)
> {
> struct nfs_server *server = NFS_SERVER(dir);
> - struct nfs_fattr dir_fattr;
> + struct nfs_fh fhandle;
> + struct nfs_fattr fattr, dir_fattr;
> struct nfs4_create_arg arg = {
> .dir_fh = NFS_FH(dir),
> .server = server,
> - .name = name,
> + .name = &dentry->d_name,
> .attrs = sattr,
> .ftype = NF4LNK,
> .bitmask = server->attr_bitmask,
> };
> struct nfs4_create_res res = {
> .server = server,
> - .fh = fhandle,
> - .fattr = fattr,
> + .fh = &fhandle,
> + .fattr = &fattr,
> .dir_fattr = &dir_fattr,
> };
> struct rpc_message msg = {
> @@ -2118,27 +2118,28 @@ static int _nfs4_proc_symlink(struct ino
>
> if (path->len > NFS4_MAXPATHLEN)
> return -ENAMETOOLONG;
> +
> arg.u.symlink = path;
> - nfs_fattr_init(fattr);
> + nfs_fattr_init(&fattr);
> nfs_fattr_init(&dir_fattr);
>
> status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
> - if (!status)
> + if (!status) {
> update_changeattr(dir, &res.dir_cinfo);
> - nfs_post_op_update_inode(dir, res.dir_fattr);
> + nfs_post_op_update_inode(dir, res.dir_fattr);
> + status = nfs_instantiate(dentry, &fhandle, &fattr);
> + }
> return status;
> }
>
> -static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
> - struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
> - struct nfs_fattr *fattr)
> +static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
> + struct qstr *path, struct iattr *sattr)
> {
> struct nfs4_exception exception = { };
> int err;
> do {
> err = nfs4_handle_exception(NFS_SERVER(dir),
> - _nfs4_proc_symlink(dir, name, path, sattr,
> - fhandle, fattr),
> + _nfs4_proc_symlink(dir, dentry, path, sattr),
> &exception);
> } while (exception.retry);
> return err;
> diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
> index b3899ea..7512f71 100644
> --- a/fs/nfs/proc.c
> +++ b/fs/nfs/proc.c
> @@ -425,14 +425,15 @@ nfs_proc_link(struct inode *inode, struc
> }
>
> static int
> -nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
> - struct iattr *sattr, struct nfs_fh *fhandle,
> - struct nfs_fattr *fattr)
> +nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct qstr *path,
> + struct iattr *sattr)
> {
> + struct nfs_fh fhandle;
> + struct nfs_fattr fattr;
> struct nfs_symlinkargs arg = {
> .fromfh = NFS_FH(dir),
> - .fromname = name->name,
> - .fromlen = name->len,
> + .fromname = dentry->d_name.name,
> + .fromlen = dentry->d_name.len,
> .topath = path->name,
> .tolen = path->len,
> .sattr = sattr
> @@ -445,11 +446,23 @@ nfs_proc_symlink(struct inode *dir, stru
>
> if (path->len > NFS2_MAXPATHLEN)
> return -ENAMETOOLONG;
> - dprintk("NFS call symlink %s -> %s\n", name->name, path->name);
> - nfs_fattr_init(fattr);
> - fhandle->size = 0;
> +
> + dprintk("NFS call symlink %s -> %s\n", dentry->d_name.name,
> + path->name);
> status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
> nfs_mark_for_revalidate(dir);
> +
> + /*
> + * V2 SYMLINK requests don't return any attributes. Setting the
> + * filehandle size to zero indicates to nfs_instantiate that it
> + * should fill in the data with a LOOKUP call on the wire.
> + */
> + if (status == 0) {
> + nfs_fattr_init(&fattr);
> + fhandle.size = 0;
> + status = nfs_instantiate(dentry, &fhandle, &fattr);
> + }
> +
> dprintk("NFS reply symlink: %d\n", status);
> return status;
> }
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index 0c1093c..cfabcd1 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -790,9 +790,8 @@ struct nfs_rpc_ops {
> int (*rename) (struct inode *, struct qstr *,
> struct inode *, struct qstr *);
> int (*link) (struct inode *, struct inode *, struct qstr *);
> - int (*symlink) (struct inode *, struct qstr *, struct qstr *,
> - struct iattr *, struct nfs_fh *,
> - struct nfs_fattr *);
> + int (*symlink) (struct inode *, struct dentry *, struct qstr *,
> + struct iattr *);
> int (*mkdir) (struct inode *, struct dentry *, struct iattr *);
> int (*rmdir) (struct inode *, struct qstr *);
> int (*readdir) (struct dentry *, struct rpc_cred *,
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
next prev parent reply other threads:[~2006-08-09 15:35 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-08-09 14:47 [PATCH 00/25] RPC client transport switch, continued Chuck Lever
2006-08-09 14:58 ` [PATCH 01/25] SUNRPC: avoid choosing an IPMI port for RPC traffic Chuck Lever
2006-08-09 15:04 ` Christoph Hellwig
2006-08-09 14:58 ` [PATCH 02/25] SUNRPC: Create a helper to tell whether a transport is bound Chuck Lever
2006-08-09 15:19 ` Trond Myklebust
2006-08-09 15:27 ` Chuck Lever
2006-08-09 15:37 ` Trond Myklebust
2006-08-09 14:58 ` [PATCH 03/25] SUNRPC: Make RPC portmapper use per-transport storage Chuck Lever
2006-08-09 14:58 ` [PATCH 04/25] SUNRPC: Clean-up after recent changes to sunrpc/pmap_clnt.c Chuck Lever
2006-08-09 14:59 ` [PATCH 05/25] SUNRPC: Support for RPC child tasks no longer needed Chuck Lever
2006-08-09 14:59 ` [PATCH 06/25] SUNRPC: Introduce transport switch callout for pluggable rpcbind Chuck Lever
2006-08-09 14:59 ` [PATCH 07/25] SUNRPC: create API for getting remote peer address Chuck Lever
2006-08-09 15:06 ` Christoph Hellwig
2006-08-09 14:59 ` [PATCH 08/25] LOCKD: Teach lockd to use the new rpc_peeraddr() API Chuck Lever
2006-08-09 14:59 ` [PATCH 09/25] SUNRPC: Teach the RPC portmapper " Chuck Lever
2006-08-09 14:59 ` [PATCH 10/25] SUNRPC: remove extraneous header inclusions Chuck Lever
2006-08-09 14:59 ` [PATCH 11/25] SUNRPC: add xprt switch API for printing formatted remote peer addresses Chuck Lever
2006-08-09 14:59 ` [PATCH 12/25] SUNRPC: Create API for displaying remote peer address Chuck Lever
2006-08-09 14:59 ` [PATCH 13/25] SUNRPC: Teach rpc_pipe.c to use new rpc_peeraddr() API Chuck Lever
2006-08-09 14:59 ` [PATCH 14/25] SUNRPC: Use "sockaddr_storage" for storing RPC client's remote peer address Chuck Lever
2006-08-09 14:59 ` [PATCH 15/25] SUNRPC: Clean-up after previous patches Chuck Lever
2006-08-09 14:59 ` [PATCH 16/25] SUNRPC: use sockaddr + size when creating remote transport endpoints Chuck Lever
2006-08-09 14:59 ` [PATCH 17/25] LOCKD: Convert to use new rpc_create() API Chuck Lever
2006-08-09 14:59 ` [PATCH 18/25] NFS: Convert NFS client " Chuck Lever
2006-08-09 15:30 ` Trond Myklebust
2006-08-09 14:59 ` [PATCH 19/25] NFSD: Convert NFS server callback logic to use new rpc_create API Chuck Lever
2006-08-09 14:59 ` [PATCH 20/25] SUNRPC: Convert RPC portmapper to use new rpc_create() API Chuck Lever
2006-08-09 14:59 ` [PATCH 21/25] SUNRPC: Eliminate xprt_create_proto and rpc_create_client Chuck Lever
2006-08-09 14:59 ` [PATCH 22/25] NFS: remove a no-longer-needed error check in nfs_symlink() Chuck Lever
2006-08-10 2:10 ` Greg Banks
2006-08-10 12:36 ` Peter Staubach
2006-08-09 14:59 ` [PATCH 23/25] NFS: Fix double d_drop in nfs_instantiate() error path Chuck Lever
2006-08-09 15:34 ` Trond Myklebust [this message]
2006-08-09 14:59 ` [PATCH 24/25] NFS: copy symlinks into page cache before sending NFS SYMLINK request Chuck Lever
2006-08-09 14:59 ` [PATCH 25/25] NFS: Use cached page as buffer for NFS symlink requests Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1155137667.5731.90.camel@localhost \
--to=trond.myklebust@fys.uio.no \
--cc=chucklever@gmail.com \
--cc=nfs@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.