aboutsummaryrefslogtreecommitdiffstats
path: root/fs/aio.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/aio.c')
-rw-r--r--fs/aio.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 06d7d4390fe7..38f62680fd63 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -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
550static int lock_kiocb_action(void *param)
551{
552 schedule();
553 return 0;
554}
555
556static 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
562static 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