aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.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/dir.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/dir.c')
-rw-r--r--fs/nfs/dir.c16
1 files changed, 4 insertions, 12 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 084e8cb41c84..affd3ae52e55 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1147,23 +1147,20 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
1147 struct inode *dir = dentry->d_parent->d_inode; 1147 struct inode *dir = dentry->d_parent->d_inode;
1148 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); 1148 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
1149 if (error) 1149 if (error)
1150 goto out_err; 1150 return error;
1151 } 1151 }
1152 if (!(fattr->valid & NFS_ATTR_FATTR)) { 1152 if (!(fattr->valid & NFS_ATTR_FATTR)) {
1153 struct nfs_server *server = NFS_SB(dentry->d_sb); 1153 struct nfs_server *server = NFS_SB(dentry->d_sb);
1154 error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); 1154 error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr);
1155 if (error < 0) 1155 if (error < 0)
1156 goto out_err; 1156 return error;
1157 } 1157 }
1158 inode = nfs_fhget(dentry->d_sb, fhandle, fattr); 1158 inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
1159 error = PTR_ERR(inode); 1159 error = PTR_ERR(inode);
1160 if (IS_ERR(inode)) 1160 if (IS_ERR(inode))
1161 goto out_err; 1161 return error;
1162 d_instantiate(dentry, inode); 1162 d_instantiate(dentry, inode);
1163 return 0; 1163 return 0;
1164out_err:
1165 d_drop(dentry);
1166 return error;
1167} 1164}
1168 1165
1169/* 1166/*
@@ -1448,8 +1445,6 @@ static int
1448nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 1445nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1449{ 1446{
1450 struct iattr attr; 1447 struct iattr attr;
1451 struct nfs_fattr sym_attr;
1452 struct nfs_fh sym_fh;
1453 struct qstr qsymname; 1448 struct qstr qsymname;
1454 int error; 1449 int error;
1455 1450
@@ -1473,12 +1468,9 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
1473 1468
1474 lock_kernel(); 1469 lock_kernel();
1475 nfs_begin_data_update(dir); 1470 nfs_begin_data_update(dir);
1476 error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname, 1471 error = NFS_PROTO(dir)->symlink(dir, dentry, &qsymname, &attr);
1477 &attr, &sym_fh, &sym_attr);
1478 nfs_end_data_update(dir); 1472 nfs_end_data_update(dir);
1479 if (!error) 1473 if (!error)
1480 error = nfs_instantiate(dentry, &sym_fh, &sym_attr);
1481 else
1482 d_drop(dentry); 1474 d_drop(dentry);
1483 unlock_kernel(); 1475 unlock_kernel();
1484 return error; 1476 return error;