Skip to content

Commit b9a1b97

Browse files
amir73iljankara
authored andcommitted
fsnotify: create method handle_inode_event() in fsnotify_operations
The method handle_event() grew a lot of complexity due to the design of fanotify and merging of ignore masks. Most backends do not care about this complex functionality, so we can hide this complexity from them. Introduce a method handle_inode_event() that serves those backends and passes a single inode mark and less arguments. This change converts all backends except fanotify and inotify to use the simplified handle_inode_event() method. In pricipal, inotify could have also used the new method, but that would require passing more arguments on the simple helper (data, data_type, cookie), so we leave it with the handle_event() method. Link: https://lore.kernel.org/r/[email protected] Suggested-by: Jan Kara <[email protected]> Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 691d976 commit b9a1b97

File tree

7 files changed

+97
-71
lines changed

7 files changed

+97
-71
lines changed

fs/nfsd/filecache.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -598,14 +598,10 @@ static struct notifier_block nfsd_file_lease_notifier = {
598598
};
599599

600600
static int
601-
nfsd_file_fsnotify_handle_event(struct fsnotify_group *group, u32 mask,
602-
const void *data, int data_type,
603-
struct inode *dir,
604-
const struct qstr *file_name, u32 cookie,
605-
struct fsnotify_iter_info *iter_info)
601+
nfsd_file_fsnotify_handle_event(struct fsnotify_mark *mark, u32 mask,
602+
struct inode *inode, struct inode *dir,
603+
const struct qstr *name)
606604
{
607-
struct inode *inode = fsnotify_data_inode(data, data_type);
608-
609605
trace_nfsd_file_fsnotify_handle_event(inode, mask);
610606

611607
/* Should be no marks on non-regular files */
@@ -626,7 +622,7 @@ nfsd_file_fsnotify_handle_event(struct fsnotify_group *group, u32 mask,
626622

627623

628624
static const struct fsnotify_ops nfsd_file_fsnotify_ops = {
629-
.handle_event = nfsd_file_fsnotify_handle_event,
625+
.handle_inode_event = nfsd_file_fsnotify_handle_event,
630626
.free_mark = nfsd_file_mark_free,
631627
};
632628

fs/notify/dnotify/dnotify.c

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,20 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
7070
* destroy the dnotify struct if it was not registered to receive multiple
7171
* events.
7272
*/
73-
static void dnotify_one_event(struct fsnotify_group *group, u32 mask,
74-
struct fsnotify_mark *inode_mark)
73+
static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
74+
struct inode *inode, struct inode *dir,
75+
const struct qstr *name)
7576
{
7677
struct dnotify_mark *dn_mark;
7778
struct dnotify_struct *dn;
7879
struct dnotify_struct **prev;
7980
struct fown_struct *fown;
8081
__u32 test_mask = mask & ~FS_EVENT_ON_CHILD;
8182

83+
/* not a dir, dnotify doesn't care */
84+
if (!dir && !(mask & FS_ISDIR))
85+
return 0;
86+
8287
dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark);
8388

8489
spin_lock(&inode_mark->lock);
@@ -100,33 +105,6 @@ static void dnotify_one_event(struct fsnotify_group *group, u32 mask,
100105
}
101106

102107
spin_unlock(&inode_mark->lock);
103-
}
104-
105-
static int dnotify_handle_event(struct fsnotify_group *group, u32 mask,
106-
const void *data, int data_type,
107-
struct inode *dir,
108-
const struct qstr *file_name, u32 cookie,
109-
struct fsnotify_iter_info *iter_info)
110-
{
111-
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
112-
struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info);
113-
114-
/* not a dir, dnotify doesn't care */
115-
if (!dir && !(mask & FS_ISDIR))
116-
return 0;
117-
118-
if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
119-
return 0;
120-
121-
/*
122-
* Some events can be sent on both parent dir and subdir marks
123-
* (e.g. DN_ATTRIB). If both parent dir and subdir are watching,
124-
* report the event once to parent dir and once to subdir.
125-
*/
126-
if (inode_mark)
127-
dnotify_one_event(group, mask, inode_mark);
128-
if (child_mark)
129-
dnotify_one_event(group, mask, child_mark);
130108

131109
return 0;
132110
}
@@ -143,7 +121,7 @@ static void dnotify_free_mark(struct fsnotify_mark *fsn_mark)
143121
}
144122

145123
static const struct fsnotify_ops dnotify_fsnotify_ops = {
146-
.handle_event = dnotify_handle_event,
124+
.handle_inode_event = dnotify_handle_event,
147125
.free_mark = dnotify_free_mark,
148126
};
149127

fs/notify/fsnotify.c

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,49 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
230230
}
231231
EXPORT_SYMBOL_GPL(__fsnotify_parent);
232232

233+
static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
234+
const void *data, int data_type,
235+
struct inode *dir, const struct qstr *name,
236+
u32 cookie, struct fsnotify_iter_info *iter_info)
237+
{
238+
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
239+
struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info);
240+
struct inode *inode = fsnotify_data_inode(data, data_type);
241+
const struct fsnotify_ops *ops = group->ops;
242+
int ret;
243+
244+
if (WARN_ON_ONCE(!ops->handle_inode_event))
245+
return 0;
246+
247+
if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) ||
248+
WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info)))
249+
return 0;
250+
251+
/*
252+
* An event can be sent on child mark iterator instead of inode mark
253+
* iterator because of other groups that have interest of this inode
254+
* and have marks on both parent and child. We can simplify this case.
255+
*/
256+
if (!inode_mark) {
257+
inode_mark = child_mark;
258+
child_mark = NULL;
259+
dir = NULL;
260+
name = NULL;
261+
}
262+
263+
ret = ops->handle_inode_event(inode_mark, mask, inode, dir, name);
264+
if (ret || !child_mark)
265+
return ret;
266+
267+
/*
268+
* Some events can be sent on both parent dir and child marks
269+
* (e.g. FS_ATTRIB). If both parent dir and child are watching,
270+
* report the event once to parent dir with name and once to child
271+
* without name.
272+
*/
273+
return ops->handle_inode_event(child_mark, mask, inode, NULL, NULL);
274+
}
275+
233276
static int send_to_group(__u32 mask, const void *data, int data_type,
234277
struct inode *dir, const struct qstr *file_name,
235278
u32 cookie, struct fsnotify_iter_info *iter_info)
@@ -275,8 +318,13 @@ static int send_to_group(__u32 mask, const void *data, int data_type,
275318
if (!(test_mask & marks_mask & ~marks_ignored_mask))
276319
return 0;
277320

278-
return group->ops->handle_event(group, mask, data, data_type, dir,
279-
file_name, cookie, iter_info);
321+
if (group->ops->handle_event) {
322+
return group->ops->handle_event(group, mask, data, data_type, dir,
323+
file_name, cookie, iter_info);
324+
}
325+
326+
return fsnotify_handle_event(group, mask, data, data_type, dir,
327+
file_name, cookie, iter_info);
280328
}
281329

282330
static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector **connp)

include/linux/fsnotify_backend.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,30 @@ struct mem_cgroup;
128128
* @cookie: inotify rename cookie
129129
* @iter_info: array of marks from this group that are interested in the event
130130
*
131+
* handle_inode_event - simple variant of handle_event() for groups that only
132+
* have inode marks and don't have ignore mask
133+
* @mark: mark to notify
134+
* @mask: event type and flags
135+
* @inode: inode that event happened on
136+
* @dir: optional directory associated with event -
137+
* if @file_name is not NULL, this is the directory that
138+
* @file_name is relative to.
139+
* @file_name: optional file name associated with event
140+
*
131141
* free_group_priv - called when a group refcnt hits 0 to clean up the private union
132142
* freeing_mark - called when a mark is being destroyed for some reason. The group
133-
* MUST be holding a reference on each mark and that reference must be
134-
* dropped in this function. inotify uses this function to send
135-
* userspace messages that marks have been removed.
143+
* MUST be holding a reference on each mark and that reference must be
144+
* dropped in this function. inotify uses this function to send
145+
* userspace messages that marks have been removed.
136146
*/
137147
struct fsnotify_ops {
138148
int (*handle_event)(struct fsnotify_group *group, u32 mask,
139149
const void *data, int data_type, struct inode *dir,
140150
const struct qstr *file_name, u32 cookie,
141151
struct fsnotify_iter_info *iter_info);
152+
int (*handle_inode_event)(struct fsnotify_mark *mark, u32 mask,
153+
struct inode *inode, struct inode *dir,
154+
const struct qstr *file_name);
142155
void (*free_group_priv)(struct fsnotify_group *group);
143156
void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
144157
void (*free_event)(struct fsnotify_event *event);

kernel/audit_fsnotify.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -152,35 +152,31 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark)
152152
}
153153

154154
/* Update mark data in audit rules based on fsnotify events. */
155-
static int audit_mark_handle_event(struct fsnotify_group *group, u32 mask,
156-
const void *data, int data_type,
157-
struct inode *dir,
158-
const struct qstr *dname, u32 cookie,
159-
struct fsnotify_iter_info *iter_info)
155+
static int audit_mark_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
156+
struct inode *inode, struct inode *dir,
157+
const struct qstr *dname)
160158
{
161-
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
162159
struct audit_fsnotify_mark *audit_mark;
163-
const struct inode *inode = fsnotify_data_inode(data, data_type);
164160

165161
audit_mark = container_of(inode_mark, struct audit_fsnotify_mark, mark);
166162

167-
BUG_ON(group != audit_fsnotify_group);
168-
169-
if (WARN_ON(!inode))
163+
if (WARN_ON_ONCE(inode_mark->group != audit_fsnotify_group) ||
164+
WARN_ON_ONCE(!inode))
170165
return 0;
171166

172167
if (mask & (FS_CREATE|FS_MOVED_TO|FS_DELETE|FS_MOVED_FROM)) {
173168
if (audit_compare_dname_path(dname, audit_mark->path, AUDIT_NAME_FULL))
174169
return 0;
175170
audit_update_mark(audit_mark, inode);
176-
} else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF))
171+
} else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF)) {
177172
audit_autoremove_mark_rule(audit_mark);
173+
}
178174

179175
return 0;
180176
}
181177

182178
static const struct fsnotify_ops audit_mark_fsnotify_ops = {
183-
.handle_event = audit_mark_handle_event,
179+
.handle_inode_event = audit_mark_handle_event,
184180
.free_mark = audit_fsnotify_free_mark,
185181
};
186182

kernel/audit_tree.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,11 +1037,9 @@ static void evict_chunk(struct audit_chunk *chunk)
10371037
audit_schedule_prune();
10381038
}
10391039

1040-
static int audit_tree_handle_event(struct fsnotify_group *group, u32 mask,
1041-
const void *data, int data_type,
1042-
struct inode *dir,
1043-
const struct qstr *file_name, u32 cookie,
1044-
struct fsnotify_iter_info *iter_info)
1040+
static int audit_tree_handle_event(struct fsnotify_mark *mark, u32 mask,
1041+
struct inode *inode, struct inode *dir,
1042+
const struct qstr *file_name)
10451043
{
10461044
return 0;
10471045
}
@@ -1070,7 +1068,7 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *mark,
10701068
}
10711069

10721070
static const struct fsnotify_ops audit_tree_ops = {
1073-
.handle_event = audit_tree_handle_event,
1071+
.handle_inode_event = audit_tree_handle_event,
10741072
.freeing_mark = audit_tree_freeing_mark,
10751073
.free_mark = audit_tree_destroy_watch,
10761074
};

kernel/audit_watch.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -464,20 +464,17 @@ void audit_remove_watch_rule(struct audit_krule *krule)
464464
}
465465

466466
/* Update watch data in audit rules based on fsnotify events. */
467-
static int audit_watch_handle_event(struct fsnotify_group *group, u32 mask,
468-
const void *data, int data_type,
469-
struct inode *dir,
470-
const struct qstr *dname, u32 cookie,
471-
struct fsnotify_iter_info *iter_info)
467+
static int audit_watch_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
468+
struct inode *inode, struct inode *dir,
469+
const struct qstr *dname)
472470
{
473-
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
474-
const struct inode *inode = fsnotify_data_inode(data, data_type);
475471
struct audit_parent *parent;
476472

477473
parent = container_of(inode_mark, struct audit_parent, mark);
478474

479-
BUG_ON(group != audit_watch_group);
480-
WARN_ON(!inode);
475+
if (WARN_ON_ONCE(inode_mark->group != audit_watch_group) ||
476+
WARN_ON_ONCE(!inode))
477+
return 0;
481478

482479
if (mask & (FS_CREATE|FS_MOVED_TO) && inode)
483480
audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0);
@@ -490,7 +487,7 @@ static int audit_watch_handle_event(struct fsnotify_group *group, u32 mask,
490487
}
491488

492489
static const struct fsnotify_ops audit_watch_fsnotify_ops = {
493-
.handle_event = audit_watch_handle_event,
490+
.handle_inode_event = audit_watch_handle_event,
494491
.free_mark = audit_watch_free_mark,
495492
};
496493

0 commit comments

Comments
 (0)