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

Configure Feed

Select the types of activity you want to include in your feed.

fsnotify: generalize iteration of marks by object type

Make some code that handles marks of object types inode and vfsmount
generic, so it can handle other object types.

Introduce fsnotify_foreach_obj_type macro to iterate marks by object type
and fsnotify_iter_{should|set}_report_type macros to set/test report_mask.

This is going to be used for adding mark of another object type
(super block mark).

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>

authored by

Amir Goldstein and committed by
Jan Kara
47d9c7cc d9a6f30b

+72 -39
+28 -24
fs/notify/fsnotify.c
··· 269 269 static unsigned int fsnotify_iter_select_report_types( 270 270 struct fsnotify_iter_info *iter_info) 271 271 { 272 - struct fsnotify_mark *inode_mark = iter_info->inode_mark; 273 - struct fsnotify_mark *vfsmount_mark = iter_info->vfsmount_mark; 274 - int cmp; 272 + struct fsnotify_group *max_prio_group = NULL; 273 + struct fsnotify_mark *mark; 274 + int type; 275 275 276 - if (!inode_mark && !vfsmount_mark) 277 - return 0; 278 - 279 - if (inode_mark && vfsmount_mark) { 280 - cmp = fsnotify_compare_groups(inode_mark->group, 281 - vfsmount_mark->group); 282 - } else { 283 - cmp = inode_mark ? -1 : 1; 276 + /* Choose max prio group among groups of all queue heads */ 277 + fsnotify_foreach_obj_type(type) { 278 + mark = iter_info->marks[type]; 279 + if (mark && 280 + fsnotify_compare_groups(max_prio_group, mark->group) > 0) 281 + max_prio_group = mark->group; 284 282 } 285 283 284 + if (!max_prio_group) 285 + return 0; 286 + 287 + /* Set the report mask for marks from same group as max prio group */ 286 288 iter_info->report_mask = 0; 287 - if (cmp <= 0) 288 - iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_INODE_FL; 289 - if (cmp >= 0) 290 - iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL; 289 + fsnotify_foreach_obj_type(type) { 290 + mark = iter_info->marks[type]; 291 + if (mark && 292 + fsnotify_compare_groups(max_prio_group, mark->group) == 0) 293 + fsnotify_iter_set_report_type(iter_info, type); 294 + } 291 295 292 296 return iter_info->report_mask; 293 297 } ··· 302 298 */ 303 299 static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) 304 300 { 305 - if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_INODE_FL) 306 - iter_info->inode_mark = 307 - fsnotify_next_mark(iter_info->inode_mark); 301 + int type; 308 302 309 - if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL) 310 - iter_info->vfsmount_mark = 311 - fsnotify_next_mark(iter_info->vfsmount_mark); 303 + fsnotify_foreach_obj_type(type) { 304 + if (fsnotify_iter_should_report_type(iter_info, type)) 305 + iter_info->marks[type] = 306 + fsnotify_next_mark(iter_info->marks[type]); 307 + } 312 308 } 313 309 314 310 /* ··· 355 351 356 352 if ((mask & FS_MODIFY) || 357 353 (test_mask & to_tell->i_fsnotify_mask)) { 358 - iter_info.inode_mark = 354 + iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = 359 355 fsnotify_first_mark(&to_tell->i_fsnotify_marks); 360 356 } 361 357 362 358 if (mnt && ((mask & FS_MODIFY) || 363 359 (test_mask & mnt->mnt_fsnotify_mask))) { 364 - iter_info.inode_mark = 360 + iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = 365 361 fsnotify_first_mark(&to_tell->i_fsnotify_marks); 366 - iter_info.vfsmount_mark = 362 + iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] = 367 363 fsnotify_first_mark(&mnt->mnt_fsnotify_marks); 368 364 } 369 365
+4 -4
fs/notify/inotify/inotify_user.c
··· 485 485 struct fsnotify_group *group) 486 486 { 487 487 struct inotify_inode_mark *i_mark; 488 - struct fsnotify_iter_info iter_info = { 489 - .inode_mark = fsn_mark, 490 - .report_mask = FSNOTIFY_OBJ_TYPE_INODE_FL, 491 - }; 488 + struct fsnotify_iter_info iter_info = { }; 489 + 490 + fsnotify_iter_set_report_type_mark(&iter_info, FSNOTIFY_OBJ_TYPE_INODE, 491 + fsn_mark); 492 492 493 493 /* Queue ignore event for the watch */ 494 494 inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL,
+15 -8
fs/notify/mark.c
··· 294 294 295 295 bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) 296 296 { 297 - /* This can fail if mark is being removed */ 298 - if (!fsnotify_get_mark_safe(iter_info->inode_mark)) 299 - return false; 300 - if (!fsnotify_get_mark_safe(iter_info->vfsmount_mark)) { 301 - fsnotify_put_mark_wake(iter_info->inode_mark); 302 - return false; 297 + int type; 298 + 299 + fsnotify_foreach_obj_type(type) { 300 + /* This can fail if mark is being removed */ 301 + if (!fsnotify_get_mark_safe(iter_info->marks[type])) 302 + goto fail; 303 303 } 304 304 305 305 /* ··· 310 310 srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx); 311 311 312 312 return true; 313 + 314 + fail: 315 + for (type--; type >= 0; type--) 316 + fsnotify_put_mark_wake(iter_info->marks[type]); 317 + return false; 313 318 } 314 319 315 320 void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info) 316 321 { 322 + int type; 323 + 317 324 iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); 318 - fsnotify_put_mark_wake(iter_info->inode_mark); 319 - fsnotify_put_mark_wake(iter_info->vfsmount_mark); 325 + fsnotify_foreach_obj_type(type) 326 + fsnotify_put_mark_wake(iter_info->marks[type]); 320 327 } 321 328 322 329 /*
+25 -3
include/linux/fsnotify_backend.h
··· 211 211 #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) 212 212 213 213 struct fsnotify_iter_info { 214 - struct fsnotify_mark *inode_mark; 215 - struct fsnotify_mark *vfsmount_mark; 214 + struct fsnotify_mark *marks[FSNOTIFY_OBJ_TYPE_COUNT]; 216 215 unsigned int report_mask; 217 216 int srcu_idx; 218 217 }; 218 + 219 + static inline bool fsnotify_iter_should_report_type( 220 + struct fsnotify_iter_info *iter_info, int type) 221 + { 222 + return (iter_info->report_mask & (1U << type)); 223 + } 224 + 225 + static inline void fsnotify_iter_set_report_type( 226 + struct fsnotify_iter_info *iter_info, int type) 227 + { 228 + iter_info->report_mask |= (1U << type); 229 + } 230 + 231 + static inline void fsnotify_iter_set_report_type_mark( 232 + struct fsnotify_iter_info *iter_info, int type, 233 + struct fsnotify_mark *mark) 234 + { 235 + iter_info->marks[type] = mark; 236 + iter_info->report_mask |= (1U << type); 237 + } 219 238 220 239 #define FSNOTIFY_ITER_FUNCS(name, NAME) \ 221 240 static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ 222 241 struct fsnotify_iter_info *iter_info) \ 223 242 { \ 224 243 return (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_##NAME##_FL) ? \ 225 - iter_info->name##_mark : NULL; \ 244 + iter_info->marks[FSNOTIFY_OBJ_TYPE_##NAME] : NULL; \ 226 245 } 227 246 228 247 FSNOTIFY_ITER_FUNCS(inode, INODE) 229 248 FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) 249 + 250 + #define fsnotify_foreach_obj_type(type) \ 251 + for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++) 230 252 231 253 /* 232 254 * Inode / vfsmount point to this structure which tracks all marks attached to