Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

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>
This commit is contained in:
David S. Miller 2015-04-13 18:18:05 -04:00
Родитель 789f558cfb 01e97e6517
Коммит 6e8a9d9148
87 изменённых файлов: 493 добавлений и 386 удалений

Просмотреть файл

@ -21,7 +21,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/aio.h> #include <linux/uio.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include "hypfs.h" #include "hypfs.h"

Просмотреть файл

@ -56,8 +56,8 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
ctx->more = 0; ctx->more = 0;
while (iov_iter_count(&msg->msg_iter)) { while (msg_data_left(msg)) {
int len = iov_iter_count(&msg->msg_iter); int len = msg_data_left(msg);
if (len > limit) if (len > limit)
len = limit; len = limit;

Просмотреть файл

@ -106,7 +106,7 @@ static void skcipher_async_cb(struct crypto_async_request *req, int err)
atomic_dec(&ctx->inflight); atomic_dec(&ctx->inflight);
skcipher_free_async_sgls(sreq); skcipher_free_async_sgls(sreq);
kfree(req); kfree(req);
aio_complete(iocb, err, err); iocb->ki_complete(iocb, err, err);
} }
static inline int skcipher_sndbuf(struct sock *sk) 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; long copied = 0;
lock_sock(sk); lock_sock(sk);
while (iov_iter_count(&msg->msg_iter)) { while (msg_data_left(msg)) {
sgl = list_first_entry(&ctx->tsgl, sgl = list_first_entry(&ctx->tsgl,
struct skcipher_sg_list, list); struct skcipher_sg_list, list);
sg = sgl->sg; sg = sgl->sg;
@ -655,7 +655,7 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
goto unlock; 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); used = af_alg_make_sg(&ctx->rsgl, &msg->msg_iter, used);
err = used; err = used;

Просмотреть файл

@ -26,7 +26,7 @@
#include <linux/pfn.h> #include <linux/pfn.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/aio.h> #include <linux/uio.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>

Просмотреть файл

@ -27,7 +27,6 @@
#include <linux/types.h> /* size_t */ #include <linux/types.h> /* size_t */
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */ #include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/aio.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>

Просмотреть файл

@ -40,7 +40,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/aio.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>

Просмотреть файл

@ -39,7 +39,6 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/aio.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <linux/delay.h> #include <linux/delay.h>

Просмотреть файл

@ -19,7 +19,6 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/aio.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/list.h> #include <linux/list.h>

Просмотреть файл

@ -22,7 +22,6 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/aio.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>

Просмотреть файл

@ -21,7 +21,6 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/aio.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>

Просмотреть файл

@ -33,7 +33,6 @@ static int sg_version_num = 30536; /* 2 digits for each component */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/aio.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/mtio.h> #include <linux/mtio.h>
#include <linux/ioctl.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/mutex.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/uio.h>
#include "scsi.h" #include "scsi.h"
#include <scsi/scsi_dbg.h> #include <scsi/scsi_dbg.h>

Просмотреть файл

@ -46,7 +46,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/aio.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>

Просмотреть файл

@ -23,6 +23,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/uio.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/usb/composite.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); 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); eventfd_signal(io_data->ffs->ffs_eventfd, 1);
usb_ep_free_request(io_data->ep, io_data->req); usb_ep_free_request(io_data->ep, io_data->req);

Просмотреть файл

@ -26,6 +26,7 @@
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/mmu_context.h> #include <linux/mmu_context.h>
#include <linux/aio.h> #include <linux/aio.h>
#include <linux/uio.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
@ -469,7 +470,7 @@ static void ep_user_copy_worker(struct work_struct *work)
ret = -EFAULT; ret = -EFAULT;
/* completing the iocb can drop the ctx and mm, don't touch mm after */ /* 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->buf);
kfree(priv->to_free); kfree(priv->to_free);
@ -497,7 +498,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
kfree(priv); kfree(priv);
iocb->private = NULL; iocb->private = NULL;
/* aio_complete() reports bytes-transferred _and_ faults */ /* 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); req->status);
} else { } else {
/* ep_copy_to_user() won't report both; we hide some faults */ /* ep_copy_to_user() won't report both; we hide some faults */

Просмотреть файл

@ -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_init(&msg.msg_iter, WRITE, vq->iov, out, len);
iov_iter_advance(&msg.msg_iter, hdr_size); iov_iter_advance(&msg.msg_iter, hdr_size);
/* Sanity check */ /* Sanity check */
if (!iov_iter_count(&msg.msg_iter)) { if (!msg_data_left(&msg)) {
vq_err(vq, "Unexpected header len for TX: " vq_err(vq, "Unexpected header len for TX: "
"%zd expected %zd\n", "%zd expected %zd\n",
len, hdr_size); len, hdr_size);
break; break;
} }
len = iov_iter_count(&msg.msg_iter); len = msg_data_left(&msg);
zcopy_used = zcopy && len >= VHOST_GOODCOPY_LEN zcopy_used = zcopy && len >= VHOST_GOODCOPY_LEN
&& (nvq->upend_idx + 1) % UIO_MAXIOV != && (nvq->upend_idx + 1) % UIO_MAXIOV !=

Просмотреть файл

@ -33,7 +33,7 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/aio.h> #include <linux/uio.h>
#include <net/9p/9p.h> #include <net/9p/9p.h>
#include <net/9p/client.h> #include <net/9p/client.h>

Просмотреть файл

@ -12,7 +12,7 @@
* affs regular file handling primitives * affs regular file handling primitives
*/ */
#include <linux/aio.h> #include <linux/uio.h>
#include "affs.h" #include "affs.h"
static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext); static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);

Просмотреть файл

@ -22,9 +22,12 @@
int afs_abort_to_error(u32 abort_code) int afs_abort_to_error(u32 abort_code)
{ {
switch (abort_code) { switch (abort_code) {
/* low errno codes inserted into abort namespace */
case 13: return -EACCES; case 13: return -EACCES;
case 27: return -EFBIG; case 27: return -EFBIG;
case 30: return -EROFS; case 30: return -EROFS;
/* VICE "special error" codes; 101 - 111 */
case VSALVAGE: return -EIO; case VSALVAGE: return -EIO;
case VNOVNODE: return -ENOENT; case VNOVNODE: return -ENOENT;
case VNOVOL: return -ENOMEDIUM; case VNOVOL: return -ENOMEDIUM;
@ -36,11 +39,18 @@ int afs_abort_to_error(u32 abort_code)
case VOVERQUOTA: return -EDQUOT; case VOVERQUOTA: return -EDQUOT;
case VBUSY: return -EBUSY; case VBUSY: return -EBUSY;
case VMOVED: return -ENXIO; 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 0x2f6df0c: return -EACCES;
case 0x2f6df0f: return -EBUSY; case 0x2f6df0f: return -EBUSY;
case 0x2f6df10: return -EEXIST; case 0x2f6df10: return -EEXIST;
case 0x2f6df11: return -EXDEV; case 0x2f6df11: return -EXDEV;
case 0x2f6df12: return -ENODEV;
case 0x2f6df13: return -ENOTDIR; case 0x2f6df13: return -ENOTDIR;
case 0x2f6df14: return -EISDIR; case 0x2f6df14: return -EISDIR;
case 0x2f6df15: return -EINVAL; case 0x2f6df15: return -EINVAL;
@ -54,8 +64,12 @@ int afs_abort_to_error(u32 abort_code)
case 0x2f6df23: return -ENAMETOOLONG; case 0x2f6df23: return -ENAMETOOLONG;
case 0x2f6df24: return -ENOLCK; case 0x2f6df24: return -ENOLCK;
case 0x2f6df26: return -ENOTEMPTY; case 0x2f6df26: return -ENOTEMPTY;
case 0x2f6df28: return -EWOULDBLOCK;
case 0x2f6df69: return -ENOTCONN;
case 0x2f6df6c: return -ETIMEDOUT;
case 0x2f6df78: return -EDQUOT; case 0x2f6df78: return -EDQUOT;
/* RXKAD abort codes; from include/rxrpc/packet.h. ET "RXK" == 0x1260B00 */
case RXKADINCONSISTENCY: return -EPROTO; case RXKADINCONSISTENCY: return -EPROTO;
case RXKADPACKETSHORT: return -EPROTO; case RXKADPACKETSHORT: return -EPROTO;
case RXKADLEVELFAIL: return -EKEYREJECTED; case RXKADLEVELFAIL: return -EKEYREJECTED;

Просмотреть файл

@ -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) void afs_send_empty_reply(struct afs_call *call)
{ {
struct msghdr msg; struct msghdr msg;
struct kvec iov[1];
_enter(""); _enter("");
iov[0].iov_base = NULL;
iov[0].iov_len = 0;
msg.msg_name = NULL; msg.msg_name = NULL;
msg.msg_namelen = 0; 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_control = NULL;
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_flags = 0; msg.msg_flags = 0;

Просмотреть файл

@ -14,7 +14,6 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/pagevec.h> #include <linux/pagevec.h>
#include <linux/aio.h>
#include "internal.h" #include "internal.h"
static int afs_write_back_from_locked_page(struct afs_writeback *wb, static int afs_write_back_from_locked_page(struct afs_writeback *wb,

150
fs/aio.c
Просмотреть файл

@ -151,6 +151,38 @@ struct kioctx {
unsigned id; 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----*/ /*------ sysctl variables----*/
static DEFINE_SPINLOCK(aio_nr_lock); static DEFINE_SPINLOCK(aio_nr_lock);
unsigned long aio_nr; /* current system wide number of aio requests */ 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)) if (IS_ERR(aio_mnt))
panic("Failed to create aio fs mount."); 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); kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
pr_debug("sizeof(struct page) = %zu\n", sizeof(struct page)); 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_FIRST_PAGE ((PAGE_SIZE - sizeof(struct aio_ring)) / sizeof(struct io_event))
#define AIO_EVENTS_OFFSET (AIO_EVENTS_PER_PAGE - AIO_EVENTS_FIRST_PAGE) #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; struct kioctx *ctx = req->ki_ctx;
unsigned long flags; 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); 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; kiocb_cancel_fn *old, *cancel;
@ -514,7 +547,7 @@ static int kiocb_cancel(struct kiocb *kiocb)
cancel = cmpxchg(&kiocb->ki_cancel, old, KIOCB_CANCELLED); cancel = cmpxchg(&kiocb->ki_cancel, old, KIOCB_CANCELLED);
} while (cancel != old); } while (cancel != old);
return cancel(kiocb); return cancel(&kiocb->common);
} }
static void free_ioctx(struct work_struct *work) 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) static void free_ioctx_users(struct percpu_ref *ref)
{ {
struct kioctx *ctx = container_of(ref, struct kioctx, users); struct kioctx *ctx = container_of(ref, struct kioctx, users);
struct kiocb *req; struct aio_kiocb *req;
spin_lock_irq(&ctx->ctx_lock); spin_lock_irq(&ctx->ctx_lock);
while (!list_empty(&ctx->active_reqs)) { while (!list_empty(&ctx->active_reqs)) {
req = list_first_entry(&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); list_del_init(&req->ki_list);
kiocb_cancel(req); kiocb_cancel(req);
@ -778,22 +811,6 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
return 0; 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 * 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 * 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. * Allocate a slot for an aio request.
* Returns NULL if no requests are free. * 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)) { if (!get_reqs_available(ctx)) {
user_refill_reqs_available(ctx); user_refill_reqs_available(ctx);
@ -971,10 +988,10 @@ out_put:
return NULL; return NULL;
} }
static void kiocb_free(struct kiocb *req) static void kiocb_free(struct aio_kiocb *req)
{ {
if (req->ki_filp) if (req->common.ki_filp)
fput(req->ki_filp); fput(req->common.ki_filp);
if (req->ki_eventfd != NULL) if (req->ki_eventfd != NULL)
eventfd_ctx_put(req->ki_eventfd); eventfd_ctx_put(req->ki_eventfd);
kmem_cache_free(kiocb_cachep, req); kmem_cache_free(kiocb_cachep, req);
@ -1010,8 +1027,9 @@ out:
/* aio_complete /* aio_complete
* Called when the io request on the given iocb is 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 kioctx *ctx = iocb->ki_ctx;
struct aio_ring *ring; struct aio_ring *ring;
struct io_event *ev_page, *event; 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 * ref, no other paths have a way to get another ref
* - the sync task helpfully left a reference to itself in the iocb * - the sync task helpfully left a reference to itself in the iocb
*/ */
if (is_sync_kiocb(iocb)) { BUG_ON(is_sync_kiocb(kiocb));
iocb->ki_user_data = res;
smp_wmb();
iocb->ki_ctx = ERR_PTR(-EXDEV);
wake_up_process(iocb->ki_obj.tsk);
return;
}
if (iocb->ki_list.next) { if (iocb->ki_list.next) {
unsigned long flags; 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]); ev_page = kmap_atomic(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
event = ev_page + 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->data = iocb->ki_user_data;
event->res = res; event->res = res;
event->res2 = res2; 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]); flush_dcache_page(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
pr_debug("%p[%u]: %p: %p %Lx %lx %lx\n", 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); res, res2);
/* after flagging the request as done, we /* 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); percpu_ref_put(&ctx->reqs);
} }
EXPORT_SYMBOL(aio_complete);
/* aio_read_events_ring /* aio_read_events_ring
* Pull an event off of the ioctx's event ring. Returns the number of * 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, static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
int rw, char __user *buf, int rw, char __user *buf,
unsigned long *nr_segs, unsigned long *nr_segs,
size_t *len,
struct iovec **iovec, struct iovec **iovec,
bool compat) bool compat)
{ {
ssize_t ret; ssize_t ret;
*nr_segs = kiocb->ki_nbytes; *nr_segs = *len;
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
if (compat) if (compat)
@ -1364,21 +1376,22 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
if (ret < 0) if (ret < 0)
return ret; return ret;
/* ki_nbytes now reflect bytes instead of segs */ /* len now reflect bytes instead of segs */
kiocb->ki_nbytes = ret; *len = ret;
return 0; return 0;
} }
static ssize_t aio_setup_single_vector(struct kiocb *kiocb, static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
int rw, char __user *buf, int rw, char __user *buf,
unsigned long *nr_segs, unsigned long *nr_segs,
size_t len,
struct iovec *iovec) struct iovec *iovec)
{ {
if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes))) if (unlikely(!access_ok(!rw, buf, len)))
return -EFAULT; return -EFAULT;
iovec->iov_base = buf; iovec->iov_base = buf;
iovec->iov_len = kiocb->ki_nbytes; iovec->iov_len = len;
*nr_segs = 1; *nr_segs = 1;
return 0; return 0;
} }
@ -1388,7 +1401,7 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
* Performs the initial checks and io submission. * Performs the initial checks and io submission.
*/ */
static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, 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; struct file *file = req->ki_filp;
ssize_t ret; ssize_t ret;
@ -1423,21 +1436,21 @@ rw_common:
if (!rw_op && !iter_op) if (!rw_op && !iter_op)
return -EINVAL; return -EINVAL;
ret = (opcode == IOCB_CMD_PREADV || if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV)
opcode == IOCB_CMD_PWRITEV) ret = aio_setup_vectored_rw(req, rw, buf, &nr_segs,
? aio_setup_vectored_rw(req, rw, buf, &nr_segs, &len, &iovec, compat);
&iovec, compat) else
: aio_setup_single_vector(req, rw, buf, &nr_segs, ret = aio_setup_single_vector(req, rw, buf, &nr_segs,
iovec); len, iovec);
if (!ret) 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 (ret < 0) {
if (iovec != inline_vecs) if (iovec != inline_vecs)
kfree(iovec); kfree(iovec);
return ret; return ret;
} }
req->ki_nbytes = ret; len = ret;
/* XXX: move/kill - rw_verify_area()? */ /* XXX: move/kill - rw_verify_area()? */
/* This matches the pread()/pwrite() logic */ /* This matches the pread()/pwrite() logic */
@ -1450,7 +1463,7 @@ rw_common:
file_start_write(file); file_start_write(file);
if (iter_op) { 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); ret = iter_op(req, &iter);
} else { } else {
ret = rw_op(req, iovec, nr_segs, req->ki_pos); 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, static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
struct iocb *iocb, bool compat) struct iocb *iocb, bool compat)
{ {
struct kiocb *req; struct aio_kiocb *req;
ssize_t ret; ssize_t ret;
/* enforce forwards compatibility on users */ /* 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)) if (unlikely(!req))
return -EAGAIN; return -EAGAIN;
req->ki_filp = fget(iocb->aio_fildes); req->common.ki_filp = fget(iocb->aio_fildes);
if (unlikely(!req->ki_filp)) { if (unlikely(!req->common.ki_filp)) {
ret = -EBADF; ret = -EBADF;
goto out_put_req; 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) { 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; req->ki_eventfd = NULL;
goto out_put_req; goto out_put_req;
} }
req->common.ki_flags |= IOCB_EVENTFD;
} }
ret = put_user(KIOCB_KEY, &user_iocb->aio_key); 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; 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_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, (char __user *)(unsigned long)iocb->aio_buf,
iocb->aio_nbytes,
compat); compat);
if (ret) if (ret)
goto out_put_req; goto out_put_req;
@ -1643,10 +1660,10 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
/* lookup_kiocb /* lookup_kiocb
* Finds a given iocb for cancellation. * Finds a given iocb for cancellation.
*/ */
static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, static struct aio_kiocb *
u32 key) 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); assert_spin_locked(&ctx->ctx_lock);
@ -1654,9 +1671,8 @@ static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
return NULL; return NULL;
/* TODO: use a hash or array, this sucks. */ /* TODO: use a hash or array, this sucks. */
list_for_each(pos, &ctx->active_reqs) { list_for_each_entry(kiocb, &ctx->active_reqs, ki_list) {
struct kiocb *kiocb = list_kiocb(pos); if (kiocb->ki_user_iocb == iocb)
if (kiocb->ki_obj.user == iocb)
return kiocb; return kiocb;
} }
return NULL; 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 io_event __user *, result)
{ {
struct kioctx *ctx; struct kioctx *ctx;
struct kiocb *kiocb; struct aio_kiocb *kiocb;
u32 key; u32 key;
int ret; int ret;

Просмотреть файл

@ -15,6 +15,7 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/uio.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "bfs.h" #include "bfs.h"

Просмотреть файл

@ -27,7 +27,6 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/cleancache.h> #include <linux/cleancache.h>
#include <linux/aio.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "internal.h" #include "internal.h"

Просмотреть файл

@ -24,7 +24,6 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/aio.h>
#include <linux/falloc.h> #include <linux/falloc.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/writeback.h> #include <linux/writeback.h>
@ -32,6 +31,7 @@
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/btrfs.h> #include <linux/btrfs.h>
#include <linux/uio.h>
#include "ctree.h" #include "ctree.h"
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h" #include "transaction.h"

Просмотреть файл

@ -32,7 +32,6 @@
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/statfs.h> #include <linux/statfs.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/aio.h>
#include <linux/bit_spinlock.h> #include <linux/bit_spinlock.h>
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/posix_acl.h> #include <linux/posix_acl.h>
@ -43,6 +42,7 @@
#include <linux/btrfs.h> #include <linux/btrfs.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/posix_acl_xattr.h> #include <linux/posix_acl_xattr.h>
#include <linux/uio.h>
#include "ctree.h" #include "ctree.h"
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h" #include "transaction.h"

Просмотреть файл

@ -7,7 +7,6 @@
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/aio.h>
#include <linux/falloc.h> #include <linux/falloc.h>
#include "super.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 file *filp = iocb->ki_filp;
struct ceph_file_info *fi = filp->private_data; 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 inode *inode = file_inode(filp);
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct page *pinned_page = NULL; struct page *pinned_page = NULL;

Просмотреть файл

@ -37,7 +37,6 @@
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/aio.h>
/* /*
* How many user pages to map in one call to get_user_pages(). This determines * 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; ret = err;
} }
aio_complete(dio->iocb, ret, 0); dio->iocb->ki_complete(dio->iocb, ret, 0);
} }
kmem_cache_free(dio_cache, dio); 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 * 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 * in fact if all the bios race to complete before we get here. In
* that case dio_complete() translates the EIOCBQUEUED into the proper * 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 * 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 * completion paths can drop their ref and use the remaining count to

Просмотреть файл

@ -31,7 +31,6 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/fs_stack.h> #include <linux/fs_stack.h>
#include <linux/aio.h>
#include "ecryptfs_kernel.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; struct file *file = iocb->ki_filp;
rc = generic_file_read_iter(iocb, to); 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) { if (rc >= 0) {
path = ecryptfs_dentry_to_lower_path(file->f_path.dentry); path = ecryptfs_dentry_to_lower_path(file->f_path.dentry);
touch_atime(path); touch_atime(path);

Просмотреть файл

@ -31,7 +31,7 @@
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/fiemap.h> #include <linux/fiemap.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/aio.h> #include <linux/uio.h>
#include "ext2.h" #include "ext2.h"
#include "acl.h" #include "acl.h"
#include "xattr.h" #include "xattr.h"

Просмотреть файл

@ -27,7 +27,7 @@
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/aio.h> #include <linux/uio.h>
#include "ext3.h" #include "ext3.h"
#include "xattr.h" #include "xattr.h"
#include "acl.h" #include "acl.h"

Просмотреть файл

@ -23,9 +23,9 @@
#include <linux/jbd2.h> #include <linux/jbd2.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/path.h> #include <linux/path.h>
#include <linux/aio.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/pagevec.h> #include <linux/pagevec.h>
#include <linux/uio.h>
#include "ext4.h" #include "ext4.h"
#include "ext4_jbd2.h" #include "ext4_jbd2.h"
#include "xattr.h" #include "xattr.h"

Просмотреть файл

@ -20,9 +20,9 @@
* (sct@redhat.com), 1993, 1998 * (sct@redhat.com), 1993, 1998
*/ */
#include <linux/aio.h>
#include "ext4_jbd2.h" #include "ext4_jbd2.h"
#include "truncate.h" #include "truncate.h"
#include <linux/uio.h>
#include <trace/events/ext4.h> #include <trace/events/ext4.h>

Просмотреть файл

@ -37,7 +37,6 @@
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/aio.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include "ext4_jbd2.h" #include "ext4_jbd2.h"

Просмотреть файл

@ -18,7 +18,6 @@
#include <linux/pagevec.h> #include <linux/pagevec.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/aio.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>

Просмотреть файл

@ -12,12 +12,12 @@
#include <linux/f2fs_fs.h> #include <linux/f2fs_fs.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/aio.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/uio.h>
#include "f2fs.h" #include "f2fs.h"
#include "node.h" #include "node.h"

Просмотреть файл

@ -19,7 +19,6 @@
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/aio.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/parser.h> #include <linux/parser.h>
#include <linux/uio.h> #include <linux/uio.h>

Просмотреть файл

@ -38,7 +38,6 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/aio.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/list.h> #include <linux/list.h>
@ -48,6 +47,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/uio.h>
#include "fuse_i.h" #include "fuse_i.h"

Просмотреть файл

@ -19,7 +19,6 @@
#include <linux/pipe_fs_i.h> #include <linux/pipe_fs_i.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/splice.h> #include <linux/splice.h>
#include <linux/aio.h>
MODULE_ALIAS_MISCDEV(FUSE_MINOR); MODULE_ALIAS_MISCDEV(FUSE_MINOR);
MODULE_ALIAS("devname:fuse"); MODULE_ALIAS("devname:fuse");

Просмотреть файл

@ -15,8 +15,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/aio.h>
#include <linux/falloc.h> #include <linux/falloc.h>
#include <linux/uio.h>
static const struct file_operations fuse_direct_io_file_operations; 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 * 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 * 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) 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; int left;
spin_lock(&io->lock); 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; io->bytes = pos;
left = --io->reqs; left = --io->reqs;
if (!left && is_sync)
complete(io->done);
spin_unlock(&io->lock); spin_unlock(&io->lock);
if (!left) { if (!left && !is_sync) {
long res; ssize_t res = fuse_get_res_by_io(io);
if (io->err) if (res >= 0) {
res = io->err; struct inode *inode = file_inode(io->iocb->ki_filp);
else if (io->bytes >= 0 && io->write) struct fuse_conn *fc = get_fuse_conn(inode);
res = -EIO; struct fuse_inode *fi = get_fuse_inode(inode);
else {
res = io->bytes < 0 ? io->size : io->bytes;
if (!is_sync_kiocb(io->iocb)) { spin_lock(&fc->lock);
struct inode *inode = file_inode(io->iocb->ki_filp); fi->attr_version = ++fc->attr_version;
struct fuse_conn *fc = get_fuse_conn(inode); spin_unlock(&fc->lock);
struct fuse_inode *fi = get_fuse_inode(inode);
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); kfree(io);
} }
} }
@ -2801,6 +2807,7 @@ static ssize_t
fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
loff_t offset) loff_t offset)
{ {
DECLARE_COMPLETION_ONSTACK(wait);
ssize_t ret = 0; ssize_t ret = 0;
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct fuse_file *ff = file->private_data; 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) if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE)
io->async = false; io->async = false;
if (io->async && is_sync_kiocb(iocb))
io->done = &wait;
if (rw == WRITE) if (rw == WRITE)
ret = __fuse_direct_write(io, iter, &pos); ret = __fuse_direct_write(io, iter, &pos);
else else
@ -2864,11 +2874,12 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
if (!is_sync_kiocb(iocb)) if (!is_sync_kiocb(iocb))
return -EIOCBQUEUED; return -EIOCBQUEUED;
ret = wait_on_sync_kiocb(iocb); wait_for_completion(&wait);
} else { ret = fuse_get_res_by_io(io);
kfree(io);
} }
kfree(io);
if (rw == WRITE) { if (rw == WRITE) {
if (ret > 0) if (ret > 0)
fuse_write_update_size(inode, pos); fuse_write_update_size(inode, pos);

Просмотреть файл

@ -263,6 +263,7 @@ struct fuse_io_priv {
int err; int err;
struct kiocb *iocb; struct kiocb *iocb;
struct file *file; struct file *file;
struct completion *done;
}; };
/** /**

Просмотреть файл

@ -20,7 +20,7 @@
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/gfs2_ondisk.h> #include <linux/gfs2_ondisk.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/aio.h> #include <linux/uio.h>
#include <trace/events/writeback.h> #include <trace/events/writeback.h>
#include "gfs2.h" #include "gfs2.h"

Просмотреть файл

@ -25,7 +25,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/dlm.h> #include <linux/dlm.h>
#include <linux/dlm_plock.h> #include <linux/dlm_plock.h>
#include <linux/aio.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "gfs2.h" #include "gfs2.h"

Просмотреть файл

@ -14,7 +14,7 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/aio.h> #include <linux/uio.h>
#include "hfs_fs.h" #include "hfs_fs.h"
#include "btree.h" #include "btree.h"

Просмотреть файл

@ -14,7 +14,7 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/aio.h> #include <linux/uio.h>
#include "hfsplus_fs.h" #include "hfsplus_fs.h"
#include "hfsplus_raw.h" #include "hfsplus_raw.h"

Просмотреть файл

@ -22,8 +22,8 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/uio.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/aio.h>
#include "jfs_incore.h" #include "jfs_incore.h"
#include "jfs_inode.h" #include "jfs_inode.h"
#include "jfs_filsys.h" #include "jfs_filsys.h"

Просмотреть файл

@ -265,7 +265,7 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t
return -EINVAL; return -EINVAL;
#else #else
VM_BUG_ON(iocb->ki_nbytes != PAGE_SIZE); VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE);
if (rw == READ) if (rw == READ)
return nfs_file_direct_read(iocb, iter, pos); 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; long res = (long) dreq->error;
if (!res) if (!res)
res = (long) dreq->count; res = (long) dreq->count;
aio_complete(dreq->iocb, res, 0); dreq->iocb->ki_complete(dreq->iocb, res, 0);
} }
complete_all(&dreq->completion); complete_all(&dreq->completion);

Просмотреть файл

@ -26,7 +26,6 @@
#include <linux/nfs_mount.h> #include <linux/nfs_mount.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/aio.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/swap.h> #include <linux/swap.h>

Просмотреть файл

@ -26,7 +26,7 @@
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/aio.h> #include <linux/uio.h>
#include "nilfs.h" #include "nilfs.h"
#include "btnode.h" #include "btnode.h"
#include "segment.h" #include "segment.h"

Просмотреть файл

@ -28,7 +28,6 @@
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/aio.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>

Просмотреть файл

@ -28,7 +28,6 @@
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/aio.h>
#include "aops.h" #include "aops.h"
#include "attrib.h" #include "attrib.h"

Просмотреть файл

@ -29,6 +29,7 @@
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/uio.h>
#include <cluster/masklog.h> #include <cluster/masklog.h>

Просмотреть файл

@ -22,7 +22,7 @@
#ifndef OCFS2_AOPS_H #ifndef OCFS2_AOPS_H
#define 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, handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
struct page *page, struct page *page,

Просмотреть файл

@ -2280,7 +2280,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
file->f_path.dentry->d_name.name, file->f_path.dentry->d_name.name,
(unsigned int)from->nr_segs); /* GRRRRR */ (unsigned int)from->nr_segs); /* GRRRRR */
if (iocb->ki_nbytes == 0) if (count == 0)
return 0; return 0;
appending = file->f_flags & O_APPEND ? 1 : 0; appending = file->f_flags & O_APPEND ? 1 : 0;
@ -2330,8 +2330,7 @@ relock:
} }
can_do_direct = direct_io; can_do_direct = direct_io;
ret = ocfs2_prepare_inode_for_write(file, ppos, ret = ocfs2_prepare_inode_for_write(file, ppos, count, appending,
iocb->ki_nbytes, appending,
&can_do_direct, &has_refcount); &can_do_direct, &has_refcount);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
@ -2339,8 +2338,7 @@ relock:
} }
if (direct_io && !is_sync_kiocb(iocb)) if (direct_io && !is_sync_kiocb(iocb))
unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_nbytes, unaligned_dio = ocfs2_is_io_unaligned(inode, count, *ppos);
*ppos);
/* /*
* We can't complete the direct I/O as requested, fall back to * We can't complete the direct I/O as requested, fall back to

Просмотреть файл

@ -21,7 +21,6 @@
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/aio.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/ioctls.h> #include <asm/ioctls.h>

Просмотреть файл

@ -9,7 +9,6 @@
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/aio.h>
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/export.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); init_sync_kiocb(&kiocb, file);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = iov_iter_count(iter);
iter->type |= READ; iter->type |= READ;
ret = file->f_op->read_iter(&kiocb, iter); ret = file->f_op->read_iter(&kiocb, iter);
if (ret == -EIOCBQUEUED) BUG_ON(ret == -EIOCBQUEUED);
ret = wait_on_sync_kiocb(&kiocb);
if (ret > 0) if (ret > 0)
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; 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); init_sync_kiocb(&kiocb, file);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = iov_iter_count(iter);
iter->type |= WRITE; iter->type |= WRITE;
ret = file->f_op->write_iter(&kiocb, iter); ret = file->f_op->write_iter(&kiocb, iter);
if (ret == -EIOCBQUEUED) BUG_ON(ret == -EIOCBQUEUED);
ret = wait_on_sync_kiocb(&kiocb);
if (ret > 0) if (ret > 0)
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; 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); init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos); ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
if (-EIOCBQUEUED == ret) BUG_ON(ret == -EIOCBQUEUED);
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; 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); init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
iov_iter_init(&iter, READ, &iov, 1, len); iov_iter_init(&iter, READ, &iov, 1, len);
ret = filp->f_op->read_iter(&kiocb, &iter); ret = filp->f_op->read_iter(&kiocb, &iter);
if (-EIOCBQUEUED == ret) BUG_ON(ret == -EIOCBQUEUED);
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; 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); init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos); ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
if (-EIOCBQUEUED == ret) BUG_ON(ret == -EIOCBQUEUED);
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; 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); init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
iov_iter_init(&iter, WRITE, &iov, 1, len); iov_iter_init(&iter, WRITE, &iov, 1, len);
ret = filp->f_op->write_iter(&kiocb, &iter); ret = filp->f_op->write_iter(&kiocb, &iter);
if (-EIOCBQUEUED == ret) BUG_ON(ret == -EIOCBQUEUED);
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; 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); init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
iov_iter_init(&iter, rw, iov, nr_segs, len); iov_iter_init(&iter, rw, iov, nr_segs, len);
ret = fn(&kiocb, &iter); ret = fn(&kiocb, &iter);
if (ret == -EIOCBQUEUED) BUG_ON(ret == -EIOCBQUEUED);
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; 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); init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos); ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
if (ret == -EIOCBQUEUED) BUG_ON(ret == -EIOCBQUEUED);
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; return ret;
} }

Просмотреть файл

@ -18,7 +18,7 @@
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/aio.h> #include <linux/uio.h>
int reiserfs_commit_write(struct file *f, struct page *page, int reiserfs_commit_write(struct file *f, struct page *page,
unsigned from, unsigned to); unsigned from, unsigned to);

Просмотреть файл

@ -32,7 +32,6 @@
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/aio.h>
#include "internal.h" #include "internal.h"
/* /*

Просмотреть файл

@ -50,7 +50,6 @@
*/ */
#include "ubifs.h" #include "ubifs.h"
#include <linux/aio.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/slab.h> #include <linux/slab.h>

Просмотреть файл

@ -34,7 +34,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/aio.h> #include <linux/uio.h>
#include "udf_i.h" #include "udf_i.h"
#include "udf_sb.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 file *file = iocb->ki_filp;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
int err, pos; int err, pos;
size_t count = iocb->ki_nbytes; size_t count = iov_iter_count(from);
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);

Просмотреть файл

@ -38,7 +38,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/crc-itu-t.h> #include <linux/crc-itu-t.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/aio.h> #include <linux/uio.h>
#include "udf_i.h" #include "udf_i.h"
#include "udf_sb.h" #include "udf_sb.h"

Просмотреть файл

@ -31,7 +31,6 @@
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "xfs_bmap_util.h" #include "xfs_bmap_util.h"
#include "xfs_bmap_btree.h" #include "xfs_bmap_btree.h"
#include <linux/aio.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/pagevec.h> #include <linux/pagevec.h>

Просмотреть файл

@ -38,7 +38,6 @@
#include "xfs_icache.h" #include "xfs_icache.h"
#include "xfs_pnfs.h" #include "xfs_pnfs.h"
#include <linux/aio.h>
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/falloc.h> #include <linux/falloc.h>
#include <linux/pagevec.h> #include <linux/pagevec.h>

Просмотреть файл

@ -1,86 +1,23 @@
#ifndef __LINUX__AIO_H #ifndef __LINUX__AIO_H
#define __LINUX__AIO_H #define __LINUX__AIO_H
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/aio_abi.h> #include <linux/aio_abi.h>
#include <linux/uio.h>
#include <linux/rcupdate.h>
#include <linux/atomic.h>
struct kioctx; struct kioctx;
struct kiocb; struct kiocb;
struct mm_struct;
#define KIOCB_KEY 0 #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 *); 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 */ /* prototypes */
#ifdef CONFIG_AIO #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 void exit_aio(struct mm_struct *mm);
extern long do_io_submit(aio_context_t ctx_id, long nr, extern long do_io_submit(aio_context_t ctx_id, long nr,
struct iocb __user *__user *iocbpp, bool compat); struct iocb __user *__user *iocbpp, bool compat);
void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel); void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
#else #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 void exit_aio(struct mm_struct *mm) { }
static inline long do_io_submit(aio_context_t ctx_id, long nr, static inline long do_io_submit(aio_context_t ctx_id, long nr,
struct iocb __user * __user *iocbpp, struct iocb __user * __user *iocbpp,
@ -89,11 +26,6 @@ static inline void kiocb_set_cancel_fn(struct kiocb *req,
kiocb_cancel_fn *cancel) { } kiocb_cancel_fn *cancel) { }
#endif /* CONFIG_AIO */ #endif /* CONFIG_AIO */
static inline struct kiocb *list_kiocb(struct list_head *h)
{
return list_entry(h, struct kiocb, ki_list);
}
/* for sysctl: */ /* for sysctl: */
extern unsigned long aio_nr; extern unsigned long aio_nr;
extern unsigned long aio_max_nr; extern unsigned long aio_max_nr;

Просмотреть файл

@ -314,6 +314,28 @@ struct page;
struct address_space; struct address_space;
struct writeback_control; 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. * "descriptor" for what we're up to with a read.
* This allows us to use the same read code yet * This allows us to use the same read code yet

Просмотреть файл

@ -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_kern(int family, int type, int proto, struct socket **res);
int sock_create_lite(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); 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 sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags); int flags);
struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname); struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname);

Просмотреть файл

@ -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); 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: */ /* "Socket"-level control message types: */
#define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */ #define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */

Просмотреть файл

@ -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_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); 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 #endif

Просмотреть файл

@ -40,7 +40,7 @@ int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
#define compat_mmsghdr mmsghdr #define compat_mmsghdr mmsghdr
#endif /* defined(CONFIG_COMPAT) */ #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 **); struct sockaddr __user **, struct iovec **);
asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *, asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *,
unsigned int); unsigned int);

Просмотреть файл

@ -57,7 +57,6 @@
#include <linux/page_counter.h> #include <linux/page_counter.h>
#include <linux/memcontrol.h> #include <linux/memcontrol.h>
#include <linux/static_key.h> #include <linux/static_key.h>
#include <linux/aio.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/filter.h> #include <linux/filter.h>

Просмотреть файл

@ -47,7 +47,8 @@ struct rxrpc_header {
#define RXRPC_PACKET_TYPE_CHALLENGE 6 /* connection security challenge (SRVR->CLNT) */ #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_RESPONSE 7 /* connection secutity response (CLNT->SRVR) */
#define RXRPC_PACKET_TYPE_DEBUG 8 /* debug info request */ #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 */ uint8_t flags; /* packet flags */
#define RXRPC_CLIENT_INITIATED 0x01 /* signifies a packet generated by a client */ #define RXRPC_CLIENT_INITIATED 0x01 /* signifies a packet generated by a client */

Просмотреть файл

@ -32,7 +32,6 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/aio.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/kdb.h> #include <linux/kdb.h>
@ -46,6 +45,7 @@
#include <linux/irq_work.h> #include <linux/irq_work.h>
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/uio.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
@ -521,7 +521,7 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from)
int i; int i;
int level = default_message_loglevel; int level = default_message_loglevel;
int facility = 1; /* LOG_USER */ int facility = 1; /* LOG_USER */
size_t len = iocb->ki_nbytes; size_t len = iov_iter_count(from);
ssize_t ret = len; ssize_t ret = len;
if (len > LOG_LINE_MAX) if (len > LOG_LINE_MAX)

Просмотреть файл

@ -19,6 +19,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/aio.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/slab.h> #include <linux/slab.h>

Просмотреть файл

@ -766,3 +766,60 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
flags); flags);
} }
EXPORT_SYMBOL(dup_iter); 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;
}

Просмотреть файл

@ -13,7 +13,6 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/aio.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/gfp.h> #include <linux/gfp.h>

Просмотреть файл

@ -20,8 +20,8 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/frontswap.h> #include <linux/frontswap.h>
#include <linux/aio.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/uio.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
static struct bio *get_swap_bio(gfp_t gfp_flags, 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); iov_iter_bvec(&from, ITER_BVEC | WRITE, &bv, 1, PAGE_SIZE);
init_sync_kiocb(&kiocb, swap_file); init_sync_kiocb(&kiocb, swap_file);
kiocb.ki_pos = page_file_offset(page); kiocb.ki_pos = page_file_offset(page);
kiocb.ki_nbytes = PAGE_SIZE;
set_page_writeback(page); set_page_writeback(page);
unlock_page(page); unlock_page(page);

Просмотреть файл

@ -31,7 +31,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/aio.h> #include <linux/uio.h>
static struct vfsmount *shm_mnt; static struct vfsmount *shm_mnt;

Просмотреть файл

@ -31,10 +31,10 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <net/compat.h> #include <net/compat.h>
ssize_t get_compat_msghdr(struct msghdr *kmsg, int get_compat_msghdr(struct msghdr *kmsg,
struct compat_msghdr __user *umsg, struct compat_msghdr __user *umsg,
struct sockaddr __user **save_addr, struct sockaddr __user **save_addr,
struct iovec **iov) struct iovec **iov)
{ {
compat_uptr_t uaddr, uiov, tmp3; compat_uptr_t uaddr, uiov, tmp3;
compat_size_t nr_segs; compat_size_t nr_segs;
@ -81,13 +81,9 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg,
kmsg->msg_iocb = NULL; kmsg->msg_iocb = NULL;
err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE, return compat_import_iovec(save_addr ? READ : WRITE,
compat_ptr(uiov), nr_segs, compat_ptr(uiov), nr_segs,
UIO_FASTIOV, *iov, iov); UIO_FASTIOV, iov, &kmsg->msg_iter);
if (err >= 0)
iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE,
*iov, nr_segs, err);
return err;
} }
/* Bleech... */ /* Bleech... */

Просмотреть файл

@ -673,7 +673,7 @@ int skb_copy_and_csum_datagram_msg(struct sk_buff *skb,
if (!chunk) if (!chunk)
return 0; return 0;
if (iov_iter_count(&msg->msg_iter) < chunk) { if (msg_data_left(msg) < chunk) {
if (__skb_checksum_complete(skb)) if (__skb_checksum_complete(skb))
goto csum_error; goto csum_error;
if (skb_copy_datagram_msg(skb, hlen, msg, chunk)) if (skb_copy_datagram_msg(skb, hlen, msg, chunk))

Просмотреть файл

@ -46,7 +46,6 @@
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/aio.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>

Просмотреть файл

@ -1119,7 +1119,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
sg = !!(sk->sk_route_caps & NETIF_F_SG); sg = !!(sk->sk_route_caps & NETIF_F_SG);
while (iov_iter_count(&msg->msg_iter)) { while (msg_data_left(msg)) {
int copy = 0; int copy = 0;
int max = size_goal; int max = size_goal;
@ -1163,8 +1163,8 @@ new_segment:
} }
/* Try to append data to the end of skb. */ /* Try to append data to the end of skb. */
if (copy > iov_iter_count(&msg->msg_iter)) if (copy > msg_data_left(msg))
copy = iov_iter_count(&msg->msg_iter); copy = msg_data_left(msg);
/* Where to copy to? */ /* Where to copy to? */
if (skb_availroom(skb) > 0) { if (skb_availroom(skb) > 0) {
@ -1221,7 +1221,7 @@ new_segment:
tcp_skb_pcount_set(skb, 0); tcp_skb_pcount_set(skb, 0);
copied += copy; copied += copy;
if (!iov_iter_count(&msg->msg_iter)) { if (!msg_data_left(msg)) {
tcp_tx_timestamp(sk, skb); tcp_tx_timestamp(sk, skb);
goto out; goto out;
} }

Просмотреть файл

@ -28,7 +28,7 @@
const char *rxrpc_pkts[] = { const char *rxrpc_pkts[] = {
"?00", "?00",
"DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG", "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); 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, static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
struct sk_buff *skb, struct sk_buff *skb,
struct rxrpc_skb_priv *sp) struct rxrpc_skb_priv *sp)
@ -699,6 +713,11 @@ void rxrpc_data_ready(struct sock *sk)
goto bad_message; 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 && if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA &&
(sp->hdr.callNumber == 0 || sp->hdr.seq == 0)) (sp->hdr.callNumber == 0 || sp->hdr.seq == 0))
goto bad_message; goto bad_message;
@ -731,6 +750,8 @@ void rxrpc_data_ready(struct sock *sk)
else else
goto cant_route_call; goto cant_route_call;
} }
out:
rxrpc_put_local(local); rxrpc_put_local(local);
return; return;

Просмотреть файл

@ -152,11 +152,13 @@ struct rxrpc_local {
struct work_struct destroyer; /* endpoint destroyer */ struct work_struct destroyer; /* endpoint destroyer */
struct work_struct acceptor; /* incoming call processor */ struct work_struct acceptor; /* incoming call processor */
struct work_struct rejecter; /* packet reject writer */ 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 services; /* services listening on this endpoint */
struct list_head link; /* link in endpoint list */ struct list_head link; /* link in endpoint list */
struct rw_semaphore defrag_sem; /* control re-enablement of IP DF bit */ 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 accept_queue; /* incoming calls awaiting acceptance */
struct sk_buff_head reject_queue; /* packets awaiting rejection */ 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 */ spinlock_t lock; /* access lock */
rwlock_t services_lock; /* lock for services list */ rwlock_t services_lock; /* lock for services list */
atomic_t usage; atomic_t usage;

Просмотреть файл

@ -13,16 +13,22 @@
#include <linux/net.h> #include <linux/net.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/udp.h>
#include <linux/ip.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/af_rxrpc.h> #include <net/af_rxrpc.h>
#include <generated/utsrelease.h>
#include "ar-internal.h" #include "ar-internal.h"
static const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC";
static LIST_HEAD(rxrpc_locals); static LIST_HEAD(rxrpc_locals);
DEFINE_RWLOCK(rxrpc_local_lock); DEFINE_RWLOCK(rxrpc_local_lock);
static DECLARE_RWSEM(rxrpc_local_sem); static DECLARE_RWSEM(rxrpc_local_sem);
static DECLARE_WAIT_QUEUE_HEAD(rxrpc_local_wq); static DECLARE_WAIT_QUEUE_HEAD(rxrpc_local_wq);
static void rxrpc_destroy_local(struct work_struct *work); static void rxrpc_destroy_local(struct work_struct *work);
static void rxrpc_process_local_events(struct work_struct *work);
/* /*
* allocate a new local * 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->destroyer, &rxrpc_destroy_local);
INIT_WORK(&local->acceptor, &rxrpc_accept_incoming_calls); INIT_WORK(&local->acceptor, &rxrpc_accept_incoming_calls);
INIT_WORK(&local->rejecter, &rxrpc_reject_packets); 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->services);
INIT_LIST_HEAD(&local->link); INIT_LIST_HEAD(&local->link);
init_rwsem(&local->defrag_sem); init_rwsem(&local->defrag_sem);
skb_queue_head_init(&local->accept_queue); skb_queue_head_init(&local->accept_queue);
skb_queue_head_init(&local->reject_queue); skb_queue_head_init(&local->reject_queue);
skb_queue_head_init(&local->event_queue);
spin_lock_init(&local->lock); spin_lock_init(&local->lock);
rwlock_init(&local->services_lock); rwlock_init(&local->services_lock);
atomic_set(&local->usage, 1); atomic_set(&local->usage, 1);
@ -264,10 +272,12 @@ static void rxrpc_destroy_local(struct work_struct *work)
ASSERT(list_empty(&local->services)); ASSERT(list_empty(&local->services));
ASSERT(!work_pending(&local->acceptor)); ASSERT(!work_pending(&local->acceptor));
ASSERT(!work_pending(&local->rejecter)); ASSERT(!work_pending(&local->rejecter));
ASSERT(!work_pending(&local->event_processor));
/* finish cleaning up the local descriptor */ /* finish cleaning up the local descriptor */
rxrpc_purge_queue(&local->accept_queue); rxrpc_purge_queue(&local->accept_queue);
rxrpc_purge_queue(&local->reject_queue); rxrpc_purge_queue(&local->reject_queue);
rxrpc_purge_queue(&local->event_queue);
kernel_sock_shutdown(local->socket, SHUT_RDWR); kernel_sock_shutdown(local->socket, SHUT_RDWR);
sock_release(local->socket); sock_release(local->socket);
@ -308,3 +318,91 @@ void __exit rxrpc_destroy_all_locals(void)
_leave(""); _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("");
}

Просмотреть файл

@ -542,11 +542,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
call->tx_pending = NULL; call->tx_pending = NULL;
copied = 0; copied = 0;
if (len > iov_iter_count(&msg->msg_iter)) do {
len = iov_iter_count(&msg->msg_iter);
while (len) {
int copy;
if (!skb) { if (!skb) {
size_t size, chunk, max, space; 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); max &= ~(call->conn->size_align - 1UL);
chunk = max; chunk = max;
if (chunk > len && !more) if (chunk > msg_data_left(msg) && !more)
chunk = len; chunk = msg_data_left(msg);
space = chunk + call->conn->size_align; space = chunk + call->conn->size_align;
space &= ~(call->conn->size_align - 1UL); space &= ~(call->conn->size_align - 1UL);
@ -612,23 +608,23 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
sp = rxrpc_skb(skb); sp = rxrpc_skb(skb);
/* append next segment of data to the current buffer */ /* append next segment of data to the current buffer */
copy = skb_tailroom(skb); if (msg_data_left(msg) > 0) {
ASSERTCMP(copy, >, 0); int copy = skb_tailroom(skb);
if (copy > len) ASSERTCMP(copy, >, 0);
copy = len; if (copy > msg_data_left(msg))
if (copy > sp->remain) copy = msg_data_left(msg);
copy = sp->remain; if (copy > sp->remain)
copy = sp->remain;
_debug("add"); _debug("add");
ret = skb_add_data(skb, &msg->msg_iter, copy); ret = skb_add_data(skb, &msg->msg_iter, copy);
_debug("added"); _debug("added");
if (ret < 0) if (ret < 0)
goto efault; goto efault;
sp->remain -= copy; sp->remain -= copy;
skb->mark += copy; skb->mark += copy;
copied += copy; copied += copy;
}
len -= copy;
/* check for the far side aborting the call or a network error /* check for the far side aborting the call or a network error
* occurring */ * occurring */
@ -636,7 +632,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
goto call_aborted; goto call_aborted;
/* add the packet to the send queue if it's now full */ /* 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; struct rxrpc_connection *conn = call->conn;
uint32_t seq; uint32_t seq;
size_t pad; size_t pad;
@ -666,7 +663,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
sp->hdr.serviceId = conn->service_id; sp->hdr.serviceId = conn->service_id;
sp->hdr.flags = conn->out_clientflag; sp->hdr.flags = conn->out_clientflag;
if (len == 0 && !more) if (msg_data_left(msg) == 0 && !more)
sp->hdr.flags |= RXRPC_LAST_PACKET; sp->hdr.flags |= RXRPC_LAST_PACKET;
else if (CIRC_SPACE(call->acks_head, call->acks_tail, else if (CIRC_SPACE(call->acks_head, call->acks_tail,
call->acks_winsz) > 1) call->acks_winsz) > 1)
@ -682,10 +679,10 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
memcpy(skb->head, &sp->hdr, memcpy(skb->head, &sp->hdr,
sizeof(struct rxrpc_header)); 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; skb = NULL;
} }
} } while (msg_data_left(msg) > 0);
success: success:
ret = copied; ret = copied;

Просмотреть файл

@ -610,35 +610,27 @@ void __sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags)
} }
EXPORT_SYMBOL(__sock_tx_timestamp); EXPORT_SYMBOL(__sock_tx_timestamp);
static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
size_t size)
{ {
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); EXPORT_SYMBOL(sock_sendmsg);
int kernel_sendmsg(struct socket *sock, struct msghdr *msg, int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
struct kvec *vec, size_t num, size_t size) struct kvec *vec, size_t num, size_t size)
{ {
mm_segment_t oldfs = get_fs(); iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
int result; return sock_sendmsg(sock, msg);
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;
} }
EXPORT_SYMBOL(kernel_sendmsg); EXPORT_SYMBOL(kernel_sendmsg);
@ -755,12 +747,8 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
mm_segment_t oldfs = get_fs(); mm_segment_t oldfs = get_fs();
int result; int result;
iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size);
set_fs(KERNEL_DS); 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); result = sock_recvmsg(sock, msg, size, flags);
set_fs(oldfs); set_fs(oldfs);
return result; return result;
@ -808,10 +796,10 @@ static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
if (iocb->ki_pos != 0) if (iocb->ki_pos != 0)
return -ESPIPE; return -ESPIPE;
if (iocb->ki_nbytes == 0) /* Match SYS5 behaviour */ if (!iov_iter_count(to)) /* Match SYS5 behaviour */
return 0; 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; *to = msg.msg_iter;
return res; return res;
} }
@ -833,7 +821,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (sock->type == SOCK_SEQPACKET) if (sock->type == SOCK_SEQPACKET)
msg.msg_flags |= MSG_EOR; msg.msg_flags |= MSG_EOR;
res = sock_sendmsg(sock, &msg, iocb->ki_nbytes); res = sock_sendmsg(sock, &msg);
*from = msg.msg_iter; *from = msg.msg_iter;
return res; return res;
} }
@ -1650,18 +1638,14 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
struct iovec iov; struct iovec iov;
int fput_needed; int fput_needed;
if (len > INT_MAX) err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
len = INT_MAX; if (unlikely(err))
if (unlikely(!access_ok(VERIFY_READ, buff, len))) return err;
return -EFAULT;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock) if (!sock)
goto out; goto out;
iov.iov_base = buff;
iov.iov_len = len;
msg.msg_name = NULL; msg.msg_name = NULL;
iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, len);
msg.msg_control = NULL; msg.msg_control = NULL;
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_namelen = 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) if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT; flags |= MSG_DONTWAIT;
msg.msg_flags = flags; msg.msg_flags = flags;
err = sock_sendmsg(sock, &msg, len); err = sock_sendmsg(sock, &msg);
out_put: out_put:
fput_light(sock->file, fput_needed); 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 err, err2;
int fput_needed; int fput_needed;
if (size > INT_MAX) err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
size = INT_MAX; if (unlikely(err))
if (unlikely(!access_ok(VERIFY_WRITE, ubuf, size))) return err;
return -EFAULT;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock) if (!sock)
goto out; goto out;
msg.msg_control = NULL; msg.msg_control = NULL;
msg.msg_controllen = 0; 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 */ /* Save some cycles and don't copy the address if not needed */
msg.msg_name = addr ? (struct sockaddr *)&address : NULL; msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
/* We assume all kernel code knows the size of sockaddr_storage */ /* We assume all kernel code knows the size of sockaddr_storage */
msg.msg_namelen = 0; msg.msg_namelen = 0;
if (sock->file->f_flags & O_NONBLOCK) if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT; 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) { if (err >= 0 && addr != NULL) {
err2 = move_addr_to_user(&address, err2 = move_addr_to_user(&address,
@ -1849,10 +1829,10 @@ struct used_address {
unsigned int name_len; unsigned int name_len;
}; };
static ssize_t copy_msghdr_from_user(struct msghdr *kmsg, static int copy_msghdr_from_user(struct msghdr *kmsg,
struct user_msghdr __user *umsg, struct user_msghdr __user *umsg,
struct sockaddr __user **save_addr, struct sockaddr __user **save_addr,
struct iovec **iov) struct iovec **iov)
{ {
struct sockaddr __user *uaddr; struct sockaddr __user *uaddr;
struct iovec __user *uiov; struct iovec __user *uiov;
@ -1898,13 +1878,8 @@ static ssize_t copy_msghdr_from_user(struct msghdr *kmsg,
kmsg->msg_iocb = NULL; kmsg->msg_iocb = NULL;
err = rw_copy_check_uvector(save_addr ? READ : WRITE, return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs,
uiov, nr_segs, UIO_FASTIOV, iov, &kmsg->msg_iter);
UIO_FASTIOV, *iov, iov);
if (err >= 0)
iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE,
*iov, nr_segs, err);
return err;
} }
static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, 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)))); __attribute__ ((aligned(sizeof(__kernel_size_t))));
/* 20 is size of ipv6_pktinfo */ /* 20 is size of ipv6_pktinfo */
unsigned char *ctl_buf = ctl; unsigned char *ctl_buf = ctl;
int ctl_len, total_len; int ctl_len;
ssize_t err; ssize_t err;
msg_sys->msg_name = &address; msg_sys->msg_name = &address;
@ -1929,8 +1904,7 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
else else
err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov); err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
if (err < 0) if (err < 0)
goto out_freeiov; return err;
total_len = err;
err = -ENOBUFS; 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 && used_address->name_len == msg_sys->msg_namelen &&
!memcmp(&used_address->name, msg_sys->msg_name, !memcmp(&used_address->name, msg_sys->msg_name,
used_address->name_len)) { used_address->name_len)) {
err = sock_sendmsg_nosec(sock, msg_sys, total_len); err = sock_sendmsg_nosec(sock, msg_sys);
goto out_freectl; 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 * If this is sendmmsg() and sending to current destination address was
* successful, remember it. * successful, remember it.
@ -1996,8 +1970,7 @@ out_freectl:
if (ctl_buf != ctl) if (ctl_buf != ctl)
sock_kfree_s(sock->sk, ctl_buf, ctl_len); sock_kfree_s(sock->sk, ctl_buf, ctl_len);
out_freeiov: out_freeiov:
if (iov != iovstack) kfree(iov);
kfree(iov);
return err; return err;
} }
@ -2122,8 +2095,8 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
else else
err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov); err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
if (err < 0) if (err < 0)
goto out_freeiov; return err;
total_len = err; total_len = iov_iter_count(&msg_sys->msg_iter);
cmsg_ptr = (unsigned long)msg_sys->msg_control; cmsg_ptr = (unsigned long)msg_sys->msg_control;
msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 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; err = len;
out_freeiov: out_freeiov:
if (iov != iovstack) kfree(iov);
kfree(iov);
return err; return err;
} }

Просмотреть файл

@ -257,7 +257,7 @@ static int svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr)
svc_set_cmsg_data(rqstp, cmh); svc_set_cmsg_data(rqstp, cmh);
if (sock_sendmsg(sock, &msg, 0) < 0) if (sock_sendmsg(sock, &msg) < 0)
goto out; goto out;
} }

Просмотреть файл

@ -25,7 +25,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/pm_qos.h> #include <linux/pm_qos.h>
#include <linux/aio.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <sound/core.h> #include <sound/core.h>
@ -35,6 +34,7 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/timer.h> #include <sound/timer.h>
#include <sound/minors.h> #include <sound/minors.h>
#include <linux/uio.h>
/* /*
* Compatibility * Compatibility