Skip to content

Commit a898850

Browse files
committed
Merge tag 'fsnotify_for_v5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull fsnotify updates from Jan Kara: "A few fsnotify improvements and cleanups" * tag 'fsnotify_for_v5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: fsnotify: remove redundant parameter judgment fsnotify: optimize FS_MODIFY events with no ignored masks fsnotify: fix merge with parent's ignored mask
2 parents cb7cbaa + f92ca72 commit a898850

File tree

4 files changed

+61
-23
lines changed

4 files changed

+61
-23
lines changed

fs/notify/fanotify/fanotify_user.c

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,17 +1003,18 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
10031003
__u32 mask, unsigned int flags,
10041004
__u32 umask, int *destroy)
10051005
{
1006-
__u32 oldmask = 0;
1006+
__u32 oldmask, newmask;
10071007

10081008
/* umask bits cannot be removed by user */
10091009
mask &= ~umask;
10101010
spin_lock(&fsn_mark->lock);
1011+
oldmask = fsnotify_calc_mask(fsn_mark);
10111012
if (!(flags & FAN_MARK_IGNORED_MASK)) {
1012-
oldmask = fsn_mark->mask;
10131013
fsn_mark->mask &= ~mask;
10141014
} else {
10151015
fsn_mark->ignored_mask &= ~mask;
10161016
}
1017+
newmask = fsnotify_calc_mask(fsn_mark);
10171018
/*
10181019
* We need to keep the mark around even if remaining mask cannot
10191020
* result in any events (e.g. mask == FAN_ONDIR) to support incremenal
@@ -1023,7 +1024,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
10231024
*destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask);
10241025
spin_unlock(&fsn_mark->lock);
10251026

1026-
return mask & oldmask;
1027+
return oldmask & ~newmask;
10271028
}
10281029

10291030
static int fanotify_remove_mark(struct fsnotify_group *group,
@@ -1080,24 +1081,42 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
10801081
flags, umask);
10811082
}
10821083

1084+
static void fanotify_mark_add_ignored_mask(struct fsnotify_mark *fsn_mark,
1085+
__u32 mask, unsigned int flags,
1086+
__u32 *removed)
1087+
{
1088+
fsn_mark->ignored_mask |= mask;
1089+
1090+
/*
1091+
* Setting FAN_MARK_IGNORED_SURV_MODIFY for the first time may lead to
1092+
* the removal of the FS_MODIFY bit in calculated mask if it was set
1093+
* because of an ignored mask that is now going to survive FS_MODIFY.
1094+
*/
1095+
if ((flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
1096+
!(fsn_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) {
1097+
fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
1098+
if (!(fsn_mark->mask & FS_MODIFY))
1099+
*removed = FS_MODIFY;
1100+
}
1101+
}
1102+
10831103
static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
1084-
__u32 mask,
1085-
unsigned int flags)
1104+
__u32 mask, unsigned int flags,
1105+
__u32 *removed)
10861106
{
1087-
__u32 oldmask = -1;
1107+
__u32 oldmask, newmask;
10881108

10891109
spin_lock(&fsn_mark->lock);
1110+
oldmask = fsnotify_calc_mask(fsn_mark);
10901111
if (!(flags & FAN_MARK_IGNORED_MASK)) {
1091-
oldmask = fsn_mark->mask;
10921112
fsn_mark->mask |= mask;
10931113
} else {
1094-
fsn_mark->ignored_mask |= mask;
1095-
if (flags & FAN_MARK_IGNORED_SURV_MODIFY)
1096-
fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
1114+
fanotify_mark_add_ignored_mask(fsn_mark, mask, flags, removed);
10971115
}
1116+
newmask = fsnotify_calc_mask(fsn_mark);
10981117
spin_unlock(&fsn_mark->lock);
10991118

1100-
return mask & ~oldmask;
1119+
return newmask & ~oldmask;
11011120
}
11021121

11031122
static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
@@ -1155,7 +1174,7 @@ static int fanotify_add_mark(struct fsnotify_group *group,
11551174
__kernel_fsid_t *fsid)
11561175
{
11571176
struct fsnotify_mark *fsn_mark;
1158-
__u32 added;
1177+
__u32 added, removed = 0;
11591178
int ret = 0;
11601179

11611180
mutex_lock(&group->mark_mutex);
@@ -1178,8 +1197,8 @@ static int fanotify_add_mark(struct fsnotify_group *group,
11781197
goto out;
11791198
}
11801199

1181-
added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
1182-
if (added & ~fsnotify_conn_mask(fsn_mark->connector))
1200+
added = fanotify_mark_add_to_mask(fsn_mark, mask, flags, &removed);
1201+
if (removed || (added & ~fsnotify_conn_mask(fsn_mark->connector)))
11831202
fsnotify_recalc_mask(fsn_mark->connector);
11841203

11851204
out:

fs/notify/fsnotify.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ static void fsnotify_unmount_inodes(struct super_block *sb)
7070
spin_unlock(&inode->i_lock);
7171
spin_unlock(&sb->s_inode_list_lock);
7272

73-
if (iput_inode)
74-
iput(iput_inode);
73+
iput(iput_inode);
7574

7675
/* for each watch, send FS_UNMOUNT and then remove it */
7776
fsnotify_inode(inode, FS_UNMOUNT);
@@ -85,8 +84,7 @@ static void fsnotify_unmount_inodes(struct super_block *sb)
8584
}
8685
spin_unlock(&sb->s_inode_list_lock);
8786

88-
if (iput_inode)
89-
iput(iput_inode);
87+
iput(iput_inode);
9088
}
9189

9290
void fsnotify_sb_delete(struct super_block *sb)
@@ -531,11 +529,13 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,
531529

532530

533531
/*
534-
* if this is a modify event we may need to clear the ignored masks
535-
* otherwise return if none of the marks care about this type of event.
532+
* If this is a modify event we may need to clear some ignored masks.
533+
* In that case, the object with ignored masks will have the FS_MODIFY
534+
* event in its mask.
535+
* Otherwise, return if none of the marks care about this type of event.
536536
*/
537537
test_mask = (mask & ALL_FSNOTIFY_EVENTS);
538-
if (!(mask & FS_MODIFY) && !(test_mask & marks_mask))
538+
if (!(test_mask & marks_mask))
539539
return 0;
540540

541541
iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);

fs/notify/mark.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
127127
return;
128128
hlist_for_each_entry(mark, &conn->list, obj_list) {
129129
if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)
130-
new_mask |= mark->mask;
130+
new_mask |= fsnotify_calc_mask(mark);
131131
}
132132
*fsnotify_conn_mask_p(conn) = new_mask;
133133
}
@@ -692,7 +692,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
692692
if (ret)
693693
goto err;
694694

695-
if (mark->mask)
695+
if (mark->mask || mark->ignored_mask)
696696
fsnotify_recalc_mask(mark->connector);
697697

698698
return ret;

include/linux/fsnotify_backend.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,25 @@ extern void fsnotify_remove_queued_event(struct fsnotify_group *group,
601601

602602
/* functions used to manipulate the marks attached to inodes */
603603

604+
/* Get mask for calculating object interest taking ignored mask into account */
605+
static inline __u32 fsnotify_calc_mask(struct fsnotify_mark *mark)
606+
{
607+
__u32 mask = mark->mask;
608+
609+
if (!mark->ignored_mask)
610+
return mask;
611+
612+
/* Interest in FS_MODIFY may be needed for clearing ignored mask */
613+
if (!(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
614+
mask |= FS_MODIFY;
615+
616+
/*
617+
* If mark is interested in ignoring events on children, the object must
618+
* show interest in those events for fsnotify_parent() to notice it.
619+
*/
620+
return mask | (mark->ignored_mask & ALL_FSNOTIFY_EVENTS);
621+
}
622+
604623
/* Get mask of events for a list of marks */
605624
extern __u32 fsnotify_conn_mask(struct fsnotify_mark_connector *conn);
606625
/* Calculate mask of events for a list of marks */

0 commit comments

Comments
 (0)