diff options
Diffstat (limited to 'fs/aio.c')
-rw-r--r-- | fs/aio.c | 27 |
1 files changed, 9 insertions, 18 deletions
@@ -937,28 +937,19 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2) | |||
937 | unsigned long tail; | 937 | unsigned long tail; |
938 | int ret; | 938 | int ret; |
939 | 939 | ||
940 | /* Special case handling for sync iocbs: events go directly | 940 | /* |
941 | * into the iocb for fast handling. Note that this will not | 941 | * Special case handling for sync iocbs: |
942 | * work if we allow sync kiocbs to be cancelled. in which | 942 | * - events go directly into the iocb for fast handling |
943 | * case the usage count checks will have to move under ctx_lock | 943 | * - the sync task with the iocb in its stack holds the single iocb |
944 | * for all cases. | 944 | * ref, no other paths have a way to get another ref |
945 | * - the sync task helpfully left a reference to itself in the iocb | ||
945 | */ | 946 | */ |
946 | if (is_sync_kiocb(iocb)) { | 947 | if (is_sync_kiocb(iocb)) { |
947 | int ret; | 948 | BUG_ON(iocb->ki_users != 1); |
948 | |||
949 | iocb->ki_user_data = res; | 949 | iocb->ki_user_data = res; |
950 | if (iocb->ki_users == 1) { | 950 | iocb->ki_users = 0; |
951 | iocb->ki_users = 0; | ||
952 | ret = 1; | ||
953 | } else { | ||
954 | spin_lock_irq(&ctx->ctx_lock); | ||
955 | iocb->ki_users--; | ||
956 | ret = (0 == iocb->ki_users); | ||
957 | spin_unlock_irq(&ctx->ctx_lock); | ||
958 | } | ||
959 | /* sync iocbs put the task here for us */ | ||
960 | wake_up_process(iocb->ki_obj.tsk); | 951 | wake_up_process(iocb->ki_obj.tsk); |
961 | return ret; | 952 | return 1; |
962 | } | 953 | } |
963 | 954 | ||
964 | info = &ctx->ring_info; | 955 | info = &ctx->ring_info; |