aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2010-05-21 15:27:26 -0400
committerJens Axboe <jens.axboe@oracle.com>2010-05-21 15:27:26 -0400
commitee9a3607fb03e804ddf624544105f4e34260c380 (patch)
treece41b6e0fa10982a306f6c142a92dbf3c9961284 /fs/fcntl.c
parentb492e95be0ae672922f4734acf3f5d35c30be948 (diff)
parentd515e86e639890b33a09390d062b0831664f04a2 (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.c66
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
622static DEFINE_RWLOCK(fasync_lock); 622static DEFINE_SPINLOCK(fasync_lock);
623static struct kmem_cache *fasync_cache __read_mostly; 623static struct kmem_cache *fasync_cache __read_mostly;
624 624
625static 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 */
636static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp) 640static 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
691out: 705out:
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
710EXPORT_SYMBOL(fasync_helper); 724EXPORT_SYMBOL(fasync_helper);
711 725
712void __kill_fasync(struct fasync_struct *fa, int sig, int band) 726/*
727 * rcu_read_lock() is held
728 */
729static 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
731EXPORT_SYMBOL(__kill_fasync);
732
733void kill_fasync(struct fasync_struct **fp, int sig, int band) 752void 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}
745EXPORT_SYMBOL(kill_fasync); 763EXPORT_SYMBOL(kill_fasync);