summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <koverstreet@google.com>2013-01-24 13:14:51 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2013-02-05 16:01:32 +1100
commitee36f1ec018db6328a39394fd10db5e93c103fb8 (patch)
treee5fda5740a52305dcbf40474f5c4bcff5e5619d3
parentfdef28a2eea9cc393dd3768aca7c0a02f225912e (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.c22
-rw-r--r--include/linux/aio.h61
2 files changed, 46 insertions, 37 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 53388ed1ae5d..4085fe742ab4 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -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)