aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/proc.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2006-08-22 20:06:22 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-09-22 23:24:52 -0400
commit4f390c152bc87165da4b1f5b7d870b46fb106d4e (patch)
tree643b5d12f76bd7d3688380fbaf69f607a34a06bf /fs/nfs/proc.c
parentd3db90e270791b21cd00d3c094884bffa907cc9e (diff)
NFS: Fix double d_drop in nfs_instantiate() error path
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. This issue was introduced because over time, the symlink proc API diverged slightly from the create/mkdir/mknod proc API. To prevent other coding mistakes 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> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/proc.c')
-rw-r--r--fs/nfs/proc.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 5a8b9407ee9a..0b507bf0f330 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -425,14 +425,15 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
425} 425}
426 426
427static int 427static int
428nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, 428nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct qstr *path,
429 struct iattr *sattr, struct nfs_fh *fhandle, 429 struct iattr *sattr)
430 struct nfs_fattr *fattr)
431{ 430{
431 struct nfs_fh fhandle;
432 struct nfs_fattr fattr;
432 struct nfs_symlinkargs arg = { 433 struct nfs_symlinkargs arg = {
433 .fromfh = NFS_FH(dir), 434 .fromfh = NFS_FH(dir),
434 .fromname = name->name, 435 .fromname = dentry->d_name.name,
435 .fromlen = name->len, 436 .fromlen = dentry->d_name.len,
436 .topath = path->name, 437 .topath = path->name,
437 .tolen = path->len, 438 .tolen = path->len,
438 .sattr = sattr 439 .sattr = sattr
@@ -445,11 +446,23 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
445 446
446 if (path->len > NFS2_MAXPATHLEN) 447 if (path->len > NFS2_MAXPATHLEN)
447 return -ENAMETOOLONG; 448 return -ENAMETOOLONG;
448 dprintk("NFS call symlink %s -> %s\n", name->name, path->name); 449
449 nfs_fattr_init(fattr); 450 dprintk("NFS call symlink %s -> %s\n", dentry->d_name.name,
450 fhandle->size = 0; 451 path->name);
451 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 452 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
452 nfs_mark_for_revalidate(dir); 453 nfs_mark_for_revalidate(dir);
454
455 /*
456 * V2 SYMLINK requests don't return any attributes. Setting the
457 * filehandle size to zero indicates to nfs_instantiate that it
458 * should fill in the data with a LOOKUP call on the wire.
459 */
460 if (status == 0) {
461 nfs_fattr_init(&fattr);
462 fhandle.size = 0;
463 status = nfs_instantiate(dentry, &fhandle, &fattr);
464 }
465
453 dprintk("NFS reply symlink: %d\n", status); 466 dprintk("NFS reply symlink: %d\n", status);
454 return status; 467 return status;
455} 468}