diff options
author | Kent Overstreet <koverstreet@google.com> | 2013-05-07 19:18:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 21:38:28 -0400 |
commit | 906b973cf0ae8f10a6e8182845729b2ecc0da95a (patch) | |
tree | 5114e6ab2158a70aece6f93831add922425a8b50 /fs/aio.c | |
parent | 2d68449e86168744513ca4f13477f081ce167130 (diff) |
aio: add kiocb_cancel()
Minor refactoring, to get rid of some duplicated code
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Kent Overstreet <koverstreet@google.com>
Cc: Zach Brown <zab@redhat.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Asai Thambi S P <asamymuthupa@micron.com>
Cc: Selvan Mani <smani@micron.com>
Cc: Sam Bradshaw <sbradshaw@micron.com>
Acked-by: Jeff Moyer <jmoyer@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Benjamin LaHaise <bcrl@kvack.org>
Reviewed-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/aio.c')
-rw-r--r-- | fs/aio.c | 79 |
1 files changed, 43 insertions, 36 deletions
@@ -220,6 +220,29 @@ static inline void put_ioctx(struct kioctx *kioctx) | |||
220 | __put_ioctx(kioctx); | 220 | __put_ioctx(kioctx); |
221 | } | 221 | } |
222 | 222 | ||
223 | static int kiocb_cancel(struct kioctx *ctx, struct kiocb *kiocb, | ||
224 | struct io_event *res) | ||
225 | { | ||
226 | int (*cancel)(struct kiocb *, struct io_event *); | ||
227 | int ret = -EINVAL; | ||
228 | |||
229 | cancel = kiocb->ki_cancel; | ||
230 | kiocbSetCancelled(kiocb); | ||
231 | if (cancel) { | ||
232 | kiocb->ki_users++; | ||
233 | spin_unlock_irq(&ctx->ctx_lock); | ||
234 | |||
235 | memset(res, 0, sizeof(*res)); | ||
236 | res->obj = (u64)(unsigned long)kiocb->ki_obj.user; | ||
237 | res->data = kiocb->ki_user_data; | ||
238 | ret = cancel(kiocb, res); | ||
239 | |||
240 | spin_lock_irq(&ctx->ctx_lock); | ||
241 | } | ||
242 | |||
243 | return ret; | ||
244 | } | ||
245 | |||
223 | /* ioctx_alloc | 246 | /* ioctx_alloc |
224 | * Allocates and initializes an ioctx. Returns an ERR_PTR if it failed. | 247 | * Allocates and initializes an ioctx. Returns an ERR_PTR if it failed. |
225 | */ | 248 | */ |
@@ -290,25 +313,19 @@ out_freectx: | |||
290 | */ | 313 | */ |
291 | static void kill_ctx(struct kioctx *ctx) | 314 | static void kill_ctx(struct kioctx *ctx) |
292 | { | 315 | { |
293 | int (*cancel)(struct kiocb *, struct io_event *); | ||
294 | struct task_struct *tsk = current; | 316 | struct task_struct *tsk = current; |
295 | DECLARE_WAITQUEUE(wait, tsk); | 317 | DECLARE_WAITQUEUE(wait, tsk); |
296 | struct io_event res; | 318 | struct io_event res; |
319 | struct kiocb *req; | ||
297 | 320 | ||
298 | spin_lock_irq(&ctx->ctx_lock); | 321 | spin_lock_irq(&ctx->ctx_lock); |
299 | ctx->dead = 1; | 322 | ctx->dead = 1; |
300 | while (!list_empty(&ctx->active_reqs)) { | 323 | while (!list_empty(&ctx->active_reqs)) { |
301 | struct list_head *pos = ctx->active_reqs.next; | 324 | req = list_first_entry(&ctx->active_reqs, |
302 | struct kiocb *iocb = list_kiocb(pos); | 325 | struct kiocb, ki_list); |
303 | list_del_init(&iocb->ki_list); | 326 | |
304 | cancel = iocb->ki_cancel; | 327 | list_del_init(&req->ki_list); |
305 | kiocbSetCancelled(iocb); | 328 | kiocb_cancel(ctx, req, &res); |
306 | if (cancel) { | ||
307 | iocb->ki_users++; | ||
308 | spin_unlock_irq(&ctx->ctx_lock); | ||
309 | cancel(iocb, &res); | ||
310 | spin_lock_irq(&ctx->ctx_lock); | ||
311 | } | ||
312 | } | 329 | } |
313 | 330 | ||
314 | if (!ctx->reqs_active) | 331 | if (!ctx->reqs_active) |
@@ -1416,7 +1433,7 @@ static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, | |||
1416 | SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, | 1433 | SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, |
1417 | struct io_event __user *, result) | 1434 | struct io_event __user *, result) |
1418 | { | 1435 | { |
1419 | int (*cancel)(struct kiocb *iocb, struct io_event *res); | 1436 | struct io_event res; |
1420 | struct kioctx *ctx; | 1437 | struct kioctx *ctx; |
1421 | struct kiocb *kiocb; | 1438 | struct kiocb *kiocb; |
1422 | u32 key; | 1439 | u32 key; |
@@ -1431,32 +1448,22 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, | |||
1431 | return -EINVAL; | 1448 | return -EINVAL; |
1432 | 1449 | ||
1433 | spin_lock_irq(&ctx->ctx_lock); | 1450 | spin_lock_irq(&ctx->ctx_lock); |
1434 | ret = -EAGAIN; | 1451 | |
1435 | kiocb = lookup_kiocb(ctx, iocb, key); | 1452 | kiocb = lookup_kiocb(ctx, iocb, key); |
1436 | if (kiocb && kiocb->ki_cancel) { | 1453 | if (kiocb) |
1437 | cancel = kiocb->ki_cancel; | 1454 | ret = kiocb_cancel(ctx, kiocb, &res); |
1438 | kiocb->ki_users ++; | 1455 | else |
1439 | kiocbSetCancelled(kiocb); | 1456 | ret = -EINVAL; |
1440 | } else | 1457 | |
1441 | cancel = NULL; | ||
1442 | spin_unlock_irq(&ctx->ctx_lock); | 1458 | spin_unlock_irq(&ctx->ctx_lock); |
1443 | 1459 | ||
1444 | if (NULL != cancel) { | 1460 | if (!ret) { |
1445 | struct io_event tmp; | 1461 | /* Cancellation succeeded -- copy the result |
1446 | pr_debug("calling cancel\n"); | 1462 | * into the user's buffer. |
1447 | memset(&tmp, 0, sizeof(tmp)); | 1463 | */ |
1448 | tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user; | 1464 | if (copy_to_user(result, &res, sizeof(res))) |
1449 | tmp.data = kiocb->ki_user_data; | 1465 | ret = -EFAULT; |
1450 | ret = cancel(kiocb, &tmp); | 1466 | } |
1451 | if (!ret) { | ||
1452 | /* Cancellation succeeded -- copy the result | ||
1453 | * into the user's buffer. | ||
1454 | */ | ||
1455 | if (copy_to_user(result, &tmp, sizeof(tmp))) | ||
1456 | ret = -EFAULT; | ||
1457 | } | ||
1458 | } else | ||
1459 | ret = -EINVAL; | ||
1460 | 1467 | ||
1461 | put_ioctx(ctx); | 1468 | put_ioctx(ctx); |
1462 | 1469 | ||