diff options
Diffstat (limited to 'fs/aio.c')
| -rw-r--r-- | fs/aio.c | 38 |
1 files changed, 32 insertions, 6 deletions
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/highmem.h> | 29 | #include <linux/highmem.h> |
| 30 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
| 31 | #include <linux/security.h> | 31 | #include <linux/security.h> |
| 32 | #include <linux/rcuref.h> | ||
| 32 | 33 | ||
| 33 | #include <asm/kmap_types.h> | 34 | #include <asm/kmap_types.h> |
| 34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
| @@ -499,7 +500,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) | |||
| 499 | /* Must be done under the lock to serialise against cancellation. | 500 | /* Must be done under the lock to serialise against cancellation. |
| 500 | * Call this aio_fput as it duplicates fput via the fput_work. | 501 | * Call this aio_fput as it duplicates fput via the fput_work. |
| 501 | */ | 502 | */ |
| 502 | if (unlikely(atomic_dec_and_test(&req->ki_filp->f_count))) { | 503 | if (unlikely(rcuref_dec_and_test(&req->ki_filp->f_count))) { |
| 503 | get_ioctx(ctx); | 504 | get_ioctx(ctx); |
| 504 | spin_lock(&fput_lock); | 505 | spin_lock(&fput_lock); |
| 505 | list_add(&req->ki_list, &fput_head); | 506 | list_add(&req->ki_list, &fput_head); |
| @@ -546,6 +547,24 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id) | |||
| 546 | return ioctx; | 547 | return ioctx; |
| 547 | } | 548 | } |
| 548 | 549 | ||
| 550 | static int lock_kiocb_action(void *param) | ||
| 551 | { | ||
| 552 | schedule(); | ||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | |||
| 556 | static inline void lock_kiocb(struct kiocb *iocb) | ||
| 557 | { | ||
| 558 | wait_on_bit_lock(&iocb->ki_flags, KIF_LOCKED, lock_kiocb_action, | ||
| 559 | TASK_UNINTERRUPTIBLE); | ||
| 560 | } | ||
| 561 | |||
| 562 | static inline void unlock_kiocb(struct kiocb *iocb) | ||
| 563 | { | ||
| 564 | kiocbClearLocked(iocb); | ||
| 565 | wake_up_bit(&iocb->ki_flags, KIF_LOCKED); | ||
| 566 | } | ||
| 567 | |||
| 549 | /* | 568 | /* |
| 550 | * use_mm | 569 | * use_mm |
| 551 | * Makes the calling kernel thread take on the specified | 570 | * Makes the calling kernel thread take on the specified |
| @@ -567,6 +586,10 @@ static void use_mm(struct mm_struct *mm) | |||
| 567 | atomic_inc(&mm->mm_count); | 586 | atomic_inc(&mm->mm_count); |
| 568 | tsk->mm = mm; | 587 | tsk->mm = mm; |
| 569 | tsk->active_mm = mm; | 588 | tsk->active_mm = mm; |
| 589 | /* | ||
| 590 | * Note that on UML this *requires* PF_BORROWED_MM to be set, otherwise | ||
| 591 | * it won't work. Update it accordingly if you change it here | ||
| 592 | */ | ||
| 570 | activate_mm(active_mm, mm); | 593 | activate_mm(active_mm, mm); |
| 571 | task_unlock(tsk); | 594 | task_unlock(tsk); |
| 572 | 595 | ||
| @@ -782,7 +805,9 @@ static int __aio_run_iocbs(struct kioctx *ctx) | |||
| 782 | * Hold an extra reference while retrying i/o. | 805 | * Hold an extra reference while retrying i/o. |
| 783 | */ | 806 | */ |
| 784 | iocb->ki_users++; /* grab extra reference */ | 807 | iocb->ki_users++; /* grab extra reference */ |
| 808 | lock_kiocb(iocb); | ||
| 785 | aio_run_iocb(iocb); | 809 | aio_run_iocb(iocb); |
| 810 | unlock_kiocb(iocb); | ||
| 786 | if (__aio_put_req(ctx, iocb)) /* drop extra ref */ | 811 | if (__aio_put_req(ctx, iocb)) /* drop extra ref */ |
| 787 | put_ioctx(ctx); | 812 | put_ioctx(ctx); |
| 788 | } | 813 | } |
| @@ -1523,10 +1548,9 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | |||
| 1523 | goto out_put_req; | 1548 | goto out_put_req; |
| 1524 | 1549 | ||
| 1525 | spin_lock_irq(&ctx->ctx_lock); | 1550 | spin_lock_irq(&ctx->ctx_lock); |
| 1526 | if (likely(list_empty(&ctx->run_list))) { | 1551 | aio_run_iocb(req); |
| 1527 | aio_run_iocb(req); | 1552 | unlock_kiocb(req); |
| 1528 | } else { | 1553 | if (!list_empty(&ctx->run_list)) { |
| 1529 | list_add_tail(&req->ki_run_list, &ctx->run_list); | ||
| 1530 | /* drain the run list */ | 1554 | /* drain the run list */ |
| 1531 | while (__aio_run_iocbs(ctx)) | 1555 | while (__aio_run_iocbs(ctx)) |
| 1532 | ; | 1556 | ; |
| @@ -1657,6 +1681,7 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, | |||
| 1657 | if (NULL != cancel) { | 1681 | if (NULL != cancel) { |
| 1658 | struct io_event tmp; | 1682 | struct io_event tmp; |
| 1659 | pr_debug("calling cancel\n"); | 1683 | pr_debug("calling cancel\n"); |
| 1684 | lock_kiocb(kiocb); | ||
| 1660 | memset(&tmp, 0, sizeof(tmp)); | 1685 | memset(&tmp, 0, sizeof(tmp)); |
| 1661 | tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user; | 1686 | tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user; |
| 1662 | tmp.data = kiocb->ki_user_data; | 1687 | tmp.data = kiocb->ki_user_data; |
| @@ -1668,8 +1693,9 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, | |||
| 1668 | if (copy_to_user(result, &tmp, sizeof(tmp))) | 1693 | if (copy_to_user(result, &tmp, sizeof(tmp))) |
| 1669 | ret = -EFAULT; | 1694 | ret = -EFAULT; |
| 1670 | } | 1695 | } |
| 1696 | unlock_kiocb(kiocb); | ||
| 1671 | } else | 1697 | } else |
| 1672 | printk(KERN_DEBUG "iocb has no cancel operation\n"); | 1698 | ret = -EINVAL; |
| 1673 | 1699 | ||
| 1674 | put_ioctx(ctx); | 1700 | put_ioctx(ctx); |
| 1675 | 1701 | ||
