diff -r 8f4a18bfccc5 stub_dev.c --- a/stub_dev.c Sat Oct 06 22:59:15 2012 +0000 +++ b/stub_dev.c Tue Oct 09 20:52:43 2012 +0000 @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include "usbip_common.h" #include "stub.h" @@ -75,25 +78,24 @@ static DEVICE_ATTR(usbip_status, S_IRUGO, show_status, NULL); /* - * usbip_sockfd gets a socket descriptor of an established TCP connection that - * is used to transfer usbip requests by kernel threads. -1 is a magic number - * by which usbip connection is finished. + * usbip_sockfd gets a file descriptor that is used to transfer usbip requests. + * -1 is a magic number by which usbip connection is finished. */ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct stub_device *sdev = dev_get_drvdata(dev); - int sockfd = 0; - struct socket *socket; + int fd = -1; + struct file *file; if (!sdev) { dev_err(dev, "sdev is null\n"); return -ENODEV; } - sscanf(buf, "%d", &sockfd); + sscanf(buf, "%d", &fd); - if (sockfd != -1) { + if (fd != -1) { dev_info(dev, "stub up\n"); spin_lock(&sdev->ud.lock); @@ -104,12 +106,13 @@ return -EINVAL; } - socket = sockfd_to_socket(sockfd); - if (!socket) { + file = fget(fd); + if (!file) { spin_unlock(&sdev->ud.lock); return -EINVAL; } - sdev->ud.tcp_socket = socket; + + sdev->ud.file = file; spin_unlock(&sdev->ud.lock); @@ -180,10 +183,9 @@ * sk_wait_data returned though stub_rx thread was already finished by * step 1? */ - if (ud->tcp_socket) { - dev_dbg(&sdev->udev->dev, "shutdown tcp_socket %p\n", - ud->tcp_socket); - kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR); + if (ud->file) { + dev_dbg(&sdev->udev->dev, "close file %p\n", + ud->file); } /* 1. stop threads */ @@ -193,14 +195,14 @@ kthread_stop(ud->tcp_tx); /* - * 2. close the socket + * 2. close the file * - * tcp_socket is freed after threads are killed so that usbip_xmit does - * not touch NULL socket. + * file is freed after threads are killed so that usbip_xmit does + * not touch NULL file. */ - if (ud->tcp_socket) { - sock_release(ud->tcp_socket); - ud->tcp_socket = NULL; + if (ud->file) { + fput(ud->file); + ud->file = NULL; } /* 3. free used data */ @@ -299,7 +301,7 @@ sdev->ud.status = SDEV_ST_AVAILABLE; /* sdev->ud.lock = SPIN_LOCK_UNLOCKED; */ spin_lock_init(&sdev->ud.lock); - sdev->ud.tcp_socket = NULL; + sdev->ud.file = NULL; INIT_LIST_HEAD(&sdev->priv_init); INIT_LIST_HEAD(&sdev->priv_tx); diff -r 8f4a18bfccc5 stub_rx.c --- a/stub_rx.c Sat Oct 06 22:59:15 2012 +0000 +++ b/stub_rx.c Tue Oct 09 20:52:43 2012 +0000 @@ -564,7 +564,7 @@ memset(&pdu, 0, sizeof(pdu)); /* 1. receive a pdu header */ - ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu)); + ret = usbip_recv(ud->file, &pdu, sizeof(pdu)); if (ret != sizeof(pdu)) { dev_err(dev, "recv a header, %d\n", ret); usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); diff -r 8f4a18bfccc5 stub_tx.c --- a/stub_tx.c Sat Oct 06 22:59:15 2012 +0000 +++ b/stub_tx.c Tue Oct 09 20:52:43 2012 +0000 @@ -18,7 +18,8 @@ */ #include -#include +#include +#include #include "usbip_common.h" #include "stub.h" @@ -157,7 +158,6 @@ unsigned long flags; struct stub_priv *priv, *tmp; - struct msghdr msg; size_t txsize; size_t total_size = 0; @@ -172,7 +172,6 @@ txsize = 0; memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) iovnum = 2 + urb->number_of_packets; @@ -259,8 +258,16 @@ iovnum++; } - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, - iov, iovnum, txsize); + { + struct file *file = sdev->ud.file; + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + + ret = vfs_writev(file, (struct iovec *) iov, iovnum, &file->f_pos); + + set_fs(old_fs); + } + if (ret != txsize) { dev_err(&sdev->interface->dev, "sendmsg failed!, retval %d for %zd\n", @@ -309,7 +316,6 @@ unsigned long flags; struct stub_unlink *unlink, *tmp; - struct msghdr msg; struct kvec iov[1]; size_t txsize; @@ -321,7 +327,6 @@ txsize = 0; memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); memset(&iov, 0, sizeof(iov)); usbip_dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum); @@ -331,11 +336,19 @@ usbip_header_correct_endian(&pdu_header, 1); iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); + iov[0].iov_len = sizeof(pdu_header); txsize += sizeof(pdu_header); - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, - 1, txsize); + { + struct file *file = sdev->ud.file; + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + + ret = vfs_writev(file, (struct iovec *) iov, 1, &file->f_pos); + + set_fs(old_fs); + } + if (ret != txsize) { dev_err(&sdev->interface->dev, "sendmsg failed!, retval %d for %zd\n", diff -r 8f4a18bfccc5 usbip_common.c --- a/usbip_common.c Sat Oct 06 22:59:15 2012 +0000 +++ b/usbip_common.c Tue Oct 09 20:52:43 2012 +0000 @@ -23,7 +23,8 @@ #include #include #include -#include +#include +#include #include "usbip_common.h" @@ -334,12 +335,11 @@ } EXPORT_SYMBOL_GPL(usbip_dump_header); -/* Receive data over TCP/IP. */ -int usbip_recv(struct socket *sock, void *buf, int size) +/* Receive data over a file descriptor. */ +int usbip_recv(struct file *file, void *buf, int size) { - int result; - struct msghdr msg; struct kvec iov; + int result = 0; int total = 0; /* for blocks of if (usbip_dbg_flag_xmit) */ @@ -348,27 +348,28 @@ usbip_dbg_xmit("enter\n"); - if (!sock || !buf || !size) { - pr_err("invalid arg, sock %p buff %p size %d\n", sock, buf, + if (!file || !buf || !size) { + pr_err("invalid arg, file %p buff %p size %d\n", file, buf, size); return -EINVAL; } do { - sock->sk->sk_allocation = GFP_NOIO; - iov.iov_base = buf; - iov.iov_len = size; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_namelen = 0; - msg.msg_flags = MSG_NOSIGNAL; + mm_segment_t old_fs; - result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); + iov.iov_base = buf; + iov.iov_len = size; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + result = vfs_readv(file, (struct iovec *) &iov, 1, &file->f_pos); + + set_fs(old_fs); + if (result <= 0) { - pr_debug("receive sock %p buf %p size %u ret %d total %d\n", - sock, buf, size, result, total); + pr_debug("receive file %p buf %p size %u ret %d total %d\n", + file, buf, size, result, total); goto err; } @@ -396,31 +397,6 @@ } EXPORT_SYMBOL_GPL(usbip_recv); -struct socket *sockfd_to_socket(unsigned int sockfd) -{ - struct socket *socket; - struct file *file; - struct inode *inode; - - file = fget(sockfd); - if (!file) { - pr_err("invalid sockfd\n"); - return NULL; - } - - inode = file->f_dentry->d_inode; - pr_err("inode is %x with mode %x\n", inode, inode ? inode->i_mode : 0); - - if (!inode || !S_ISSOCK(inode->i_mode)) - return NULL; - - socket = SOCKET_I(inode); - pr_err("socket is %x\n", socket); - - return socket; -} -EXPORT_SYMBOL_GPL(sockfd_to_socket); - /* there may be more cases to tweak the flags. */ static unsigned int tweak_transfer_flags(unsigned int flags) { @@ -693,7 +669,7 @@ if (!buff) return -ENOMEM; - ret = usbip_recv(ud->tcp_socket, buff, size); + ret = usbip_recv(ud->file, buff, size); if (ret != size) { dev_err(&urb->dev->dev, "recv iso_frame_descriptor, %d\n", ret); @@ -804,7 +780,7 @@ if (!(size > 0)) return 0; - ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size); + ret = usbip_recv(ud->file, urb->transfer_buffer, size); if (ret != size) { dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret); if (ud->side == USBIP_STUB) { diff -r 8f4a18bfccc5 usbip_common.h --- a/usbip_common.h Sat Oct 06 22:59:15 2012 +0000 +++ b/usbip_common.h Tue Oct 09 20:52:43 2012 +0000 @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -276,7 +277,7 @@ /* lock for status */ spinlock_t lock; - struct socket *tcp_socket; + struct file *file; struct task_struct *tcp_rx; struct task_struct *tcp_tx; @@ -296,8 +297,7 @@ void usbip_dump_urb(struct urb *purb); void usbip_dump_header(struct usbip_header *pdu); -int usbip_recv(struct socket *sock, void *buf, int size); -struct socket *sockfd_to_socket(unsigned int sockfd); +int usbip_recv(struct file *file, void *buf, int size); void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack); diff -r 8f4a18bfccc5 vhci_hcd.c --- a/vhci_hcd.c Sat Oct 06 22:59:15 2012 +0000 +++ b/vhci_hcd.c Tue Oct 09 20:52:43 2012 +0000 @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include #include "usbip_common.h" #include "vhci.h" @@ -738,8 +741,8 @@ /* send unlink request here? */ vdev = priv->vdev; - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ + if (!vdev->ud.file) { + /* no available file for communication */ unsigned long flags2; spin_lock_irqsave(&vdev->priv_lock, flags2); @@ -867,9 +870,9 @@ struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); /* need this? see stub_dev.c */ - if (ud->tcp_socket) { - pr_debug("shutdown tcp_socket %p\n", ud->tcp_socket); - kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR); + if (!ud->file) { + pr_debug("close file %p\n", ud->file); + fput(ud->file); } /* kill threads related to this sdev, if v.c. exists */ @@ -881,11 +884,10 @@ pr_info("stop threads\n"); /* active connection is closed */ - if (vdev->ud.tcp_socket != NULL) { - sock_release(vdev->ud.tcp_socket); - vdev->ud.tcp_socket = NULL; + if (!vdev->ud.file) { + vdev->ud.file = NULL; } - pr_info("release socket\n"); + pr_info("release file\n"); vhci_device_unlink_cleanup(vdev); @@ -928,7 +930,7 @@ usb_put_dev(vdev->udev); vdev->udev = NULL; - ud->tcp_socket = NULL; + ud->file = NULL; ud->status = VDEV_ST_NULL; spin_unlock(&ud->lock); diff -r 8f4a18bfccc5 vhci_rx.c --- a/vhci_rx.c Sat Oct 06 22:59:15 2012 +0000 +++ b/vhci_rx.c Tue Oct 09 20:52:43 2012 +0000 @@ -206,7 +206,7 @@ memset(&pdu, 0, sizeof(pdu)); /* 1. receive a pdu header */ - ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu)); + ret = usbip_recv(ud->file, &pdu, sizeof(pdu)); if (ret < 0) { if (ret == -ECONNRESET) pr_info("connection reset by peer\n"); diff -r 8f4a18bfccc5 vhci_sysfs.c --- a/vhci_sysfs.c Sat Oct 06 22:59:15 2012 +0000 +++ b/vhci_sysfs.c Tue Oct 09 20:52:43 2012 +0000 @@ -19,6 +19,8 @@ #include #include +#include +#include #include "usbip_common.h" #include "vhci.h" @@ -38,15 +40,11 @@ /* * output example: - * prt sta spd dev socket local_busid + * prt sta spd dev file local_busid * 000 004 000 000 c5a7bb80 1-2.3 * 001 004 000 000 d8cee980 2-3.4 - * - * IP address can be retrieved from a socket pointer address by looking - * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a - * port number and its peer IP address. */ - out += sprintf(out, "prt sta spd bus dev socket " + out += sprintf(out, "prt sta spd bus dev file " "local_busid\n"); for (i = 0; i < VHCI_NPORTS; i++) { @@ -58,7 +56,7 @@ if (vdev->ud.status == VDEV_ST_USED) { out += sprintf(out, "%03u %08x ", vdev->speed, vdev->devid); - out += sprintf(out, "%16p ", vdev->ud.tcp_socket); + out += sprintf(out, "%16p ", vdev->ud.file); out += sprintf(out, "%s", dev_name(&vdev->udev->dev)); } else { @@ -156,9 +154,9 @@ } /* - * To start a new USB/IP attachment, a userland program needs to setup a TCP - * connection and then write its socket descriptor with remote device - * information into this sysfs file. + * To start a new USB/IP attachment, a userland program needs to open a file + * descriptor and then write this descriptor with remote device information + * into this sysfs file. * * A remote device is virtually attached to the root-hub port of @rhport with * @speed. @devid is embedded into a request to specify the remote device in a @@ -170,21 +168,21 @@ const char *buf, size_t count) { struct vhci_device *vdev; - struct socket *socket; - int sockfd = 0; + int fd = -1; + struct file *file; __u32 rhport = 0, devid = 0, speed = 0; pr_err("store_attach\n"); /* * @rhport: port number of vhci_hcd - * @sockfd: socket descriptor of an established TCP connection + * @fd: file descriptor for a connection to a remote host * @devid: unique device identifier in a remote host * @speed: usb device speed in a remote host */ - sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed); + sscanf(buf, "%u %u %u %u", &rhport, &fd, &devid, &speed); - usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n", - rhport, sockfd, devid, speed); + usbip_dbg_vhci_sysfs("rhport(%u) fd(%u) devid(%u) speed(%u)\n", + rhport, fd, devid, speed); /* check received parameters */ if (valid_args(rhport, speed) < 0) { @@ -192,11 +190,11 @@ return -EINVAL; } - /* check sockfd */ - pr_err("check sockfd %d.\n", sockfd); - socket = sockfd_to_socket(sockfd); - pr_err("socket is %x\n", socket); - if (!socket) + /* check fd */ + pr_err("check fd %d.\n", fd); + file = fget(fd); + pr_err("file is %p.\n", file); + if (!file) return -EINVAL; /* now need lock until setting vdev status as used */ @@ -215,12 +213,12 @@ return -EINVAL; } - dev_info(dev, "rhport(%u) sockfd(%d) devid(%u) speed(%u)\n", - rhport, sockfd, devid, speed); + dev_info(dev, "rhport(%u) file(%p) devid(%u) speed(%u)\n", + rhport, file, devid, speed); vdev->devid = devid; vdev->speed = speed; - vdev->ud.tcp_socket = socket; + vdev->ud.file = file; vdev->ud.status = VDEV_ST_NOTASSIGNED; spin_unlock(&vdev->ud.lock); diff -r 8f4a18bfccc5 vhci_tx.c --- a/vhci_tx.c Sat Oct 06 22:59:15 2012 +0000 +++ b/vhci_tx.c Tue Oct 09 20:52:43 2012 +0000 @@ -19,6 +19,9 @@ #include #include +#include +#include +#include #include "usbip_common.h" #include "vhci.h" @@ -66,7 +69,6 @@ { struct vhci_priv *priv = NULL; - struct msghdr msg; struct kvec iov[3]; size_t txsize; @@ -80,7 +82,6 @@ txsize = 0; memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); memset(&iov, 0, sizeof(iov)); usbip_dbg_vhci_tx("setup txdata urb %p\n", urb); @@ -121,7 +122,18 @@ } usbip_dbg_vhci_tx("txsize = %d\n", txsize); - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 3, txsize); + + { + struct file *file = vdev->ud.file; + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + + usbip_dbg_vhci_tx("iov = %p (%d)\n", iov, access_ok(VERIFY_WRITE, iov, sizeof(*iov))); + ret = vfs_writev(file, (struct iovec *) iov, 3, &file->f_pos); + + set_fs(old_fs); + } + if (ret != txsize) { pr_err("sendmsg failed!, ret=%d for %zd\n", ret, txsize); @@ -161,8 +173,7 @@ { struct vhci_unlink *unlink = NULL; - struct msghdr msg; - struct kvec iov[3]; + struct kvec iov[1]; size_t txsize; size_t total_size = 0; @@ -173,7 +184,6 @@ txsize = 0; memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); memset(&iov, 0, sizeof(iov)); usbip_dbg_vhci_tx("setup cmd unlink, %lu\n", unlink->seqnum); @@ -191,7 +201,16 @@ iov[0].iov_len = sizeof(pdu_header); txsize += sizeof(pdu_header); - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 1, txsize); + { + struct file *file = vdev->ud.file; + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + + ret = vfs_writev(file, (struct iovec *) iov, 1, &file->f_pos); + + set_fs(old_fs); + } + if (ret != txsize) { pr_err("sendmsg failed!, ret=%d for %zd\n", ret, txsize);