diff options
author | Kent Overstreet <koverstreet@google.com> | 2013-01-24 13:14:51 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2013-02-05 16:01:32 +1100 |
commit | ee36f1ec018db6328a39394fd10db5e93c103fb8 (patch) | |
tree | e5fda5740a52305dcbf40474f5c4bcff5e5619d3 | |
parent | fdef28a2eea9cc393dd3768aca7c0a02f225912e (diff) |
aio: smoosh struct kiocb
This patch squishes struct kiocb down to 160 bytes, from 208 previously -
mainly, some of the fields aren't needed until after aio_complete() is
called.
Also, reorder the fields to reduce the amount of memory that has to be
zeroed in aio_get_req(), and to keep members next to each other that are
used in the same place.
Signed-off-by: Kent Overstreet <koverstreet@google.com>
Cc: Zach Brown <zab@redhat.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Asai Thambi S P <asamymuthupa@micron.com>
Cc: Selvan Mani <smani@micron.com>
Cc: Sam Bradshaw <sbradshaw@micron.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Benjamin LaHaise <bcrl@kvack.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-rw-r--r-- | fs/aio.c | 22 | ||||
-rw-r--r-- | include/linux/aio.h | 61 |
2 files changed, 46 insertions, 37 deletions
@@ -573,12 +573,13 @@ static inline struct kiocb *aio_get_req(struct kioctx *ctx) if (!get_reqs_available(ctx)) return NULL; - req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL|__GFP_ZERO); + req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL); if (unlikely(!req)) goto out_put; - atomic_set(&req->ki_users, 1); + memset(req, 0, offsetof(struct kiocb, ki_ctx)); req->ki_ctx = ctx; + atomic_set(&req->ki_users, 1); return req; out_put: put_reqs_available(ctx, 1); @@ -636,8 +637,8 @@ static inline unsigned kioctx_ring_put(struct kioctx *ctx, struct kiocb *req, ev_page = kmap_atomic(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]); event = ev_page + pos % AIO_EVENTS_PER_PAGE; - event->obj = (u64)(unsigned long)req->ki_obj.user; event->data = req->ki_user_data; + event->obj = (u64)(unsigned long)req->ki_obj.user; event->res = req->ki_res; event->res2 = req->ki_res2; @@ -1249,13 +1250,16 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, goto out_put_req; } - req->ki_obj.user = user_iocb; - req->ki_user_data = iocb->aio_data; - req->ki_pos = iocb->aio_offset; + req->ki_user_data = iocb->aio_data; + req->ki_obj.user = user_iocb; - req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf; - req->ki_left = req->ki_nbytes = iocb->aio_nbytes; - req->ki_opcode = iocb->aio_lio_opcode; + req->ki_opcode = iocb->aio_lio_opcode; + req->ki_pos = iocb->aio_offset; + req->ki_nbytes = iocb->aio_nbytes; + req->ki_left = iocb->aio_nbytes; + req->ki_buf = (char __user *) iocb->aio_buf; + req->ki_nr_segs = 0; + req->ki_cur_seg = 0; ret = aio_run_iocb(req, compat); if (ret) diff --git a/include/linux/aio.h b/include/linux/aio.h index 5d333e5172a6..8eaa49037fa7 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -20,45 +20,50 @@ struct batch_complete; typedef int (kiocb_cancel_fn)(struct kiocb *, struct io_event *); struct kiocb { - struct rb_node ki_node; + struct list_head ki_list; /* the aio core uses this + * for cancellation */ + kiocb_cancel_fn *ki_cancel; + void (*ki_dtor)(struct kiocb *); + void *private; + struct iovec *ki_iovec; + + /* + * 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; + struct kioctx *ki_ctx; /* NULL for sync ops */ + struct file *ki_filp; atomic_t ki_users; - struct file *ki_filp; - struct kioctx *ki_ctx; /* NULL for sync ops */ - kiocb_cancel_fn *ki_cancel; - void (*ki_dtor)(struct kiocb *); + /* State that we remember to be able to restart/retry */ + unsigned ki_opcode; + __u64 ki_user_data; /* user's data for completion */ union { void __user *user; struct task_struct *tsk; } ki_obj; - __u64 ki_user_data; /* user's data for completion */ - long ki_res; - long ki_res2; - - loff_t ki_pos; + union { + struct { + loff_t ki_pos; + size_t ki_nbytes; /* copy of iocb->aio_nbytes */ + size_t ki_left; /* remaining bytes */ + char __user *ki_buf; /* remaining iocb->aio_buf */ + unsigned long ki_nr_segs; + unsigned long ki_cur_seg; + }; + + struct { + long ki_res; + long ki_res2; + struct rb_node ki_node; + }; + }; - void *private; - /* State that we remember to be able to restart/retry */ - unsigned short ki_opcode; - size_t ki_nbytes; /* copy of iocb->aio_nbytes */ - char __user *ki_buf; /* remaining iocb->aio_buf */ - size_t ki_left; /* remaining bytes */ struct iovec ki_inline_vec; /* inline vector */ - struct iovec *ki_iovec; - unsigned long ki_nr_segs; - unsigned long ki_cur_seg; - - 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) |