Merge branch 'fasync-helper'

* fasync-helper:
fasync: split 'fasync_helper()' into separate add/remove functions

+70 -40
+70 -40
fs/fcntl.c
··· 618 618 static struct kmem_cache *fasync_cache __read_mostly; 619 619 620 620 /* 621 - * fasync_helper() is used by almost all character device drivers 622 - * to set up the fasync queue. It returns negative on error, 0 if it did 623 - * no changes and positive if it added/deleted the entry. 621 + * Remove a fasync entry. If successfully removed, return 622 + * positive and clear the FASYNC flag. If no entry exists, 623 + * do nothing and return 0. 624 + * 625 + * NOTE! It is very important that the FASYNC flag always 626 + * match the state "is the filp on a fasync list". 627 + * 628 + * We always take the 'filp->f_lock', in since fasync_lock 629 + * needs to be irq-safe. 624 630 */ 625 - int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) 631 + static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp) 626 632 { 627 633 struct fasync_struct *fa, **fp; 628 - struct fasync_struct *new = NULL; 629 634 int result = 0; 630 635 631 - if (on) { 632 - new = kmem_cache_alloc(fasync_cache, GFP_KERNEL); 633 - if (!new) 634 - return -ENOMEM; 635 - } 636 - 637 - /* 638 - * We need to take f_lock first since it's not an IRQ-safe 639 - * lock. 640 - */ 641 636 spin_lock(&filp->f_lock); 642 637 write_lock_irq(&fasync_lock); 643 638 for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { 644 - if (fa->fa_file == filp) { 645 - if(on) { 646 - fa->fa_fd = fd; 647 - kmem_cache_free(fasync_cache, new); 648 - } else { 649 - *fp = fa->fa_next; 650 - kmem_cache_free(fasync_cache, fa); 651 - result = 1; 652 - } 653 - goto out; 654 - } 655 - } 656 - 657 - if (on) { 658 - new->magic = FASYNC_MAGIC; 659 - new->fa_file = filp; 660 - new->fa_fd = fd; 661 - new->fa_next = *fapp; 662 - *fapp = new; 663 - result = 1; 664 - } 665 - out: 666 - if (on) 667 - filp->f_flags |= FASYNC; 668 - else 639 + if (fa->fa_file != filp) 640 + continue; 641 + *fp = fa->fa_next; 642 + kmem_cache_free(fasync_cache, fa); 669 643 filp->f_flags &= ~FASYNC; 644 + result = 1; 645 + break; 646 + } 670 647 write_unlock_irq(&fasync_lock); 671 648 spin_unlock(&filp->f_lock); 672 649 return result; 650 + } 651 + 652 + /* 653 + * Add a fasync entry. Return negative on error, positive if 654 + * added, and zero if did nothing but change an existing one. 655 + * 656 + * NOTE! It is very important that the FASYNC flag always 657 + * match the state "is the filp on a fasync list". 658 + */ 659 + static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp) 660 + { 661 + struct fasync_struct *new, *fa, **fp; 662 + int result = 0; 663 + 664 + new = kmem_cache_alloc(fasync_cache, GFP_KERNEL); 665 + if (!new) 666 + return -ENOMEM; 667 + 668 + spin_lock(&filp->f_lock); 669 + write_lock_irq(&fasync_lock); 670 + for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { 671 + if (fa->fa_file != filp) 672 + continue; 673 + fa->fa_fd = fd; 674 + kmem_cache_free(fasync_cache, new); 675 + goto out; 676 + } 677 + 678 + new->magic = FASYNC_MAGIC; 679 + new->fa_file = filp; 680 + new->fa_fd = fd; 681 + new->fa_next = *fapp; 682 + *fapp = new; 683 + result = 1; 684 + filp->f_flags |= FASYNC; 685 + 686 + out: 687 + write_unlock_irq(&fasync_lock); 688 + spin_unlock(&filp->f_lock); 689 + return result; 690 + } 691 + 692 + /* 693 + * fasync_helper() is used by almost all character device drivers 694 + * to set up the fasync queue, and for regular files by the file 695 + * lease code. It returns negative on error, 0 if it did no changes 696 + * and positive if it added/deleted the entry. 697 + */ 698 + int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) 699 + { 700 + if (!on) 701 + return fasync_remove_entry(filp, fapp); 702 + return fasync_add_entry(fd, filp, fapp); 673 703 } 674 704 675 705 EXPORT_SYMBOL(fasync_helper);