Skip to content

Commit 4897e72

Browse files
committed
Merge tag 'fsnotify_for_v5.17-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull fsnotify fixes from Jan Kara: "Fixes for userspace breakage caused by fsnotify changes ~3 years ago and one fanotify cleanup" * tag 'fsnotify_for_v5.17-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: fsnotify: fix fsnotify hooks in pseudo filesystems fsnotify: invalidate dcache before IN_DELETE event fanotify: remove variable set but not used
2 parents c2b19fd + 29044da commit 4897e72

File tree

8 files changed

+59
-26
lines changed

8 files changed

+59
-26
lines changed

fs/btrfs/ioctl.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3152,10 +3152,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
31523152
btrfs_inode_lock(inode, 0);
31533153
err = btrfs_delete_subvolume(dir, dentry);
31543154
btrfs_inode_unlock(inode, 0);
3155-
if (!err) {
3156-
fsnotify_rmdir(dir, dentry);
3157-
d_delete(dentry);
3158-
}
3155+
if (!err)
3156+
d_delete_notify(dir, dentry);
31593157

31603158
out_dput:
31613159
dput(dentry);

fs/configfs/dir.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,8 +1780,8 @@ void configfs_unregister_group(struct config_group *group)
17801780
configfs_detach_group(&group->cg_item);
17811781
d_inode(dentry)->i_flags |= S_DEAD;
17821782
dont_mount(dentry);
1783+
d_drop(dentry);
17831784
fsnotify_rmdir(d_inode(parent), dentry);
1784-
d_delete(dentry);
17851785
inode_unlock(d_inode(parent));
17861786

17871787
dput(dentry);
@@ -1922,10 +1922,10 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
19221922
configfs_detach_group(&group->cg_item);
19231923
d_inode(dentry)->i_flags |= S_DEAD;
19241924
dont_mount(dentry);
1925-
fsnotify_rmdir(d_inode(root), dentry);
19261925
inode_unlock(d_inode(dentry));
19271926

1928-
d_delete(dentry);
1927+
d_drop(dentry);
1928+
fsnotify_rmdir(d_inode(root), dentry);
19291929

19301930
inode_unlock(d_inode(root));
19311931

fs/devpts/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,8 @@ void devpts_pty_kill(struct dentry *dentry)
621621

622622
dentry->d_fsdata = NULL;
623623
drop_nlink(dentry->d_inode);
624-
fsnotify_unlink(d_inode(dentry->d_parent), dentry);
625624
d_drop(dentry);
625+
fsnotify_unlink(d_inode(dentry->d_parent), dentry);
626626
dput(dentry); /* d_alloc_name() in devpts_pty_new() */
627627
}
628628

fs/namei.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4024,13 +4024,12 @@ int vfs_rmdir(struct user_namespace *mnt_userns, struct inode *dir,
40244024
dentry->d_inode->i_flags |= S_DEAD;
40254025
dont_mount(dentry);
40264026
detach_mounts(dentry);
4027-
fsnotify_rmdir(dir, dentry);
40284027

40294028
out:
40304029
inode_unlock(dentry->d_inode);
40314030
dput(dentry);
40324031
if (!error)
4033-
d_delete(dentry);
4032+
d_delete_notify(dir, dentry);
40344033
return error;
40354034
}
40364035
EXPORT_SYMBOL(vfs_rmdir);
@@ -4152,17 +4151,18 @@ int vfs_unlink(struct user_namespace *mnt_userns, struct inode *dir,
41524151
if (!error) {
41534152
dont_mount(dentry);
41544153
detach_mounts(dentry);
4155-
fsnotify_unlink(dir, dentry);
41564154
}
41574155
}
41584156
}
41594157
out:
41604158
inode_unlock(target);
41614159

41624160
/* We don't d_delete() NFS sillyrenamed files--they still exist. */
4163-
if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
4161+
if (!error && dentry->d_flags & DCACHE_NFSFS_RENAMED) {
4162+
fsnotify_unlink(dir, dentry);
4163+
} else if (!error) {
41644164
fsnotify_link_count(target);
4165-
d_delete(dentry);
4165+
d_delete_notify(dir, dentry);
41664166
}
41674167

41684168
return error;

fs/nfsd/nfsctl.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,8 @@ static void nfsdfs_remove_file(struct inode *dir, struct dentry *dentry)
12471247
clear_ncl(d_inode(dentry));
12481248
dget(dentry);
12491249
ret = simple_unlink(dir, dentry);
1250-
d_delete(dentry);
1250+
d_drop(dentry);
1251+
fsnotify_unlink(dir, dentry);
12511252
dput(dentry);
12521253
WARN_ON_ONCE(ret);
12531254
}
@@ -1338,8 +1339,8 @@ void nfsd_client_rmdir(struct dentry *dentry)
13381339
dget(dentry);
13391340
ret = simple_rmdir(dir, dentry);
13401341
WARN_ON_ONCE(ret);
1342+
d_drop(dentry);
13411343
fsnotify_rmdir(dir, dentry);
1342-
d_delete(dentry);
13431344
dput(dentry);
13441345
inode_unlock(dir);
13451346
}

fs/notify/fanotify/fanotify_user.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ static size_t fanotify_event_len(unsigned int info_mode,
158158
struct fanotify_event *event)
159159
{
160160
size_t event_len = FAN_EVENT_METADATA_LEN;
161-
struct fanotify_info *info;
162161
int fh_len;
163162
int dot_len = 0;
164163

@@ -168,8 +167,6 @@ static size_t fanotify_event_len(unsigned int info_mode,
168167
if (fanotify_is_error_event(event->mask))
169168
event_len += FANOTIFY_ERROR_INFO_LEN;
170169

171-
info = fanotify_event_info(event);
172-
173170
if (fanotify_event_has_any_dir_fh(event)) {
174171
event_len += fanotify_dir_name_info_len(event);
175172
} else if ((info_mode & FAN_REPORT_NAME) &&

include/linux/fsnotify.h

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,17 +224,54 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode,
224224
dir, &new_dentry->d_name, 0);
225225
}
226226

227+
/*
228+
* fsnotify_delete - @dentry was unlinked and unhashed
229+
*
230+
* Caller must make sure that dentry->d_name is stable.
231+
*
232+
* Note: unlike fsnotify_unlink(), we have to pass also the unlinked inode
233+
* as this may be called after d_delete() and old_dentry may be negative.
234+
*/
235+
static inline void fsnotify_delete(struct inode *dir, struct inode *inode,
236+
struct dentry *dentry)
237+
{
238+
__u32 mask = FS_DELETE;
239+
240+
if (S_ISDIR(inode->i_mode))
241+
mask |= FS_ISDIR;
242+
243+
fsnotify_name(mask, inode, FSNOTIFY_EVENT_INODE, dir, &dentry->d_name,
244+
0);
245+
}
246+
247+
/**
248+
* d_delete_notify - delete a dentry and call fsnotify_delete()
249+
* @dentry: The dentry to delete
250+
*
251+
* This helper is used to guaranty that the unlinked inode cannot be found
252+
* by lookup of this name after fsnotify_delete() event has been delivered.
253+
*/
254+
static inline void d_delete_notify(struct inode *dir, struct dentry *dentry)
255+
{
256+
struct inode *inode = d_inode(dentry);
257+
258+
ihold(inode);
259+
d_delete(dentry);
260+
fsnotify_delete(dir, inode, dentry);
261+
iput(inode);
262+
}
263+
227264
/*
228265
* fsnotify_unlink - 'name' was unlinked
229266
*
230267
* Caller must make sure that dentry->d_name is stable.
231268
*/
232269
static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry)
233270
{
234-
/* Expected to be called before d_delete() */
235-
WARN_ON_ONCE(d_is_negative(dentry));
271+
if (WARN_ON_ONCE(d_is_negative(dentry)))
272+
return;
236273

237-
fsnotify_dirent(dir, dentry, FS_DELETE);
274+
fsnotify_delete(dir, d_inode(dentry), dentry);
238275
}
239276

240277
/*
@@ -258,10 +295,10 @@ static inline void fsnotify_mkdir(struct inode *dir, struct dentry *dentry)
258295
*/
259296
static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry)
260297
{
261-
/* Expected to be called before d_delete() */
262-
WARN_ON_ONCE(d_is_negative(dentry));
298+
if (WARN_ON_ONCE(d_is_negative(dentry)))
299+
return;
263300

264-
fsnotify_dirent(dir, dentry, FS_DELETE | FS_ISDIR);
301+
fsnotify_delete(dir, d_inode(dentry), dentry);
265302
}
266303

267304
/*

net/sunrpc/rpc_pipe.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -600,9 +600,9 @@ static int __rpc_rmdir(struct inode *dir, struct dentry *dentry)
600600

601601
dget(dentry);
602602
ret = simple_rmdir(dir, dentry);
603+
d_drop(dentry);
603604
if (!ret)
604605
fsnotify_rmdir(dir, dentry);
605-
d_delete(dentry);
606606
dput(dentry);
607607
return ret;
608608
}
@@ -613,9 +613,9 @@ static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
613613

614614
dget(dentry);
615615
ret = simple_unlink(dir, dentry);
616+
d_drop(dentry);
616617
if (!ret)
617618
fsnotify_unlink(dir, dentry);
618-
d_delete(dentry);
619619
dput(dentry);
620620
return ret;
621621
}

0 commit comments

Comments
 (0)