hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/fs/notify/fsnotify.c
....@@ -1,19 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License as published by
6
- * the Free Software Foundation; either version 2, or (at your option)
7
- * any later version.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
13
- *
14
- * You should have received a copy of the GNU General Public License
15
- * along with this program; see the file COPYING. If not, write to
16
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
174 */
185
196 #include <linux/dcache.h>
....@@ -48,7 +35,7 @@
4835 * Called during unmount with no locks held, so needs to be safe against
4936 * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block.
5037 */
51
-void fsnotify_unmount_inodes(struct super_block *sb)
38
+static void fsnotify_unmount_inodes(struct super_block *sb)
5239 {
5340 struct inode *inode, *iput_inode = NULL;
5441
....@@ -70,6 +57,9 @@
7057 * doing an __iget/iput with SB_ACTIVE clear would actually
7158 * evict all inodes with zero i_count from icache which is
7259 * unnecessarily violent and may in fact be illegal to do.
60
+ * However, we should have been called /after/ evict_inodes
61
+ * removed all zero refcount inodes, in any case. Test to
62
+ * be sure.
7363 */
7464 if (!atomic_read(&inode->i_count)) {
7565 spin_unlock(&inode->i_lock);
....@@ -84,7 +74,7 @@
8474 iput(iput_inode);
8575
8676 /* for each watch, send FS_UNMOUNT and then remove it */
87
- fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
77
+ fsnotify_inode(inode, FS_UNMOUNT);
8878
8979 fsnotify_inode_delete(inode);
9080
....@@ -100,6 +90,12 @@
10090 /* Wait for outstanding inode references from connectors */
10191 wait_var_event(&sb->s_fsnotify_inode_refs,
10292 !atomic_long_read(&sb->s_fsnotify_inode_refs));
93
+}
94
+
95
+void fsnotify_sb_delete(struct super_block *sb)
96
+{
97
+ fsnotify_unmount_inodes(sb);
98
+ fsnotify_clear_marks_by_sb(sb);
10399 }
104100
105101 /*
....@@ -146,52 +142,178 @@
146142 spin_unlock(&inode->i_lock);
147143 }
148144
149
-/* Notify this dentry's parent about a child's events. */
150
-int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask)
145
+/* Are inode/sb/mount interested in parent and name info with this event? */
146
+static bool fsnotify_event_needs_parent(struct inode *inode, struct mount *mnt,
147
+ __u32 mask)
151148 {
149
+ __u32 marks_mask = 0;
150
+
151
+ /* We only send parent/name to inode/sb/mount for events on non-dir */
152
+ if (mask & FS_ISDIR)
153
+ return false;
154
+
155
+ /*
156
+ * All events that are possible on child can also may be reported with
157
+ * parent/name info to inode/sb/mount. Otherwise, a watching parent
158
+ * could result in events reported with unexpected name info to sb/mount.
159
+ */
160
+ BUILD_BUG_ON(FS_EVENTS_POSS_ON_CHILD & ~FS_EVENTS_POSS_TO_PARENT);
161
+
162
+ /* Did either inode/sb/mount subscribe for events with parent/name? */
163
+ marks_mask |= fsnotify_parent_needed_mask(inode->i_fsnotify_mask);
164
+ marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask);
165
+ if (mnt)
166
+ marks_mask |= fsnotify_parent_needed_mask(mnt->mnt_fsnotify_mask);
167
+
168
+ /* Did they subscribe for this event with parent/name info? */
169
+ return mask & marks_mask;
170
+}
171
+
172
+/*
173
+ * Notify this dentry's parent about a child's events with child name info
174
+ * if parent is watching or if inode/sb/mount are interested in events with
175
+ * parent and name info.
176
+ *
177
+ * Notify only the child without name info if parent is not watching and
178
+ * inode/sb/mount are not interested in events with parent and name info.
179
+ */
180
+int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
181
+ int data_type)
182
+{
183
+ const struct path *path = fsnotify_data_path(data, data_type);
184
+ struct mount *mnt = path ? real_mount(path->mnt) : NULL;
185
+ struct inode *inode = d_inode(dentry);
152186 struct dentry *parent;
153
- struct inode *p_inode;
187
+ bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED;
188
+ bool parent_needed, parent_interested;
189
+ __u32 p_mask;
190
+ struct inode *p_inode = NULL;
191
+ struct name_snapshot name;
192
+ struct qstr *file_name = NULL;
154193 int ret = 0;
155194
156
- if (!dentry)
157
- dentry = path->dentry;
158
-
159
- if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
195
+ /*
196
+ * Do inode/sb/mount care about parent and name info on non-dir?
197
+ * Do they care about any event at all?
198
+ */
199
+ if (!inode->i_fsnotify_marks && !inode->i_sb->s_fsnotify_marks &&
200
+ (!mnt || !mnt->mnt_fsnotify_marks) && !parent_watched)
160201 return 0;
161202
203
+ parent = NULL;
204
+ parent_needed = fsnotify_event_needs_parent(inode, mnt, mask);
205
+ if (!parent_watched && !parent_needed)
206
+ goto notify;
207
+
208
+ /* Does parent inode care about events on children? */
162209 parent = dget_parent(dentry);
163210 p_inode = parent->d_inode;
164
-
165
- if (unlikely(!fsnotify_inode_watches_children(p_inode))) {
211
+ p_mask = fsnotify_inode_watches_children(p_inode);
212
+ if (unlikely(parent_watched && !p_mask))
166213 __fsnotify_update_child_dentry_flags(p_inode);
167
- } else if (p_inode->i_fsnotify_mask & mask & ALL_FSNOTIFY_EVENTS) {
168
- struct name_snapshot name;
169214
170
- /* we are notifying a parent so come up with the new mask which
171
- * specifies these are events which came from a child. */
172
- mask |= FS_EVENT_ON_CHILD;
215
+ /*
216
+ * Include parent/name in notification either if some notification
217
+ * groups require parent info or the parent is interested in this event.
218
+ */
219
+ parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS;
220
+ if (parent_needed || parent_interested) {
221
+ /* When notifying parent, child should be passed as data */
222
+ WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));
173223
224
+ /* Notify both parent and child with child name info */
174225 take_dentry_name_snapshot(&name, dentry);
175
- if (path)
176
- ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
177
- name.name, 0);
178
- else
179
- ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
180
- name.name, 0);
181
- release_dentry_name_snapshot(&name);
226
+ file_name = &name.name;
227
+ if (parent_interested)
228
+ mask |= FS_EVENT_ON_CHILD;
182229 }
183230
231
+notify:
232
+ ret = fsnotify(mask, data, data_type, p_inode, file_name, inode, 0);
233
+
234
+ if (file_name)
235
+ release_dentry_name_snapshot(&name);
184236 dput(parent);
185237
186238 return ret;
187239 }
188240 EXPORT_SYMBOL_GPL(__fsnotify_parent);
189241
190
-static int send_to_group(struct inode *to_tell,
191
- __u32 mask, const void *data,
192
- int data_is, u32 cookie,
193
- const unsigned char *file_name,
194
- struct fsnotify_iter_info *iter_info)
242
+static int fsnotify_handle_inode_event(struct fsnotify_group *group,
243
+ struct fsnotify_mark *inode_mark,
244
+ u32 mask, const void *data, int data_type,
245
+ struct inode *dir, const struct qstr *name,
246
+ u32 cookie)
247
+{
248
+ const struct path *path = fsnotify_data_path(data, data_type);
249
+ struct inode *inode = fsnotify_data_inode(data, data_type);
250
+ const struct fsnotify_ops *ops = group->ops;
251
+
252
+ if (WARN_ON_ONCE(!ops->handle_inode_event))
253
+ return 0;
254
+
255
+ if ((inode_mark->mask & FS_EXCL_UNLINK) &&
256
+ path && d_unlinked(path->dentry))
257
+ return 0;
258
+
259
+ /* Check interest of this mark in case event was sent with two marks */
260
+ if (!(mask & inode_mark->mask & ALL_FSNOTIFY_EVENTS))
261
+ return 0;
262
+
263
+ return ops->handle_inode_event(inode_mark, mask, inode, dir, name, cookie);
264
+}
265
+
266
+static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
267
+ const void *data, int data_type,
268
+ struct inode *dir, const struct qstr *name,
269
+ u32 cookie, struct fsnotify_iter_info *iter_info)
270
+{
271
+ struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
272
+ struct fsnotify_mark *parent_mark = fsnotify_iter_parent_mark(iter_info);
273
+ int ret;
274
+
275
+ if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) ||
276
+ WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info)))
277
+ return 0;
278
+
279
+ if (parent_mark) {
280
+ /*
281
+ * parent_mark indicates that the parent inode is watching
282
+ * children and interested in this event, which is an event
283
+ * possible on child. But is *this mark* watching children and
284
+ * interested in this event?
285
+ */
286
+ if (parent_mark->mask & FS_EVENT_ON_CHILD) {
287
+ ret = fsnotify_handle_inode_event(group, parent_mark, mask,
288
+ data, data_type, dir, name, 0);
289
+ if (ret)
290
+ return ret;
291
+ }
292
+ if (!inode_mark)
293
+ return 0;
294
+ }
295
+
296
+ if (mask & FS_EVENT_ON_CHILD) {
297
+ /*
298
+ * Some events can be sent on both parent dir and child marks
299
+ * (e.g. FS_ATTRIB). If both parent dir and child are
300
+ * watching, report the event once to parent dir with name (if
301
+ * interested) and once to child without name (if interested).
302
+ * The child watcher is expecting an event without a file name
303
+ * and without the FS_EVENT_ON_CHILD flag.
304
+ */
305
+ mask &= ~FS_EVENT_ON_CHILD;
306
+ dir = NULL;
307
+ name = NULL;
308
+ }
309
+
310
+ return fsnotify_handle_inode_event(group, inode_mark, mask, data, data_type,
311
+ dir, name, cookie);
312
+}
313
+
314
+static int send_to_group(__u32 mask, const void *data, int data_type,
315
+ struct inode *dir, const struct qstr *file_name,
316
+ u32 cookie, struct fsnotify_iter_info *iter_info)
195317 {
196318 struct fsnotify_group *group = NULL;
197319 __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS);
....@@ -227,16 +349,20 @@
227349 }
228350 }
229351
230
- pr_debug("%s: group=%p to_tell=%p mask=%x marks_mask=%x marks_ignored_mask=%x"
231
- " data=%p data_is=%d cookie=%d\n",
232
- __func__, group, to_tell, mask, marks_mask, marks_ignored_mask,
233
- data, data_is, cookie);
352
+ pr_debug("%s: group=%p mask=%x marks_mask=%x marks_ignored_mask=%x data=%p data_type=%d dir=%p cookie=%d\n",
353
+ __func__, group, mask, marks_mask, marks_ignored_mask,
354
+ data, data_type, dir, cookie);
234355
235356 if (!(test_mask & marks_mask & ~marks_ignored_mask))
236357 return 0;
237358
238
- return group->ops->handle_event(group, to_tell, mask, data, data_is,
239
- file_name, cookie, iter_info);
359
+ if (group->ops->handle_event) {
360
+ return group->ops->handle_event(group, mask, data, data_type, dir,
361
+ file_name, cookie, iter_info);
362
+ }
363
+
364
+ return fsnotify_handle_event(group, mask, data, data_type, dir,
365
+ file_name, cookie, iter_info);
240366 }
241367
242368 static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector **connp)
....@@ -314,27 +440,50 @@
314440 }
315441
316442 /*
317
- * This is the main call to fsnotify. The VFS calls into hook specific functions
318
- * in linux/fsnotify.h. Those functions then in turn call here. Here will call
319
- * out to all of the registered fsnotify_group. Those groups can then use the
320
- * notification event in whatever means they feel necessary.
443
+ * fsnotify - This is the main call to fsnotify.
444
+ *
445
+ * The VFS calls into hook specific functions in linux/fsnotify.h.
446
+ * Those functions then in turn call here. Here will call out to all of the
447
+ * registered fsnotify_group. Those groups can then use the notification event
448
+ * in whatever means they feel necessary.
449
+ *
450
+ * @mask: event type and flags
451
+ * @data: object that event happened on
452
+ * @data_type: type of object for fanotify_data_XXX() accessors
453
+ * @dir: optional directory associated with event -
454
+ * if @file_name is not NULL, this is the directory that
455
+ * @file_name is relative to
456
+ * @file_name: optional file name associated with event
457
+ * @inode: optional inode associated with event -
458
+ * either @dir or @inode must be non-NULL.
459
+ * if both are non-NULL event may be reported to both.
460
+ * @cookie: inotify rename cookie
321461 */
322
-int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
323
- const unsigned char *file_name, u32 cookie)
462
+int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,
463
+ const struct qstr *file_name, struct inode *inode, u32 cookie)
324464 {
465
+ const struct path *path = fsnotify_data_path(data, data_type);
325466 struct fsnotify_iter_info iter_info = {};
326
- struct mount *mnt;
467
+ struct super_block *sb;
468
+ struct mount *mnt = NULL;
469
+ struct inode *parent = NULL;
327470 int ret = 0;
328
- __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS);
471
+ __u32 test_mask, marks_mask;
329472
330
- if (data_is == FSNOTIFY_EVENT_PATH)
331
- mnt = real_mount(((const struct path *)data)->mnt);
332
- else
333
- mnt = NULL;
473
+ if (path)
474
+ mnt = real_mount(path->mnt);
334475
335
- /* An event "on child" is not intended for a mount mark */
336
- if (mask & FS_EVENT_ON_CHILD)
337
- mnt = NULL;
476
+ if (!inode) {
477
+ /* Dirent event - report on TYPE_INODE to dir */
478
+ inode = dir;
479
+ } else if (mask & FS_EVENT_ON_CHILD) {
480
+ /*
481
+ * Event on child - report on TYPE_PARENT to dir if it is
482
+ * watching children and on TYPE_INODE to child.
483
+ */
484
+ parent = dir;
485
+ }
486
+ sb = inode->i_sb;
338487
339488 /*
340489 * Optimization: srcu_read_lock() has a memory barrier which can
....@@ -343,36 +492,54 @@
343492 * SRCU because we have no references to any objects and do not
344493 * need SRCU to keep them "alive".
345494 */
346
- if (!to_tell->i_fsnotify_marks &&
347
- (!mnt || !mnt->mnt_fsnotify_marks))
495
+ if (!sb->s_fsnotify_marks &&
496
+ (!mnt || !mnt->mnt_fsnotify_marks) &&
497
+ (!inode || !inode->i_fsnotify_marks) &&
498
+ (!parent || !parent->i_fsnotify_marks))
348499 return 0;
500
+
501
+ marks_mask = sb->s_fsnotify_mask;
502
+ if (mnt)
503
+ marks_mask |= mnt->mnt_fsnotify_mask;
504
+ if (inode)
505
+ marks_mask |= inode->i_fsnotify_mask;
506
+ if (parent)
507
+ marks_mask |= parent->i_fsnotify_mask;
508
+
509
+
349510 /*
350511 * if this is a modify event we may need to clear the ignored masks
351
- * otherwise return if neither the inode nor the vfsmount care about
352
- * this type of event.
512
+ * otherwise return if none of the marks care about this type of event.
353513 */
354
- if (!(mask & FS_MODIFY) &&
355
- !(test_mask & to_tell->i_fsnotify_mask) &&
356
- !(mnt && test_mask & mnt->mnt_fsnotify_mask))
514
+ test_mask = (mask & ALL_FSNOTIFY_EVENTS);
515
+ if (!(mask & FS_MODIFY) && !(test_mask & marks_mask))
357516 return 0;
358517
359518 iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
360519
361
- iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
362
- fsnotify_first_mark(&to_tell->i_fsnotify_marks);
520
+ iter_info.marks[FSNOTIFY_OBJ_TYPE_SB] =
521
+ fsnotify_first_mark(&sb->s_fsnotify_marks);
363522 if (mnt) {
364523 iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] =
365524 fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
366525 }
526
+ if (inode) {
527
+ iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
528
+ fsnotify_first_mark(&inode->i_fsnotify_marks);
529
+ }
530
+ if (parent) {
531
+ iter_info.marks[FSNOTIFY_OBJ_TYPE_PARENT] =
532
+ fsnotify_first_mark(&parent->i_fsnotify_marks);
533
+ }
367534
368535 /*
369
- * We need to merge inode & vfsmount mark lists so that inode mark
370
- * ignore masks are properly reflected for mount mark notifications.
536
+ * We need to merge inode/vfsmount/sb mark lists so that e.g. inode mark
537
+ * ignore masks are properly reflected for mount/sb mark notifications.
371538 * That's why this traversal is so complicated...
372539 */
373540 while (fsnotify_iter_select_report_types(&iter_info)) {
374
- ret = send_to_group(to_tell, mask, data, data_is, cookie,
375
- file_name, &iter_info);
541
+ ret = send_to_group(mask, data, data_type, dir, file_name,
542
+ cookie, &iter_info);
376543
377544 if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
378545 goto out;
....@@ -387,13 +554,11 @@
387554 }
388555 EXPORT_SYMBOL_GPL(fsnotify);
389556
390
-extern struct kmem_cache *fsnotify_mark_connector_cachep;
391
-
392557 static __init int fsnotify_init(void)
393558 {
394559 int ret;
395560
396
- BUG_ON(hweight32(ALL_FSNOTIFY_BITS) != 23);
561
+ BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 25);
397562
398563 ret = init_srcu_struct(&fsnotify_mark_srcu);
399564 if (ret)