Commit 68adb0af authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: rpc_unlink() must check for unhashed dentries



A prior call to rpc_depopulate() by rpc_rmdir() on the parent directory may
have already called simple_unlink() on this entry.
Add the same check to rpc_rmdir(). Also remove a redundant call to
rpc_close_pipes() in rpc_rmdir.

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
(cherry picked from 0bbfb9d20f6437c4031aa3bf9b4d311a053e58e3 commit)
parent dff02cc1
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -539,6 +539,7 @@ repeat:
				rpc_close_pipes(dentry->d_inode);
				simple_unlink(dir, dentry);
			}
			inode_dir_notify(dir, DN_DELETE);
			dput(dentry);
		} while (n);
		goto repeat;
@@ -610,8 +611,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry)
	int error;

	shrink_dcache_parent(dentry);
	if (dentry->d_inode)
		rpc_close_pipes(dentry->d_inode);
	if (d_unhashed(dentry))
		return 0;
	if ((error = simple_rmdir(dir, dentry)) != 0)
		return error;
	if (!error) {
@@ -747,13 +748,15 @@ rpc_unlink(struct dentry *dentry)
	parent = dget_parent(dentry);
	dir = parent->d_inode;
	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
	if (!d_unhashed(dentry)) {
		d_drop(dentry);
		if (dentry->d_inode) {
			rpc_close_pipes(dentry->d_inode);
			error = simple_unlink(dir, dentry);
		}
	dput(dentry);
		inode_dir_notify(dir, DN_DELETE);
	}
	dput(dentry);
	mutex_unlock(&dir->i_mutex);
	dput(parent);
	return error;