#include <linux/aio_abi.h>
#include <linux/module.h>
-//#define DEBUG 1
+#define DEBUG 0
#include <linux/sched.h>
#include <linux/fs.h>
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");
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.
{
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--;
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);
}
* single context. */
if (is_sync_kiocb(iocb)) {
kiocbSetKicked(iocb);
- wake_up_process(iocb->ki_user_obj);
+ wake_up_process(iocb->ki_obj.tsk);
return;
}
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);
}
}
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;
}
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
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,
* 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;
ret = put_user(ioctx->user_id, ctxp);
if (!ret)
return 0;
+ get_ioctx(ioctx);
io_destroy(ioctx);
}
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;
* 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;
/* 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;
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) {