patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / aio.c
index bc42eb7..6249313 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -15,7 +15,7 @@
 #include <linux/aio_abi.h>
 #include <linux/module.h>
 
-//#define DEBUG 1
+#define DEBUG 0
 
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -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) {