X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Faio.c;h=6249313cec8ffd586563bc6cebed56ee441df857;hb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;hp=bc42eb7a76b34acf6e28b321c65f926e05c832e3;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/aio.c b/fs/aio.c index bc42eb7a7..6249313ce 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -15,7 +15,7 @@ #include #include -//#define DEBUG 1 +#define DEBUG 0 #include #include @@ -64,14 +64,9 @@ static void aio_kick_handler(void *); static int __init aio_setup(void) { kiocb_cachep = kmem_cache_create("kiocb", sizeof(struct kiocb), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!kiocb_cachep) - panic("unable to create kiocb cache\n"); - + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); kioctx_cachep = kmem_cache_create("kioctx", sizeof(struct kioctx), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!kioctx_cachep) - panic("unable to create kioctx cache"); + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); aio_wq = create_workqueue("aio"); @@ -399,7 +394,7 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx) req->ki_ctx = ctx; req->ki_cancel = NULL; req->ki_retry = NULL; - req->ki_user_obj = NULL; + req->ki_obj.user = NULL; /* Check if the completion queue has enough free space to * accept an event from this io. @@ -442,7 +437,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) { req->ki_ctx = NULL; req->ki_filp = NULL; - req->ki_user_obj = NULL; + req->ki_obj.user = NULL; kmem_cache_free(kiocb_cachep, req); ctx->reqs_active--; @@ -543,19 +538,25 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id) static void use_mm(struct mm_struct *mm) { - struct mm_struct *active_mm = current->active_mm; + struct mm_struct *active_mm; + atomic_inc(&mm->mm_count); + task_lock(current); + active_mm = current->active_mm; current->mm = mm; if (mm != active_mm) { current->active_mm = mm; activate_mm(active_mm, mm); } + task_unlock(current); mmdrop(active_mm); } static void unuse_mm(struct mm_struct *mm) { + task_lock(current); current->mm = NULL; + task_unlock(current); /* active_mm is still 'mm' */ enter_lazy_tlb(mm, current); } @@ -604,7 +605,7 @@ void fastcall kick_iocb(struct kiocb *iocb) * single context. */ if (is_sync_kiocb(iocb)) { kiocbSetKicked(iocb); - wake_up_process(iocb->ki_user_obj); + wake_up_process(iocb->ki_obj.tsk); return; } @@ -613,7 +614,7 @@ void fastcall kick_iocb(struct kiocb *iocb) spin_lock_irqsave(&ctx->ctx_lock, flags); list_add_tail(&iocb->ki_run_list, &ctx->run_list); spin_unlock_irqrestore(&ctx->ctx_lock, flags); - schedule_work(&ctx->wq); + queue_work(aio_wq, &ctx->wq); } } @@ -652,7 +653,7 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2) spin_unlock_irq(&ctx->ctx_lock); } /* sync iocbs put the task here for us */ - wake_up_process(iocb->ki_user_obj); + wake_up_process(iocb->ki_obj.tsk); return ret; } @@ -672,13 +673,13 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2) event = aio_ring_event(info, tail, KM_IRQ0); tail = (tail + 1) % info->nr; - event->obj = (u64)(unsigned long)iocb->ki_user_obj; + event->obj = (u64)(unsigned long)iocb->ki_obj.user; event->data = iocb->ki_user_data; event->res = res; event->res2 = res2; dprintk("aio_complete: %p[%lu]: %p: %p %Lx %lx %lx\n", - ctx, tail, iocb, iocb->ki_user_obj, iocb->ki_user_data, + ctx, tail, iocb, iocb->ki_obj.user, iocb->ki_user_data, res, res2); /* after flagging the request as done, we @@ -776,24 +777,16 @@ static inline void init_timeout(struct timeout *to) static inline void set_timeout(long start_jiffies, struct timeout *to, const struct timespec *ts) { - unsigned long how_long; - - if (ts->tv_sec < 0 || (!ts->tv_sec && !ts->tv_nsec)) { + to->timer.expires = start_jiffies + timespec_to_jiffies(ts); + if (time_after(to->timer.expires, jiffies)) + add_timer(&to->timer); + else to->timed_out = 1; - return; - } - - how_long = ts->tv_sec * HZ; -#define HZ_NS (1000000000 / HZ) - how_long += (ts->tv_nsec + HZ_NS - 1) / HZ_NS; - - to->timer.expires = jiffies + how_long; - add_timer(&to->timer); } static inline void clear_timeout(struct timeout *to) { - del_timer_sync(&to->timer); + del_singleshot_timer_sync(&to->timer); } static int read_events(struct kioctx *ctx, @@ -939,7 +932,7 @@ static void io_destroy(struct kioctx *ioctx) * pointer is passed for ctxp. Will fail with -ENOSYS if not * implemented. */ -asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t *ctxp) +asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp) { struct kioctx *ioctx = NULL; unsigned long ctx; @@ -961,6 +954,7 @@ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t *ctxp) ret = put_user(ioctx->user_id, ctxp); if (!ret) return 0; + get_ioctx(ioctx); io_destroy(ioctx); } @@ -1028,7 +1022,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, goto out_put_req; } - req->ki_user_obj = user_iocb; + req->ki_obj.user = user_iocb; req->ki_user_data = iocb->aio_data; req->ki_pos = iocb->aio_offset; @@ -1099,7 +1093,7 @@ out_put_req: * fail with -ENOSYS if not implemented. */ asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr, - struct iocb __user **iocbpp) + struct iocb __user * __user *iocbpp) { struct kioctx *ctx; long ret = 0; @@ -1154,7 +1148,7 @@ struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, u32 key /* TODO: use a hash or array, this sucks. */ list_for_each(pos, &ctx->active_reqs) { struct kiocb *kiocb = list_kiocb(pos); - if (kiocb->ki_user_obj == iocb && kiocb->ki_key == key) + if (kiocb->ki_obj.user == iocb && kiocb->ki_key == key) return kiocb; } return NULL; @@ -1201,7 +1195,7 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, struct io_event tmp; pr_debug("calling cancel\n"); memset(&tmp, 0, sizeof(tmp)); - tmp.obj = (u64)(unsigned long)kiocb->ki_user_obj; + tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user; tmp.data = kiocb->ki_user_data; ret = cancel(kiocb, &tmp); if (!ret) {