aboutsummaryrefslogtreecommitdiffstats
path: root/fs/aio.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/aio.c')
-rw-r--r--fs/aio.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 4f641abac3..38f62680fd 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
@@ -786,7 +805,9 @@ static int __aio_run_iocbs(struct kioctx *ctx)
786 * Hold an extra reference while retrying i/o. 805 * Hold an extra reference while retrying i/o.
787 */ 806 */
788 iocb->ki_users++; /* grab extra reference */ 807 iocb->ki_users++; /* grab extra reference */
808 lock_kiocb(iocb);
789 aio_run_iocb(iocb); 809 aio_run_iocb(iocb);
810 unlock_kiocb(iocb);
790 if (__aio_put_req(ctx, iocb)) /* drop extra ref */ 811 if (__aio_put_req(ctx, iocb)) /* drop extra ref */
791 put_ioctx(ctx); 812 put_ioctx(ctx);
792 } 813 }
@@ -1527,10 +1548,9 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1527 goto out_put_req; 1548 goto out_put_req;
1528 1549
1529 spin_lock_irq(&ctx->ctx_lock); 1550 spin_lock_irq(&ctx->ctx_lock);
1530 if (likely(list_empty(&ctx->run_list))) { 1551 aio_run_iocb(req);
1531 aio_run_iocb(req); 1552 unlock_kiocb(req);
1532 } else { 1553 if (!list_empty(&ctx->run_list)) {
1533 list_add_tail(&req->ki_run_list, &ctx->run_list);
1534 /* drain the run list */ 1554 /* drain the run list */
1535 while (__aio_run_iocbs(ctx)) 1555 while (__aio_run_iocbs(ctx))
1536 ; 1556 ;
@@ -1661,6 +1681,7 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
1661 if (NULL != cancel) { 1681 if (NULL != cancel) {
1662 struct io_event tmp; 1682 struct io_event tmp;
1663 pr_debug("calling cancel\n"); 1683 pr_debug("calling cancel\n");
1684 lock_kiocb(kiocb);
1664 memset(&tmp, 0, sizeof(tmp)); 1685 memset(&tmp, 0, sizeof(tmp));
1665 tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user; 1686 tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user;
1666 tmp.data = kiocb->ki_user_data; 1687 tmp.data = kiocb->ki_user_data;
@@ -1672,8 +1693,9 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
1672 if (copy_to_user(result, &tmp, sizeof(tmp))) 1693 if (copy_to_user(result, &tmp, sizeof(tmp)))
1673 ret = -EFAULT; 1694 ret = -EFAULT;
1674 } 1695 }
1696 unlock_kiocb(kiocb);
1675 } else 1697 } else
1676 printk(KERN_DEBUG "iocb has no cancel operation\n"); 1698 ret = -EINVAL;
1677 1699
1678 put_ioctx(ctx); 1700 put_ioctx(ctx);
1679 1701