-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEq1nRK9aeMoq1VSgcnJ2qBz9kQNkFAl0kWgwACgkQnJ2qBz9k QNkkdggA7bdy6xZRPdumZMxtASGDs1JJ4diNs+apgyc6wUfsT1lCE2ap20EdzfzK drAvlJt1vYEW+6apOzUXJ0qWXMVRzy4XRl+jVMO9GW6BoY4OyJQ86AQZlEv1zZ4n vxeYnlbxA7JyfkWgup0ZSb5EKRSO1eSxZKEZou0wu2jRCRr/E5RyjPQHXaiE5ihc 7ilEtTI3Qg3nnAK30F0Iy0X3lGqgXj+rlJ0TgR8BBEDllct2wV16vvMl/Sy+BXip 5sSWjSy8zntMnkSN8yH/oJN0D+fqmCsnYafwqTpPek8izvEz4xpjshbWTDnPm0HM eiMC1U3ZJoD3Z4/wxRZ91m60VYgJBA== =SVKR -----END PGP SIGNATURE----- Merge tag 'fsnotify_for_v5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs Pull fsnotify updates from Jan Kara: "This contains cleanups of the fsnotify name removal hook and also a patch to disable fanotify permission events for 'proc' filesystem" * tag 'fsnotify_for_v5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: fsnotify: get rid of fsnotify_nameremove() fsnotify: move fsnotify_nameremove() hook out of d_delete() configfs: call fsnotify_rmdir() hook debugfs: call fsnotify_{unlink,rmdir}() hooks debugfs: simplify __debugfs_remove_file() devpts: call fsnotify_unlink() hook tracefs: call fsnotify_{unlink,rmdir}() hooks rpc_pipefs: call fsnotify_{unlink,rmdir}() hooks btrfs: call fsnotify_rmdir() hook fsnotify: add empty fsnotify_{unlink,rmdir}() hooks fanotify: Disallow permission events for proc filesystem
This commit is contained in:
commit
e6983afd92
|
@ -60,11 +60,6 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
|
||||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||||
afs_edit_dir_add(dvnode, &new->d_name,
|
afs_edit_dir_add(dvnode, &new->d_name,
|
||||||
&vnode->fid, afs_edit_dir_for_silly_1);
|
&vnode->fid, afs_edit_dir_for_silly_1);
|
||||||
|
|
||||||
/* vfs_unlink and the like do not issue this when a file is
|
|
||||||
* sillyrenamed, so do it here.
|
|
||||||
*/
|
|
||||||
fsnotify_nameremove(old, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(scb);
|
kfree(scb);
|
||||||
|
|
|
@ -2928,8 +2928,10 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
|
||||||
inode_lock(inode);
|
inode_lock(inode);
|
||||||
err = btrfs_delete_subvolume(dir, dentry);
|
err = btrfs_delete_subvolume(dir, dentry);
|
||||||
inode_unlock(inode);
|
inode_unlock(inode);
|
||||||
if (!err)
|
if (!err) {
|
||||||
|
fsnotify_rmdir(dir, dentry);
|
||||||
d_delete(dentry);
|
d_delete(dentry);
|
||||||
|
}
|
||||||
|
|
||||||
out_dput:
|
out_dput:
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/fsnotify.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -1788,6 +1789,7 @@ void configfs_unregister_group(struct config_group *group)
|
||||||
configfs_detach_group(&group->cg_item);
|
configfs_detach_group(&group->cg_item);
|
||||||
d_inode(dentry)->i_flags |= S_DEAD;
|
d_inode(dentry)->i_flags |= S_DEAD;
|
||||||
dont_mount(dentry);
|
dont_mount(dentry);
|
||||||
|
fsnotify_rmdir(d_inode(parent), dentry);
|
||||||
d_delete(dentry);
|
d_delete(dentry);
|
||||||
inode_unlock(d_inode(parent));
|
inode_unlock(d_inode(parent));
|
||||||
|
|
||||||
|
@ -1916,6 +1918,7 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
|
||||||
configfs_detach_group(&group->cg_item);
|
configfs_detach_group(&group->cg_item);
|
||||||
d_inode(dentry)->i_flags |= S_DEAD;
|
d_inode(dentry)->i_flags |= S_DEAD;
|
||||||
dont_mount(dentry);
|
dont_mount(dentry);
|
||||||
|
fsnotify_rmdir(d_inode(root), dentry);
|
||||||
inode_unlock(d_inode(dentry));
|
inode_unlock(d_inode(dentry));
|
||||||
|
|
||||||
d_delete(dentry);
|
d_delete(dentry);
|
||||||
|
|
|
@ -2372,7 +2372,6 @@ EXPORT_SYMBOL(d_hash_and_lookup);
|
||||||
void d_delete(struct dentry * dentry)
|
void d_delete(struct dentry * dentry)
|
||||||
{
|
{
|
||||||
struct inode *inode = dentry->d_inode;
|
struct inode *inode = dentry->d_inode;
|
||||||
int isdir = d_is_dir(dentry);
|
|
||||||
|
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
spin_lock(&dentry->d_lock);
|
spin_lock(&dentry->d_lock);
|
||||||
|
@ -2387,7 +2386,6 @@ void d_delete(struct dentry * dentry)
|
||||||
spin_unlock(&dentry->d_lock);
|
spin_unlock(&dentry->d_lock);
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
}
|
}
|
||||||
fsnotify_nameremove(dentry, isdir);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(d_delete);
|
EXPORT_SYMBOL(d_delete);
|
||||||
|
|
||||||
|
|
|
@ -617,13 +617,10 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(debugfs_create_symlink);
|
EXPORT_SYMBOL_GPL(debugfs_create_symlink);
|
||||||
|
|
||||||
static void __debugfs_remove_file(struct dentry *dentry, struct dentry *parent)
|
static void __debugfs_file_removed(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct debugfs_fsdata *fsd;
|
struct debugfs_fsdata *fsd;
|
||||||
|
|
||||||
simple_unlink(d_inode(parent), dentry);
|
|
||||||
d_delete(dentry);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Paired with the closing smp_mb() implied by a successful
|
* Paired with the closing smp_mb() implied by a successful
|
||||||
* cmpxchg() in debugfs_file_get(): either
|
* cmpxchg() in debugfs_file_get(): either
|
||||||
|
@ -644,16 +641,18 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
|
||||||
|
|
||||||
if (simple_positive(dentry)) {
|
if (simple_positive(dentry)) {
|
||||||
dget(dentry);
|
dget(dentry);
|
||||||
if (!d_is_reg(dentry)) {
|
if (d_is_dir(dentry)) {
|
||||||
if (d_is_dir(dentry))
|
ret = simple_rmdir(d_inode(parent), dentry);
|
||||||
ret = simple_rmdir(d_inode(parent), dentry);
|
|
||||||
else
|
|
||||||
simple_unlink(d_inode(parent), dentry);
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
d_delete(dentry);
|
fsnotify_rmdir(d_inode(parent), dentry);
|
||||||
} else {
|
} else {
|
||||||
__debugfs_remove_file(dentry, parent);
|
simple_unlink(d_inode(parent), dentry);
|
||||||
|
fsnotify_unlink(d_inode(parent), dentry);
|
||||||
}
|
}
|
||||||
|
if (!ret)
|
||||||
|
d_delete(dentry);
|
||||||
|
if (d_is_reg(dentry))
|
||||||
|
__debugfs_file_removed(dentry);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -621,6 +621,7 @@ void devpts_pty_kill(struct dentry *dentry)
|
||||||
|
|
||||||
dentry->d_fsdata = NULL;
|
dentry->d_fsdata = NULL;
|
||||||
drop_nlink(dentry->d_inode);
|
drop_nlink(dentry->d_inode);
|
||||||
|
fsnotify_unlink(d_inode(dentry->d_parent), dentry);
|
||||||
d_delete(dentry);
|
d_delete(dentry);
|
||||||
dput(dentry); /* d_alloc_name() in devpts_pty_new() */
|
dput(dentry); /* d_alloc_name() in devpts_pty_new() */
|
||||||
}
|
}
|
||||||
|
|
|
@ -3883,6 +3883,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
dentry->d_inode->i_flags |= S_DEAD;
|
dentry->d_inode->i_flags |= S_DEAD;
|
||||||
dont_mount(dentry);
|
dont_mount(dentry);
|
||||||
detach_mounts(dentry);
|
detach_mounts(dentry);
|
||||||
|
fsnotify_rmdir(dir, dentry);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
inode_unlock(dentry->d_inode);
|
inode_unlock(dentry->d_inode);
|
||||||
|
@ -3999,6 +4000,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegate
|
||||||
if (!error) {
|
if (!error) {
|
||||||
dont_mount(dentry);
|
dont_mount(dentry);
|
||||||
detach_mounts(dentry);
|
detach_mounts(dentry);
|
||||||
|
fsnotify_unlink(dir, dentry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -396,12 +396,6 @@ nfs_complete_sillyrename(struct rpc_task *task, struct nfs_renamedata *data)
|
||||||
nfs_cancel_async_unlink(dentry);
|
nfs_cancel_async_unlink(dentry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* vfs_unlink and the like do not issue this when a file is
|
|
||||||
* sillyrenamed, so do it here.
|
|
||||||
*/
|
|
||||||
fsnotify_nameremove(dentry, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SILLYNAME_PREFIX ".nfs"
|
#define SILLYNAME_PREFIX ".nfs"
|
||||||
|
|
|
@ -920,6 +920,22 @@ static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fanotify_events_supported(struct path *path, __u64 mask)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Some filesystems such as 'proc' acquire unusual locks when opening
|
||||||
|
* files. For them fanotify permission events have high chances of
|
||||||
|
* deadlocking the system - open done when reporting fanotify event
|
||||||
|
* blocks on this "unusual" lock while another process holding the lock
|
||||||
|
* waits for fanotify permission event to be answered. Just disallow
|
||||||
|
* permission events for such filesystems.
|
||||||
|
*/
|
||||||
|
if (mask & FANOTIFY_PERM_EVENTS &&
|
||||||
|
path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM)
|
||||||
|
return -EINVAL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
||||||
int dfd, const char __user *pathname)
|
int dfd, const char __user *pathname)
|
||||||
{
|
{
|
||||||
|
@ -1018,6 +1034,12 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fput_and_out;
|
goto fput_and_out;
|
||||||
|
|
||||||
|
if (flags & FAN_MARK_ADD) {
|
||||||
|
ret = fanotify_events_supported(&path, mask);
|
||||||
|
if (ret)
|
||||||
|
goto path_put_and_out;
|
||||||
|
}
|
||||||
|
|
||||||
if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
|
if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
|
||||||
ret = fanotify_test_fid(&path, &__fsid);
|
ret = fanotify_test_fid(&path, &__fsid);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -94,47 +94,6 @@ void fsnotify_sb_delete(struct super_block *sb)
|
||||||
fsnotify_clear_marks_by_sb(sb);
|
fsnotify_clear_marks_by_sb(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* fsnotify_nameremove - a filename was removed from a directory
|
|
||||||
*
|
|
||||||
* This is mostly called under parent vfs inode lock so name and
|
|
||||||
* dentry->d_parent should be stable. However there are some corner cases where
|
|
||||||
* inode lock is not held. So to be on the safe side and be reselient to future
|
|
||||||
* callers and out of tree users of d_delete(), we do not assume that d_parent
|
|
||||||
* and d_name are stable and we use dget_parent() and
|
|
||||||
* take_dentry_name_snapshot() to grab stable references.
|
|
||||||
*/
|
|
||||||
void fsnotify_nameremove(struct dentry *dentry, int isdir)
|
|
||||||
{
|
|
||||||
struct dentry *parent;
|
|
||||||
struct name_snapshot name;
|
|
||||||
__u32 mask = FS_DELETE;
|
|
||||||
|
|
||||||
/* d_delete() of pseudo inode? (e.g. __ns_get_path() playing tricks) */
|
|
||||||
if (IS_ROOT(dentry))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (isdir)
|
|
||||||
mask |= FS_ISDIR;
|
|
||||||
|
|
||||||
parent = dget_parent(dentry);
|
|
||||||
/* Avoid unneeded take_dentry_name_snapshot() */
|
|
||||||
if (!(d_inode(parent)->i_fsnotify_mask & FS_DELETE) &&
|
|
||||||
!(dentry->d_sb->s_fsnotify_mask & FS_DELETE))
|
|
||||||
goto out_dput;
|
|
||||||
|
|
||||||
take_dentry_name_snapshot(&name, dentry);
|
|
||||||
|
|
||||||
fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
|
|
||||||
&name.name, 0);
|
|
||||||
|
|
||||||
release_dentry_name_snapshot(&name);
|
|
||||||
|
|
||||||
out_dput:
|
|
||||||
dput(parent);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(fsnotify_nameremove);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given an inode, first check if we care what happens to our children. Inotify
|
* Given an inode, first check if we care what happens to our children. Inotify
|
||||||
* and dnotify both tell their parents about events. If we care about any event
|
* and dnotify both tell their parents about events. If we care about any event
|
||||||
|
|
|
@ -211,7 +211,7 @@ static struct file_system_type proc_fs_type = {
|
||||||
.init_fs_context = proc_init_fs_context,
|
.init_fs_context = proc_init_fs_context,
|
||||||
.parameters = &proc_fs_parameters,
|
.parameters = &proc_fs_parameters,
|
||||||
.kill_sb = proc_kill_sb,
|
.kill_sb = proc_kill_sb,
|
||||||
.fs_flags = FS_USERNS_MOUNT,
|
.fs_flags = FS_USERNS_MOUNT | FS_DISALLOW_NOTIFY_PERM,
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init proc_root_init(void)
|
void __init proc_root_init(void)
|
||||||
|
|
|
@ -505,9 +505,12 @@ static int __tracefs_remove(struct dentry *dentry, struct dentry *parent)
|
||||||
switch (dentry->d_inode->i_mode & S_IFMT) {
|
switch (dentry->d_inode->i_mode & S_IFMT) {
|
||||||
case S_IFDIR:
|
case S_IFDIR:
|
||||||
ret = simple_rmdir(parent->d_inode, dentry);
|
ret = simple_rmdir(parent->d_inode, dentry);
|
||||||
|
if (!ret)
|
||||||
|
fsnotify_rmdir(parent->d_inode, dentry);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
simple_unlink(parent->d_inode, dentry);
|
simple_unlink(parent->d_inode, dentry);
|
||||||
|
fsnotify_unlink(parent->d_inode, dentry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
|
@ -2184,6 +2184,7 @@ struct file_system_type {
|
||||||
#define FS_BINARY_MOUNTDATA 2
|
#define FS_BINARY_MOUNTDATA 2
|
||||||
#define FS_HAS_SUBTYPE 4
|
#define FS_HAS_SUBTYPE 4
|
||||||
#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
|
#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
|
||||||
|
#define FS_DISALLOW_NOTIFY_PERM 16 /* Disable fanotify permission events */
|
||||||
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
|
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
|
||||||
int (*init_fs_context)(struct fs_context *);
|
int (*init_fs_context)(struct fs_context *);
|
||||||
const struct fs_parameter_description *parameters;
|
const struct fs_parameter_description *parameters;
|
||||||
|
|
|
@ -188,6 +188,19 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct
|
||||||
fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, &new_dentry->d_name, 0);
|
fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, &new_dentry->d_name, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsnotify_unlink - 'name' was unlinked
|
||||||
|
*
|
||||||
|
* Caller must make sure that dentry->d_name is stable.
|
||||||
|
*/
|
||||||
|
static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
|
{
|
||||||
|
/* Expected to be called before d_delete() */
|
||||||
|
WARN_ON_ONCE(d_is_negative(dentry));
|
||||||
|
|
||||||
|
fsnotify_dirent(dir, dentry, FS_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fsnotify_mkdir - directory 'name' was created
|
* fsnotify_mkdir - directory 'name' was created
|
||||||
*/
|
*/
|
||||||
|
@ -198,6 +211,19 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
|
||||||
fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR);
|
fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsnotify_rmdir - directory 'name' was removed
|
||||||
|
*
|
||||||
|
* Caller must make sure that dentry->d_name is stable.
|
||||||
|
*/
|
||||||
|
static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
|
{
|
||||||
|
/* Expected to be called before d_delete() */
|
||||||
|
WARN_ON_ONCE(d_is_negative(dentry));
|
||||||
|
|
||||||
|
fsnotify_dirent(dir, dentry, FS_DELETE | FS_ISDIR);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fsnotify_access - file was read
|
* fsnotify_access - file was read
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -357,7 +357,6 @@ extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u
|
||||||
extern void __fsnotify_inode_delete(struct inode *inode);
|
extern void __fsnotify_inode_delete(struct inode *inode);
|
||||||
extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
|
extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
|
||||||
extern void fsnotify_sb_delete(struct super_block *sb);
|
extern void fsnotify_sb_delete(struct super_block *sb);
|
||||||
extern void fsnotify_nameremove(struct dentry *dentry, int isdir);
|
|
||||||
extern u32 fsnotify_get_cookie(void);
|
extern u32 fsnotify_get_cookie(void);
|
||||||
|
|
||||||
static inline int fsnotify_inode_watches_children(struct inode *inode)
|
static inline int fsnotify_inode_watches_children(struct inode *inode)
|
||||||
|
@ -527,9 +526,6 @@ static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
|
||||||
static inline void fsnotify_sb_delete(struct super_block *sb)
|
static inline void fsnotify_sb_delete(struct super_block *sb)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
|
|
||||||
{}
|
|
||||||
|
|
||||||
static inline void fsnotify_update_flags(struct dentry *dentry)
|
static inline void fsnotify_update_flags(struct dentry *dentry)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
@ -598,6 +598,8 @@ static int __rpc_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
|
|
||||||
dget(dentry);
|
dget(dentry);
|
||||||
ret = simple_rmdir(dir, dentry);
|
ret = simple_rmdir(dir, dentry);
|
||||||
|
if (!ret)
|
||||||
|
fsnotify_rmdir(dir, dentry);
|
||||||
d_delete(dentry);
|
d_delete(dentry);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -609,6 +611,8 @@ static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
|
|
||||||
dget(dentry);
|
dget(dentry);
|
||||||
ret = simple_unlink(dir, dentry);
|
ret = simple_unlink(dir, dentry);
|
||||||
|
if (!ret)
|
||||||
|
fsnotify_unlink(dir, dentry);
|
||||||
d_delete(dentry);
|
d_delete(dentry);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue