Commit 432c7997 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

aio: separate out ring reservation from req allocation

This is in preparation for certain types of IO not needing a ring
reserveration.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent bc9bff61
...@@ -902,7 +902,7 @@ static void put_reqs_available(struct kioctx *ctx, unsigned nr) ...@@ -902,7 +902,7 @@ static void put_reqs_available(struct kioctx *ctx, unsigned nr)
local_irq_restore(flags); local_irq_restore(flags);
} }
static bool get_reqs_available(struct kioctx *ctx) static bool __get_reqs_available(struct kioctx *ctx)
{ {
struct kioctx_cpu *kcpu; struct kioctx_cpu *kcpu;
bool ret = false; bool ret = false;
...@@ -994,6 +994,14 @@ static void user_refill_reqs_available(struct kioctx *ctx) ...@@ -994,6 +994,14 @@ static void user_refill_reqs_available(struct kioctx *ctx)
spin_unlock_irq(&ctx->completion_lock); spin_unlock_irq(&ctx->completion_lock);
} }
static bool get_reqs_available(struct kioctx *ctx)
{
if (__get_reqs_available(ctx))
return true;
user_refill_reqs_available(ctx);
return __get_reqs_available(ctx);
}
/* aio_get_req /* aio_get_req
* Allocate a slot for an aio request. * Allocate a slot for an aio request.
* Returns NULL if no requests are free. * Returns NULL if no requests are free.
...@@ -1002,24 +1010,15 @@ static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx) ...@@ -1002,24 +1010,15 @@ static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx)
{ {
struct aio_kiocb *req; struct aio_kiocb *req;
if (!get_reqs_available(ctx)) {
user_refill_reqs_available(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|__GFP_ZERO);
if (unlikely(!req)) if (unlikely(!req))
goto out_put; return NULL;
percpu_ref_get(&ctx->reqs); percpu_ref_get(&ctx->reqs);
INIT_LIST_HEAD(&req->ki_list); INIT_LIST_HEAD(&req->ki_list);
refcount_set(&req->ki_refcnt, 0); refcount_set(&req->ki_refcnt, 0);
req->ki_ctx = ctx; req->ki_ctx = ctx;
return req; return req;
out_put:
put_reqs_available(ctx, 1);
return NULL;
} }
static struct kioctx *lookup_ioctx(unsigned long ctx_id) static struct kioctx *lookup_ioctx(unsigned long ctx_id)
...@@ -1807,9 +1806,13 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, ...@@ -1807,9 +1806,13 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
return -EINVAL; return -EINVAL;
} }
if (!get_reqs_available(ctx))
return -EAGAIN;
ret = -EAGAIN;
req = aio_get_req(ctx); req = aio_get_req(ctx);
if (unlikely(!req)) if (unlikely(!req))
return -EAGAIN; goto out_put_reqs_available;
if (iocb.aio_flags & IOCB_FLAG_RESFD) { if (iocb.aio_flags & IOCB_FLAG_RESFD) {
/* /*
...@@ -1872,11 +1875,12 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, ...@@ -1872,11 +1875,12 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
goto out_put_req; goto out_put_req;
return 0; return 0;
out_put_req: out_put_req:
put_reqs_available(ctx, 1);
percpu_ref_put(&ctx->reqs); percpu_ref_put(&ctx->reqs);
if (req->ki_eventfd) if (req->ki_eventfd)
eventfd_ctx_put(req->ki_eventfd); eventfd_ctx_put(req->ki_eventfd);
kmem_cache_free(kiocb_cachep, req); kmem_cache_free(kiocb_cachep, req);
out_put_reqs_available:
put_reqs_available(ctx, 1);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment