diff options
| author | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-01-24 15:34:47 -0500 |
|---|---|---|
| committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-01-24 15:34:47 -0500 |
| commit | 0a0fc0ddbe732779366ab6b1b879f62195e65967 (patch) | |
| tree | 7b42490a676cf39ae0691b6859ecf7fd410f229b /net/socket.c | |
| parent | 4d5dbd0945d9e0833dd7964a3d6ee33157f7cc7a (diff) | |
| parent | 3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff) | |
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 245 |
1 files changed, 125 insertions, 120 deletions
diff --git a/net/socket.c b/net/socket.c index 3145103cdf54..b38a263853c3 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -640,154 +640,150 @@ static void sock_aio_dtor(struct kiocb *iocb) | |||
| 640 | kfree(iocb->private); | 640 | kfree(iocb->private); |
| 641 | } | 641 | } |
| 642 | 642 | ||
| 643 | /* | 643 | static ssize_t sock_sendpage(struct file *file, struct page *page, |
| 644 | * Read data from a socket. ubuf is a user mode pointer. We make sure the user | 644 | int offset, size_t size, loff_t *ppos, int more) |
| 645 | * area ubuf...ubuf+size-1 is writable before asking the protocol. | ||
| 646 | */ | ||
| 647 | |||
| 648 | static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, | ||
| 649 | size_t size, loff_t pos) | ||
| 650 | { | 645 | { |
| 651 | struct sock_iocb *x, siocb; | ||
| 652 | struct socket *sock; | 646 | struct socket *sock; |
| 653 | int flags; | 647 | int flags; |
| 654 | 648 | ||
| 655 | if (pos != 0) | 649 | sock = file->private_data; |
| 656 | return -ESPIPE; | ||
| 657 | if (size==0) /* Match SYS5 behaviour */ | ||
| 658 | return 0; | ||
| 659 | 650 | ||
| 660 | if (is_sync_kiocb(iocb)) | 651 | flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT; |
| 661 | x = &siocb; | 652 | if (more) |
| 662 | else { | 653 | flags |= MSG_MORE; |
| 663 | x = kmalloc(sizeof(struct sock_iocb), GFP_KERNEL); | 654 | |
| 664 | if (!x) | 655 | return sock->ops->sendpage(sock, page, offset, size, flags); |
| 665 | return -ENOMEM; | 656 | } |
| 657 | |||
| 658 | static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, | ||
| 659 | char __user *ubuf, size_t size, struct sock_iocb *siocb) | ||
| 660 | { | ||
| 661 | if (!is_sync_kiocb(iocb)) { | ||
| 662 | siocb = kmalloc(sizeof(*siocb), GFP_KERNEL); | ||
| 663 | if (!siocb) | ||
| 664 | return NULL; | ||
| 666 | iocb->ki_dtor = sock_aio_dtor; | 665 | iocb->ki_dtor = sock_aio_dtor; |
| 667 | } | 666 | } |
| 668 | iocb->private = x; | ||
| 669 | x->kiocb = iocb; | ||
| 670 | sock = iocb->ki_filp->private_data; | ||
| 671 | 667 | ||
| 672 | x->async_msg.msg_name = NULL; | 668 | siocb->kiocb = iocb; |
| 673 | x->async_msg.msg_namelen = 0; | 669 | siocb->async_iov.iov_base = ubuf; |
| 674 | x->async_msg.msg_iov = &x->async_iov; | 670 | siocb->async_iov.iov_len = size; |
| 675 | x->async_msg.msg_iovlen = 1; | ||
| 676 | x->async_msg.msg_control = NULL; | ||
| 677 | x->async_msg.msg_controllen = 0; | ||
| 678 | x->async_iov.iov_base = ubuf; | ||
| 679 | x->async_iov.iov_len = size; | ||
| 680 | flags = !(iocb->ki_filp->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT; | ||
| 681 | 671 | ||
| 682 | return __sock_recvmsg(iocb, sock, &x->async_msg, size, flags); | 672 | iocb->private = siocb; |
| 673 | return siocb; | ||
| 683 | } | 674 | } |
| 684 | 675 | ||
| 676 | static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, | ||
| 677 | struct file *file, struct iovec *iov, unsigned long nr_segs) | ||
| 678 | { | ||
| 679 | struct socket *sock = file->private_data; | ||
| 680 | size_t size = 0; | ||
| 681 | int i; | ||
| 685 | 682 | ||
| 686 | /* | 683 | for (i = 0 ; i < nr_segs ; i++) |
| 687 | * Write data to a socket. We verify that the user area ubuf..ubuf+size-1 | 684 | size += iov[i].iov_len; |
| 688 | * is readable by the user process. | ||
| 689 | */ | ||
| 690 | 685 | ||
| 691 | static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, | 686 | msg->msg_name = NULL; |
| 692 | size_t size, loff_t pos) | 687 | msg->msg_namelen = 0; |
| 688 | msg->msg_control = NULL; | ||
| 689 | msg->msg_controllen = 0; | ||
| 690 | msg->msg_iov = (struct iovec *) iov; | ||
| 691 | msg->msg_iovlen = nr_segs; | ||
| 692 | msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; | ||
| 693 | |||
| 694 | return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags); | ||
| 695 | } | ||
| 696 | |||
| 697 | static ssize_t sock_readv(struct file *file, const struct iovec *iov, | ||
| 698 | unsigned long nr_segs, loff_t *ppos) | ||
| 693 | { | 699 | { |
| 694 | struct sock_iocb *x, siocb; | 700 | struct kiocb iocb; |
| 695 | struct socket *sock; | 701 | struct sock_iocb siocb; |
| 696 | 702 | struct msghdr msg; | |
| 703 | int ret; | ||
| 704 | |||
| 705 | init_sync_kiocb(&iocb, NULL); | ||
| 706 | iocb.private = &siocb; | ||
| 707 | |||
| 708 | ret = do_sock_read(&msg, &iocb, file, (struct iovec *)iov, nr_segs); | ||
| 709 | if (-EIOCBQUEUED == ret) | ||
| 710 | ret = wait_on_sync_kiocb(&iocb); | ||
| 711 | return ret; | ||
| 712 | } | ||
| 713 | |||
| 714 | static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, | ||
| 715 | size_t count, loff_t pos) | ||
| 716 | { | ||
| 717 | struct sock_iocb siocb, *x; | ||
| 718 | |||
| 697 | if (pos != 0) | 719 | if (pos != 0) |
| 698 | return -ESPIPE; | 720 | return -ESPIPE; |
| 699 | if(size==0) /* Match SYS5 behaviour */ | 721 | if (count == 0) /* Match SYS5 behaviour */ |
| 700 | return 0; | 722 | return 0; |
| 701 | 723 | ||
| 702 | if (is_sync_kiocb(iocb)) | 724 | x = alloc_sock_iocb(iocb, ubuf, count, &siocb); |
| 703 | x = &siocb; | 725 | if (!x) |
| 704 | else { | 726 | return -ENOMEM; |
| 705 | x = kmalloc(sizeof(struct sock_iocb), GFP_KERNEL); | 727 | return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, |
| 706 | if (!x) | 728 | &x->async_iov, 1); |
| 707 | return -ENOMEM; | ||
| 708 | iocb->ki_dtor = sock_aio_dtor; | ||
| 709 | } | ||
| 710 | iocb->private = x; | ||
| 711 | x->kiocb = iocb; | ||
| 712 | sock = iocb->ki_filp->private_data; | ||
| 713 | |||
| 714 | x->async_msg.msg_name = NULL; | ||
| 715 | x->async_msg.msg_namelen = 0; | ||
| 716 | x->async_msg.msg_iov = &x->async_iov; | ||
| 717 | x->async_msg.msg_iovlen = 1; | ||
| 718 | x->async_msg.msg_control = NULL; | ||
| 719 | x->async_msg.msg_controllen = 0; | ||
| 720 | x->async_msg.msg_flags = !(iocb->ki_filp->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT; | ||
| 721 | if (sock->type == SOCK_SEQPACKET) | ||
| 722 | x->async_msg.msg_flags |= MSG_EOR; | ||
| 723 | x->async_iov.iov_base = (void __user *)ubuf; | ||
| 724 | x->async_iov.iov_len = size; | ||
| 725 | |||
| 726 | return __sock_sendmsg(iocb, sock, &x->async_msg, size); | ||
| 727 | } | 729 | } |
| 728 | 730 | ||
| 729 | static ssize_t sock_sendpage(struct file *file, struct page *page, | 731 | static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, |
| 730 | int offset, size_t size, loff_t *ppos, int more) | 732 | struct file *file, struct iovec *iov, unsigned long nr_segs) |
| 731 | { | 733 | { |
| 732 | struct socket *sock; | 734 | struct socket *sock = file->private_data; |
| 733 | int flags; | 735 | size_t size = 0; |
| 736 | int i; | ||
| 734 | 737 | ||
| 735 | sock = file->private_data; | 738 | for (i = 0 ; i < nr_segs ; i++) |
| 739 | size += iov[i].iov_len; | ||
| 736 | 740 | ||
| 737 | flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT; | 741 | msg->msg_name = NULL; |
| 738 | if (more) | 742 | msg->msg_namelen = 0; |
| 739 | flags |= MSG_MORE; | 743 | msg->msg_control = NULL; |
| 744 | msg->msg_controllen = 0; | ||
| 745 | msg->msg_iov = (struct iovec *) iov; | ||
| 746 | msg->msg_iovlen = nr_segs; | ||
| 747 | msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; | ||
| 748 | if (sock->type == SOCK_SEQPACKET) | ||
| 749 | msg->msg_flags |= MSG_EOR; | ||
| 740 | 750 | ||
| 741 | return sock->ops->sendpage(sock, page, offset, size, flags); | 751 | return __sock_sendmsg(iocb, sock, msg, size); |
| 742 | } | 752 | } |
| 743 | 753 | ||
| 744 | static int sock_readv_writev(int type, | 754 | static ssize_t sock_writev(struct file *file, const struct iovec *iov, |
| 745 | struct file * file, const struct iovec * iov, | 755 | unsigned long nr_segs, loff_t *ppos) |
| 746 | long count, size_t size) | ||
| 747 | { | 756 | { |
| 748 | struct msghdr msg; | 757 | struct msghdr msg; |
| 749 | struct socket *sock; | 758 | struct kiocb iocb; |
| 759 | struct sock_iocb siocb; | ||
| 760 | int ret; | ||
| 750 | 761 | ||
| 751 | sock = file->private_data; | 762 | init_sync_kiocb(&iocb, NULL); |
| 763 | iocb.private = &siocb; | ||
| 752 | 764 | ||
| 753 | msg.msg_name = NULL; | 765 | ret = do_sock_write(&msg, &iocb, file, (struct iovec *)iov, nr_segs); |
| 754 | msg.msg_namelen = 0; | 766 | if (-EIOCBQUEUED == ret) |
| 755 | msg.msg_control = NULL; | 767 | ret = wait_on_sync_kiocb(&iocb); |
| 756 | msg.msg_controllen = 0; | 768 | return ret; |
| 757 | msg.msg_iov = (struct iovec *) iov; | 769 | } |
| 758 | msg.msg_iovlen = count; | ||
| 759 | msg.msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; | ||
| 760 | 770 | ||
| 761 | /* read() does a VERIFY_WRITE */ | 771 | static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, |
| 762 | if (type == VERIFY_WRITE) | 772 | size_t count, loff_t pos) |
| 763 | return sock_recvmsg(sock, &msg, size, msg.msg_flags); | 773 | { |
| 774 | struct sock_iocb siocb, *x; | ||
| 764 | 775 | ||
| 765 | if (sock->type == SOCK_SEQPACKET) | 776 | if (pos != 0) |
| 766 | msg.msg_flags |= MSG_EOR; | 777 | return -ESPIPE; |
| 778 | if (count == 0) /* Match SYS5 behaviour */ | ||
| 779 | return 0; | ||
| 767 | 780 | ||
| 768 | return sock_sendmsg(sock, &msg, size); | 781 | x = alloc_sock_iocb(iocb, (void __user *)ubuf, count, &siocb); |
| 769 | } | 782 | if (!x) |
| 783 | return -ENOMEM; | ||
| 770 | 784 | ||
| 771 | static ssize_t sock_readv(struct file *file, const struct iovec *vector, | 785 | return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, |
| 772 | unsigned long count, loff_t *ppos) | 786 | &x->async_iov, 1); |
| 773 | { | ||
| 774 | size_t tot_len = 0; | ||
| 775 | int i; | ||
| 776 | for (i = 0 ; i < count ; i++) | ||
| 777 | tot_len += vector[i].iov_len; | ||
| 778 | return sock_readv_writev(VERIFY_WRITE, | ||
| 779 | file, vector, count, tot_len); | ||
| 780 | } | ||
| 781 | |||
| 782 | static ssize_t sock_writev(struct file *file, const struct iovec *vector, | ||
| 783 | unsigned long count, loff_t *ppos) | ||
| 784 | { | ||
| 785 | size_t tot_len = 0; | ||
| 786 | int i; | ||
| 787 | for (i = 0 ; i < count ; i++) | ||
| 788 | tot_len += vector[i].iov_len; | ||
| 789 | return sock_readv_writev(VERIFY_READ, | ||
| 790 | file, vector, count, tot_len); | ||
| 791 | } | 787 | } |
| 792 | 788 | ||
| 793 | 789 | ||
| @@ -904,6 +900,13 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
| 904 | break; | 900 | break; |
| 905 | default: | 901 | default: |
| 906 | err = sock->ops->ioctl(sock, cmd, arg); | 902 | err = sock->ops->ioctl(sock, cmd, arg); |
| 903 | |||
| 904 | /* | ||
| 905 | * If this ioctl is unknown try to hand it down | ||
| 906 | * to the NIC driver. | ||
| 907 | */ | ||
| 908 | if (err == -ENOIOCTLCMD) | ||
| 909 | err = dev_ioctl(cmd, argp); | ||
| 907 | break; | 910 | break; |
| 908 | } | 911 | } |
| 909 | return err; | 912 | return err; |
| @@ -990,7 +993,7 @@ static int sock_fasync(int fd, struct file *filp, int on) | |||
| 990 | 993 | ||
| 991 | if (on) | 994 | if (on) |
| 992 | { | 995 | { |
| 993 | fna=(struct fasync_struct *)kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); | 996 | fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); |
| 994 | if(fna==NULL) | 997 | if(fna==NULL) |
| 995 | return -ENOMEM; | 998 | return -ENOMEM; |
| 996 | } | 999 | } |
| @@ -2036,7 +2039,7 @@ int sock_unregister(int family) | |||
| 2036 | return 0; | 2039 | return 0; |
| 2037 | } | 2040 | } |
| 2038 | 2041 | ||
| 2039 | void __init sock_init(void) | 2042 | static int __init sock_init(void) |
| 2040 | { | 2043 | { |
| 2041 | /* | 2044 | /* |
| 2042 | * Initialize sock SLAB cache. | 2045 | * Initialize sock SLAB cache. |
| @@ -2044,12 +2047,10 @@ void __init sock_init(void) | |||
| 2044 | 2047 | ||
| 2045 | sk_init(); | 2048 | sk_init(); |
| 2046 | 2049 | ||
| 2047 | #ifdef SLAB_SKB | ||
| 2048 | /* | 2050 | /* |
| 2049 | * Initialize skbuff SLAB cache | 2051 | * Initialize skbuff SLAB cache |
| 2050 | */ | 2052 | */ |
| 2051 | skb_init(); | 2053 | skb_init(); |
| 2052 | #endif | ||
| 2053 | 2054 | ||
| 2054 | /* | 2055 | /* |
| 2055 | * Initialize the protocols module. | 2056 | * Initialize the protocols module. |
| @@ -2058,15 +2059,19 @@ void __init sock_init(void) | |||
| 2058 | init_inodecache(); | 2059 | init_inodecache(); |
| 2059 | register_filesystem(&sock_fs_type); | 2060 | register_filesystem(&sock_fs_type); |
| 2060 | sock_mnt = kern_mount(&sock_fs_type); | 2061 | sock_mnt = kern_mount(&sock_fs_type); |
| 2061 | /* The real protocol initialization is performed when | 2062 | |
| 2062 | * do_initcalls is run. | 2063 | /* The real protocol initialization is performed in later initcalls. |
| 2063 | */ | 2064 | */ |
| 2064 | 2065 | ||
| 2065 | #ifdef CONFIG_NETFILTER | 2066 | #ifdef CONFIG_NETFILTER |
| 2066 | netfilter_init(); | 2067 | netfilter_init(); |
| 2067 | #endif | 2068 | #endif |
| 2069 | |||
| 2070 | return 0; | ||
| 2068 | } | 2071 | } |
| 2069 | 2072 | ||
| 2073 | core_initcall(sock_init); /* early initcall */ | ||
| 2074 | |||
| 2070 | #ifdef CONFIG_PROC_FS | 2075 | #ifdef CONFIG_PROC_FS |
| 2071 | void socket_seq_show(struct seq_file *seq) | 2076 | void socket_seq_show(struct seq_file *seq) |
| 2072 | { | 2077 | { |
