mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
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>
This commit is contained in:
parent
d3db90e270
commit
4f390c152b
5 changed files with 59 additions and 48 deletions
|
@ -425,14 +425,15 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
|
|||
}
|
||||
|
||||
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, struct qstr *name, struct qstr *path,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue