Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorDavid S. Miller <davem@davemloft.net>
Mon, 13 Apr 2015 22:18:05 +0000 (18:18 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 13 Apr 2015 22:18:05 +0000 (18:18 -0400)
Al Viro says:

====================
netdev-related stuff in vfs.git

There are several commits sitting in vfs.git that probably ought to go in
via net-next.git.  First of all, there's merge with vfs.git#iocb - that's
Christoph's aio rework, which has triggered conflicts with the ->sendmsg()
and ->recvmsg() patches a while ago.  It's not so much Christoph's stuff
that ought to be in net-next, as (pretty simple) conflict resolution on merge.
The next chunk is switch to {compat_,}import_iovec/import_single_range - new
safer primitives for initializing iov_iter.  The primitives themselves come
from vfs/git#iov_iter (and they are used quite a lot in vfs part of queue),
conversion of net/socket.c syscalls belongs in net-next, IMO.  Next there's
afs and rxrpc stuff from dhowells.  And then there's sanitizing kernel_sendmsg
et.al.  + missing inlined helper for "how much data is left in msg->msg_iter" -
this stuff is used in e.g.  cifs stuff, but it belongs in net-next.

That pile is pullable from
git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git for-davem

I'll post the individual patches in there in followups; could you take a look
and tell if everything in there is OK with you?
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
87 files changed:
arch/s390/hypfs/inode.c
crypto/algif_hash.c
crypto/algif_skcipher.c
drivers/char/mem.c
drivers/char/tile-srom.c
drivers/infiniband/hw/ipath/ipath_file_ops.c
drivers/infiniband/hw/qib/qib_file_ops.c
drivers/misc/mei/amthif.c
drivers/misc/mei/main.c
drivers/misc/mei/pci-me.c
drivers/scsi/sg.c
drivers/staging/unisys/include/timskmod.h
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/legacy/inode.c
drivers/vhost/net.c
fs/9p/vfs_addr.c
fs/affs/file.c
fs/afs/misc.c
fs/afs/rxrpc.c
fs/afs/write.c
fs/aio.c
fs/bfs/inode.c
fs/block_dev.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/ceph/file.c
fs/direct-io.c
fs/ecryptfs/file.c
fs/ext2/inode.c
fs/ext3/inode.c
fs/ext4/file.c
fs/ext4/indirect.c
fs/ext4/inode.c
fs/ext4/page-io.c
fs/f2fs/data.c
fs/fat/inode.c
fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/gfs2/aops.c
fs/gfs2/file.c
fs/hfs/inode.c
fs/hfsplus/inode.c
fs/jfs/inode.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nilfs2/inode.c
fs/ntfs/file.c
fs/ntfs/inode.c
fs/ocfs2/aops.c
fs/ocfs2/aops.h
fs/ocfs2/file.c
fs/pipe.c
fs/read_write.c
fs/reiserfs/inode.c
fs/splice.c
fs/ubifs/file.c
fs/udf/file.c
fs/udf/inode.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_file.c
include/linux/aio.h
include/linux/fs.h
include/linux/net.h
include/linux/socket.h
include/linux/uio.h
include/net/compat.h
include/net/sock.h
include/rxrpc/packet.h
kernel/printk/printk.c
kernel/sysctl.c
lib/iov_iter.c
mm/filemap.c
mm/page_io.c
mm/shmem.c
net/compat.c
net/core/datagram.c
net/ipv4/raw.c
net/ipv4/tcp.c
net/rxrpc/ar-input.c
net/rxrpc/ar-internal.h
net/rxrpc/ar-local.c
net/rxrpc/ar-output.c
net/socket.c
net/sunrpc/svcsock.c
sound/core/pcm_native.c

index 99824ff8dd354e74ff421a2c9bb59243e045d541..df7d8cbee377a229c5f609d92ea7b72045c9cc86 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include <asm/ebcdic.h>
 #include "hypfs.h"
 
index 0a465e0f301291f3e63b4306905f25bcffa50284..1396ad0787fc6b84ebdd9a9d552ce7eaccf1e698 100644 (file)
@@ -56,8 +56,8 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
 
        ctx->more = 0;
 
-       while (iov_iter_count(&msg->msg_iter)) {
-               int len = iov_iter_count(&msg->msg_iter);
+       while (msg_data_left(msg)) {
+               int len = msg_data_left(msg);
 
                if (len > limit)
                        len = limit;
index 0aa02635ceda67a0591c6eb2a25a1d789a8a2012..945075292bc9584e57f4612bb1b7549a8e9e9b22 100644 (file)
@@ -106,7 +106,7 @@ static void skcipher_async_cb(struct crypto_async_request *req, int err)
        atomic_dec(&ctx->inflight);
        skcipher_free_async_sgls(sreq);
        kfree(req);
-       aio_complete(iocb, err, err);
+       iocb->ki_complete(iocb, err, err);
 }
 
 static inline int skcipher_sndbuf(struct sock *sk)
@@ -641,7 +641,7 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
        long copied = 0;
 
        lock_sock(sk);
-       while (iov_iter_count(&msg->msg_iter)) {
+       while (msg_data_left(msg)) {
                sgl = list_first_entry(&ctx->tsgl,
                                       struct skcipher_sg_list, list);
                sg = sgl->sg;
@@ -655,7 +655,7 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
                                goto unlock;
                }
 
-               used = min_t(unsigned long, ctx->used, iov_iter_count(&msg->msg_iter));
+               used = min_t(unsigned long, ctx->used, msg_data_left(msg));
 
                used = af_alg_make_sg(&ctx->rsgl, &msg->msg_iter, used);
                err = used;
index 297110c12635d3b8c36b53a7f089aa2666024eca..9c4fd7a8e2e5c466e6df5144082a22b868214d9f 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/pfn.h>
 #include <linux/export.h>
 #include <linux/io.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include <linux/uaccess.h>
 
index 02e76ac6d282d5a26a31598b05b4d89a6fefd671..69f6b4acc377143d87a54d5e46dd9710f4d53f73 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/types.h>       /* size_t */
 #include <linux/proc_fs.h>
 #include <linux/fcntl.h>       /* O_ACCMODE */
-#include <linux/aio.h>
 #include <linux/pagemap.h>
 #include <linux/hugetlb.h>
 #include <linux/uaccess.h>
index 6d7f453b4d05ef7da7f74aeafe22608b85dc00fc..aed8afee56da16a6a3609a247c9bea2c54060c44 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
-#include <linux/aio.h>
 #include <linux/jiffies.h>
 #include <linux/cpu.h>
 #include <asm/pgtable.h>
index 41937c6f888af13deadb6c7b25678cfc34596cf8..14046f5a37fa332cf5e5b25ba1a86a5fe7918188 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
-#include <linux/aio.h>
 #include <linux/jiffies.h>
 #include <asm/pgtable.h>
 #include <linux/delay.h>
index c4cb9a984a5fb3965bba581eab0dd5c9096ec851..40ea639fa413a92f0239e1835894e73d36ddc1c1 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 #include <linux/ioctl.h>
 #include <linux/cdev.h>
 #include <linux/list.h>
index 3c019c0e60eb859ede0621f26c4d71d72fca8abe..47680c84801c766f158bf65c2e2dd3893fdff300 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/ioctl.h>
index bd3039ab8f98e67e86de56ef8429dfd164c89d86..af44ee26075d8b520401a2cc52150b74d45157f0 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 #include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/ioctl.h>
index 2270bd51f9c2c240c669e562eb77052f89425a83..d383f84869aa45475bb25f149123092a0f3beb0c 100644 (file)
@@ -33,7 +33,6 @@ static int sg_version_num = 30536;    /* 2 digits for each component */
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/aio.h>
 #include <linux/errno.h>
 #include <linux/mtio.h>
 #include <linux/ioctl.h>
@@ -51,6 +50,7 @@ static int sg_version_num = 30536;    /* 2 digits for each component */
 #include <linux/mutex.h>
 #include <linux/atomic.h>
 #include <linux/ratelimit.h>
+#include <linux/uio.h>
 
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
index 4019a0d63645fe53380caec301679a68f9979e87..52648d4d99220cc6916cef894299dd4102248097 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 #include <linux/workqueue.h>
 #include <linux/kthread.h>
 #include <linux/seq_file.h>
index 175c9956cbe3a36949526029103d38b4c97225c3..a12315a78248d4a40349586062e043b8574d1308 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/export.h>
 #include <linux/hid.h>
 #include <linux/module.h>
+#include <linux/uio.h>
 #include <asm/unaligned.h>
 
 #include <linux/usb/composite.h>
@@ -655,9 +656,10 @@ static void ffs_user_copy_worker(struct work_struct *work)
                unuse_mm(io_data->mm);
        }
 
-       aio_complete(io_data->kiocb, ret, ret);
+       io_data->kiocb->ki_complete(io_data->kiocb, ret, ret);
 
-       if (io_data->ffs->ffs_eventfd && !io_data->kiocb->ki_eventfd)
+       if (io_data->ffs->ffs_eventfd &&
+           !(io_data->kiocb->ki_flags & IOCB_EVENTFD))
                eventfd_signal(io_data->ffs->ffs_eventfd, 1);
 
        usb_ep_free_request(io_data->ep, io_data->req);
index 200f9a584064fd9199ba99ff75a2e26a33c788f7..662ef2c1c62b67d0340cbf8593d515f14f2568dc 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/poll.h>
 #include <linux/mmu_context.h>
 #include <linux/aio.h>
+#include <linux/uio.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -469,7 +470,7 @@ static void ep_user_copy_worker(struct work_struct *work)
                ret = -EFAULT;
 
        /* completing the iocb can drop the ctx and mm, don't touch mm after */
-       aio_complete(iocb, ret, ret);
+       iocb->ki_complete(iocb, ret, ret);
 
        kfree(priv->buf);
        kfree(priv->to_free);
@@ -497,7 +498,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
                kfree(priv);
                iocb->private = NULL;
                /* aio_complete() reports bytes-transferred _and_ faults */
-               aio_complete(iocb, req->actual ? req->actual : req->status,
+
+               iocb->ki_complete(iocb, req->actual ? req->actual : req->status,
                                req->status);
        } else {
                /* ep_copy_to_user() won't report both; we hide some faults */
index 18f05bff8826672a17a645d8fddc2a7df489e302..7d137a43cc86842ed98bc27e63d6dfcb2042f177 100644 (file)
@@ -357,13 +357,13 @@ static void handle_tx(struct vhost_net *net)
                iov_iter_init(&msg.msg_iter, WRITE, vq->iov, out, len);
                iov_iter_advance(&msg.msg_iter, hdr_size);
                /* Sanity check */
-               if (!iov_iter_count(&msg.msg_iter)) {
+               if (!msg_data_left(&msg)) {
                        vq_err(vq, "Unexpected header len for TX: "
                               "%zd expected %zd\n",
                               len, hdr_size);
                        break;
                }
-               len = iov_iter_count(&msg.msg_iter);
+               len = msg_data_left(&msg);
 
                zcopy_used = zcopy && len >= VHOST_GOODCOPY_LEN
                                   && (nvq->upend_idx + 1) % UIO_MAXIOV !=
index eb14e055ea83e8509e7ea6ae569e3c1966d3b896..ff1a5bac420098d528a46c6cccecfa1caa73c421 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/pagemap.h>
 #include <linux/idr.h>
 #include <linux/sched.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 
index a91795e01a7ff0c0e85abf1bdf69f3d1d828b231..3aa7eb66547ea31b7556c1502d3900dce0aa80dd 100644 (file)
@@ -12,7 +12,7 @@
  *  affs regular file handling primitives
  */
 
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include "affs.h"
 
 static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
index 0dd4dafee10b391f7d92b89f8c4e491ed5f09810..91ea1aa0d8b3ab0a817b525e9f9b3deec98f775f 100644 (file)
 int afs_abort_to_error(u32 abort_code)
 {
        switch (abort_code) {
+       /* low errno codes inserted into abort namespace */
        case 13:                return -EACCES;
        case 27:                return -EFBIG;
        case 30:                return -EROFS;
+
+       /* VICE "special error" codes; 101 - 111 */
        case VSALVAGE:          return -EIO;
        case VNOVNODE:          return -ENOENT;
        case VNOVOL:            return -ENOMEDIUM;
@@ -36,11 +39,18 @@ int afs_abort_to_error(u32 abort_code)
        case VOVERQUOTA:        return -EDQUOT;
        case VBUSY:             return -EBUSY;
        case VMOVED:            return -ENXIO;
-       case 0x2f6df0a:         return -EWOULDBLOCK;
+
+       /* Unified AFS error table; ET "uae" == 0x2f6df00 */
+       case 0x2f6df00:         return -EPERM;
+       case 0x2f6df01:         return -ENOENT;
+       case 0x2f6df04:         return -EIO;
+       case 0x2f6df0a:         return -EAGAIN;
+       case 0x2f6df0b:         return -ENOMEM;
        case 0x2f6df0c:         return -EACCES;
        case 0x2f6df0f:         return -EBUSY;
        case 0x2f6df10:         return -EEXIST;
        case 0x2f6df11:         return -EXDEV;
+       case 0x2f6df12:         return -ENODEV;
        case 0x2f6df13:         return -ENOTDIR;
        case 0x2f6df14:         return -EISDIR;
        case 0x2f6df15:         return -EINVAL;
@@ -54,8 +64,12 @@ int afs_abort_to_error(u32 abort_code)
        case 0x2f6df23:         return -ENAMETOOLONG;
        case 0x2f6df24:         return -ENOLCK;
        case 0x2f6df26:         return -ENOTEMPTY;
+       case 0x2f6df28:         return -EWOULDBLOCK;
+       case 0x2f6df69:         return -ENOTCONN;
+       case 0x2f6df6c:         return -ETIMEDOUT;
        case 0x2f6df78:         return -EDQUOT;
 
+       /* RXKAD abort codes; from include/rxrpc/packet.h.  ET "RXK" == 0x1260B00 */
        case RXKADINCONSISTENCY: return -EPROTO;
        case RXKADPACKETSHORT:  return -EPROTO;
        case RXKADLEVELFAIL:    return -EKEYREJECTED;
index dbc732e9a5c01eb18ab91af910a997881dfe5fd8..3a57a1b0fb510b8c8167835ca62eb06d0c4b53ca 100644 (file)
@@ -770,15 +770,12 @@ static int afs_deliver_cm_op_id(struct afs_call *call, struct sk_buff *skb,
 void afs_send_empty_reply(struct afs_call *call)
 {
        struct msghdr msg;
-       struct kvec iov[1];
 
        _enter("");
 
-       iov[0].iov_base         = NULL;
-       iov[0].iov_len          = 0;
        msg.msg_name            = NULL;
        msg.msg_namelen         = 0;
-       iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iov, 0, 0);     /* WTF? */
+       iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, NULL, 0, 0);
        msg.msg_control         = NULL;
        msg.msg_controllen      = 0;
        msg.msg_flags           = 0;
index c13cb08964eda91afe26754733054147e220ecb7..0714abcd7f32321754287e46aec129196832e2ef 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
 #include <linux/pagevec.h>
-#include <linux/aio.h>
 #include "internal.h"
 
 static int afs_write_back_from_locked_page(struct afs_writeback *wb,
index f8e52a1854c1ab383e32383ac65a0f167e385793..435ca29eca31431649b4df125e933488b8d4073e 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -151,6 +151,38 @@ struct kioctx {
        unsigned                id;
 };
 
+/*
+ * We use ki_cancel == KIOCB_CANCELLED to indicate that a kiocb has been either
+ * cancelled or completed (this makes a certain amount of sense because
+ * successful cancellation - io_cancel() - does deliver the completion to
+ * userspace).
+ *
+ * And since most things don't implement kiocb cancellation and we'd really like
+ * kiocb completion to be lockless when possible, we use ki_cancel to
+ * synchronize cancellation and completion - we only set it to KIOCB_CANCELLED
+ * with xchg() or cmpxchg(), see batch_complete_aio() and kiocb_cancel().
+ */
+#define KIOCB_CANCELLED                ((void *) (~0ULL))
+
+struct aio_kiocb {
+       struct kiocb            common;
+
+       struct kioctx           *ki_ctx;
+       kiocb_cancel_fn         *ki_cancel;
+
+       struct iocb __user      *ki_user_iocb;  /* user's aiocb */
+       __u64                   ki_user_data;   /* user's data for completion */
+
+       struct list_head        ki_list;        /* the aio core uses this
+                                                * for cancellation */
+
+       /*
+        * If the aio_resfd field of the userspace iocb is not zero,
+        * this is the underlying eventfd context to deliver events to.
+        */
+       struct eventfd_ctx      *ki_eventfd;
+};
+
 /*------ sysctl variables----*/
 static DEFINE_SPINLOCK(aio_nr_lock);
 unsigned long aio_nr;          /* current system wide number of aio requests */
@@ -220,7 +252,7 @@ static int __init aio_setup(void)
        if (IS_ERR(aio_mnt))
                panic("Failed to create aio fs mount.");
 
-       kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
+       kiocb_cachep = KMEM_CACHE(aio_kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
        kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
        pr_debug("sizeof(struct page) = %zu\n", sizeof(struct page));
@@ -480,8 +512,9 @@ static int aio_setup_ring(struct kioctx *ctx)
 #define AIO_EVENTS_FIRST_PAGE  ((PAGE_SIZE - sizeof(struct aio_ring)) / sizeof(struct io_event))
 #define AIO_EVENTS_OFFSET      (AIO_EVENTS_PER_PAGE - AIO_EVENTS_FIRST_PAGE)
 
-void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel)
+void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
 {
+       struct aio_kiocb *req = container_of(iocb, struct aio_kiocb, common);
        struct kioctx *ctx = req->ki_ctx;
        unsigned long flags;
 
@@ -496,7 +529,7 @@ void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel)
 }
 EXPORT_SYMBOL(kiocb_set_cancel_fn);
 
-static int kiocb_cancel(struct kiocb *kiocb)
+static int kiocb_cancel(struct aio_kiocb *kiocb)
 {
        kiocb_cancel_fn *old, *cancel;
 
@@ -514,7 +547,7 @@ static int kiocb_cancel(struct kiocb *kiocb)
                cancel = cmpxchg(&kiocb->ki_cancel, old, KIOCB_CANCELLED);
        } while (cancel != old);
 
-       return cancel(kiocb);
+       return cancel(&kiocb->common);
 }
 
 static void free_ioctx(struct work_struct *work)
@@ -550,13 +583,13 @@ static void free_ioctx_reqs(struct percpu_ref *ref)
 static void free_ioctx_users(struct percpu_ref *ref)
 {
        struct kioctx *ctx = container_of(ref, struct kioctx, users);
-       struct kiocb *req;
+       struct aio_kiocb *req;
 
        spin_lock_irq(&ctx->ctx_lock);
 
        while (!list_empty(&ctx->active_reqs)) {
                req = list_first_entry(&ctx->active_reqs,
-                                      struct kiocb, ki_list);
+                                      struct aio_kiocb, ki_list);
 
                list_del_init(&req->ki_list);
                kiocb_cancel(req);
@@ -778,22 +811,6 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
        return 0;
 }
 
-/* wait_on_sync_kiocb:
- *     Waits on the given sync kiocb to complete.
- */
-ssize_t wait_on_sync_kiocb(struct kiocb *req)
-{
-       while (!req->ki_ctx) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               if (req->ki_ctx)
-                       break;
-               io_schedule();
-       }
-       __set_current_state(TASK_RUNNING);
-       return req->ki_user_data;
-}
-EXPORT_SYMBOL(wait_on_sync_kiocb);
-
 /*
  * exit_aio: called when the last user of mm goes away.  At this point, there is
  * no way for any new requests to be submited or any of the io_* syscalls to be
@@ -948,9 +965,9 @@ static void user_refill_reqs_available(struct kioctx *ctx)
  *     Allocate a slot for an aio request.
  * Returns NULL if no requests are free.
  */
-static inline struct kiocb *aio_get_req(struct kioctx *ctx)
+static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx)
 {
-       struct kiocb *req;
+       struct aio_kiocb *req;
 
        if (!get_reqs_available(ctx)) {
                user_refill_reqs_available(ctx);
@@ -971,10 +988,10 @@ out_put:
        return NULL;
 }
 
-static void kiocb_free(struct kiocb *req)
+static void kiocb_free(struct aio_kiocb *req)
 {
-       if (req->ki_filp)
-               fput(req->ki_filp);
+       if (req->common.ki_filp)
+               fput(req->common.ki_filp);
        if (req->ki_eventfd != NULL)
                eventfd_ctx_put(req->ki_eventfd);
        kmem_cache_free(kiocb_cachep, req);
@@ -1010,8 +1027,9 @@ out:
 /* aio_complete
  *     Called when the io request on the given iocb is complete.
  */
-void aio_complete(struct kiocb *iocb, long res, long res2)
+static void aio_complete(struct kiocb *kiocb, long res, long res2)
 {
+       struct aio_kiocb *iocb = container_of(kiocb, struct aio_kiocb, common);
        struct kioctx   *ctx = iocb->ki_ctx;
        struct aio_ring *ring;
        struct io_event *ev_page, *event;
@@ -1025,13 +1043,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
         *    ref, no other paths have a way to get another ref
         *  - the sync task helpfully left a reference to itself in the iocb
         */
-       if (is_sync_kiocb(iocb)) {
-               iocb->ki_user_data = res;
-               smp_wmb();
-               iocb->ki_ctx = ERR_PTR(-EXDEV);
-               wake_up_process(iocb->ki_obj.tsk);
-               return;
-       }
+       BUG_ON(is_sync_kiocb(kiocb));
 
        if (iocb->ki_list.next) {
                unsigned long flags;
@@ -1057,7 +1069,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
        ev_page = kmap_atomic(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
        event = ev_page + pos % AIO_EVENTS_PER_PAGE;
 
-       event->obj = (u64)(unsigned long)iocb->ki_obj.user;
+       event->obj = (u64)(unsigned long)iocb->ki_user_iocb;
        event->data = iocb->ki_user_data;
        event->res = res;
        event->res2 = res2;
@@ -1066,7 +1078,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
        flush_dcache_page(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
 
        pr_debug("%p[%u]: %p: %p %Lx %lx %lx\n",
-                ctx, tail, iocb, iocb->ki_obj.user, iocb->ki_user_data,
+                ctx, tail, iocb, iocb->ki_user_iocb, iocb->ki_user_data,
                 res, res2);
 
        /* after flagging the request as done, we
@@ -1113,7 +1125,6 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
 
        percpu_ref_put(&ctx->reqs);
 }
-EXPORT_SYMBOL(aio_complete);
 
 /* aio_read_events_ring
  *     Pull an event off of the ioctx's event ring.  Returns the number of
@@ -1344,12 +1355,13 @@ typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *);
 static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
                                     int rw, char __user *buf,
                                     unsigned long *nr_segs,
+                                    size_t *len,
                                     struct iovec **iovec,
                                     bool compat)
 {
        ssize_t ret;
 
-       *nr_segs = kiocb->ki_nbytes;
+       *nr_segs = *len;
 
 #ifdef CONFIG_COMPAT
        if (compat)
@@ -1364,21 +1376,22 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
        if (ret < 0)
                return ret;
 
-       /* ki_nbytes now reflect bytes instead of segs */
-       kiocb->ki_nbytes = ret;
+       /* len now reflect bytes instead of segs */
+       *len = ret;
        return 0;
 }
 
 static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
                                       int rw, char __user *buf,
                                       unsigned long *nr_segs,
+                                      size_t len,
                                       struct iovec *iovec)
 {
-       if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes)))
+       if (unlikely(!access_ok(!rw, buf, len)))
                return -EFAULT;
 
        iovec->iov_base = buf;
-       iovec->iov_len = kiocb->ki_nbytes;
+       iovec->iov_len = len;
        *nr_segs = 1;
        return 0;
 }
@@ -1388,7 +1401,7 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
  *     Performs the initial checks and io submission.
  */
 static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
-                           char __user *buf, bool compat)
+                           char __user *buf, size_t len, bool compat)
 {
        struct file *file = req->ki_filp;
        ssize_t ret;
@@ -1423,21 +1436,21 @@ rw_common:
                if (!rw_op && !iter_op)
                        return -EINVAL;
 
-               ret = (opcode == IOCB_CMD_PREADV ||
-                      opcode == IOCB_CMD_PWRITEV)
-                       ? aio_setup_vectored_rw(req, rw, buf, &nr_segs,
-                                               &iovec, compat)
-                       : aio_setup_single_vector(req, rw, buf, &nr_segs,
-                                                 iovec);
+               if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV)
+                       ret = aio_setup_vectored_rw(req, rw, buf, &nr_segs,
+                                               &len, &iovec, compat);
+               else
+                       ret = aio_setup_single_vector(req, rw, buf, &nr_segs,
+                                                 len, iovec);
                if (!ret)
-                       ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
+                       ret = rw_verify_area(rw, file, &req->ki_pos, len);
                if (ret < 0) {
                        if (iovec != inline_vecs)
                                kfree(iovec);
                        return ret;
                }
 
-               req->ki_nbytes = ret;
+               len = ret;
 
                /* XXX: move/kill - rw_verify_area()? */
                /* This matches the pread()/pwrite() logic */
@@ -1450,7 +1463,7 @@ rw_common:
                        file_start_write(file);
 
                if (iter_op) {
-                       iov_iter_init(&iter, rw, iovec, nr_segs, req->ki_nbytes);
+                       iov_iter_init(&iter, rw, iovec, nr_segs, len);
                        ret = iter_op(req, &iter);
                } else {
                        ret = rw_op(req, iovec, nr_segs, req->ki_pos);
@@ -1500,7 +1513,7 @@ rw_common:
 static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                         struct iocb *iocb, bool compat)
 {
-       struct kiocb *req;
+       struct aio_kiocb *req;
        ssize_t ret;
 
        /* enforce forwards compatibility on users */
@@ -1523,11 +1536,14 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
        if (unlikely(!req))
                return -EAGAIN;
 
-       req->ki_filp = fget(iocb->aio_fildes);
-       if (unlikely(!req->ki_filp)) {
+       req->common.ki_filp = fget(iocb->aio_fildes);
+       if (unlikely(!req->common.ki_filp)) {
                ret = -EBADF;
                goto out_put_req;
        }
+       req->common.ki_pos = iocb->aio_offset;
+       req->common.ki_complete = aio_complete;
+       req->common.ki_flags = 0;
 
        if (iocb->aio_flags & IOCB_FLAG_RESFD) {
                /*
@@ -1542,6 +1558,8 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                        req->ki_eventfd = NULL;
                        goto out_put_req;
                }
+
+               req->common.ki_flags |= IOCB_EVENTFD;
        }
 
        ret = put_user(KIOCB_KEY, &user_iocb->aio_key);
@@ -1550,13 +1568,12 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                goto out_put_req;
        }
 
-       req->ki_obj.user = user_iocb;
+       req->ki_user_iocb = user_iocb;
        req->ki_user_data = iocb->aio_data;
-       req->ki_pos = iocb->aio_offset;
-       req->ki_nbytes = iocb->aio_nbytes;
 
-       ret = aio_run_iocb(req, iocb->aio_lio_opcode,
+       ret = aio_run_iocb(&req->common, iocb->aio_lio_opcode,
                           (char __user *)(unsigned long)iocb->aio_buf,
+                          iocb->aio_nbytes,
                           compat);
        if (ret)
                goto out_put_req;
@@ -1643,10 +1660,10 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
 /* lookup_kiocb
  *     Finds a given iocb for cancellation.
  */
-static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
-                                 u32 key)
+static struct aio_kiocb *
+lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, u32 key)
 {
-       struct list_head *pos;
+       struct aio_kiocb *kiocb;
 
        assert_spin_locked(&ctx->ctx_lock);
 
@@ -1654,9 +1671,8 @@ static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
                return NULL;
 
        /* TODO: use a hash or array, this sucks. */
-       list_for_each(pos, &ctx->active_reqs) {
-               struct kiocb *kiocb = list_kiocb(pos);
-               if (kiocb->ki_obj.user == iocb)
+       list_for_each_entry(kiocb, &ctx->active_reqs, ki_list) {
+               if (kiocb->ki_user_iocb == iocb)
                        return kiocb;
        }
        return NULL;
@@ -1676,7 +1692,7 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
                struct io_event __user *, result)
 {
        struct kioctx *ctx;
-       struct kiocb *kiocb;
+       struct aio_kiocb *kiocb;
        u32 key;
        int ret;
 
index 90bc079d9982928b7a9b5bcb6ad3efd6ebf1375f..fdcb4d69f430db6370e1eed7c1c04c9a3f333746 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
+#include <linux/uio.h>
 #include <asm/uaccess.h>
 #include "bfs.h"
 
index 975266be67d319aa019a48e94cfda0a3ca8ce1e0..2e522aed6584d3a7837155897b2a47085b5ed303 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/namei.h>
 #include <linux/log2.h>
 #include <linux/cleancache.h>
-#include <linux/aio.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
index 30982bbd31c30c2b154836b0f51b94c37e22923c..aee18f84e3159c1e369a0c14eff0baad8ddbb59a 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/string.h>
 #include <linux/backing-dev.h>
 #include <linux/mpage.h>
-#include <linux/aio.h>
 #include <linux/falloc.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
@@ -32,6 +31,7 @@
 #include <linux/compat.h>
 #include <linux/slab.h>
 #include <linux/btrfs.h>
+#include <linux/uio.h>
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
index d2e732d7af524640bc2c197da3e7123182b4537e..686331f22b15ce0fcc8233c2529a50c2eb6190c7 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/writeback.h>
 #include <linux/statfs.h>
 #include <linux/compat.h>
-#include <linux/aio.h>
 #include <linux/bit_spinlock.h>
 #include <linux/xattr.h>
 #include <linux/posix_acl.h>
@@ -43,6 +42,7 @@
 #include <linux/btrfs.h>
 #include <linux/blkdev.h>
 #include <linux/posix_acl_xattr.h>
+#include <linux/uio.h>
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
index d533075a823d5eb92e709547b8fe790c59cba981..139f2fea91a0fe8472cf138e900bfe580db43f50 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/writeback.h>
-#include <linux/aio.h>
 #include <linux/falloc.h>
 
 #include "super.h"
@@ -808,7 +807,7 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
        struct file *filp = iocb->ki_filp;
        struct ceph_file_info *fi = filp->private_data;
-       size_t len = iocb->ki_nbytes;
+       size_t len = iov_iter_count(to);
        struct inode *inode = file_inode(filp);
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct page *pinned_page = NULL;
index e181b6b2e297fb5d3bd03a07efe382f0dd204972..6fb00e3f1059791d21b4ffc80671f3d051ecbc8e 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/uio.h>
 #include <linux/atomic.h>
 #include <linux/prefetch.h>
-#include <linux/aio.h>
 
 /*
  * How many user pages to map in one call to get_user_pages().  This determines
@@ -265,7 +264,7 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret,
                                ret = err;
                }
 
-               aio_complete(dio->iocb, ret, 0);
+               dio->iocb->ki_complete(dio->iocb, ret, 0);
        }
 
        kmem_cache_free(dio_cache, dio);
@@ -1056,7 +1055,7 @@ static inline int drop_refcount(struct dio *dio)
         * operation.  AIO can if it was a broken operation described above or
         * in fact if all the bios race to complete before we get here.  In
         * that case dio_complete() translates the EIOCBQUEUED into the proper
-        * return code that the caller will hand to aio_complete().
+        * return code that the caller will hand to ->complete().
         *
         * This is managed by the bio_lock instead of being an atomic_t so that
         * completion paths can drop their ref and use the remaining count to
index fd39bad6f1bdf8bbcb4321a8fc8ff1934d67167c..79675089443df98c23de1602d3ca59a887cbb4d4 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/fs_stack.h>
-#include <linux/aio.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -52,12 +51,6 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
        struct file *file = iocb->ki_filp;
 
        rc = generic_file_read_iter(iocb, to);
-       /*
-        * Even though this is a async interface, we need to wait
-        * for IO to finish to update atime
-        */
-       if (-EIOCBQUEUED == rc)
-               rc = wait_on_sync_kiocb(iocb);
        if (rc >= 0) {
                path = ecryptfs_dentry_to_lower_path(file->f_path.dentry);
                touch_atime(path);
index 6434bc00012517a30ace1cb97f2160b0c48eea3a..df9d6afbc5d5eb745e00a9a2575b28890e94d7b7 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/mpage.h>
 #include <linux/fiemap.h>
 #include <linux/namei.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include "ext2.h"
 #include "acl.h"
 #include "xattr.h"
index 2c6ccc49ba279cacf77fe6609fe44a50b970898c..db07ffbe7c85cdabbe89d49b3b2294dd8a1d84cf 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/writeback.h>
 #include <linux/mpage.h>
 #include <linux/namei.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include "ext3.h"
 #include "xattr.h"
 #include "acl.h"
index 33a09da16c9ce1e8049fdcacdf3e8833410fd78f..598abbbe678619c347dbe53d8dfe2c8cd6c86c65 100644 (file)
@@ -23,9 +23,9 @@
 #include <linux/jbd2.h>
 #include <linux/mount.h>
 #include <linux/path.h>
-#include <linux/aio.h>
 #include <linux/quotaops.h>
 #include <linux/pagevec.h>
+#include <linux/uio.h>
 #include "ext4.h"
 #include "ext4_jbd2.h"
 #include "xattr.h"
index 45fe924f82bce2ff76e3e74b45ec1833729433ea..740c7871c11770a683395989df5548d3d3357c22 100644 (file)
@@ -20,9 +20,9 @@
  *     (sct@redhat.com), 1993, 1998
  */
 
-#include <linux/aio.h>
 #include "ext4_jbd2.h"
 #include "truncate.h"
+#include <linux/uio.h>
 
 #include <trace/events/ext4.h>
 
index 5cb9a212b86f3efd69ca604df07dc20b901dabb1..a3f451370bef4b49a23343daf63af2459de0741c 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/printk.h>
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
-#include <linux/aio.h>
 #include <linux/bitops.h>
 
 #include "ext4_jbd2.h"
index b24a2541a9baaa0d4c22e80a75050af2517a417d..464984261e698af8317621c45b8d2089551bc790 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/pagevec.h>
 #include <linux/mpage.h>
 #include <linux/namei.h>
-#include <linux/aio.h>
 #include <linux/uio.h>
 #include <linux/bio.h>
 #include <linux/workqueue.h>
index 985ed023a750170b924455ea23e2684c50baeba4..497f8515d2056283d040b912dd638e65a4576fe7 100644 (file)
 #include <linux/f2fs_fs.h>
 #include <linux/buffer_head.h>
 #include <linux/mpage.h>
-#include <linux/aio.h>
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
 #include <linux/blkdev.h>
 #include <linux/bio.h>
 #include <linux/prefetch.h>
+#include <linux/uio.h>
 
 #include "f2fs.h"
 #include "node.h"
index 497c7c5263c7ca3962c385605fbbb558d351f759..8521207de22935464f074b70448cae781ed403e1 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mpage.h>
 #include <linux/buffer_head.h>
 #include <linux/mount.h>
-#include <linux/aio.h>
 #include <linux/vfs.h>
 #include <linux/parser.h>
 #include <linux/uio.h>
index 28d0c7abba1c2fa7748d3b1c2874b855427b3897..b3fa0503223411ff97b3ab5c2f775310b1f3cccb 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/device.h>
 #include <linux/file.h>
 #include <linux/fs.h>
-#include <linux/aio.h>
 #include <linux/kdev_t.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
@@ -48,6 +47,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/module.h>
+#include <linux/uio.h>
 
 #include "fuse_i.h"
 
index 39706c57ad3cb157d81594065a15f154f61d7bd8..95a2797eef66d8db6edb1c7c4310be292744a427 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/swap.h>
 #include <linux/splice.h>
-#include <linux/aio.h>
 
 MODULE_ALIAS_MISCDEV(FUSE_MINOR);
 MODULE_ALIAS("devname:fuse");
index c01ec3bdcfd81090fae2cb26ae166f351d4505eb..ff102cbf16eab45bdd74eb7cffeafc99a4d7b064 100644 (file)
@@ -15,8 +15,8 @@
 #include <linux/module.h>
 #include <linux/compat.h>
 #include <linux/swap.h>
-#include <linux/aio.h>
 #include <linux/falloc.h>
+#include <linux/uio.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -528,6 +528,17 @@ static void fuse_release_user_pages(struct fuse_req *req, int write)
        }
 }
 
+static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io)
+{
+       if (io->err)
+               return io->err;
+
+       if (io->bytes >= 0 && io->write)
+               return -EIO;
+
+       return io->bytes < 0 ? io->size : io->bytes;
+}
+
 /**
  * In case of short read, the caller sets 'pos' to the position of
  * actual end of fuse request in IO request. Otherwise, if bytes_requested
@@ -546,6 +557,7 @@ static void fuse_release_user_pages(struct fuse_req *req, int write)
  */
 static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos)
 {
+       bool is_sync = is_sync_kiocb(io->iocb);
        int left;
 
        spin_lock(&io->lock);
@@ -555,30 +567,24 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos)
                io->bytes = pos;
 
        left = --io->reqs;
+       if (!left && is_sync)
+               complete(io->done);
        spin_unlock(&io->lock);
 
-       if (!left) {
-               long res;
+       if (!left && !is_sync) {
+               ssize_t res = fuse_get_res_by_io(io);
 
-               if (io->err)
-                       res = io->err;
-               else if (io->bytes >= 0 && io->write)
-                       res = -EIO;
-               else {
-                       res = io->bytes < 0 ? io->size : io->bytes;
+               if (res >= 0) {
+                       struct inode *inode = file_inode(io->iocb->ki_filp);
+                       struct fuse_conn *fc = get_fuse_conn(inode);
+                       struct fuse_inode *fi = get_fuse_inode(inode);
 
-                       if (!is_sync_kiocb(io->iocb)) {
-                               struct inode *inode = file_inode(io->iocb->ki_filp);
-                               struct fuse_conn *fc = get_fuse_conn(inode);
-                               struct fuse_inode *fi = get_fuse_inode(inode);
-
-                               spin_lock(&fc->lock);
-                               fi->attr_version = ++fc->attr_version;
-                               spin_unlock(&fc->lock);
-                       }
+                       spin_lock(&fc->lock);
+                       fi->attr_version = ++fc->attr_version;
+                       spin_unlock(&fc->lock);
                }
 
-               aio_complete(io->iocb, res, 0);
+               io->iocb->ki_complete(io->iocb, res, 0);
                kfree(io);
        }
 }
@@ -2801,6 +2807,7 @@ static ssize_t
 fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
                        loff_t offset)
 {
+       DECLARE_COMPLETION_ONSTACK(wait);
        ssize_t ret = 0;
        struct file *file = iocb->ki_filp;
        struct fuse_file *ff = file->private_data;
@@ -2852,6 +2859,9 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
        if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE)
                io->async = false;
 
+       if (io->async && is_sync_kiocb(iocb))
+               io->done = &wait;
+
        if (rw == WRITE)
                ret = __fuse_direct_write(io, iter, &pos);
        else
@@ -2864,11 +2874,12 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
                if (!is_sync_kiocb(iocb))
                        return -EIOCBQUEUED;
 
-               ret = wait_on_sync_kiocb(iocb);
-       } else {
-               kfree(io);
+               wait_for_completion(&wait);
+               ret = fuse_get_res_by_io(io);
        }
 
+       kfree(io);
+
        if (rw == WRITE) {
                if (ret > 0)
                        fuse_write_update_size(inode, pos);
index 1cdfb07c1376b4f4b5633e86fdbdfc4320953de2..7354dc142a50845a62e9a413d82d185afc1f5b0d 100644 (file)
@@ -263,6 +263,7 @@ struct fuse_io_priv {
        int err;
        struct kiocb *iocb;
        struct file *file;
+       struct completion *done;
 };
 
 /**
index 4ad4f94edebe25cc8afa3fa7c4ec35913cb00642..fe6634d25d1ddb591a60a40f32f054cae89ed5f2 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/swap.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/backing-dev.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include <trace/events/writeback.h>
 
 #include "gfs2.h"
index 3e32bb8e2d7e573df59dc360a1ac38fe4ec759bd..f6fc412b1100e7f1340f6f479ebbcf8e18edca6c 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/uaccess.h>
 #include <linux/dlm.h>
 #include <linux/dlm_plock.h>
-#include <linux/aio.h>
 #include <linux/delay.h>
 
 #include "gfs2.h"
index d0929bc817826e012cc829bb0f021832eea24379..98d4ea45bb70aad886641f66d81e0007f0d0e34d 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/sched.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include "hfs_fs.h"
 #include "btree.h"
index 0cf786f2d046f9fbae9b110a2a2d212c008fb3aa..f541196d4ee910a3f9ec6ce26841937c9fa7eb73 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/sched.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
index bd3df1ca3c9b7f955571c056f86f98e97beda7b9..3197aed106148d8b0839b80405ecad125c14e7aa 100644 (file)
@@ -22,8 +22,8 @@
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
+#include <linux/uio.h>
 #include <linux/writeback.h>
-#include <linux/aio.h>
 #include "jfs_incore.h"
 #include "jfs_inode.h"
 #include "jfs_filsys.h"
index e907c8cf732e3cff6bc9711ccf0b20c9261cdca2..c3929fb2ab26c2971e2e4a9f09e0f5a88387c144 100644 (file)
@@ -265,7 +265,7 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t
 
        return -EINVAL;
 #else
-       VM_BUG_ON(iocb->ki_nbytes != PAGE_SIZE);
+       VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE);
 
        if (rw == READ)
                return nfs_file_direct_read(iocb, iter, pos);
@@ -393,7 +393,7 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write)
                long res = (long) dreq->error;
                if (!res)
                        res = (long) dreq->count;
-               aio_complete(dreq->iocb, res, 0);
+               dreq->iocb->ki_complete(dreq->iocb, res, 0);
        }
 
        complete_all(&dreq->completion);
index e679d24c39d3a57d5ef510a22d5ccbe2832c5335..37b15582e0de960a966e80fcda3aa1680caa094d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/nfs_mount.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
-#include <linux/aio.h>
 #include <linux/gfp.h>
 #include <linux/swap.h>
 
index 8b5969538f39229cede14416a067d2e056c1a677..ab4987bc637f8b084298086cf48f00e31bfe1298 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/mpage.h>
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include "nilfs.h"
 #include "btnode.h"
 #include "segment.h"
index 1da9b2d184dc4e32d9ac9a95eb0ee2553c5a1e46..f16f2d8401febeaf4911491e92f8deac377e8a93 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/swap.h>
 #include <linux/uio.h>
 #include <linux/writeback.h>
-#include <linux/aio.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
index 898b9949d36357a8b7998600f3fdbacaa498d08f..1d0c21df0d805cd73248afd42dc05c1108c49700 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/log2.h>
-#include <linux/aio.h>
 
 #include "aops.h"
 #include "attrib.h"
index 44db1808cdb598df6b91548410b3634480c06c31..e1bf18c5d25e1cc907abf53e4ac984870dc0584e 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mpage.h>
 #include <linux/quotaops.h>
 #include <linux/blkdev.h>
+#include <linux/uio.h>
 
 #include <cluster/masklog.h>
 
index 6cae155d54df0d68be4f90f4754d15c30302159c..dd59599b022d5ab26dffd82807d048cac170a154 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef OCFS2_AOPS_H
 #define OCFS2_AOPS_H
 
-#include <linux/aio.h>
+#include <linux/fs.h>
 
 handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
                                                         struct page *page,
index 46e0d4e857c7f493f512196603d3725ca8d3dfaa..266845de210016e5cc25a71599116f7f1f3b3290 100644 (file)
@@ -2280,7 +2280,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
                file->f_path.dentry->d_name.name,
                (unsigned int)from->nr_segs);   /* GRRRRR */
 
-       if (iocb->ki_nbytes == 0)
+       if (count == 0)
                return 0;
 
        appending = file->f_flags & O_APPEND ? 1 : 0;
@@ -2330,8 +2330,7 @@ relock:
        }
 
        can_do_direct = direct_io;
-       ret = ocfs2_prepare_inode_for_write(file, ppos,
-                                           iocb->ki_nbytes, appending,
+       ret = ocfs2_prepare_inode_for_write(file, ppos, count, appending,
                                            &can_do_direct, &has_refcount);
        if (ret < 0) {
                mlog_errno(ret);
@@ -2339,8 +2338,7 @@ relock:
        }
 
        if (direct_io && !is_sync_kiocb(iocb))
-               unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_nbytes,
-                                                     *ppos);
+               unaligned_dio = ocfs2_is_io_unaligned(inode, count, *ppos);
 
        /*
         * We can't complete the direct I/O as requested, fall back to
index 21981e58e2a634c09b9ebb9b327860d849fb6b53..2d084f2d0b83c698a7df720c35d2fdbeadb65fcb 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -21,7 +21,6 @@
 #include <linux/audit.h>
 #include <linux/syscalls.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
index 8e1b68786d663d4be5551efcd7b0bf7d5ed8b192..99a6ef946d0182711542b77f17b22bc84cfe7526 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/fcntl.h>
 #include <linux/file.h>
 #include <linux/uio.h>
-#include <linux/aio.h>
 #include <linux/fsnotify.h>
 #include <linux/security.h>
 #include <linux/export.h>
@@ -343,13 +342,10 @@ ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos)
 
        init_sync_kiocb(&kiocb, file);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = iov_iter_count(iter);
 
        iter->type |= READ;
        ret = file->f_op->read_iter(&kiocb, iter);
-       if (ret == -EIOCBQUEUED)
-               ret = wait_on_sync_kiocb(&kiocb);
-
+       BUG_ON(ret == -EIOCBQUEUED);
        if (ret > 0)
                *ppos = kiocb.ki_pos;
        return ret;
@@ -366,13 +362,10 @@ ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos)
 
        init_sync_kiocb(&kiocb, file);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = iov_iter_count(iter);
 
        iter->type |= WRITE;
        ret = file->f_op->write_iter(&kiocb, iter);
-       if (ret == -EIOCBQUEUED)
-               ret = wait_on_sync_kiocb(&kiocb);
-
+       BUG_ON(ret == -EIOCBQUEUED);
        if (ret > 0)
                *ppos = kiocb.ki_pos;
        return ret;
@@ -426,11 +419,9 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
 
        ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
@@ -446,12 +437,10 @@ ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *p
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
        iov_iter_init(&iter, READ, &iov, 1, len);
 
        ret = filp->f_op->read_iter(&kiocb, &iter);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
@@ -510,11 +499,9 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
 
        ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
@@ -530,12 +517,10 @@ ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, lo
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
        iov_iter_init(&iter, WRITE, &iov, 1, len);
 
        ret = filp->f_op->write_iter(&kiocb, &iter);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
@@ -719,12 +704,10 @@ static ssize_t do_iter_readv_writev(struct file *filp, int rw, const struct iove
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
 
        iov_iter_init(&iter, rw, iov, nr_segs, len);
        ret = fn(&kiocb, &iter);
-       if (ret == -EIOCBQUEUED)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
@@ -737,11 +720,9 @@ static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
 
        ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
-       if (ret == -EIOCBQUEUED)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
index e72401e1f9956238064c91805279233a721bffe1..9312b7842e036f64ac02135102b445f0769e7702 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/writeback.h>
 #include <linux/quotaops.h>
 #include <linux/swap.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 int reiserfs_commit_write(struct file *f, struct page *page,
                          unsigned from, unsigned to);
index 7968da96bebbb5d1cd087cbfa2ece65c09cc8b4a..4bbfa95b5bfea8b20aa557cff35c2efd610289da 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/gfp.h>
 #include <linux/socket.h>
 #include <linux/compat.h>
-#include <linux/aio.h>
 #include "internal.h"
 
 /*
index e627c0acf6264f6aabc4b2777ab79214e9c32e64..c3d15fe834033d4d080ea408dbbb961f1e4719c6 100644 (file)
@@ -50,7 +50,6 @@
  */
 
 #include "ubifs.h"
-#include <linux/aio.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/slab.h>
index 08f3555fbeac3f6ceeda033cb8f6ec82557623d0..7f885cc8b0b798dca3239a9f72f87741fd8b023f 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/errno.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -122,7 +122,7 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        int err, pos;
-       size_t count = iocb->ki_nbytes;
+       size_t count = iov_iter_count(from);
        struct udf_inode_info *iinfo = UDF_I(inode);
 
        mutex_lock(&inode->i_mutex);
index a445d599098d7ad1ccace2a81a86a0bc563af391..9c1fbd23913db541c3facc1342614793b1403bfd 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/slab.h>
 #include <linux/crc-itu-t.h>
 #include <linux/mpage.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
index 3a9b7a1b8704be66439ea797dd2183c035a929e5..4f8cdc59bc38154b45f1adfd69c0a371df4394e3 100644 (file)
@@ -31,7 +31,6 @@
 #include "xfs_bmap.h"
 #include "xfs_bmap_util.h"
 #include "xfs_bmap_btree.h"
-#include <linux/aio.h>
 #include <linux/gfp.h>
 #include <linux/mpage.h>
 #include <linux/pagevec.h>
index a2e1cb8a568bf9d45e32c43539a2e6f8b56d83f4..f44212fae65327347db1ba9f8ec1739d30650f44 100644 (file)
@@ -38,7 +38,6 @@
 #include "xfs_icache.h"
 #include "xfs_pnfs.h"
 
-#include <linux/aio.h>
 #include <linux/dcache.h>
 #include <linux/falloc.h>
 #include <linux/pagevec.h>
index d9c92daa3944e43a13f285a7baaa1443868cce3d..9eb42dbc5582ace99283629f0905861ac820c7d5 100644 (file)
@@ -1,86 +1,23 @@
 #ifndef __LINUX__AIO_H
 #define __LINUX__AIO_H
 
-#include <linux/list.h>
-#include <linux/workqueue.h>
 #include <linux/aio_abi.h>
-#include <linux/uio.h>
-#include <linux/rcupdate.h>
-
-#include <linux/atomic.h>
 
 struct kioctx;
 struct kiocb;
+struct mm_struct;
 
 #define KIOCB_KEY              0
 
-/*
- * We use ki_cancel == KIOCB_CANCELLED to indicate that a kiocb has been either
- * cancelled or completed (this makes a certain amount of sense because
- * successful cancellation - io_cancel() - does deliver the completion to
- * userspace).
- *
- * And since most things don't implement kiocb cancellation and we'd really like
- * kiocb completion to be lockless when possible, we use ki_cancel to
- * synchronize cancellation and completion - we only set it to KIOCB_CANCELLED
- * with xchg() or cmpxchg(), see batch_complete_aio() and kiocb_cancel().
- */
-#define KIOCB_CANCELLED                ((void *) (~0ULL))
-
 typedef int (kiocb_cancel_fn)(struct kiocb *);
 
-struct kiocb {
-       struct file             *ki_filp;
-       struct kioctx           *ki_ctx;        /* NULL for sync ops */
-       kiocb_cancel_fn         *ki_cancel;
-       void                    *private;
-
-       union {
-               void __user             *user;
-               struct task_struct      *tsk;
-       } ki_obj;
-
-       __u64                   ki_user_data;   /* user's data for completion */
-       loff_t                  ki_pos;
-       size_t                  ki_nbytes;      /* copy of iocb->aio_nbytes */
-
-       struct list_head        ki_list;        /* the aio core uses this
-                                                * for cancellation */
-
-       /*
-        * If the aio_resfd field of the userspace iocb is not zero,
-        * this is the underlying eventfd context to deliver events to.
-        */
-       struct eventfd_ctx      *ki_eventfd;
-};
-
-static inline bool is_sync_kiocb(struct kiocb *kiocb)
-{
-       return kiocb->ki_ctx == NULL;
-}
-
-static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
-{
-       *kiocb = (struct kiocb) {
-                       .ki_ctx = NULL,
-                       .ki_filp = filp,
-                       .ki_obj.tsk = current,
-               };
-}
-
 /* prototypes */
 #ifdef CONFIG_AIO
-extern ssize_t wait_on_sync_kiocb(struct kiocb *iocb);
-extern void aio_complete(struct kiocb *iocb, long res, long res2);
-struct mm_struct;
 extern void exit_aio(struct mm_struct *mm);
 extern long do_io_submit(aio_context_t ctx_id, long nr,
                         struct iocb __user *__user *iocbpp, bool compat);
 void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
 #else
-static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
-static inline void aio_complete(struct kiocb *iocb, long res, long res2) { }
-struct mm_struct;
 static inline void exit_aio(struct mm_struct *mm) { }
 static inline long do_io_submit(aio_context_t ctx_id, long nr,
                                struct iocb __user * __user *iocbpp,
@@ -89,11 +26,6 @@ static inline void kiocb_set_cancel_fn(struct kiocb *req,
                                       kiocb_cancel_fn *cancel) { }
 #endif /* CONFIG_AIO */
 
-static inline struct kiocb *list_kiocb(struct list_head *h)
-{
-       return list_entry(h, struct kiocb, ki_list);
-}
-
 /* for sysctl: */
 extern unsigned long aio_nr;
 extern unsigned long aio_max_nr;
index f4131e8ead74965a73272949b3a9eae8fa08b5c7..fdce1ddf230cb95a413593978a04c84c02961b3c 100644 (file)
@@ -314,6 +314,28 @@ struct page;
 struct address_space;
 struct writeback_control;
 
+#define IOCB_EVENTFD           (1 << 0)
+
+struct kiocb {
+       struct file             *ki_filp;
+       loff_t                  ki_pos;
+       void (*ki_complete)(struct kiocb *iocb, long ret, long ret2);
+       void                    *private;
+       int                     ki_flags;
+};
+
+static inline bool is_sync_kiocb(struct kiocb *kiocb)
+{
+       return kiocb->ki_complete == NULL;
+}
+
+static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
+{
+       *kiocb = (struct kiocb) {
+               .ki_filp = filp,
+       };
+}
+
 /*
  * "descriptor" for what we're up to with a read.
  * This allows us to use the same read code yet
index e74114bcca686f73517c635320bbdeeddb011770..738ea48be889e670275616bae5063259ca3d61d9 100644 (file)
@@ -211,7 +211,7 @@ int sock_create(int family, int type, int proto, struct socket **res);
 int sock_create_kern(int family, int type, int proto, struct socket **res);
 int sock_create_lite(int family, int type, int proto, struct socket **res);
 void sock_release(struct socket *sock);
-int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len);
+int sock_sendmsg(struct socket *sock, struct msghdr *msg);
 int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
                 int flags);
 struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname);
index c9852ef7e317a6167675f68e7948b6aebea85947..5bf59c8493b763c6dc11ccce18da9c0ac6c0da46 100644 (file)
@@ -139,6 +139,11 @@ static inline struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr
        return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg);
 }
 
+static inline size_t msg_data_left(struct msghdr *msg)
+{
+       return iov_iter_count(&msg->msg_iter);
+}
+
 /* "Socket"-level control message types: */
 
 #define        SCM_RIGHTS      0x01            /* rw: access rights (array of int) */
index 71880299ed487b68dc7b278248a4fb29ddb6b6ec..1f4a37f1f025827c9a561a8e5a856680062227cc 100644 (file)
@@ -139,4 +139,18 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
 size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
 size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
 
+int import_iovec(int type, const struct iovec __user * uvector,
+                unsigned nr_segs, unsigned fast_segs,
+                struct iovec **iov, struct iov_iter *i);
+
+#ifdef CONFIG_COMPAT
+struct compat_iovec;
+int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
+                unsigned nr_segs, unsigned fast_segs,
+                struct iovec **iov, struct iov_iter *i);
+#endif
+
+int import_single_range(int type, void __user *buf, size_t len,
+                struct iovec *iov, struct iov_iter *i);
+
 #endif
index 42a9c8431177c295276068e18967c1bce12e648e..48103cf94e976e9c13809cfec895e9bb1c9fa96c 100644 (file)
@@ -40,7 +40,7 @@ int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
 #define compat_mmsghdr mmsghdr
 #endif /* defined(CONFIG_COMPAT) */
 
-ssize_t get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
+int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
                      struct sockaddr __user **, struct iovec **);
 asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *,
                                   unsigned int);
index bd6f523f2251a9efe255bb11c3d995df2b6f8db2..3a4898ec8c67c5242e9467a0d32f2e68f3a55302 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/page_counter.h>
 #include <linux/memcontrol.h>
 #include <linux/static_key.h>
-#include <linux/aio.h>
 #include <linux/sched.h>
 
 #include <linux/filter.h>
index f2902ef7ab75cdf2f81880b95db6fea4486bd461..4dce116bfd80c81ab09aec171817e082723ad74e 100644 (file)
@@ -47,7 +47,8 @@ struct rxrpc_header {
 #define RXRPC_PACKET_TYPE_CHALLENGE    6       /* connection security challenge (SRVR->CLNT) */
 #define RXRPC_PACKET_TYPE_RESPONSE     7       /* connection secutity response (CLNT->SRVR) */
 #define RXRPC_PACKET_TYPE_DEBUG                8       /* debug info request */
-#define RXRPC_N_PACKET_TYPES           9       /* number of packet types (incl type 0) */
+#define RXRPC_PACKET_TYPE_VERSION      13      /* version string request */
+#define RXRPC_N_PACKET_TYPES           14      /* number of packet types (incl type 0) */
 
        uint8_t         flags;          /* packet flags */
 #define RXRPC_CLIENT_INITIATED 0x01            /* signifies a packet generated by a client */
index bb0635bd74f26a2ecb9f651de9e0c4113e4f2476..879edfc5ee52d2985d4fb925ec820ba6b113d6d0 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/security.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
-#include <linux/aio.h>
 #include <linux/syscalls.h>
 #include <linux/kexec.h>
 #include <linux/kdb.h>
@@ -46,6 +45,7 @@
 #include <linux/irq_work.h>
 #include <linux/utsname.h>
 #include <linux/ctype.h>
+#include <linux/uio.h>
 
 #include <asm/uaccess.h>
 
@@ -521,7 +521,7 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from)
        int i;
        int level = default_message_loglevel;
        int facility = 1;       /* LOG_USER */
-       size_t len = iocb->ki_nbytes;
+       size_t len = iov_iter_count(from);
        ssize_t ret = len;
 
        if (len > LOG_LINE_MAX)
index ce410bb9f2e103e0fcfda7d7b844948a0a28fbce..4012336de30f6fe88688bc0366bba216af72ea9d 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/aio.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
index 9d96e283520cc7f3ec27714dfa4abfcb3800e319..fc6e33f6b7f3376b365c1b04409eb23580b729e2 100644 (file)
@@ -766,3 +766,60 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
                                   flags);
 }
 EXPORT_SYMBOL(dup_iter);
+
+int import_iovec(int type, const struct iovec __user * uvector,
+                unsigned nr_segs, unsigned fast_segs,
+                struct iovec **iov, struct iov_iter *i)
+{
+       ssize_t n;
+       struct iovec *p;
+       n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
+                                 *iov, &p);
+       if (n < 0) {
+               if (p != *iov)
+                       kfree(p);
+               *iov = NULL;
+               return n;
+       }
+       iov_iter_init(i, type, p, nr_segs, n);
+       *iov = p == *iov ? NULL : p;
+       return 0;
+}
+EXPORT_SYMBOL(import_iovec);
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
+                unsigned nr_segs, unsigned fast_segs,
+                struct iovec **iov, struct iov_iter *i)
+{
+       ssize_t n;
+       struct iovec *p;
+       n = compat_rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
+                                 *iov, &p);
+       if (n < 0) {
+               if (p != *iov)
+                       kfree(p);
+               *iov = NULL;
+               return n;
+       }
+       iov_iter_init(i, type, p, nr_segs, n);
+       *iov = p == *iov ? NULL : p;
+       return 0;
+}
+#endif
+
+int import_single_range(int rw, void __user *buf, size_t len,
+                struct iovec *iov, struct iov_iter *i)
+{
+       if (len > MAX_RW_COUNT)
+               len = MAX_RW_COUNT;
+       if (unlikely(!access_ok(!rw, buf, len)))
+               return -EFAULT;
+
+       iov->iov_base = buf;
+       iov->iov_len = len;
+       iov_iter_init(i, rw, iov, 1, len);
+       return 0;
+}
index ad7242043bdb8b74872e536b61d01ca05a1de6b3..876f4e6f3ed6674537e5acad829ac43c7aa8e110 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/compiler.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
-#include <linux/aio.h>
 #include <linux/capability.h>
 #include <linux/kernel_stat.h>
 #include <linux/gfp.h>
index e6045804c8d876db5c480d6c64e3c5f4e7bb7a84..a96c8562d83567466b6633dd169c84ff63418e66 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
 #include <linux/frontswap.h>
-#include <linux/aio.h>
 #include <linux/blkdev.h>
+#include <linux/uio.h>
 #include <asm/pgtable.h>
 
 static struct bio *get_swap_bio(gfp_t gfp_flags,
@@ -274,7 +274,6 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
                iov_iter_bvec(&from, ITER_BVEC | WRITE, &bv, 1, PAGE_SIZE);
                init_sync_kiocb(&kiocb, swap_file);
                kiocb.ki_pos = page_file_offset(page);
-               kiocb.ki_nbytes = PAGE_SIZE;
 
                set_page_writeback(page);
                unlock_page(page);
index cf2d0ca010bc52efd5ea86c7f6ba760a5c3ef286..80b360c7bcd1696a77cf74f44b334ce53d367688 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/mm.h>
 #include <linux/export.h>
 #include <linux/swap.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 static struct vfsmount *shm_mnt;
 
index c4b6b0f43d5d4243d8c35274a4669333bd9f5f25..5cfd26a0006f07d15ee62a5660e0177745f454cf 100644 (file)
 #include <asm/uaccess.h>
 #include <net/compat.h>
 
-ssize_t get_compat_msghdr(struct msghdr *kmsg,
-                         struct compat_msghdr __user *umsg,
-                         struct sockaddr __user **save_addr,
-                         struct iovec **iov)
+int get_compat_msghdr(struct msghdr *kmsg,
+                     struct compat_msghdr __user *umsg,
+                     struct sockaddr __user **save_addr,
+                     struct iovec **iov)
 {
        compat_uptr_t uaddr, uiov, tmp3;
        compat_size_t nr_segs;
@@ -81,13 +81,9 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg,
 
        kmsg->msg_iocb = NULL;
 
-       err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE,
-                                          compat_ptr(uiov), nr_segs,
-                                          UIO_FASTIOV, *iov, iov);
-       if (err >= 0)
-               iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE,
-                             *iov, nr_segs, err);
-       return err;
+       return compat_import_iovec(save_addr ? READ : WRITE,
+                                  compat_ptr(uiov), nr_segs,
+                                  UIO_FASTIOV, iov, &kmsg->msg_iter);
 }
 
 /* Bleech... */
index df493d68330c03d1cb5b59e40d31294d7f45b3f8..b80fb91bb3f7e8dc630663cb5e012dc97ac6924f 100644 (file)
@@ -673,7 +673,7 @@ int skb_copy_and_csum_datagram_msg(struct sk_buff *skb,
        if (!chunk)
                return 0;
 
-       if (iov_iter_count(&msg->msg_iter) < chunk) {
+       if (msg_data_left(msg) < chunk) {
                if (__skb_checksum_complete(skb))
                        goto csum_error;
                if (skb_copy_datagram_msg(skb, hlen, msg, chunk))
index c0bb648fb2f98dc5804e413b211276033465a872..561cd4b8fc6e07b49222d788651e93c42ee3adcb 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/aio.h>
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
index 094a6822c71d8cc69b1be28a9c6bb511f8f8b87b..18e3a12eb1b283bd370bdb4c16f5969e30bcec15 100644 (file)
@@ -1119,7 +1119,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 
        sg = !!(sk->sk_route_caps & NETIF_F_SG);
 
-       while (iov_iter_count(&msg->msg_iter)) {
+       while (msg_data_left(msg)) {
                int copy = 0;
                int max = size_goal;
 
@@ -1163,8 +1163,8 @@ new_segment:
                }
 
                /* Try to append data to the end of skb. */
-               if (copy > iov_iter_count(&msg->msg_iter))
-                       copy = iov_iter_count(&msg->msg_iter);
+               if (copy > msg_data_left(msg))
+                       copy = msg_data_left(msg);
 
                /* Where to copy to? */
                if (skb_availroom(skb) > 0) {
@@ -1221,7 +1221,7 @@ new_segment:
                tcp_skb_pcount_set(skb, 0);
 
                copied += copy;
-               if (!iov_iter_count(&msg->msg_iter)) {
+               if (!msg_data_left(msg)) {
                        tcp_tx_timestamp(sk, skb);
                        goto out;
                }
index 481f89f93789a147fd5979e894e62145f4d9d767..4505a691d88c283bbbd8038c2dd088825015bd32 100644 (file)
@@ -28,7 +28,7 @@
 const char *rxrpc_pkts[] = {
        "?00",
        "DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG",
-       "?09", "?10", "?11", "?12", "?13", "?14", "?15"
+       "?09", "?10", "?11", "?12", "VERSION", "?14", "?15"
 };
 
 /*
@@ -593,6 +593,20 @@ static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
        rxrpc_queue_conn(conn);
 }
 
+/*
+ * post endpoint-level events to the local endpoint
+ * - this includes debug and version messages
+ */
+static void rxrpc_post_packet_to_local(struct rxrpc_local *local,
+                                      struct sk_buff *skb)
+{
+       _enter("%p,%p", local, skb);
+
+       atomic_inc(&local->usage);
+       skb_queue_tail(&local->event_queue, skb);
+       rxrpc_queue_work(&local->event_processor);
+}
+
 static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
                                               struct sk_buff *skb,
                                               struct rxrpc_skb_priv *sp)
@@ -699,6 +713,11 @@ void rxrpc_data_ready(struct sock *sk)
                goto bad_message;
        }
 
+       if (sp->hdr.type == RXRPC_PACKET_TYPE_VERSION) {
+               rxrpc_post_packet_to_local(local, skb);
+               goto out;
+       }
+       
        if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA &&
            (sp->hdr.callNumber == 0 || sp->hdr.seq == 0))
                goto bad_message;
@@ -731,6 +750,8 @@ void rxrpc_data_ready(struct sock *sk)
                else
                        goto cant_route_call;
        }
+
+out:
        rxrpc_put_local(local);
        return;
 
index 2fc1e659e5c9ec1e14ac9bf897988907e9edd1b0..aef1bd294e1796b68052936bdc8d0b62b52814fe 100644 (file)
@@ -152,11 +152,13 @@ struct rxrpc_local {
        struct work_struct      destroyer;      /* endpoint destroyer */
        struct work_struct      acceptor;       /* incoming call processor */
        struct work_struct      rejecter;       /* packet reject writer */
+       struct work_struct      event_processor; /* endpoint event processor */
        struct list_head        services;       /* services listening on this endpoint */
        struct list_head        link;           /* link in endpoint list */
        struct rw_semaphore     defrag_sem;     /* control re-enablement of IP DF bit */
        struct sk_buff_head     accept_queue;   /* incoming calls awaiting acceptance */
        struct sk_buff_head     reject_queue;   /* packets awaiting rejection */
+       struct sk_buff_head     event_queue;    /* endpoint event packets awaiting processing */
        spinlock_t              lock;           /* access lock */
        rwlock_t                services_lock;  /* lock for services list */
        atomic_t                usage;
index 87f7135d238b498f9208543cf4608c1cb78a59d3..ca904ed5400a11bd08e47fea56d0caeb30f0a442 100644 (file)
 #include <linux/net.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
+#include <linux/udp.h>
+#include <linux/ip.h>
 #include <net/sock.h>
 #include <net/af_rxrpc.h>
+#include <generated/utsrelease.h>
 #include "ar-internal.h"
 
+static const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC";
+
 static LIST_HEAD(rxrpc_locals);
 DEFINE_RWLOCK(rxrpc_local_lock);
 static DECLARE_RWSEM(rxrpc_local_sem);
 static DECLARE_WAIT_QUEUE_HEAD(rxrpc_local_wq);
 
 static void rxrpc_destroy_local(struct work_struct *work);
+static void rxrpc_process_local_events(struct work_struct *work);
 
 /*
  * allocate a new local
@@ -37,11 +43,13 @@ struct rxrpc_local *rxrpc_alloc_local(struct sockaddr_rxrpc *srx)
                INIT_WORK(&local->destroyer, &rxrpc_destroy_local);
                INIT_WORK(&local->acceptor, &rxrpc_accept_incoming_calls);
                INIT_WORK(&local->rejecter, &rxrpc_reject_packets);
+               INIT_WORK(&local->event_processor, &rxrpc_process_local_events);
                INIT_LIST_HEAD(&local->services);
                INIT_LIST_HEAD(&local->link);
                init_rwsem(&local->defrag_sem);
                skb_queue_head_init(&local->accept_queue);
                skb_queue_head_init(&local->reject_queue);
+               skb_queue_head_init(&local->event_queue);
                spin_lock_init(&local->lock);
                rwlock_init(&local->services_lock);
                atomic_set(&local->usage, 1);
@@ -264,10 +272,12 @@ static void rxrpc_destroy_local(struct work_struct *work)
        ASSERT(list_empty(&local->services));
        ASSERT(!work_pending(&local->acceptor));
        ASSERT(!work_pending(&local->rejecter));
+       ASSERT(!work_pending(&local->event_processor));
 
        /* finish cleaning up the local descriptor */
        rxrpc_purge_queue(&local->accept_queue);
        rxrpc_purge_queue(&local->reject_queue);
+       rxrpc_purge_queue(&local->event_queue);
        kernel_sock_shutdown(local->socket, SHUT_RDWR);
        sock_release(local->socket);
 
@@ -308,3 +318,91 @@ void __exit rxrpc_destroy_all_locals(void)
 
        _leave("");
 }
+
+/*
+ * Reply to a version request
+ */
+static void rxrpc_send_version_request(struct rxrpc_local *local,
+                                      struct rxrpc_header *hdr,
+                                      struct sk_buff *skb)
+{
+       struct sockaddr_in sin;
+       struct msghdr msg;
+       struct kvec iov[2];
+       size_t len;
+       int ret;
+
+       _enter("");
+
+       sin.sin_family = AF_INET;
+       sin.sin_port = udp_hdr(skb)->source;
+       sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
+
+       msg.msg_name    = &sin;
+       msg.msg_namelen = sizeof(sin);
+       msg.msg_control = NULL;
+       msg.msg_controllen = 0;
+       msg.msg_flags   = 0;
+
+       hdr->seq        = 0;
+       hdr->serial     = 0;
+       hdr->type       = RXRPC_PACKET_TYPE_VERSION;
+       hdr->flags      = RXRPC_LAST_PACKET | (~hdr->flags & RXRPC_CLIENT_INITIATED);
+       hdr->userStatus = 0;
+       hdr->_rsvd      = 0;
+
+       iov[0].iov_base = hdr;
+       iov[0].iov_len  = sizeof(*hdr);
+       iov[1].iov_base = (char *)rxrpc_version_string;
+       iov[1].iov_len  = sizeof(rxrpc_version_string);
+
+       len = iov[0].iov_len + iov[1].iov_len;
+
+       _proto("Tx VERSION (reply)");
+
+       ret = kernel_sendmsg(local->socket, &msg, iov, 2, len);
+       if (ret < 0)
+               _debug("sendmsg failed: %d", ret);
+
+       _leave("");
+}
+
+/*
+ * Process event packets targetted at a local endpoint.
+ */
+static void rxrpc_process_local_events(struct work_struct *work)
+{
+       struct rxrpc_local *local = container_of(work, struct rxrpc_local, event_processor);
+       struct sk_buff *skb;
+       char v;
+
+       _enter("");
+
+       atomic_inc(&local->usage);
+       
+       while ((skb = skb_dequeue(&local->event_queue))) {
+               struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+               kdebug("{%d},{%u}", local->debug_id, sp->hdr.type);
+
+               switch (sp->hdr.type) {
+               case RXRPC_PACKET_TYPE_VERSION:
+                       if (skb_copy_bits(skb, 0, &v, 1) < 0)
+                               return;
+                       _proto("Rx VERSION { %02x }", v);
+                       if (v == 0)
+                               rxrpc_send_version_request(local, &sp->hdr, skb);
+                       break;
+
+               default:
+                       /* Just ignore anything we don't understand */
+                       break;
+               }
+
+               rxrpc_put_local(local);
+               rxrpc_free_skb(skb);
+       }
+
+       rxrpc_put_local(local);
+       _leave("");
+}
index 09f584566e234ba7e53e76a653ee87883f419549..c0042807bfc6a5e2b6e03d70fbcffe097be73326 100644 (file)
@@ -542,11 +542,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
        call->tx_pending = NULL;
 
        copied = 0;
-       if (len > iov_iter_count(&msg->msg_iter))
-               len = iov_iter_count(&msg->msg_iter);
-       while (len) {
-               int copy;
-
+       do {
                if (!skb) {
                        size_t size, chunk, max, space;
 
@@ -568,8 +564,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                        max &= ~(call->conn->size_align - 1UL);
 
                        chunk = max;
-                       if (chunk > len && !more)
-                               chunk = len;
+                       if (chunk > msg_data_left(msg) && !more)
+                               chunk = msg_data_left(msg);
 
                        space = chunk + call->conn->size_align;
                        space &= ~(call->conn->size_align - 1UL);
@@ -612,23 +608,23 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                sp = rxrpc_skb(skb);
 
                /* append next segment of data to the current buffer */
-               copy = skb_tailroom(skb);
-               ASSERTCMP(copy, >, 0);
-               if (copy > len)
-                       copy = len;
-               if (copy > sp->remain)
-                       copy = sp->remain;
-
-               _debug("add");
-               ret = skb_add_data(skb, &msg->msg_iter, copy);
-               _debug("added");
-               if (ret < 0)
-                       goto efault;
-               sp->remain -= copy;
-               skb->mark += copy;
-               copied += copy;
-
-               len -= copy;
+               if (msg_data_left(msg) > 0) {
+                       int copy = skb_tailroom(skb);
+                       ASSERTCMP(copy, >, 0);
+                       if (copy > msg_data_left(msg))
+                               copy = msg_data_left(msg);
+                       if (copy > sp->remain)
+                               copy = sp->remain;
+
+                       _debug("add");
+                       ret = skb_add_data(skb, &msg->msg_iter, copy);
+                       _debug("added");
+                       if (ret < 0)
+                               goto efault;
+                       sp->remain -= copy;
+                       skb->mark += copy;
+                       copied += copy;
+               }
 
                /* check for the far side aborting the call or a network error
                 * occurring */
@@ -636,7 +632,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                        goto call_aborted;
 
                /* add the packet to the send queue if it's now full */
-               if (sp->remain <= 0 || (!len && !more)) {
+               if (sp->remain <= 0 ||
+                   (msg_data_left(msg) == 0 && !more)) {
                        struct rxrpc_connection *conn = call->conn;
                        uint32_t seq;
                        size_t pad;
@@ -666,7 +663,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                        sp->hdr.serviceId = conn->service_id;
 
                        sp->hdr.flags = conn->out_clientflag;
-                       if (len == 0 && !more)
+                       if (msg_data_left(msg) == 0 && !more)
                                sp->hdr.flags |= RXRPC_LAST_PACKET;
                        else if (CIRC_SPACE(call->acks_head, call->acks_tail,
                                            call->acks_winsz) > 1)
@@ -682,10 +679,10 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 
                        memcpy(skb->head, &sp->hdr,
                               sizeof(struct rxrpc_header));
-                       rxrpc_queue_packet(call, skb, !iov_iter_count(&msg->msg_iter) && !more);
+                       rxrpc_queue_packet(call, skb, !msg_data_left(msg) && !more);
                        skb = NULL;
                }
-       }
+       } while (msg_data_left(msg) > 0);
 
 success:
        ret = copied;
index 073809f4125f276799418342f9c60519a3da82e9..5b0126234606dac94152b69fb42a571b1f3cc7bf 100644 (file)
@@ -610,35 +610,27 @@ void __sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags)
 }
 EXPORT_SYMBOL(__sock_tx_timestamp);
 
-static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg,
-                                    size_t size)
+static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
 {
-       return sock->ops->sendmsg(sock, msg, size);
+       int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
+       BUG_ON(ret == -EIOCBQUEUED);
+       return ret;
 }
 
-int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+int sock_sendmsg(struct socket *sock, struct msghdr *msg)
 {
-       int err = security_socket_sendmsg(sock, msg, size);
+       int err = security_socket_sendmsg(sock, msg,
+                                         msg_data_left(msg));
 
-       return err ?: sock_sendmsg_nosec(sock, msg, size);
+       return err ?: sock_sendmsg_nosec(sock, msg);
 }
 EXPORT_SYMBOL(sock_sendmsg);
 
 int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
                   struct kvec *vec, size_t num, size_t size)
 {
-       mm_segment_t oldfs = get_fs();
-       int result;
-
-       set_fs(KERNEL_DS);
-       /*
-        * the following is safe, since for compiler definitions of kvec and
-        * iovec are identical, yielding the same in-core layout and alignment
-        */
-       iov_iter_init(&msg->msg_iter, WRITE, (struct iovec *)vec, num, size);
-       result = sock_sendmsg(sock, msg, size);
-       set_fs(oldfs);
-       return result;
+       iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
+       return sock_sendmsg(sock, msg);
 }
 EXPORT_SYMBOL(kernel_sendmsg);
 
@@ -755,12 +747,8 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
        mm_segment_t oldfs = get_fs();
        int result;
 
+       iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size);
        set_fs(KERNEL_DS);
-       /*
-        * the following is safe, since for compiler definitions of kvec and
-        * iovec are identical, yielding the same in-core layout and alignment
-        */
-       iov_iter_init(&msg->msg_iter, READ, (struct iovec *)vec, num, size);
        result = sock_recvmsg(sock, msg, size, flags);
        set_fs(oldfs);
        return result;
@@ -808,10 +796,10 @@ static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
        if (iocb->ki_pos != 0)
                return -ESPIPE;
 
-       if (iocb->ki_nbytes == 0)       /* Match SYS5 behaviour */
+       if (!iov_iter_count(to))        /* Match SYS5 behaviour */
                return 0;
 
-       res = sock_recvmsg(sock, &msg, iocb->ki_nbytes, msg.msg_flags);
+       res = sock_recvmsg(sock, &msg, iov_iter_count(to), msg.msg_flags);
        *to = msg.msg_iter;
        return res;
 }
@@ -833,7 +821,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (sock->type == SOCK_SEQPACKET)
                msg.msg_flags |= MSG_EOR;
 
-       res = sock_sendmsg(sock, &msg, iocb->ki_nbytes);
+       res = sock_sendmsg(sock, &msg);
        *from = msg.msg_iter;
        return res;
 }
@@ -1650,18 +1638,14 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
        struct iovec iov;
        int fput_needed;
 
-       if (len > INT_MAX)
-               len = INT_MAX;
-       if (unlikely(!access_ok(VERIFY_READ, buff, len)))
-               return -EFAULT;
+       err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
+       if (unlikely(err))
+               return err;
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
 
-       iov.iov_base = buff;
-       iov.iov_len = len;
        msg.msg_name = NULL;
-       iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, len);
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
        msg.msg_namelen = 0;
@@ -1675,7 +1659,7 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
        if (sock->file->f_flags & O_NONBLOCK)
                flags |= MSG_DONTWAIT;
        msg.msg_flags = flags;
-       err = sock_sendmsg(sock, &msg, len);
+       err = sock_sendmsg(sock, &msg);
 
 out_put:
        fput_light(sock->file, fput_needed);
@@ -1710,26 +1694,22 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
        int err, err2;
        int fput_needed;
 
-       if (size > INT_MAX)
-               size = INT_MAX;
-       if (unlikely(!access_ok(VERIFY_WRITE, ubuf, size)))
-               return -EFAULT;
+       err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
+       if (unlikely(err))
+               return err;
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
 
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
-       iov.iov_len = size;
-       iov.iov_base = ubuf;
-       iov_iter_init(&msg.msg_iter, READ, &iov, 1, size);
        /* Save some cycles and don't copy the address if not needed */
        msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
        /* We assume all kernel code knows the size of sockaddr_storage */
        msg.msg_namelen = 0;
        if (sock->file->f_flags & O_NONBLOCK)
                flags |= MSG_DONTWAIT;
-       err = sock_recvmsg(sock, &msg, size, flags);
+       err = sock_recvmsg(sock, &msg, iov_iter_count(&msg.msg_iter), flags);
 
        if (err >= 0 && addr != NULL) {
                err2 = move_addr_to_user(&address,
@@ -1849,10 +1829,10 @@ struct used_address {
        unsigned int name_len;
 };
 
-static ssize_t copy_msghdr_from_user(struct msghdr *kmsg,
-                                    struct user_msghdr __user *umsg,
-                                    struct sockaddr __user **save_addr,
-                                    struct iovec **iov)
+static int copy_msghdr_from_user(struct msghdr *kmsg,
+                                struct user_msghdr __user *umsg,
+                                struct sockaddr __user **save_addr,
+                                struct iovec **iov)
 {
        struct sockaddr __user *uaddr;
        struct iovec __user *uiov;
@@ -1898,13 +1878,8 @@ static ssize_t copy_msghdr_from_user(struct msghdr *kmsg,
 
        kmsg->msg_iocb = NULL;
 
-       err = rw_copy_check_uvector(save_addr ? READ : WRITE,
-                                   uiov, nr_segs,
-                                   UIO_FASTIOV, *iov, iov);
-       if (err >= 0)
-               iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE,
-                             *iov, nr_segs, err);
-       return err;
+       return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs,
+                           UIO_FASTIOV, iov, &kmsg->msg_iter);
 }
 
 static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
@@ -1919,7 +1894,7 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
            __attribute__ ((aligned(sizeof(__kernel_size_t))));
        /* 20 is size of ipv6_pktinfo */
        unsigned char *ctl_buf = ctl;
-       int ctl_len, total_len;
+       int ctl_len;
        ssize_t err;
 
        msg_sys->msg_name = &address;
@@ -1929,8 +1904,7 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
        else
                err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
        if (err < 0)
-               goto out_freeiov;
-       total_len = err;
+               return err;
 
        err = -ENOBUFS;
 
@@ -1977,10 +1951,10 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
            used_address->name_len == msg_sys->msg_namelen &&
            !memcmp(&used_address->name, msg_sys->msg_name,
                    used_address->name_len)) {
-               err = sock_sendmsg_nosec(sock, msg_sys, total_len);
+               err = sock_sendmsg_nosec(sock, msg_sys);
                goto out_freectl;
        }
-       err = sock_sendmsg(sock, msg_sys, total_len);
+       err = sock_sendmsg(sock, msg_sys);
        /*
         * If this is sendmmsg() and sending to current destination address was
         * successful, remember it.
@@ -1996,8 +1970,7 @@ out_freectl:
        if (ctl_buf != ctl)
                sock_kfree_s(sock->sk, ctl_buf, ctl_len);
 out_freeiov:
-       if (iov != iovstack)
-               kfree(iov);
+       kfree(iov);
        return err;
 }
 
@@ -2122,8 +2095,8 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
        else
                err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
        if (err < 0)
-               goto out_freeiov;
-       total_len = err;
+               return err;
+       total_len = iov_iter_count(&msg_sys->msg_iter);
 
        cmsg_ptr = (unsigned long)msg_sys->msg_control;
        msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
@@ -2161,8 +2134,7 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
        err = len;
 
 out_freeiov:
-       if (iov != iovstack)
-               kfree(iov);
+       kfree(iov);
        return err;
 }
 
index cc331b6cf573d95340fddf0ea0e3ae8dd8ae8f3d..0c8120229a0353967138d20c5fe009a1c6e81d1f 100644 (file)
@@ -257,7 +257,7 @@ static int svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr)
 
                svc_set_cmsg_data(rqstp, cmh);
 
-               if (sock_sendmsg(sock, &msg, 0) < 0)
+               if (sock_sendmsg(sock, &msg) < 0)
                        goto out;
        }
 
index 279e24f613051fddb8ca16375ab9031e6a703b03..a69ebc79bc5008e8251c8837a5ea973eb2c458b9 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/pm_qos.h>
-#include <linux/aio.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
 #include <sound/core.h>
@@ -35,6 +34,7 @@
 #include <sound/pcm_params.h>
 #include <sound/timer.h>
 #include <sound/minors.h>
+#include <linux/uio.h>
 
 /*
  *  Compatibility