[NET][AIO] add vfs_sendmsg() and vfs_recvmsg() operations for aio Add file based vfs_sendmsg() and vfs_recvmsg() operations to allow aio for fallbacks which already do an fget() in common code to call into networking. Signed-off-by: Benjamin LaHaise diff -purN --exclude=description 85_vectored_fallback/include/linux/net.h 862_net_vfsmsg/include/linux/net.h --- 85_vectored_fallback/include/linux/net.h 2005-06-20 13:33:40.000000000 -0400 +++ 862_net_vfsmsg/include/linux/net.h 2005-08-17 13:58:26.000000000 -0400 @@ -186,6 +186,10 @@ extern int sock_sendmsg(struct s size_t len); extern int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags); +extern long vfs_sendmsg(struct file *file, struct msghdr __user *msg, + unsigned flags); +extern long vfs_recvmsg(struct file *file, struct msghdr __user *msg, + unsigned flags); extern int sock_map_fd(struct socket *sock); extern struct socket *sockfd_lookup(int fd, int *err); #define sockfd_put(sock) fput(sock->file) diff -purN --exclude=description 85_vectored_fallback/net/socket.c 862_net_vfsmsg/net/socket.c --- 85_vectored_fallback/net/socket.c 2005-08-15 16:59:50.000000000 -0400 +++ 862_net_vfsmsg/net/socket.c 2005-08-17 14:26:24.000000000 -0400 @@ -82,6 +82,7 @@ #include #include #include +#include #ifdef CONFIG_NET_RADIO #include /* Note : will define WIRELESS_EXT */ @@ -420,6 +421,13 @@ out: return fd; } +static inline struct socket *file_to_socket(struct file *file) +{ + if (file->f_op == &socket_file_ops) + return file->private_data; + return ERR_PTR(-ENOTSOCK); +} + /** * sockfd_lookup - Go from a file number to its socket slot * @fd: file handle @@ -445,8 +453,9 @@ struct socket *sockfd_lookup(int fd, int return NULL; } - if (file->f_op == &socket_file_ops) - return file->private_data; + sock = file_to_socket(file); + if (!IS_ERR(sock)) + return sock; inode = file->f_dentry->d_inode; if (!S_ISSOCK(inode->i_mode)) { @@ -1714,15 +1723,31 @@ asmlinkage long sys_shutdown(int fd, int asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) { - struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; struct socket *sock; + int err; + + sock = sockfd_lookup(fd, &err); + if (!sock) + goto out; + err = vfs_sendmsg(sock->file, msg, flags); + sockfd_put(sock); +out: + return err; +} + +long vfs_sendmsg(struct file *file, struct msghdr __user *msg, unsigned flags) +{ + struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; + struct socket *sock = file_to_socket(file); char address[MAX_SOCK_ADDR]; struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ unsigned char *ctl_buf = ctl; struct msghdr msg_sys; int err, ctl_len, iov_size, total_len; - + + if (IS_ERR(sock)) + return PTR_ERR(sock); err = -EFAULT; if (MSG_CMSG_COMPAT & flags) { if (get_compat_msghdr(&msg_sys, msg_compat)) @@ -1730,14 +1755,10 @@ asmlinkage long sys_sendmsg(int fd, stru } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) return -EFAULT; - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - /* do not move before msg_sys is valid */ err = -EMSGSIZE; if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; + goto out; /* Check whether to allocate the iovec area*/ err = -ENOMEM; @@ -1745,7 +1766,7 @@ asmlinkage long sys_sendmsg(int fd, stru if (msg_sys.msg_iovlen > UIO_FASTIOV) { iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); if (!iov) - goto out_put; + goto out; } /* This will also move the address data into kernel space */ @@ -1796,8 +1817,6 @@ out_freectl: out_freeiov: if (iov != iovstack) sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); out: return err; } @@ -1808,8 +1827,22 @@ out: asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags) { - struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; struct socket *sock; + int err; + + sock = sockfd_lookup(fd, &err); + if (!sock) + goto out; + err = vfs_recvmsg(sock->file, msg, flags); + sockfd_put(sock); +out: + return err; +} + +long vfs_recvmsg(struct file *file, struct msghdr __user *msg, unsigned int flags) +{ + struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; + struct socket *sock = file_to_socket(file); struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov=iovstack; struct msghdr msg_sys; @@ -1822,7 +1855,9 @@ asmlinkage long sys_recvmsg(int fd, stru /* user mode address pointers */ struct sockaddr __user *uaddr; int __user *uaddr_len; - + + if (IS_ERR(sock)) + return PTR_ERR(sock); if (MSG_CMSG_COMPAT & flags) { if (get_compat_msghdr(&msg_sys, msg_compat)) return -EFAULT; @@ -1830,13 +1865,9 @@ asmlinkage long sys_recvmsg(int fd, stru if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) return -EFAULT; - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - err = -EMSGSIZE; if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; + goto out; /* Check whether to allocate the iovec area*/ err = -ENOMEM; @@ -1844,7 +1875,7 @@ asmlinkage long sys_recvmsg(int fd, stru if (msg_sys.msg_iovlen > UIO_FASTIOV) { iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); if (!iov) - goto out_put; + goto out; } /* @@ -1895,8 +1926,6 @@ asmlinkage long sys_recvmsg(int fd, stru out_freeiov: if (iov != iovstack) sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); out: return err; }