Skip to content

Commit 9385a84

Browse files
committed
fsnotify: Pass fsnotify_iter_info into handle_event handler
Pass fsnotify_iter_info into ->handle_event() handler so that it can release and reacquire SRCU lock via fsnotify_prepare_user_wait() and fsnotify_finish_user_wait() functions. These functions also make sure current marks are appropriately pinned so that iteration protected by srcu in fsnotify() stays safe. Reviewed-by: Miklos Szeredi <mszeredi@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
1 parent abc7757 commit 9385a84

File tree

10 files changed

+30
-15
lines changed

10 files changed

+30
-15
lines changed

fs/notify/dnotify/dnotify.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
8585
struct fsnotify_mark *inode_mark,
8686
struct fsnotify_mark *vfsmount_mark,
8787
u32 mask, const void *data, int data_type,
88-
const unsigned char *file_name, u32 cookie)
88+
const unsigned char *file_name, u32 cookie,
89+
struct fsnotify_iter_info *iter_info)
8990
{
9091
struct dnotify_mark *dn_mark;
9192
struct dnotify_struct *dn;

fs/notify/fanotify/fanotify.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ static int fanotify_handle_event(struct fsnotify_group *group,
174174
struct fsnotify_mark *inode_mark,
175175
struct fsnotify_mark *fanotify_mark,
176176
u32 mask, const void *data, int data_type,
177-
const unsigned char *file_name, u32 cookie)
177+
const unsigned char *file_name, u32 cookie,
178+
struct fsnotify_iter_info *iter_info)
178179
{
179180
int ret = 0;
180181
struct fanotify_event_info *event;

fs/notify/fsnotify.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ static int send_to_group(struct inode *to_tell,
127127
struct fsnotify_mark *vfsmount_mark,
128128
__u32 mask, const void *data,
129129
int data_is, u32 cookie,
130-
const unsigned char *file_name)
130+
const unsigned char *file_name,
131+
struct fsnotify_iter_info *iter_info)
131132
{
132133
struct fsnotify_group *group = NULL;
133134
__u32 inode_test_mask = 0;
@@ -178,7 +179,7 @@ static int send_to_group(struct inode *to_tell,
178179

179180
return group->ops->handle_event(group, to_tell, inode_mark,
180181
vfsmount_mark, mask, data, data_is,
181-
file_name, cookie);
182+
file_name, cookie, iter_info);
182183
}
183184

184185
/*
@@ -194,8 +195,9 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
194195
struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL;
195196
struct fsnotify_group *inode_group, *vfsmount_group;
196197
struct fsnotify_mark_connector *inode_conn, *vfsmount_conn;
198+
struct fsnotify_iter_info iter_info;
197199
struct mount *mnt;
198-
int idx, ret = 0;
200+
int ret = 0;
199201
/* global tests shouldn't care about events on child only the specific event */
200202
__u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
201203

@@ -224,7 +226,7 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
224226
!(mnt && test_mask & mnt->mnt_fsnotify_mask))
225227
return 0;
226228

227-
idx = srcu_read_lock(&fsnotify_mark_srcu);
229+
iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
228230

229231
if ((mask & FS_MODIFY) ||
230232
(test_mask & to_tell->i_fsnotify_mask)) {
@@ -284,8 +286,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
284286
vfsmount_mark = NULL;
285287
}
286288
}
289+
290+
iter_info.inode_mark = inode_mark;
291+
iter_info.vfsmount_mark = vfsmount_mark;
292+
287293
ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
288-
data, data_is, cookie, file_name);
294+
data, data_is, cookie, file_name,
295+
&iter_info);
289296

290297
if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
291298
goto out;
@@ -299,7 +306,7 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
299306
}
300307
ret = 0;
301308
out:
302-
srcu_read_unlock(&fsnotify_mark_srcu, idx);
309+
srcu_read_unlock(&fsnotify_mark_srcu, iter_info.srcu_idx);
303310

304311
return ret;
305312
}

fs/notify/inotify/inotify.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ extern int inotify_handle_event(struct fsnotify_group *group,
2727
struct fsnotify_mark *inode_mark,
2828
struct fsnotify_mark *vfsmount_mark,
2929
u32 mask, const void *data, int data_type,
30-
const unsigned char *file_name, u32 cookie);
30+
const unsigned char *file_name, u32 cookie,
31+
struct fsnotify_iter_info *iter_info);
3132

3233
extern const struct fsnotify_ops inotify_fsnotify_ops;
3334

fs/notify/inotify/inotify_fsnotify.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ int inotify_handle_event(struct fsnotify_group *group,
6868
struct fsnotify_mark *inode_mark,
6969
struct fsnotify_mark *vfsmount_mark,
7070
u32 mask, const void *data, int data_type,
71-
const unsigned char *file_name, u32 cookie)
71+
const unsigned char *file_name, u32 cookie,
72+
struct fsnotify_iter_info *iter_info)
7273
{
7374
struct inotify_inode_mark *i_mark;
7475
struct inotify_event_info *event;

fs/notify/inotify/inotify_user.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
474474

475475
/* Queue ignore event for the watch */
476476
inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED,
477-
NULL, FSNOTIFY_EVENT_NONE, NULL, 0);
477+
NULL, FSNOTIFY_EVENT_NONE, NULL, 0, NULL);
478478

479479
i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
480480
/* remove this mark from the idr */

include/linux/fsnotify_backend.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ struct fsnotify_ops {
9999
struct fsnotify_mark *inode_mark,
100100
struct fsnotify_mark *vfsmount_mark,
101101
u32 mask, const void *data, int data_type,
102-
const unsigned char *file_name, u32 cookie);
102+
const unsigned char *file_name, u32 cookie,
103+
struct fsnotify_iter_info *iter_info);
103104
void (*free_group_priv)(struct fsnotify_group *group);
104105
void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
105106
void (*free_event)(struct fsnotify_event *event);

kernel/audit_fsnotify.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ static int audit_mark_handle_event(struct fsnotify_group *group,
168168
struct fsnotify_mark *inode_mark,
169169
struct fsnotify_mark *vfsmount_mark,
170170
u32 mask, const void *data, int data_type,
171-
const unsigned char *dname, u32 cookie)
171+
const unsigned char *dname, u32 cookie,
172+
struct fsnotify_iter_info *iter_info)
172173
{
173174
struct audit_fsnotify_mark *audit_mark;
174175
const struct inode *inode = NULL;

kernel/audit_tree.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,8 @@ static int audit_tree_handle_event(struct fsnotify_group *group,
989989
struct fsnotify_mark *inode_mark,
990990
struct fsnotify_mark *vfsmount_mark,
991991
u32 mask, const void *data, int data_type,
992-
const unsigned char *file_name, u32 cookie)
992+
const unsigned char *file_name, u32 cookie,
993+
struct fsnotify_iter_info *iter_info)
993994
{
994995
return 0;
995996
}

kernel/audit_watch.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,8 @@ static int audit_watch_handle_event(struct fsnotify_group *group,
472472
struct fsnotify_mark *inode_mark,
473473
struct fsnotify_mark *vfsmount_mark,
474474
u32 mask, const void *data, int data_type,
475-
const unsigned char *dname, u32 cookie)
475+
const unsigned char *dname, u32 cookie,
476+
struct fsnotify_iter_info *iter_info)
476477
{
477478
const struct inode *inode;
478479
struct audit_parent *parent;

0 commit comments

Comments
 (0)