From: Andreas Gruenbacher Subject: Pass nameidata2 to vfs_unlink() Instead of passing independent dentry and vfsmount parameters, use a nameidata2. Signed-off-by: Andreas Gruenbacher --- fs/ecryptfs/inode.c | 18 ++++++------------ fs/namei.c | 7 ++++--- fs/nfsd/nfs4recover.c | 6 +++++- fs/nfsd/vfs.c | 2 +- include/linux/fs.h | 2 +- ipc/mqueue.c | 6 +++++- 6 files changed, 22 insertions(+), 19 deletions(-) --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -42,12 +42,6 @@ static struct dentry *lock_parent(struct return dir; } -static void unlock_parent(struct dentry *dentry) -{ - mutex_unlock(&(dentry->d_parent->d_inode->i_mutex)); - dput(dentry->d_parent); -} - static void unlock_dir(struct dentry *dir) { mutex_unlock(&dir->d_inode->i_mutex); @@ -447,23 +441,23 @@ out_lock: static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) { + struct nameidata2 nd = {}; int rc = 0; struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); - struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); - lock_parent(lower_dentry); - rc = vfs_unlink(lower_dir_inode, lower_dentry, lower_mnt); + nd.dentry = lock_parent(lower_dentry); + nd.mnt = ecryptfs_dentry_to_lower_mnt(dentry); + rc = vfs_unlink(&nd, lower_dentry); if (rc) { printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); goto out_unlock; } - fsstack_copy_attr_times(dir, lower_dir_inode); + fsstack_copy_attr_times(dir, nd.dentry->d_inode); dentry->d_inode->i_nlink = ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink; dentry->d_inode->i_ctime = dir->i_ctime; out_unlock: - unlock_parent(lower_dentry); + unlock_dir(nd.dentry); return rc; } --- a/fs/namei.c +++ b/fs/namei.c @@ -2090,8 +2090,9 @@ asmlinkage long sys_rmdir(const char __u return do_rmdir(AT_FDCWD, pathname); } -int vfs_unlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt) +int vfs_unlink(struct nameidata2 *nd, struct dentry *dentry) { + struct inode *dir = nd->dentry->d_inode; int error = may_delete(dir, dentry, 0); if (error) @@ -2106,7 +2107,7 @@ int vfs_unlink(struct inode *dir, struct if (d_mountpoint(dentry)) error = -EBUSY; else { - error = security_inode_unlink(dir, dentry, mnt); + error = security_inode_unlink(dir, dentry, nd->mnt); if (!error) error = dir->i_op->unlink(dir, dentry); } @@ -2154,7 +2155,7 @@ static long do_unlinkat(int dfd, const c inode = dentry->d_inode; if (inode) atomic_inc(&inode->i_count); - error = vfs_unlink(nd.dentry->d_inode, dentry, nd.mnt); + error = vfs_unlink(ND2(&nd), dentry); exit2: dput(dentry); } --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -253,6 +253,10 @@ out: static int nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry) { + struct nameidata2 nd = { + .dentry = dir, + .mnt = rec_dir.mnt, + }; int status; if (!S_ISREG(dir->d_inode->i_mode)) { @@ -260,7 +264,7 @@ nfsd4_remove_clid_file(struct dentry *di return -EINVAL; } mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); - status = vfs_unlink(dir->d_inode, dentry, rec_dir.mnt); + status = vfs_unlink(&nd, dentry); mutex_unlock(&dir->d_inode->i_mutex); return status; } --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1724,7 +1724,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru host_err = -EPERM; } else #endif - host_err = vfs_unlink(dirp, rdentry, exp->ex_mnt); + host_err = vfs_unlink(&nd, rdentry); } else { /* It's RMDIR */ host_err = vfs_rmdir(&nd, rdentry); } --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -989,7 +989,7 @@ extern int vfs_mknod(struct nameidata2 * extern int vfs_symlink(struct nameidata2 *, struct dentry *, const char *, int); extern int vfs_link(struct nameidata2 *, struct dentry *, struct nameidata2 *); extern int vfs_rmdir(struct nameidata2 *, struct dentry *); -extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *); +extern int vfs_unlink(struct nameidata2 *, struct dentry *); extern int vfs_rename(struct nameidata2 *, struct dentry *, struct nameidata2 *, struct dentry *); /* --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -725,6 +725,10 @@ out_putname: asmlinkage long sys_mq_unlink(const char __user *u_name) { + struct nameidata2 nd = { + .dentry = mqueue_mnt->mnt_root, + /* Not a mounted filesystem, so set .mnt to NULL. */ + }; int err; char *name; struct dentry *dentry; @@ -751,7 +755,7 @@ asmlinkage long sys_mq_unlink(const char if (inode) atomic_inc(&inode->i_count); - err = vfs_unlink(dentry->d_parent->d_inode, dentry, mqueue_mnt); + err = vfs_unlink(&nd, dentry); out_err: dput(dentry);