Skip to content

Commit fb2d448

Browse files
committed
aio: report error from io_destroy() when threads race in io_destroy()
As reported by Anatol Pomozov, io_destroy() fails to report an error when it loses the race to destroy a given ioctx. Since there is a difference in behaviour between the thread that wins the race (which blocks on outstanding io requests) versus lthe thread that loses (which returns immediately), wire up a return code from kill_ioctx() to the io_destroy() syscall. Signed-off-by: Benjamin LaHaise <[email protected]> Cc: Anatol Pomozov <[email protected]>
1 parent d52a8f9 commit fb2d448

File tree

1 file changed

+9
-7
lines changed

1 file changed

+9
-7
lines changed

fs/aio.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
727727
* when the processes owning a context have all exited to encourage
728728
* the rapid destruction of the kioctx.
729729
*/
730-
static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
730+
static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
731731
struct completion *requests_done)
732732
{
733733
if (!atomic_xchg(&ctx->dead, 1)) {
@@ -759,10 +759,10 @@ static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
759759

760760
ctx->requests_done = requests_done;
761761
percpu_ref_kill(&ctx->users);
762-
} else {
763-
if (requests_done)
764-
complete(requests_done);
762+
return 0;
765763
}
764+
765+
return -EINVAL;
766766
}
767767

768768
/* wait_on_sync_kiocb:
@@ -1219,21 +1219,23 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
12191219
if (likely(NULL != ioctx)) {
12201220
struct completion requests_done =
12211221
COMPLETION_INITIALIZER_ONSTACK(requests_done);
1222+
int ret;
12221223

12231224
/* Pass requests_done to kill_ioctx() where it can be set
12241225
* in a thread-safe way. If we try to set it here then we have
12251226
* a race condition if two io_destroy() called simultaneously.
12261227
*/
1227-
kill_ioctx(current->mm, ioctx, &requests_done);
1228+
ret = kill_ioctx(current->mm, ioctx, &requests_done);
12281229
percpu_ref_put(&ioctx->users);
12291230

12301231
/* Wait until all IO for the context are done. Otherwise kernel
12311232
* keep using user-space buffers even if user thinks the context
12321233
* is destroyed.
12331234
*/
1234-
wait_for_completion(&requests_done);
1235+
if (!ret)
1236+
wait_for_completion(&requests_done);
12351237

1236-
return 0;
1238+
return ret;
12371239
}
12381240
pr_debug("EINVAL: io_destroy: invalid context id\n");
12391241
return -EINVAL;

0 commit comments

Comments
 (0)