aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZach Brown <zach.brown@oracle.com>2005-11-13 19:07:33 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-13 21:14:16 -0500
commit20dcae32439384b6863c626bb3b2a09bed65b33e (patch)
tree9750c39119447fb32963448bf1935e1ba22b2f9d
parent4557398f8cbaf9f254cff747534b4724c7f75c4f (diff)
[PATCH] aio: remove kioctx from mm_struct
Sync iocbs have a life cycle that don't need a kioctx. Their retrying, if any, is done in the context of their owner who has allocated them on the stack. The sole user of a sync iocb's ctx reference was aio_complete() checking for an elevated iocb ref count that could never happen. No path which grabs an iocb ref has access to sync iocbs. If we were to implement sync iocb cancelation it would be done by the owner of the iocb using its on-stack reference. Removing this chunk from aio_complete allows us to remove the entire kioctx instance from mm_struct, reducing its size by a third. On a i386 testing box the slab size went from 768 to 504 bytes and from 5 to 8 per page. Signed-off-by: Zach Brown <zach.brown@oracle.com> Acked-by: Benjamin LaHaise <bcrl@kvack.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/aio.c27
-rw-r--r--include/linux/aio.h2
-rw-r--r--include/linux/init_task.h1
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/fork.c1
5 files changed, 10 insertions, 22 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 20bb919eb195..e7cd40b626b7 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -937,28 +937,19 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
937 unsigned long tail; 937 unsigned long tail;
938 int ret; 938 int ret;
939 939
940 /* Special case handling for sync iocbs: events go directly 940 /*
941 * into the iocb for fast handling. Note that this will not 941 * Special case handling for sync iocbs:
942 * work if we allow sync kiocbs to be cancelled. in which 942 * - events go directly into the iocb for fast handling
943 * case the usage count checks will have to move under ctx_lock 943 * - the sync task with the iocb in its stack holds the single iocb
944 * for all cases. 944 * ref, no other paths have a way to get another ref
945 * - the sync task helpfully left a reference to itself in the iocb
945 */ 946 */
946 if (is_sync_kiocb(iocb)) { 947 if (is_sync_kiocb(iocb)) {
947 int ret; 948 BUG_ON(iocb->ki_users != 1);
948
949 iocb->ki_user_data = res; 949 iocb->ki_user_data = res;
950 if (iocb->ki_users == 1) { 950 iocb->ki_users = 0;
951 iocb->ki_users = 0;
952 ret = 1;
953 } else {
954 spin_lock_irq(&ctx->ctx_lock);
955 iocb->ki_users--;
956 ret = (0 == iocb->ki_users);
957 spin_unlock_irq(&ctx->ctx_lock);
958 }
959 /* sync iocbs put the task here for us */
960 wake_up_process(iocb->ki_obj.tsk); 951 wake_up_process(iocb->ki_obj.tsk);
961 return ret; 952 return 1;
962 } 953 }
963 954
964 info = &ctx->ring_info; 955 info = &ctx->ring_info;
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 403d71dcb7c8..9e0ae8711276 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -124,7 +124,7 @@ struct kiocb {
124 (x)->ki_users = 1; \ 124 (x)->ki_users = 1; \
125 (x)->ki_key = KIOCB_SYNC_KEY; \ 125 (x)->ki_key = KIOCB_SYNC_KEY; \
126 (x)->ki_filp = (filp); \ 126 (x)->ki_filp = (filp); \
127 (x)->ki_ctx = &tsk->active_mm->default_kioctx; \ 127 (x)->ki_ctx = NULL; \
128 (x)->ki_cancel = NULL; \ 128 (x)->ki_cancel = NULL; \
129 (x)->ki_dtor = NULL; \ 129 (x)->ki_dtor = NULL; \
130 (x)->ki_obj.tsk = tsk; \ 130 (x)->ki_obj.tsk = tsk; \
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 68ab5f2ab9cd..dcfd2ecccb5d 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -51,7 +51,6 @@
51 .page_table_lock = SPIN_LOCK_UNLOCKED, \ 51 .page_table_lock = SPIN_LOCK_UNLOCKED, \
52 .mmlist = LIST_HEAD_INIT(name.mmlist), \ 52 .mmlist = LIST_HEAD_INIT(name.mmlist), \
53 .cpu_vm_mask = CPU_MASK_ALL, \ 53 .cpu_vm_mask = CPU_MASK_ALL, \
54 .default_kioctx = INIT_KIOCTX(name.default_kioctx, name), \
55} 54}
56 55
57#define INIT_SIGNALS(sig) { \ 56#define INIT_SIGNALS(sig) { \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 41df81395719..2038bd27b041 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -357,7 +357,6 @@ struct mm_struct {
357 /* aio bits */ 357 /* aio bits */
358 rwlock_t ioctx_list_lock; 358 rwlock_t ioctx_list_lock;
359 struct kioctx *ioctx_list; 359 struct kioctx *ioctx_list;
360 struct kioctx default_kioctx;
361}; 360};
362 361
363struct sighand_struct { 362struct sighand_struct {
diff --git a/kernel/fork.c b/kernel/fork.c
index 2c70c9cdf5dc..e0d0b77343f8 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -323,7 +323,6 @@ static struct mm_struct * mm_init(struct mm_struct * mm)
323 spin_lock_init(&mm->page_table_lock); 323 spin_lock_init(&mm->page_table_lock);
324 rwlock_init(&mm->ioctx_list_lock); 324 rwlock_init(&mm->ioctx_list_lock);
325 mm->ioctx_list = NULL; 325 mm->ioctx_list = NULL;
326 mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
327 mm->free_area_cache = TASK_UNMAPPED_BASE; 326 mm->free_area_cache = TASK_UNMAPPED_BASE;
328 mm->cached_hole_size = ~0UL; 327 mm->cached_hole_size = ~0UL;
329 328