aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.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/nfs4proc.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/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a825547e8214..2d18eac6bee5 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2084,24 +2084,24 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n
2084 return err; 2084 return err;
2085} 2085}
2086 2086
2087static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, 2087static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
2088 struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, 2088 struct qstr *path, struct iattr *sattr)
2089 struct nfs_fattr *fattr)
2090{ 2089{
2091 struct nfs_server *server = NFS_SERVER(dir); 2090 struct nfs_server *server = NFS_SERVER(dir);
2092 struct nfs_fattr dir_fattr; 2091 struct nfs_fh fhandle;
2092 struct nfs_fattr fattr, dir_fattr;
2093 struct nfs4_create_arg arg = { 2093 struct nfs4_create_arg arg = {
2094 .dir_fh = NFS_FH(dir), 2094 .dir_fh = NFS_FH(dir),
2095 .server = server, 2095 .server = server,
2096 .name = name, 2096 .name = &dentry->d_name,
2097 .attrs = sattr, 2097 .attrs = sattr,
2098 .ftype = NF4LNK, 2098 .ftype = NF4LNK,
2099 .bitmask = server->attr_bitmask, 2099 .bitmask = server->attr_bitmask,
2100 }; 2100 };
2101 struct nfs4_create_res res = { 2101 struct nfs4_create_res res = {
2102 .server = server, 2102 .server = server,
2103 .fh = fhandle, 2103 .fh = &fhandle,
2104 .fattr = fattr, 2104 .fattr = &fattr,
2105 .dir_fattr = &dir_fattr, 2105 .dir_fattr = &dir_fattr,
2106 }; 2106 };
2107 struct rpc_message msg = { 2107 struct rpc_message msg = {
@@ -2113,27 +2113,28 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
2113 2113
2114 if (path->len > NFS4_MAXPATHLEN) 2114 if (path->len > NFS4_MAXPATHLEN)
2115 return -ENAMETOOLONG; 2115 return -ENAMETOOLONG;
2116
2116 arg.u.symlink = path; 2117 arg.u.symlink = path;
2117 nfs_fattr_init(fattr); 2118 nfs_fattr_init(&fattr);
2118 nfs_fattr_init(&dir_fattr); 2119 nfs_fattr_init(&dir_fattr);
2119 2120
2120 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2121 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
2121 if (!status) 2122 if (!status) {
2122 update_changeattr(dir, &res.dir_cinfo); 2123 update_changeattr(dir, &res.dir_cinfo);
2123 nfs_post_op_update_inode(dir, res.dir_fattr); 2124 nfs_post_op_update_inode(dir, res.dir_fattr);
2125 status = nfs_instantiate(dentry, &fhandle, &fattr);
2126 }
2124 return status; 2127 return status;
2125} 2128}
2126 2129
2127static int nfs4_proc_symlink(struct inode *dir, struct qstr *name, 2130static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
2128 struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, 2131 struct qstr *path, struct iattr *sattr)
2129 struct nfs_fattr *fattr)
2130{ 2132{
2131 struct nfs4_exception exception = { }; 2133 struct nfs4_exception exception = { };
2132 int err; 2134 int err;
2133 do { 2135 do {
2134 err = nfs4_handle_exception(NFS_SERVER(dir), 2136 err = nfs4_handle_exception(NFS_SERVER(dir),
2135 _nfs4_proc_symlink(dir, name, path, sattr, 2137 _nfs4_proc_symlink(dir, dentry, path, sattr),
2136 fhandle, fattr),
2137 &exception); 2138 &exception);
2138 } while (exception.retry); 2139 } while (exception.retry);
2139 return err; 2140 return err;