Skip to content

Commit 40a100d

Browse files
amir73iljankara
authored andcommitted
fsnotify: pass dir and inode arguments to fsnotify()
The arguments of fsnotify() are overloaded and mean different things for different event types. Replace the to_tell argument with separate arguments @dir and @iNode, because we may be sending to both dir and child. Using the @DaTa argument to pass the child is not enough, because dirent events pass this argument (for audit), but we do not report to child. Document the new fsnotify() function argumenets. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 82ace1e commit 40a100d

File tree

4 files changed

+52
-26
lines changed

4 files changed

+52
-26
lines changed

fs/kernfs/file.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -902,8 +902,9 @@ static void kernfs_notify_workfn(struct work_struct *work)
902902
if (parent) {
903903
p_inode = ilookup(info->sb, kernfs_ino(parent));
904904
if (p_inode) {
905-
fsnotify(p_inode, FS_MODIFY | FS_EVENT_ON_CHILD,
906-
inode, FSNOTIFY_EVENT_INODE, &name, 0);
905+
fsnotify(FS_MODIFY | FS_EVENT_ON_CHILD,
906+
inode, FSNOTIFY_EVENT_INODE,
907+
p_inode, &name, inode, 0);
907908
iput(p_inode);
908909
}
909910

fs/notify/fsnotify.c

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
152152
{
153153
struct inode *inode = d_inode(dentry);
154154
struct dentry *parent;
155-
struct inode *p_inode;
155+
struct inode *p_inode = NULL;
156156
struct name_snapshot name;
157157
struct qstr *file_name = NULL;
158158
int ret = 0;
@@ -171,14 +171,13 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
171171
WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));
172172

173173
/* Notify both parent and child with child name info */
174-
inode = p_inode;
175174
take_dentry_name_snapshot(&name, dentry);
176175
file_name = &name.name;
177176
mask |= FS_EVENT_ON_CHILD;
178177
}
179178

180179
notify:
181-
ret = fsnotify(inode, mask, data, data_type, file_name, 0);
180+
ret = fsnotify(mask, data, data_type, p_inode, file_name, inode, 0);
182181

183182
if (file_name)
184183
release_dentry_name_snapshot(&name);
@@ -312,18 +311,31 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
312311
}
313312

314313
/*
315-
* This is the main call to fsnotify. The VFS calls into hook specific functions
316-
* in linux/fsnotify.h. Those functions then in turn call here. Here will call
317-
* out to all of the registered fsnotify_group. Those groups can then use the
318-
* notification event in whatever means they feel necessary.
314+
* fsnotify - This is the main call to fsnotify.
315+
*
316+
* The VFS calls into hook specific functions in linux/fsnotify.h.
317+
* Those functions then in turn call here. Here will call out to all of the
318+
* registered fsnotify_group. Those groups can then use the notification event
319+
* in whatever means they feel necessary.
320+
*
321+
* @mask: event type and flags
322+
* @data: object that event happened on
323+
* @data_type: type of object for fanotify_data_XXX() accessors
324+
* @dir: optional directory associated with event -
325+
* if @file_name is not NULL, this is the directory that
326+
* @file_name is relative to
327+
* @file_name: optional file name associated with event
328+
* @inode: optional inode associated with event -
329+
* either @dir or @inode must be non-NULL.
330+
* if both are non-NULL event may be reported to both.
331+
* @cookie: inotify rename cookie
319332
*/
320-
int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_type,
321-
const struct qstr *file_name, u32 cookie)
333+
int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,
334+
const struct qstr *file_name, struct inode *inode, u32 cookie)
322335
{
323336
const struct path *path = fsnotify_data_path(data, data_type);
324337
struct fsnotify_iter_info iter_info = {};
325-
struct super_block *sb = to_tell->i_sb;
326-
struct inode *dir = file_name ? to_tell : NULL;
338+
struct super_block *sb;
327339
struct mount *mnt = NULL;
328340
struct inode *child = NULL;
329341
int ret = 0;
@@ -332,8 +344,18 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_type,
332344
if (path)
333345
mnt = real_mount(path->mnt);
334346

335-
if (mask & FS_EVENT_ON_CHILD)
336-
child = fsnotify_data_inode(data, data_type);
347+
if (!inode) {
348+
/* Dirent event - report on TYPE_INODE to dir */
349+
inode = dir;
350+
} else if (mask & FS_EVENT_ON_CHILD) {
351+
/*
352+
* Event on child - report on TYPE_INODE to dir
353+
* and on TYPE_CHILD to child.
354+
*/
355+
child = inode;
356+
inode = dir;
357+
}
358+
sb = inode->i_sb;
337359

338360
/*
339361
* Optimization: srcu_read_lock() has a memory barrier which can
@@ -342,12 +364,12 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_type,
342364
* SRCU because we have no references to any objects and do not
343365
* need SRCU to keep them "alive".
344366
*/
345-
if (!to_tell->i_fsnotify_marks && !sb->s_fsnotify_marks &&
367+
if (!inode->i_fsnotify_marks && !sb->s_fsnotify_marks &&
346368
(!mnt || !mnt->mnt_fsnotify_marks) &&
347369
(!child || !child->i_fsnotify_marks))
348370
return 0;
349371

350-
marks_mask = to_tell->i_fsnotify_mask | sb->s_fsnotify_mask;
372+
marks_mask = inode->i_fsnotify_mask | sb->s_fsnotify_mask;
351373
if (mnt)
352374
marks_mask |= mnt->mnt_fsnotify_mask;
353375
if (child)
@@ -365,7 +387,7 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_type,
365387
iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
366388

367389
iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
368-
fsnotify_first_mark(&to_tell->i_fsnotify_marks);
390+
fsnotify_first_mark(&inode->i_fsnotify_marks);
369391
iter_info.marks[FSNOTIFY_OBJ_TYPE_SB] =
370392
fsnotify_first_mark(&sb->s_fsnotify_marks);
371393
if (mnt) {

include/linux/fsnotify.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@
2323
* have changed (i.e. renamed over).
2424
*
2525
* Unlike fsnotify_parent(), the event will be reported regardless of the
26-
* FS_EVENT_ON_CHILD mask on the parent inode.
26+
* FS_EVENT_ON_CHILD mask on the parent inode and will not be reported if only
27+
* the child is interested and not the parent.
2728
*/
2829
static inline void fsnotify_name(struct inode *dir, __u32 mask,
2930
struct inode *child,
3031
const struct qstr *name, u32 cookie)
3132
{
32-
fsnotify(dir, mask, child, FSNOTIFY_EVENT_INODE, name, cookie);
33+
fsnotify(mask, child, FSNOTIFY_EVENT_INODE, dir, name, NULL, cookie);
3334
}
3435

3536
static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry,
@@ -43,7 +44,7 @@ static inline void fsnotify_inode(struct inode *inode, __u32 mask)
4344
if (S_ISDIR(inode->i_mode))
4445
mask |= FS_ISDIR;
4546

46-
fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
47+
fsnotify(mask, inode, FSNOTIFY_EVENT_INODE, NULL, NULL, inode, 0);
4748
}
4849

4950
/* Notify this dentry's parent about a child's events. */
@@ -61,7 +62,7 @@ static inline int fsnotify_parent(struct dentry *dentry, __u32 mask,
6162
return __fsnotify_parent(dentry, mask, data, data_type);
6263

6364
notify_child:
64-
return fsnotify(inode, mask, data, data_type, NULL, 0);
65+
return fsnotify(mask, data, data_type, NULL, NULL, inode, 0);
6566
}
6667

6768
/*

include/linux/fsnotify_backend.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,9 @@ struct fsnotify_mark {
387387
/* called from the vfs helpers */
388388

389389
/* main fsnotify call to send events */
390-
extern int fsnotify(struct inode *to_tell, __u32 mask, const void *data,
391-
int data_type, const struct qstr *name, u32 cookie);
390+
extern int fsnotify(__u32 mask, const void *data, int data_type,
391+
struct inode *dir, const struct qstr *name,
392+
struct inode *inode, u32 cookie);
392393
extern int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
393394
int data_type);
394395
extern void __fsnotify_inode_delete(struct inode *inode);
@@ -545,8 +546,9 @@ static inline void fsnotify_init_event(struct fsnotify_event *event,
545546

546547
#else
547548

548-
static inline int fsnotify(struct inode *to_tell, __u32 mask, const void *data,
549-
int data_type, const struct qstr *name, u32 cookie)
549+
static inline int fsnotify(__u32 mask, const void *data, int data_type,
550+
struct inode *dir, const struct qstr *name,
551+
struct inode *inode, u32 cookie)
550552
{
551553
return 0;
552554
}

0 commit comments

Comments
 (0)