@@ -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)
@@ -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);