diff options
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index e16076d386c4..4e1d8ec77b04 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -524,14 +524,18 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, | |||
524 | __u32 removed; | 524 | __u32 removed; |
525 | int destroy_mark; | 525 | int destroy_mark; |
526 | 526 | ||
527 | mutex_lock(&group->mark_mutex); | ||
527 | fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); | 528 | fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); |
528 | if (!fsn_mark) | 529 | if (!fsn_mark) { |
530 | mutex_unlock(&group->mark_mutex); | ||
529 | return -ENOENT; | 531 | return -ENOENT; |
532 | } | ||
530 | 533 | ||
531 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags, | 534 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags, |
532 | &destroy_mark); | 535 | &destroy_mark); |
533 | if (destroy_mark) | 536 | if (destroy_mark) |
534 | fsnotify_destroy_mark(fsn_mark, group); | 537 | fsnotify_destroy_mark_locked(fsn_mark, group); |
538 | mutex_unlock(&group->mark_mutex); | ||
535 | 539 | ||
536 | fsnotify_put_mark(fsn_mark); | 540 | fsnotify_put_mark(fsn_mark); |
537 | if (removed & real_mount(mnt)->mnt_fsnotify_mask) | 541 | if (removed & real_mount(mnt)->mnt_fsnotify_mask) |
@@ -548,14 +552,19 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group, | |||
548 | __u32 removed; | 552 | __u32 removed; |
549 | int destroy_mark; | 553 | int destroy_mark; |
550 | 554 | ||
555 | mutex_lock(&group->mark_mutex); | ||
551 | fsn_mark = fsnotify_find_inode_mark(group, inode); | 556 | fsn_mark = fsnotify_find_inode_mark(group, inode); |
552 | if (!fsn_mark) | 557 | if (!fsn_mark) { |
558 | mutex_unlock(&group->mark_mutex); | ||
553 | return -ENOENT; | 559 | return -ENOENT; |
560 | } | ||
554 | 561 | ||
555 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags, | 562 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags, |
556 | &destroy_mark); | 563 | &destroy_mark); |
557 | if (destroy_mark) | 564 | if (destroy_mark) |
558 | fsnotify_destroy_mark(fsn_mark, group); | 565 | fsnotify_destroy_mark_locked(fsn_mark, group); |
566 | mutex_unlock(&group->mark_mutex); | ||
567 | |||
559 | /* matches the fsnotify_find_inode_mark() */ | 568 | /* matches the fsnotify_find_inode_mark() */ |
560 | fsnotify_put_mark(fsn_mark); | 569 | fsnotify_put_mark(fsn_mark); |
561 | if (removed & inode->i_fsnotify_mask) | 570 | if (removed & inode->i_fsnotify_mask) |
@@ -599,21 +608,29 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, | |||
599 | __u32 added; | 608 | __u32 added; |
600 | int ret = 0; | 609 | int ret = 0; |
601 | 610 | ||
611 | mutex_lock(&group->mark_mutex); | ||
602 | fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); | 612 | fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); |
603 | if (!fsn_mark) { | 613 | if (!fsn_mark) { |
604 | if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks) | 614 | if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks) { |
615 | mutex_unlock(&group->mark_mutex); | ||
605 | return -ENOSPC; | 616 | return -ENOSPC; |
617 | } | ||
606 | 618 | ||
607 | fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); | 619 | fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); |
608 | if (!fsn_mark) | 620 | if (!fsn_mark) { |
621 | mutex_unlock(&group->mark_mutex); | ||
609 | return -ENOMEM; | 622 | return -ENOMEM; |
623 | } | ||
610 | 624 | ||
611 | fsnotify_init_mark(fsn_mark, fanotify_free_mark); | 625 | fsnotify_init_mark(fsn_mark, fanotify_free_mark); |
612 | ret = fsnotify_add_mark(fsn_mark, group, NULL, mnt, 0); | 626 | ret = fsnotify_add_mark_locked(fsn_mark, group, NULL, mnt, 0); |
613 | if (ret) | 627 | if (ret) { |
628 | mutex_unlock(&group->mark_mutex); | ||
614 | goto err; | 629 | goto err; |
630 | } | ||
615 | } | 631 | } |
616 | added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); | 632 | added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); |
633 | mutex_unlock(&group->mark_mutex); | ||
617 | 634 | ||
618 | if (added & ~real_mount(mnt)->mnt_fsnotify_mask) | 635 | if (added & ~real_mount(mnt)->mnt_fsnotify_mask) |
619 | fsnotify_recalc_vfsmount_mask(mnt); | 636 | fsnotify_recalc_vfsmount_mask(mnt); |
@@ -642,21 +659,29 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group, | |||
642 | (atomic_read(&inode->i_writecount) > 0)) | 659 | (atomic_read(&inode->i_writecount) > 0)) |
643 | return 0; | 660 | return 0; |
644 | 661 | ||
662 | mutex_lock(&group->mark_mutex); | ||
645 | fsn_mark = fsnotify_find_inode_mark(group, inode); | 663 | fsn_mark = fsnotify_find_inode_mark(group, inode); |
646 | if (!fsn_mark) { | 664 | if (!fsn_mark) { |
647 | if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks) | 665 | if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks) { |
666 | mutex_unlock(&group->mark_mutex); | ||
648 | return -ENOSPC; | 667 | return -ENOSPC; |
668 | } | ||
649 | 669 | ||
650 | fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); | 670 | fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); |
651 | if (!fsn_mark) | 671 | if (!fsn_mark) { |
672 | mutex_unlock(&group->mark_mutex); | ||
652 | return -ENOMEM; | 673 | return -ENOMEM; |
674 | } | ||
653 | 675 | ||
654 | fsnotify_init_mark(fsn_mark, fanotify_free_mark); | 676 | fsnotify_init_mark(fsn_mark, fanotify_free_mark); |
655 | ret = fsnotify_add_mark(fsn_mark, group, inode, NULL, 0); | 677 | ret = fsnotify_add_mark_locked(fsn_mark, group, inode, NULL, 0); |
656 | if (ret) | 678 | if (ret) { |
679 | mutex_unlock(&group->mark_mutex); | ||
657 | goto err; | 680 | goto err; |
681 | } | ||
658 | } | 682 | } |
659 | added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); | 683 | added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); |
684 | mutex_unlock(&group->mark_mutex); | ||
660 | 685 | ||
661 | if (added & ~inode->i_fsnotify_mask) | 686 | if (added & ~inode->i_fsnotify_mask) |
662 | fsnotify_recalc_inode_mask(inode); | 687 | fsnotify_recalc_inode_mask(inode); |