diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2009-12-17 21:24:28 -0500 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2010-07-28 09:58:58 -0400 |
commit | 912ee3946c5e57de0d05baf3b60b65ce6bf3ff96 (patch) | |
tree | e6b9c6f4ab5f513e088159a2aa759e3f225559e7 /fs/notify/fanotify | |
parent | 088b09b0ac7a866a35962eeaea5d5607bd1840b7 (diff) |
fanotify: do not call fanotify_update_object_mask in fanotify_add_mark
Recalculate masks in fanotify_add_mark, don't use
fanotify_update_object_mask. This gets us one step closers to readable
code.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify/fanotify')
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 144 |
1 files changed, 50 insertions, 94 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 96d4ffd72519..db7467782e8c 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -295,64 +295,6 @@ out: | |||
295 | return ret; | 295 | return ret; |
296 | } | 296 | } |
297 | 297 | ||
298 | static void fanotify_update_object_mask(struct fsnotify_group *group, | ||
299 | struct inode *inode, | ||
300 | struct vfsmount *mnt, | ||
301 | struct fsnotify_mark *fsn_mark, | ||
302 | unsigned int flags, | ||
303 | __u32 mask) | ||
304 | { | ||
305 | __u32 old_mask, new_mask; | ||
306 | |||
307 | pr_debug("%s: group=%p inode=%p mnt=%p fsn_mark=%p flags=%x mask=%x\n", | ||
308 | __func__, group, inode, mnt, fsn_mark, flags, mask); | ||
309 | |||
310 | spin_lock(&fsn_mark->lock); | ||
311 | old_mask = fsn_mark->mask; | ||
312 | if (flags & FAN_MARK_ADD) | ||
313 | fsn_mark->mask |= mask; | ||
314 | else if (flags & FAN_MARK_REMOVE) | ||
315 | fsn_mark->mask &= ~mask; | ||
316 | else | ||
317 | BUG(); | ||
318 | new_mask = fsn_mark->mask; | ||
319 | spin_unlock(&fsn_mark->lock); | ||
320 | |||
321 | if (!new_mask) | ||
322 | fsnotify_destroy_mark(fsn_mark); | ||
323 | |||
324 | /* we made changes to a mask, update the group mask and the object mask | ||
325 | * so things happen quickly. */ | ||
326 | if (old_mask != new_mask) { | ||
327 | __u32 dropped, do_object, do_group; | ||
328 | |||
329 | /* more bits in old than in new? */ | ||
330 | dropped = (old_mask & ~new_mask); | ||
331 | /* more bits in this fsn_mark than the group? */ | ||
332 | do_group = (new_mask & ~group->mask); | ||
333 | |||
334 | if (inode) { | ||
335 | /* more bits in this fsn_mark than the object's mask? */ | ||
336 | do_object = (new_mask & ~inode->i_fsnotify_mask); | ||
337 | /* update the object with this new fsn_mark */ | ||
338 | if (dropped || do_object) | ||
339 | fsnotify_recalc_inode_mask(inode); | ||
340 | } else if (mnt) { | ||
341 | /* more bits in this fsn_mark than the object's mask? */ | ||
342 | do_object = (new_mask & ~mnt->mnt_fsnotify_mask); | ||
343 | /* update the object with this new fsn_mark */ | ||
344 | if (dropped || do_object) | ||
345 | fsnotify_recalc_vfsmount_mask(mnt); | ||
346 | } else { | ||
347 | BUG(); | ||
348 | } | ||
349 | |||
350 | /* update the group mask with the new mask */ | ||
351 | if (dropped || do_group) | ||
352 | fsnotify_recalc_group_mask(group); | ||
353 | } | ||
354 | } | ||
355 | |||
356 | static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u32 mask) | 298 | static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u32 mask) |
357 | { | 299 | { |
358 | __u32 oldmask; | 300 | __u32 oldmask; |
@@ -404,89 +346,103 @@ static int fanotify_remove_mark(struct fsnotify_group *group, struct inode *inod | |||
404 | return 0; | 346 | return 0; |
405 | } | 347 | } |
406 | 348 | ||
349 | static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, __u32 mask) | ||
350 | { | ||
351 | __u32 oldmask; | ||
352 | |||
353 | spin_lock(&fsn_mark->lock); | ||
354 | oldmask = fsn_mark->mask; | ||
355 | fsn_mark->mask = oldmask | mask; | ||
356 | spin_unlock(&fsn_mark->lock); | ||
357 | |||
358 | return mask & ~oldmask; | ||
359 | } | ||
360 | |||
407 | static struct fsnotify_mark *fanotify_add_vfsmount_mark(struct fsnotify_group *group, | 361 | static struct fsnotify_mark *fanotify_add_vfsmount_mark(struct fsnotify_group *group, |
408 | struct vfsmount *mnt) | 362 | struct vfsmount *mnt, __u32 mask) |
409 | { | 363 | { |
410 | struct fsnotify_mark *fsn_mark; | 364 | struct fsnotify_mark *fsn_mark; |
365 | __u32 added; | ||
411 | 366 | ||
412 | fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); | 367 | fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); |
413 | if (!fsn_mark) { | 368 | if (!fsn_mark) { |
414 | struct fsnotify_mark *new_fsn_mark; | ||
415 | int ret; | 369 | int ret; |
416 | 370 | ||
417 | fsn_mark = ERR_PTR(-ENOMEM); | 371 | fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); |
418 | new_fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); | 372 | if (!fsn_mark) |
419 | if (!new_fsn_mark) | 373 | return ERR_PTR(-ENOMEM); |
420 | goto out; | ||
421 | 374 | ||
422 | fsnotify_init_mark(new_fsn_mark, fanotify_free_mark); | 375 | fsnotify_init_mark(fsn_mark, fanotify_free_mark); |
423 | ret = fsnotify_add_mark(new_fsn_mark, group, NULL, mnt, 0); | 376 | ret = fsnotify_add_mark(fsn_mark, group, NULL, mnt, 0); |
424 | if (ret) { | 377 | if (ret) { |
425 | fsn_mark = ERR_PTR(ret); | 378 | fanotify_free_mark(fsn_mark); |
426 | fanotify_free_mark(new_fsn_mark); | 379 | return ERR_PTR(ret); |
427 | goto out; | ||
428 | } | 380 | } |
429 | |||
430 | fsn_mark = new_fsn_mark; | ||
431 | } | 381 | } |
432 | out: | 382 | added = fanotify_mark_add_to_mask(fsn_mark, mask); |
383 | if (added) { | ||
384 | if (added & ~group->mask) | ||
385 | fsnotify_recalc_group_mask(group); | ||
386 | if (added & ~mnt->mnt_fsnotify_mask) | ||
387 | fsnotify_recalc_vfsmount_mask(mnt); | ||
388 | } | ||
433 | return fsn_mark; | 389 | return fsn_mark; |
434 | } | 390 | } |
435 | 391 | ||
436 | static struct fsnotify_mark *fanotify_add_inode_mark(struct fsnotify_group *group, | 392 | static struct fsnotify_mark *fanotify_add_inode_mark(struct fsnotify_group *group, |
437 | struct inode *inode) | 393 | struct inode *inode, __u32 mask) |
438 | { | 394 | { |
439 | struct fsnotify_mark *fsn_mark; | 395 | struct fsnotify_mark *fsn_mark; |
396 | __u32 added; | ||
440 | 397 | ||
441 | pr_debug("%s: group=%p inode=%p\n", __func__, group, inode); | 398 | pr_debug("%s: group=%p inode=%p\n", __func__, group, inode); |
442 | 399 | ||
443 | fsn_mark = fsnotify_find_inode_mark(group, inode); | 400 | fsn_mark = fsnotify_find_inode_mark(group, inode); |
444 | if (!fsn_mark) { | 401 | if (!fsn_mark) { |
445 | struct fsnotify_mark *new_fsn_mark; | ||
446 | int ret; | 402 | int ret; |
447 | 403 | ||
448 | fsn_mark = ERR_PTR(-ENOMEM); | 404 | fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); |
449 | new_fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); | 405 | if (!fsn_mark) |
450 | if (!new_fsn_mark) | 406 | return ERR_PTR(-ENOMEM); |
451 | goto out; | ||
452 | 407 | ||
453 | fsnotify_init_mark(new_fsn_mark, fanotify_free_mark); | 408 | fsnotify_init_mark(fsn_mark, fanotify_free_mark); |
454 | ret = fsnotify_add_mark(new_fsn_mark, group, inode, NULL, 0); | 409 | ret = fsnotify_add_mark(fsn_mark, group, inode, NULL, 0); |
455 | if (ret) { | 410 | if (ret) { |
456 | fsn_mark = ERR_PTR(ret); | 411 | fanotify_free_mark(fsn_mark); |
457 | fanotify_free_mark(new_fsn_mark); | 412 | return ERR_PTR(ret); |
458 | goto out; | ||
459 | } | 413 | } |
460 | |||
461 | fsn_mark = new_fsn_mark; | ||
462 | } | 414 | } |
463 | out: | 415 | added = fanotify_mark_add_to_mask(fsn_mark, mask); |
416 | if (added) { | ||
417 | if (added & ~group->mask) | ||
418 | fsnotify_recalc_group_mask(group); | ||
419 | if (added & ~inode->i_fsnotify_mask) | ||
420 | fsnotify_recalc_inode_mask(inode); | ||
421 | } | ||
464 | return fsn_mark; | 422 | return fsn_mark; |
465 | } | 423 | } |
466 | 424 | ||
467 | static int fanotify_add_mark(struct fsnotify_group *group, struct inode *inode, | 425 | static int fanotify_add_mark(struct fsnotify_group *group, struct inode *inode, |
468 | struct vfsmount *mnt, unsigned int flags, __u32 mask) | 426 | struct vfsmount *mnt, __u32 mask) |
469 | { | 427 | { |
470 | struct fsnotify_mark *fsn_mark; | 428 | struct fsnotify_mark *fsn_mark; |
471 | 429 | ||
472 | pr_debug("%s: group=%p inode=%p mnt=%p flags=%x mask=%x\n", | 430 | pr_debug("%s: group=%p inode=%p mnt=%p mask=%x\n", |
473 | __func__, group, inode, mnt, flags, mask); | 431 | __func__, group, inode, mnt, mask); |
474 | 432 | ||
475 | BUG_ON(inode && mnt); | 433 | BUG_ON(inode && mnt); |
476 | BUG_ON(!inode && !mnt); | 434 | BUG_ON(!inode && !mnt); |
477 | 435 | ||
478 | if (inode) | 436 | if (inode) |
479 | fsn_mark = fanotify_add_inode_mark(group, inode); | 437 | fsn_mark = fanotify_add_inode_mark(group, inode, mask); |
480 | else if (mnt) | 438 | else if (mnt) |
481 | fsn_mark = fanotify_add_vfsmount_mark(group, mnt); | 439 | fsn_mark = fanotify_add_vfsmount_mark(group, mnt, mask); |
482 | else | 440 | else |
483 | BUG(); | 441 | BUG(); |
484 | 442 | ||
485 | if (IS_ERR(fsn_mark)) | 443 | if (IS_ERR(fsn_mark)) |
486 | goto out; | 444 | goto out; |
487 | 445 | ||
488 | fanotify_update_object_mask(group, inode, mnt, fsn_mark, flags, mask); | ||
489 | |||
490 | /* match the init or the find.... */ | 446 | /* match the init or the find.... */ |
491 | fsnotify_put_mark(fsn_mark); | 447 | fsnotify_put_mark(fsn_mark); |
492 | out: | 448 | out: |
@@ -590,7 +546,7 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, | |||
590 | /* create/update an inode mark */ | 546 | /* create/update an inode mark */ |
591 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { | 547 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { |
592 | case FAN_MARK_ADD: | 548 | case FAN_MARK_ADD: |
593 | ret = fanotify_add_mark(group, inode, NULL, flags, mask); | 549 | ret = fanotify_add_mark(group, inode, NULL, mask); |
594 | break; | 550 | break; |
595 | case FAN_MARK_REMOVE: | 551 | case FAN_MARK_REMOVE: |
596 | ret = fanotify_remove_mark(group, inode, NULL, mask); | 552 | ret = fanotify_remove_mark(group, inode, NULL, mask); |