Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+62 -24
+34 -15
fs/notify/fanotify/fanotify_user.c
··· 1003 1003 __u32 mask, unsigned int flags, 1004 1004 __u32 umask, int *destroy) 1005 1005 { 1006 - __u32 oldmask = 0; 1006 + __u32 oldmask, newmask; 1007 1007 1008 1008 /* umask bits cannot be removed by user */ 1009 1009 mask &= ~umask; 1010 1010 spin_lock(&fsn_mark->lock); 1011 + oldmask = fsnotify_calc_mask(fsn_mark); 1011 1012 if (!(flags & FAN_MARK_IGNORED_MASK)) { 1012 - oldmask = fsn_mark->mask; 1013 1013 fsn_mark->mask &= ~mask; 1014 1014 } else { 1015 1015 fsn_mark->ignored_mask &= ~mask; 1016 1016 } 1017 + newmask = fsnotify_calc_mask(fsn_mark); 1017 1018 /* 1018 1019 * We need to keep the mark around even if remaining mask cannot 1019 1020 * result in any events (e.g. mask == FAN_ONDIR) to support incremenal ··· 1024 1023 *destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask); 1025 1024 spin_unlock(&fsn_mark->lock); 1026 1025 1027 - return mask & oldmask; 1026 + return oldmask & ~newmask; 1028 1027 } 1029 1028 1030 1029 static int fanotify_remove_mark(struct fsnotify_group *group, ··· 1081 1080 flags, umask); 1082 1081 } 1083 1082 1084 - static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, 1085 - __u32 mask, 1086 - unsigned int flags) 1083 + static void fanotify_mark_add_ignored_mask(struct fsnotify_mark *fsn_mark, 1084 + __u32 mask, unsigned int flags, 1085 + __u32 *removed) 1087 1086 { 1088 - __u32 oldmask = -1; 1087 + fsn_mark->ignored_mask |= mask; 1088 + 1089 + /* 1090 + * Setting FAN_MARK_IGNORED_SURV_MODIFY for the first time may lead to 1091 + * the removal of the FS_MODIFY bit in calculated mask if it was set 1092 + * because of an ignored mask that is now going to survive FS_MODIFY. 1093 + */ 1094 + if ((flags & FAN_MARK_IGNORED_SURV_MODIFY) && 1095 + !(fsn_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) { 1096 + fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY; 1097 + if (!(fsn_mark->mask & FS_MODIFY)) 1098 + *removed = FS_MODIFY; 1099 + } 1100 + } 1101 + 1102 + static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, 1103 + __u32 mask, unsigned int flags, 1104 + __u32 *removed) 1105 + { 1106 + __u32 oldmask, newmask; 1089 1107 1090 1108 spin_lock(&fsn_mark->lock); 1109 + oldmask = fsnotify_calc_mask(fsn_mark); 1091 1110 if (!(flags & FAN_MARK_IGNORED_MASK)) { 1092 - oldmask = fsn_mark->mask; 1093 1111 fsn_mark->mask |= mask; 1094 1112 } else { 1095 - fsn_mark->ignored_mask |= mask; 1096 - if (flags & FAN_MARK_IGNORED_SURV_MODIFY) 1097 - fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY; 1113 + fanotify_mark_add_ignored_mask(fsn_mark, mask, flags, removed); 1098 1114 } 1115 + newmask = fsnotify_calc_mask(fsn_mark); 1099 1116 spin_unlock(&fsn_mark->lock); 1100 1117 1101 - return mask & ~oldmask; 1118 + return newmask & ~oldmask; 1102 1119 } 1103 1120 1104 1121 static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group, ··· 1174 1155 __kernel_fsid_t *fsid) 1175 1156 { 1176 1157 struct fsnotify_mark *fsn_mark; 1177 - __u32 added; 1158 + __u32 added, removed = 0; 1178 1159 int ret = 0; 1179 1160 1180 1161 mutex_lock(&group->mark_mutex); ··· 1197 1178 goto out; 1198 1179 } 1199 1180 1200 - added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); 1201 - if (added & ~fsnotify_conn_mask(fsn_mark->connector)) 1181 + added = fanotify_mark_add_to_mask(fsn_mark, mask, flags, &removed); 1182 + if (removed || (added & ~fsnotify_conn_mask(fsn_mark->connector))) 1202 1183 fsnotify_recalc_mask(fsn_mark->connector); 1203 1184 1204 1185 out:
+7 -7
fs/notify/fsnotify.c
··· 70 70 spin_unlock(&inode->i_lock); 71 71 spin_unlock(&sb->s_inode_list_lock); 72 72 73 - if (iput_inode) 74 - iput(iput_inode); 73 + iput(iput_inode); 75 74 76 75 /* for each watch, send FS_UNMOUNT and then remove it */ 77 76 fsnotify_inode(inode, FS_UNMOUNT); ··· 84 85 } 85 86 spin_unlock(&sb->s_inode_list_lock); 86 87 87 - if (iput_inode) 88 - iput(iput_inode); 88 + iput(iput_inode); 89 89 } 90 90 91 91 void fsnotify_sb_delete(struct super_block *sb) ··· 529 531 530 532 531 533 /* 532 - * if this is a modify event we may need to clear the ignored masks 533 - * otherwise return if none of the marks care about this type of event. 534 + * If this is a modify event we may need to clear some ignored masks. 535 + * In that case, the object with ignored masks will have the FS_MODIFY 536 + * event in its mask. 537 + * Otherwise, return if none of the marks care about this type of event. 534 538 */ 535 539 test_mask = (mask & ALL_FSNOTIFY_EVENTS); 536 - if (!(mask & FS_MODIFY) && !(test_mask & marks_mask)) 540 + if (!(test_mask & marks_mask)) 537 541 return 0; 538 542 539 543 iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
+2 -2
fs/notify/mark.c
··· 127 127 return; 128 128 hlist_for_each_entry(mark, &conn->list, obj_list) { 129 129 if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) 130 - new_mask |= mark->mask; 130 + new_mask |= fsnotify_calc_mask(mark); 131 131 } 132 132 *fsnotify_conn_mask_p(conn) = new_mask; 133 133 } ··· 692 692 if (ret) 693 693 goto err; 694 694 695 - if (mark->mask) 695 + if (mark->mask || mark->ignored_mask) 696 696 fsnotify_recalc_mask(mark->connector); 697 697 698 698 return ret;
+19
include/linux/fsnotify_backend.h
··· 601 601 602 602 /* functions used to manipulate the marks attached to inodes */ 603 603 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 + 604 623 /* Get mask of events for a list of marks */ 605 624 extern __u32 fsnotify_conn_mask(struct fsnotify_mark_connector *conn); 606 625 /* Calculate mask of events for a list of marks */