Skip to content

Commit da90382

Browse files
committed
aio: fix error handling and rcu usage in "convert the ioctx list to table lookup v3"
In the patch "aio: convert the ioctx list to table lookup v3", incorrect handling in the ioctx_alloc() error path was introduced that lead to an ioctx being added via ioctx_add_table() while freed when the ioctx_alloc() call returned -EAGAIN due to hitting the aio_max_nr limit. Fix this by only calling ioctx_add_table() as the last step in ioctx_alloc(). Also, several unnecessary rcu_dereference() calls were added that lead to RCU warnings where the system was already protected by a spin lock for accessing mm->ioctx_table. Signed-off-by: Benjamin LaHaise <bcrl@kvack.org>
1 parent 6878ea7 commit da90382

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

fs/aio.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
475475
struct aio_ring *ring;
476476

477477
spin_lock(&mm->ioctx_lock);
478-
table = rcu_dereference(mm->ioctx_table);
478+
table = mm->ioctx_table;
479479

480480
while (1) {
481481
if (table)
@@ -503,7 +503,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
503503
table->nr = new_nr;
504504

505505
spin_lock(&mm->ioctx_lock);
506-
old = rcu_dereference(mm->ioctx_table);
506+
old = mm->ioctx_table;
507507

508508
if (!old) {
509509
rcu_assign_pointer(mm->ioctx_table, table);
@@ -579,10 +579,6 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
579579
if (ctx->req_batch < 1)
580580
ctx->req_batch = 1;
581581

582-
err = ioctx_add_table(ctx, mm);
583-
if (err)
584-
goto out_cleanup_noerr;
585-
586582
/* limit the number of system wide aios */
587583
spin_lock(&aio_nr_lock);
588584
if (aio_nr + nr_events > (aio_max_nr * 2UL) ||
@@ -595,13 +591,18 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
595591

596592
percpu_ref_get(&ctx->users); /* io_setup() will drop this ref */
597593

594+
err = ioctx_add_table(ctx, mm);
595+
if (err)
596+
goto out_cleanup_put;
597+
598598
pr_debug("allocated ioctx %p[%ld]: mm=%p mask=0x%x\n",
599599
ctx, ctx->user_id, mm, ctx->nr_events);
600600
return ctx;
601601

602+
out_cleanup_put:
603+
percpu_ref_put(&ctx->users);
602604
out_cleanup:
603605
err = -EAGAIN;
604-
out_cleanup_noerr:
605606
aio_free_ring(ctx);
606607
out_freepcpu:
607608
free_percpu(ctx->cpu);
@@ -626,7 +627,7 @@ static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx)
626627
struct kioctx_table *table;
627628

628629
spin_lock(&mm->ioctx_lock);
629-
table = rcu_dereference(mm->ioctx_table);
630+
table = mm->ioctx_table;
630631

631632
WARN_ON(ctx != table->table[ctx->id]);
632633
table->table[ctx->id] = NULL;

0 commit comments

Comments
 (0)