aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2005-12-23 00:08:46 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-03 16:11:18 -0500
commitce1d4d3e88b3a69d23c3feb436a0b36b6ca0642b (patch)
tree6bec428bddf30c88155d2523fc82a05f8e6876a6
parentcbeb321a64af5437fbde249605b191ff0fdfa21c (diff)
[NET]: restructure sock_aio_{read,write} / sock_{readv,writev}
Mid-term I plan to restructure the file_operations so that we don't need to have all these duplicate aio and vectored versions. This patch is a small step in that direction but also a worthwile cleanup on it's own: (1) introduce a alloc_sock_iocb helper that encapsulates allocating a proper sock_iocb (2) add do_sock_read and do_sock_write helpers for common read/write code Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/socket.c224
1 files changed, 110 insertions, 114 deletions
diff --git a/net/socket.c b/net/socket.c
index f40957adc7c7..0dde6dade2b1 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/* 643static 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
648static 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
658static 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
676static 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
691static 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
697static 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
714static 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
729static ssize_t sock_sendpage(struct file *file, struct page *page, 731static 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
744static int sock_readv_writev(int type, 754static 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 */ 771static 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
771static 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
782static 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