Move the body of vfs_unlink() into a static helper, __vfs_unlink(), that calls the method it is passed in place of ->unlink(), or ->unlink() when passed NULL. vfs_unlink() becomes a wrapper that passes NULL, so every caller behaves exactly as before; its kerneldoc, including the requirement that the caller hold the parent directory's lock exclusive, does not change. This prepares for a second removal method, called with the parent directory's lock held shared, which a following patch adds. Signed-off-by: Jonathan Flynn --- fs/namei.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index ce10a408d3..1b3a605ded 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -5679,6 +5679,12 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname) return filename_rmdir(AT_FDCWD, name); } +static int __vfs_unlink(const struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, + struct delegated_inode *delegated_inode, + int (*method)(struct inode *dir, + struct dentry *dentry)); + /** * vfs_unlink - unlink a filesystem object * @idmap: idmap of the mount the inode was found from @@ -5706,6 +5712,20 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname) */ int vfs_unlink(const struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, struct delegated_inode *delegated_inode) +{ + return __vfs_unlink(idmap, dir, dentry, delegated_inode, NULL); +} +EXPORT_SYMBOL(vfs_unlink); + +/* + * The body of vfs_unlink(). @method, if not NULL, is called in place of + * dir->i_op->unlink(); vfs_unlink() passes NULL. + */ +static int __vfs_unlink(const struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, + struct delegated_inode *delegated_inode, + int (*method)(struct inode *dir, + struct dentry *dentry)) { struct inode *target = dentry->d_inode; int error = may_delete_dentry(idmap, dir, dentry, false); @@ -5730,7 +5750,10 @@ int vfs_unlink(const struct mnt_idmap *idmap, struct inode *dir, error = try_break_deleg(target, 0, delegated_inode); if (error) goto out; - error = dir->i_op->unlink(dir, dentry); + if (method) + error = method(dir, dentry); + else + error = dir->i_op->unlink(dir, dentry); if (!error) { dont_mount(dentry); detach_mounts(dentry); @@ -5750,7 +5773,6 @@ int vfs_unlink(const struct mnt_idmap *idmap, struct inode *dir, return error; } -EXPORT_SYMBOL(vfs_unlink); /* * Make sure that the actual truncation of the file will occur outside its -- 2.43.0