diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2006-08-22 20:06:22 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-09-22 23:24:52 -0400 |
commit | 4f390c152bc87165da4b1f5b7d870b46fb106d4e (patch) | |
tree | 643b5d12f76bd7d3688380fbaf69f607a34a06bf /fs/nfs/nfs4proc.c | |
parent | d3db90e270791b21cd00d3c094884bffa907cc9e (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.c | 31 |
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 | ||
2087 | static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | 2087 | static 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 | ||
2127 | static int nfs4_proc_symlink(struct inode *dir, struct qstr *name, | 2130 | static 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; |