diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2010-05-21 15:27:26 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2010-05-21 15:27:26 -0400 |
commit | ee9a3607fb03e804ddf624544105f4e34260c380 (patch) | |
tree | ce41b6e0fa10982a306f6c142a92dbf3c9961284 /fs/fcntl.c | |
parent | b492e95be0ae672922f4734acf3f5d35c30be948 (diff) | |
parent | d515e86e639890b33a09390d062b0831664f04a2 (diff) |
Merge branch 'master' into for-2.6.35
Conflicts:
fs/ext3/fsync.c
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 66 |
1 files changed, 42 insertions, 24 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index bcba960328fa..f74d270ba155 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -619,9 +619,15 @@ int send_sigurg(struct fown_struct *fown) | |||
619 | return ret; | 619 | return ret; |
620 | } | 620 | } |
621 | 621 | ||
622 | static DEFINE_RWLOCK(fasync_lock); | 622 | static DEFINE_SPINLOCK(fasync_lock); |
623 | static struct kmem_cache *fasync_cache __read_mostly; | 623 | static struct kmem_cache *fasync_cache __read_mostly; |
624 | 624 | ||
625 | static void fasync_free_rcu(struct rcu_head *head) | ||
626 | { | ||
627 | kmem_cache_free(fasync_cache, | ||
628 | container_of(head, struct fasync_struct, fa_rcu)); | ||
629 | } | ||
630 | |||
625 | /* | 631 | /* |
626 | * Remove a fasync entry. If successfully removed, return | 632 | * Remove a fasync entry. If successfully removed, return |
627 | * positive and clear the FASYNC flag. If no entry exists, | 633 | * positive and clear the FASYNC flag. If no entry exists, |
@@ -630,8 +636,6 @@ static struct kmem_cache *fasync_cache __read_mostly; | |||
630 | * NOTE! It is very important that the FASYNC flag always | 636 | * NOTE! It is very important that the FASYNC flag always |
631 | * match the state "is the filp on a fasync list". | 637 | * match the state "is the filp on a fasync list". |
632 | * | 638 | * |
633 | * We always take the 'filp->f_lock', in since fasync_lock | ||
634 | * needs to be irq-safe. | ||
635 | */ | 639 | */ |
636 | static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp) | 640 | static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp) |
637 | { | 641 | { |
@@ -639,17 +643,22 @@ static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp) | |||
639 | int result = 0; | 643 | int result = 0; |
640 | 644 | ||
641 | spin_lock(&filp->f_lock); | 645 | spin_lock(&filp->f_lock); |
642 | write_lock_irq(&fasync_lock); | 646 | spin_lock(&fasync_lock); |
643 | for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { | 647 | for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { |
644 | if (fa->fa_file != filp) | 648 | if (fa->fa_file != filp) |
645 | continue; | 649 | continue; |
650 | |||
651 | spin_lock_irq(&fa->fa_lock); | ||
652 | fa->fa_file = NULL; | ||
653 | spin_unlock_irq(&fa->fa_lock); | ||
654 | |||
646 | *fp = fa->fa_next; | 655 | *fp = fa->fa_next; |
647 | kmem_cache_free(fasync_cache, fa); | 656 | call_rcu(&fa->fa_rcu, fasync_free_rcu); |
648 | filp->f_flags &= ~FASYNC; | 657 | filp->f_flags &= ~FASYNC; |
649 | result = 1; | 658 | result = 1; |
650 | break; | 659 | break; |
651 | } | 660 | } |
652 | write_unlock_irq(&fasync_lock); | 661 | spin_unlock(&fasync_lock); |
653 | spin_unlock(&filp->f_lock); | 662 | spin_unlock(&filp->f_lock); |
654 | return result; | 663 | return result; |
655 | } | 664 | } |
@@ -671,25 +680,30 @@ static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fa | |||
671 | return -ENOMEM; | 680 | return -ENOMEM; |
672 | 681 | ||
673 | spin_lock(&filp->f_lock); | 682 | spin_lock(&filp->f_lock); |
674 | write_lock_irq(&fasync_lock); | 683 | spin_lock(&fasync_lock); |
675 | for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { | 684 | for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { |
676 | if (fa->fa_file != filp) | 685 | if (fa->fa_file != filp) |
677 | continue; | 686 | continue; |
687 | |||
688 | spin_lock_irq(&fa->fa_lock); | ||
678 | fa->fa_fd = fd; | 689 | fa->fa_fd = fd; |
690 | spin_unlock_irq(&fa->fa_lock); | ||
691 | |||
679 | kmem_cache_free(fasync_cache, new); | 692 | kmem_cache_free(fasync_cache, new); |
680 | goto out; | 693 | goto out; |
681 | } | 694 | } |
682 | 695 | ||
696 | spin_lock_init(&new->fa_lock); | ||
683 | new->magic = FASYNC_MAGIC; | 697 | new->magic = FASYNC_MAGIC; |
684 | new->fa_file = filp; | 698 | new->fa_file = filp; |
685 | new->fa_fd = fd; | 699 | new->fa_fd = fd; |
686 | new->fa_next = *fapp; | 700 | new->fa_next = *fapp; |
687 | *fapp = new; | 701 | rcu_assign_pointer(*fapp, new); |
688 | result = 1; | 702 | result = 1; |
689 | filp->f_flags |= FASYNC; | 703 | filp->f_flags |= FASYNC; |
690 | 704 | ||
691 | out: | 705 | out: |
692 | write_unlock_irq(&fasync_lock); | 706 | spin_unlock(&fasync_lock); |
693 | spin_unlock(&filp->f_lock); | 707 | spin_unlock(&filp->f_lock); |
694 | return result; | 708 | return result; |
695 | } | 709 | } |
@@ -709,37 +723,41 @@ int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fap | |||
709 | 723 | ||
710 | EXPORT_SYMBOL(fasync_helper); | 724 | EXPORT_SYMBOL(fasync_helper); |
711 | 725 | ||
712 | void __kill_fasync(struct fasync_struct *fa, int sig, int band) | 726 | /* |
727 | * rcu_read_lock() is held | ||
728 | */ | ||
729 | static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band) | ||
713 | { | 730 | { |
714 | while (fa) { | 731 | while (fa) { |
715 | struct fown_struct * fown; | 732 | struct fown_struct *fown; |
716 | if (fa->magic != FASYNC_MAGIC) { | 733 | if (fa->magic != FASYNC_MAGIC) { |
717 | printk(KERN_ERR "kill_fasync: bad magic number in " | 734 | printk(KERN_ERR "kill_fasync: bad magic number in " |
718 | "fasync_struct!\n"); | 735 | "fasync_struct!\n"); |
719 | return; | 736 | return; |
720 | } | 737 | } |
721 | fown = &fa->fa_file->f_owner; | 738 | spin_lock(&fa->fa_lock); |
722 | /* Don't send SIGURG to processes which have not set a | 739 | if (fa->fa_file) { |
723 | queued signum: SIGURG has its own default signalling | 740 | fown = &fa->fa_file->f_owner; |
724 | mechanism. */ | 741 | /* Don't send SIGURG to processes which have not set a |
725 | if (!(sig == SIGURG && fown->signum == 0)) | 742 | queued signum: SIGURG has its own default signalling |
726 | send_sigio(fown, fa->fa_fd, band); | 743 | mechanism. */ |
727 | fa = fa->fa_next; | 744 | if (!(sig == SIGURG && fown->signum == 0)) |
745 | send_sigio(fown, fa->fa_fd, band); | ||
746 | } | ||
747 | spin_unlock(&fa->fa_lock); | ||
748 | fa = rcu_dereference(fa->fa_next); | ||
728 | } | 749 | } |
729 | } | 750 | } |
730 | 751 | ||
731 | EXPORT_SYMBOL(__kill_fasync); | ||
732 | |||
733 | void kill_fasync(struct fasync_struct **fp, int sig, int band) | 752 | void kill_fasync(struct fasync_struct **fp, int sig, int band) |
734 | { | 753 | { |
735 | /* First a quick test without locking: usually | 754 | /* First a quick test without locking: usually |
736 | * the list is empty. | 755 | * the list is empty. |
737 | */ | 756 | */ |
738 | if (*fp) { | 757 | if (*fp) { |
739 | read_lock(&fasync_lock); | 758 | rcu_read_lock(); |
740 | /* reread *fp after obtaining the lock */ | 759 | kill_fasync_rcu(rcu_dereference(*fp), sig, band); |
741 | __kill_fasync(*fp, sig, band); | 760 | rcu_read_unlock(); |
742 | read_unlock(&fasync_lock); | ||
743 | } | 761 | } |
744 | } | 762 | } |
745 | EXPORT_SYMBOL(kill_fasync); | 763 | EXPORT_SYMBOL(kill_fasync); |