Dear pseudo fs maintainer, Today you received a patch from me titled "fs: convert <your>fs to use simple_remove() helper" The patch that you received depends on this patch from my series and this patch is obviously needed for the context of your review. Please review the use of the helper as a cleanup/refactoring patch for your fs that should not change logic regardless of the wider scope of my series. For complete context and motivation, please see the rest of the series at: https://lore.kernel.org/linux-fsdevel/20190516102641.6574-1-amir73il@xxxxxxxxx/ Thanks, Amir. ---------- Forwarded message --------- From: Amir Goldstein <amir73il@xxxxxxxxx> Date: Thu, May 16, 2019 at 1:26 PM Subject: [PATCH v2 02/14] fs: create simple_remove() helper To: Jan Kara <jack@xxxxxxx> Cc: Matthew Bobrowski <mbobrowski@xxxxxxxxxxxxxx>, <linux-fsdevel@xxxxxxxxxxxxxxx> There is a common pattern among pseudo filesystems for removing a dentry from code paths that are NOT coming from vfs_{unlink,rmdir}, using a combination of simple_{unlink,rmdir} and d_delete(). Create an helper to perform this common operation. This helper is going to be used as a place holder for the new fsnotify_{unlink,rmdir} hooks. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/libfs.c | 27 +++++++++++++++++++++++++++ include/linux/fs.h | 1 + 2 files changed, 28 insertions(+) diff --git a/fs/libfs.c b/fs/libfs.c index 4b59b1816efb..ca1132f1d5c6 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -353,6 +353,33 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry) } EXPORT_SYMBOL(simple_rmdir); +/* + * Unlike simple_unlink/rmdir, this helper is NOT called from vfs_unlink/rmdir. + * Caller must guaranty that d_parent and d_name are stable. + */ +int simple_remove(struct inode *dir, struct dentry *dentry) +{ + int ret; + + /* + * 'simple_' operations get a dentry reference on create/mkdir and drop + * it on unlink/rmdir. So we have to get dentry reference here to + * protect d_delete() from accessing a freed dentry. + */ + dget(dentry); + if (d_is_dir(dentry)) + ret = simple_rmdir(dir, dentry); + else + ret = simple_unlink(dir, dentry); + + if (!ret) + d_delete(dentry); + dput(dentry); + + return ret; +} +EXPORT_SYMBOL(simple_remove); + int simple_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) diff --git a/include/linux/fs.h b/include/linux/fs.h index f7fdfe93e25d..74ea5f0b3b9d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3245,6 +3245,7 @@ extern int simple_open(struct inode *inode, struct file *file); extern int simple_link(struct dentry *, struct inode *, struct dentry *); extern int simple_unlink(struct inode *, struct dentry *); extern int simple_rmdir(struct inode *, struct dentry *); +extern int simple_remove(struct inode *, struct dentry *); extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, unsigned int); extern int noop_fsync(struct file *, loff_t, loff_t, int); -- 2.17.1