Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

aio: percpu ioctx refcount

This just converts the ioctx refcount to the new generic dynamic percpu
refcount code.

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>
Cc: 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: Benjamin LaHaise <bcrl@kvack.org>

authored by

Kent Overstreet and committed by
Benjamin LaHaise
723be6e3 e1bdd5f2

+27 -39
+27 -39
fs/aio.c
··· 39 39 #include <linux/anon_inodes.h> 40 40 #include <linux/migrate.h> 41 41 #include <linux/ramfs.h> 42 + #include <linux/percpu-refcount.h> 42 43 43 44 #include <asm/kmap_types.h> 44 45 #include <asm/uaccess.h> ··· 71 70 }; 72 71 73 72 struct kioctx { 74 - atomic_t users; 73 + struct percpu_ref users; 75 74 atomic_t dead; 76 75 77 76 /* This needs improving */ ··· 104 103 long nr_pages; 105 104 106 105 struct rcu_head rcu_head; 107 - struct work_struct rcu_work; 106 + struct work_struct free_work; 108 107 109 108 struct { 110 109 /* ··· 404 403 * and ctx->users has dropped to 0, so we know no more kiocbs can be submitted - 405 404 * now it's safe to cancel any that need to be. 406 405 */ 407 - static void free_ioctx(struct kioctx *ctx) 406 + static void free_ioctx(struct work_struct *work) 408 407 { 408 + struct kioctx *ctx = container_of(work, struct kioctx, free_work); 409 409 struct aio_ring *ring; 410 410 struct io_event res; 411 411 struct kiocb *req; ··· 464 462 call_rcu(&ctx->rcu_head, free_ioctx_rcu); 465 463 } 466 464 467 - static void put_ioctx(struct kioctx *ctx) 465 + static void free_ioctx_ref(struct percpu_ref *ref) 468 466 { 469 - if (unlikely(atomic_dec_and_test(&ctx->users))) 470 - free_ioctx(ctx); 467 + struct kioctx *ctx = container_of(ref, struct kioctx, users); 468 + 469 + INIT_WORK(&ctx->free_work, free_ioctx); 470 + schedule_work(&ctx->free_work); 471 471 } 472 472 473 473 /* ioctx_alloc ··· 509 505 510 506 ctx->max_reqs = nr_events; 511 507 512 - atomic_set(&ctx->users, 2); 513 - atomic_set(&ctx->dead, 0); 508 + if (percpu_ref_init(&ctx->users, free_ioctx_ref)) 509 + goto out_freectx; 510 + 514 511 spin_lock_init(&ctx->ctx_lock); 515 512 spin_lock_init(&ctx->completion_lock); 516 513 mutex_init(&ctx->ring_lock); ··· 521 516 522 517 ctx->cpu = alloc_percpu(struct kioctx_cpu); 523 518 if (!ctx->cpu) 524 - goto out_freectx; 519 + goto out_freeref; 525 520 526 521 if (aio_setup_ring(ctx) < 0) 527 522 goto out_freepcpu; ··· 540 535 aio_nr += ctx->max_reqs; 541 536 spin_unlock(&aio_nr_lock); 542 537 538 + percpu_ref_get(&ctx->users); /* io_setup() will drop this ref */ 539 + 543 540 /* now link into global list. */ 544 541 spin_lock(&mm->ioctx_lock); 545 542 hlist_add_head_rcu(&ctx->list, &mm->ioctx_list); ··· 556 549 aio_free_ring(ctx); 557 550 out_freepcpu: 558 551 free_percpu(ctx->cpu); 552 + out_freeref: 553 + free_percpu(ctx->users.pcpu_count); 559 554 out_freectx: 560 555 if (ctx->aio_ring_file) 561 556 fput(ctx->aio_ring_file); 562 557 kmem_cache_free(kioctx_cachep, ctx); 563 558 pr_debug("error allocating ioctx %d\n", err); 564 559 return ERR_PTR(err); 565 - } 566 - 567 - static void kill_ioctx_work(struct work_struct *work) 568 - { 569 - struct kioctx *ctx = container_of(work, struct kioctx, rcu_work); 570 - 571 - wake_up_all(&ctx->wait); 572 - put_ioctx(ctx); 573 - } 574 - 575 - static void kill_ioctx_rcu(struct rcu_head *head) 576 - { 577 - struct kioctx *ctx = container_of(head, struct kioctx, rcu_head); 578 - 579 - INIT_WORK(&ctx->rcu_work, kill_ioctx_work); 580 - schedule_work(&ctx->rcu_work); 581 560 } 582 561 583 562 /* kill_ioctx ··· 575 582 { 576 583 if (!atomic_xchg(&ctx->dead, 1)) { 577 584 hlist_del_rcu(&ctx->list); 585 + /* percpu_ref_kill() will do the necessary call_rcu() */ 586 + wake_up_all(&ctx->wait); 578 587 579 588 /* 580 589 * It'd be more correct to do this in free_ioctx(), after all ··· 593 598 if (ctx->mmap_size) 594 599 vm_munmap(ctx->mmap_base, ctx->mmap_size); 595 600 596 - /* Between hlist_del_rcu() and dropping the initial ref */ 597 - call_rcu(&ctx->rcu_head, kill_ioctx_rcu); 601 + percpu_ref_kill(&ctx->users); 598 602 } 599 603 } 600 604 ··· 627 633 struct hlist_node *n; 628 634 629 635 hlist_for_each_entry_safe(ctx, n, &mm->ioctx_list, list) { 630 - if (1 != atomic_read(&ctx->users)) 631 - printk(KERN_DEBUG 632 - "exit_aio:ioctx still alive: %d %d %d\n", 633 - atomic_read(&ctx->users), 634 - atomic_read(&ctx->dead), 635 - atomic_read(&ctx->reqs_available)); 636 636 /* 637 637 * We don't need to bother with munmap() here - 638 638 * exit_mmap(mm) is coming and it'll unmap everything. ··· 745 757 746 758 hlist_for_each_entry_rcu(ctx, &mm->ioctx_list, list) { 747 759 if (ctx->user_id == ctx_id) { 748 - atomic_inc(&ctx->users); 760 + percpu_ref_get(&ctx->users); 749 761 ret = ctx; 750 762 break; 751 763 } ··· 1042 1054 ret = put_user(ioctx->user_id, ctxp); 1043 1055 if (ret) 1044 1056 kill_ioctx(ioctx); 1045 - put_ioctx(ioctx); 1057 + percpu_ref_put(&ioctx->users); 1046 1058 } 1047 1059 1048 1060 out: ··· 1060 1072 struct kioctx *ioctx = lookup_ioctx(ctx); 1061 1073 if (likely(NULL != ioctx)) { 1062 1074 kill_ioctx(ioctx); 1063 - put_ioctx(ioctx); 1075 + percpu_ref_put(&ioctx->users); 1064 1076 return 0; 1065 1077 } 1066 1078 pr_debug("EINVAL: io_destroy: invalid context id\n"); ··· 1382 1394 } 1383 1395 blk_finish_plug(&plug); 1384 1396 1385 - put_ioctx(ctx); 1397 + percpu_ref_put(&ctx->users); 1386 1398 return i ? i : ret; 1387 1399 } 1388 1400 ··· 1471 1483 ret = -EFAULT; 1472 1484 } 1473 1485 1474 - put_ioctx(ctx); 1486 + percpu_ref_put(&ctx->users); 1475 1487 1476 1488 return ret; 1477 1489 } ··· 1500 1512 if (likely(ioctx)) { 1501 1513 if (likely(min_nr <= nr && min_nr >= 0)) 1502 1514 ret = read_events(ioctx, min_nr, nr, events, timeout); 1503 - put_ioctx(ioctx); 1515 + percpu_ref_put(&ioctx->users); 1504 1516 } 1505 1517 return ret; 1506 1518 }