| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * An async IO implementation for Linux | |||
| 3 | * Written by Benjamin LaHaise <bcrl@kvack.org> | |||
| 4 | * | |||
| 5 | * Implements an efficient asynchronous io interface. | |||
| 6 | * | |||
| 7 | * Copyright 2000, 2001, 2002 Red Hat, Inc. All Rights Reserved. | |||
| 8 | * | |||
| 9 | * See ../COPYING for licensing terms. | |||
| 10 | */ | |||
| 11 | #include <linux/kernel.h> | |||
| 12 | #include <linux/init.h> | |||
| 13 | #include <linux/errno.h> | |||
| 14 | #include <linux/time.h> | |||
| 15 | #include <linux/aio_abi.h> | |||
| 16 | #include <linux/module.h> | |||
| 17 | #include <linux/syscalls.h> | |||
| 18 | ||||
| 19 | #define DEBUG 0 | |||
| 20 | ||||
| 21 | #include <linux/sched.h> | |||
| 22 | #include <linux/fs.h> | |||
| 23 | #include <linux/file.h> | |||
| 24 | #include <linux/mm.h> | |||
| 25 | #include <linux/mman.h> | |||
| 26 | #include <linux/slab.h> | |||
| 27 | #include <linux/timer.h> | |||
| 28 | #include <linux/aio.h> | |||
| 29 | #include <linux/highmem.h> | |||
| 30 | #include <linux/workqueue.h> | |||
| 31 | #include <linux/security.h> | |||
| 32 | ||||
| 33 | #include <asm/kmap_types.h> | |||
| 34 | #include <asm/uaccess.h> | |||
| 35 | #include <asm/mmu_context.h> | |||
| 36 | ||||
| 37 | #if DEBUG > 1 | |||
| 38 | #define dprintk printk | |||
| 39 | #else | |||
| 40 | #define dprintk(x...) do { ; } while (0) | |||
| 41 | #endif | |||
| 42 | ||||
| 43 | /*------ sysctl variables----*/ | |||
| 44 | static DEFINE_SPINLOCK(aio_nr_lock); | |||
| 45 | unsigned long aio_nr; /* current system wide number of aio requests */ | |||
| 46 | unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ | |||
| 47 | /*----end sysctl variables---*/ | |||
| 48 | ||||
| 49 | static kmem_cache_t *kiocb_cachep; | |||
| 50 | static kmem_cache_t *kioctx_cachep; | |||
| 51 | ||||
| 52 | static struct workqueue_struct *aio_wq; | |||
| 53 | ||||
| 54 | /* Used for rare fput completion. */ | |||
| 55 | static void aio_fput_routine(void *); | |||
| 56 | static DECLARE_WORK(fput_work, aio_fput_routine, NULL); | |||
| 57 | ||||
| 58 | static DEFINE_SPINLOCK(fput_lock); | |||
| 59 | static LIST_HEAD(fput_head); | |||
| 60 | ||||
| 61 | static void aio_kick_handler(void *); | |||
| 62 | static void aio_queue_work(struct kioctx *); | |||
| 63 | ||||
| 64 | /* aio_setup | |||
| 65 | * Creates the slab caches used by the aio routines, panic on | |||
| 66 | * failure as this is done early during the boot sequence. | |||
| 67 | */ | |||
| 6 | 0 | 68 | static int __init aio_setup(void) | |
| 69 | { | |||
| 70 | kiocb_cachep = kmem_cache_create("kiocb", sizeof(struct kiocb), | |||
| 71 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); | |||
| 72 | kioctx_cachep = kmem_cache_create("kioctx", sizeof(struct kioctx), | |||
| 73 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); | |||
| 74 | ||||
| 75 | aio_wq = create_workqueue("aio"); | |||
| 76 | ||||
| 77 | pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page)); | |||
| 0 | 6 | - | 77 | do-while (0) |
| 78 | ||||
| 6 | 79 | return 0; | ||
| 80 | } | |||
| 81 | ||||
| 0 | 0 | - | 82 | static void aio_free_ring(struct kioctx *ctx) |
| 83 | { | |||
| 84 | struct aio_ring_info *info = &ctx->ring_info; | |||
| 85 | long i; | |||
| 86 | ||||
| 0 | 0 | - | 87 | for (i=0; i<info->nr_pages; i++) |
| 88 | put_page(info->ring_pages[i]); | |||
| 89 | ||||
| 0 | 0 | - | 90 | if (info->mmap_size) { |
| 91 | down_write(&ctx->mm->mmap_sem); | |||
| 92 | do_munmap(ctx->mm, info->mmap_base, info->mmap_size); | |||
| 93 | up_write(&ctx->mm->mmap_sem); | |||
| 94 | } | |||
| 95 | ||||
| 0 | 0 | - | 96 | if (info->ring_pages && info->ring_pages != info->internal_pages) |
| 0 | - | 96 | T && T | |
| 0 | - | 96 | T && F | |
| 0 | - | 96 | F && _ | |
| 97 | kfree(info->ring_pages); | |||
| 98 | info->ring_pages = NULL; | |||
| 99 | info->nr = 0; | |||
| 100 | } | |||
| 101 | ||||
| 0 | 0 | - | 102 | static int aio_setup_ring(struct kioctx *ctx) |
| 103 | { | |||
| 104 | struct aio_ring *ring; | |||
| 105 | struct aio_ring_info *info = &ctx->ring_info; | |||
| 106 | unsigned nr_events = ctx->max_reqs; | |||
| 107 | unsigned long size; | |||
| 108 | int nr_pages; | |||
| 109 | ||||
| 110 | /* Compensate for the ring buffer's head/tail overlap entry */ | |||
| 111 | nr_events += 2; /* 1 is required, 2 for good luck */ | |||
| 112 | ||||
| 113 | size = sizeof(struct aio_ring); | |||
| 114 | size += sizeof(struct io_event) * nr_events; | |||
| 115 | nr_pages = (size + PAGE_SIZE-1) >> PAGE_SHIFT; | |||
| 116 | ||||
| 0 | 0 | - | 117 | if (nr_pages < 0) |
| 0 | - | 118 | return -EINVAL; | |
| 119 | ||||
| 120 | nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring)) / sizeof(struct io_event); | |||
| 121 | ||||
| 122 | info->nr = 0; | |||
| 123 | info->ring_pages = info->internal_pages; | |||
| 0 | 0 | - | 124 | if (nr_pages > AIO_RING_PAGES) { |
| 125 | info->ring_pages = kmalloc(sizeof(struct page *) * nr_pages, GFP_KERNEL); | |||
| 0 | 0 | - | 126 | if (!info->ring_pages) |
| 0 | - | 127 | return -ENOMEM; | |
| 128 | memset(info->ring_pages, 0, sizeof(struct page *) * nr_pages); | |||
| 129 | } | |||
| 130 | ||||
| 131 | info->mmap_size = nr_pages * PAGE_SIZE; | |||
| 132 | dprintk("attempting mmap of %lu bytes\n", info->mmap_size); | |||
| 0 | 0 | - | 132 | do-while (0) |
| 133 | down_write(&ctx->mm->mmap_sem); | |||
| 134 | info->mmap_base = do_mmap(NULL, 0, info->mmap_size, | |||
| 135 | PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, | |||
| 136 | 0); | |||
| 0 | 0 | - | 137 | if (IS_ERR((void *)info->mmap_base)) { |
| 138 | up_write(&ctx->mm->mmap_sem); | |||
| 139 | printk("mmap err: %ld\n", -info->mmap_base); | |||
| 140 | info->mmap_size = 0; | |||
| 141 | aio_free_ring(ctx); | |||
| 0 | - | 142 | return -EAGAIN; | |
| 143 | } | |||
| 144 | ||||
| 145 | dprintk("mmap address: 0x%08lx\n", info->mmap_base); | |||
| 0 | 0 | - | 145 | do-while (0) |
| 146 | info->nr_pages = get_user_pages(current, ctx->mm, | |||
| 147 | info->mmap_base, nr_pages, | |||
| 148 | 1, 0, info->ring_pages, NULL); | |||
| 149 | up_write(&ctx->mm->mmap_sem); | |||
| 150 | ||||
| 0 | 0 | - | 151 | if (unlikely(info->nr_pages != nr_pages)) { |
| 152 | aio_free_ring(ctx); | |||
| 0 | - | 153 | return -EAGAIN; | |
| 154 | } | |||
| 155 | ||||
| 156 | ctx->user_id = info->mmap_base; | |||
| 157 | ||||
| 158 | info->nr = nr_events; /* trusted copy */ | |||
| 159 | ||||
| 160 | ring = kmap_atomic(info->ring_pages[0], KM_USER0); | |||
| 161 | ring->nr = nr_events; /* user copy */ | |||
| 162 | ring->id = ctx->user_id; | |||
| 163 | ring->head = ring->tail = 0; | |||
| 164 | ring->magic = AIO_RING_MAGIC; | |||
| 165 | ring->compat_features = AIO_RING_COMPAT_FEATURES; | |||
| 166 | ring->incompat_features = AIO_RING_INCOMPAT_FEATURES; | |||
| 167 | ring->header_length = sizeof(struct aio_ring); | |||
| 168 | kunmap_atomic(ring, KM_USER0); | |||
| 0 | 0 | - | 168 | do-while (0) |
| 169 | ||||
| 0 | - | 170 | return 0; | |
| 171 | } | |||
| 172 | ||||
| 173 | ||||
| 174 | /* aio_ring_event: returns a pointer to the event at the given index from | |||
| 175 | * kmap_atomic(, km). Release the pointer with put_aio_ring_event(); | |||
| 176 | */ | |||
| 177 | #define AIO_EVENTS_PER_PAGE (PAGE_SIZE / sizeof(struct io_event)) | |||
| 178 | #define AIO_EVENTS_FIRST_PAGE ((PAGE_SIZE - sizeof(struct aio_ring)) / sizeof(struct io_event)) | |||
| 179 | #define AIO_EVENTS_OFFSET (AIO_EVENTS_PER_PAGE - AIO_EVENTS_FIRST_PAGE) | |||
| 180 | ||||
| 181 | #define aio_ring_event(info, nr, km) ({ \ | |||
| 182 | unsigned pos = (nr) + AIO_EVENTS_OFFSET; \ | |||
| 183 | struct io_event *__event; \ | |||
| 184 | __event = kmap_atomic( \ | |||
| 185 | (info)->ring_pages[pos / AIO_EVENTS_PER_PAGE], km); \ | |||
| 186 | __event += pos % AIO_EVENTS_PER_PAGE; \ | |||
| 187 | __event; \ | |||
| 188 | }) | |||
| 189 | ||||
| 190 | #define put_aio_ring_event(event, km) do { \ | |||
| 191 | struct io_event *__event = (event); \ | |||
| 192 | (void)__event; \ | |||
| 193 | kunmap_atomic((void *)((unsigned long)__event & PAGE_MASK), km); \ | |||
| 194 | } while(0) | |||
| 195 | ||||
| 196 | /* ioctx_alloc | |||
| 197 | * Allocates and initializes an ioctx. Returns an ERR_PTR if it failed. | |||
| 198 | */ | |||
| 0 | 0 | - | 199 | static struct kioctx *ioctx_alloc(unsigned nr_events) |
| 200 | { | |||
| 201 | struct mm_struct *mm; | |||
| 202 | struct kioctx *ctx; | |||
| 203 | ||||
| 204 | /* Prevent overflows */ | |||
| 205 | if ((nr_events > (0x10000000U / sizeof(struct io_event))) || | |||
| 0 | 0 | - | 206 | (nr_events > (0x10000000U / sizeof(struct kiocb)))) { |
| 0 | - | 206 | (T) || (_) | |
| 0 | - | 206 | (F) || (T) | |
| 0 | - | 206 | (F) || (F) | |
| 207 | pr_debug("ENOMEM: nr_events too high\n"); | |||
| 0 | 0 | - | 207 | do-while (0) |
| 0 | - | 208 | return ERR_PTR(-EINVAL); | |
| 209 | } | |||
| 210 | ||||
| 0 | 0 | - | 211 | if ((unsigned long)nr_events > aio_max_nr) |
| 0 | - | 212 | return ERR_PTR(-EAGAIN); | |
| 213 | ||||
| 214 | ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL); | |||
| 0 | 0 | - | 215 | if (!ctx) |
| 0 | - | 216 | return ERR_PTR(-ENOMEM); | |
| 217 | ||||
| 218 | memset(ctx, 0, sizeof(*ctx)); | |||
| 219 | ctx->max_reqs = nr_events; | |||
| 220 | mm = ctx->mm = current->mm; | |||
| 221 | atomic_inc(&mm->mm_count); | |||
| 222 | ||||
| 223 | atomic_set(&ctx->users, 1); | |||
| 224 | spin_lock_init(&ctx->ctx_lock); | |||
| 0 | 0 | - | 224 | do-while (0) |
| 225 | spin_lock_init(&ctx->ring_info.ring_lock); | |||
| 0 | 0 | - | 225 | do-while (0) |
| 226 | init_waitqueue_head(&ctx->wait); | |||
| 227 | ||||
| 228 | INIT_LIST_HEAD(&ctx->active_reqs); | |||
| 229 | INIT_LIST_HEAD(&ctx->run_list); | |||
| 230 | INIT_WORK(&ctx->wq, aio_kick_handler, ctx); | |||
| 230 | do | |||
| 0 | 0 | - | 230 | do-while (0) |
| 0 | 0 | - | 230 | do-while (0) |
| 231 | ||||
| 0 | 0 | - | 232 | if (aio_setup_ring(ctx) < 0) |
| 0 | - | 233 | goto out_freectx; | |
| 234 | ||||
| 235 | /* limit the number of system wide aios */ | |||
| 236 | spin_lock(&aio_nr_lock); | |||
| 236 | do | |||
| 0 | 0 | - | 236 | do-while (0) |
| 0 | 0 | - | 236 | do-while (0) |
| 237 | if (aio_nr + ctx->max_reqs > aio_max_nr || | |||
| 0 | 0 | - | 238 | aio_nr + ctx->max_reqs < aio_nr) |
| 0 | - | 238 | T || _ | |
| 0 | - | 238 | F || T | |
| 0 | - | 238 | F || F | |
| 239 | ctx->max_reqs = 0; | |||
| 240 | else | |||
| 241 | aio_nr += ctx->max_reqs; | |||
| 242 | spin_unlock(&aio_nr_lock); | |||
| 242 | do | |||
| 0 | 0 | - | 242 | do-while (0) |
| 0 | 0 | - | 242 | do-while (0) |
| 0 | 0 | - | 243 | if (ctx->max_reqs == 0) |
| 0 | - | 244 | goto out_cleanup; | |
| 245 | ||||
| 246 | /* now link into global list. kludge. FIXME */ | |||
| 247 | write_lock(&mm->ioctx_list_lock); | |||
| 247 | do | |||
| 0 | 0 | - | 247 | do-while (0) |
| 0 | 0 | - | 247 | do-while (0) |
| 248 | ctx->next = mm->ioctx_list; | |||
| 249 | mm->ioctx_list = ctx; | |||
| 250 | write_unlock(&mm->ioctx_list_lock); | |||
| 250 | do | |||
| 0 | 0 | - | 250 | do-while (0) |
| 0 | 0 | - | 250 | do-while (0) |
| 251 | ||||
| 252 | dprintk("aio: allocated ioctx %p[%ld]: mm=%p mask=0x%x\n", | |||
| 0 | 0 | - | 252 | do-while (0) |
| 253 | ctx, ctx->user_id, current->mm, ctx->ring_info.nr); | |||
| 0 | - | 254 | return ctx; | |
| 255 | ||||
| 256 | out_cleanup: | |||
| 257 | __put_ioctx(ctx); | |||
| 0 | - | 258 | return ERR_PTR(-EAGAIN); | |
| 259 | ||||
| 260 | out_freectx: | |||
| 261 | mmdrop(mm); | |||
| 262 | kmem_cache_free(kioctx_cachep, ctx); | |||
| 263 | ctx = ERR_PTR(-ENOMEM); | |||
| 264 | ||||
| 265 | dprintk("aio: error allocating ioctx %p\n", ctx); | |||
| 0 | 0 | - | 265 | do-while (0) |
| 0 | - | 266 | return ctx; | |
| 267 | } | |||
| 268 | ||||
| 269 | /* aio_cancel_all | |||
| 270 | * Cancels all outstanding aio requests on an aio context. Used | |||
| 271 | * when the processes owning a context have all exited to encourage | |||
| 272 | * the rapid destruction of the kioctx. | |||
| 273 | */ | |||
| 0 | 0 | - | 274 | static void aio_cancel_all(struct kioctx *ctx) |
| 275 | { | |||
| 276 | int (*cancel)(struct kiocb *, struct io_event *); | |||
| 277 | struct io_event res; | |||
| 278 | spin_lock_irq(&ctx->ctx_lock); | |||
| 278 | do | |||
| 278 | do | |||
| 0 | 0 | - | 278 | do-while (0) |
| 0 | 0 | - | 278 | do-while (0) |
| 0 | 0 | - | 278 | do-while (0) |
| 279 | ctx->dead = 1; | |||
| 0 | 0 | - | 280 | while (!list_empty(&ctx->active_reqs)) { |
| 281 | struct list_head *pos = ctx->active_reqs.next; | |||
| 282 | struct kiocb *iocb = list_kiocb(pos); | |||
| 283 | list_del_init(&iocb->ki_list); | |||
| 284 | cancel = iocb->ki_cancel; | |||
| 285 | kiocbSetCancelled(iocb); | |||
| 0 | 0 | - | 286 | if (cancel) { |
| 287 | iocb->ki_users++; | |||
| 288 | spin_unlock_irq(&ctx->ctx_lock); | |||
| 288 | do | |||
| 288 | do | |||
| 0 | 0 | - | 288 | do-while (0) |
| 0 | 0 | - | 288 | do-while (0) |
| 0 | 0 | - | 288 | do-while (0) |
| 289 | cancel(iocb, &res); | |||
| 290 | spin_lock_irq(&ctx->ctx_lock); | |||
| 290 | do | |||
| 290 | do | |||
| 0 | 0 | - | 290 | do-while (0) |
| 0 | 0 | - | 290 | do-while (0) |
| 0 | 0 | - | 290 | do-while (0) |
| 291 | } | |||
| 292 | } | |||
| 293 | spin_unlock_irq(&ctx->ctx_lock); | |||
| 293 | do | |||
| 293 | do | |||
| 0 | 0 | - | 293 | do-while (0) |
| 0 | 0 | - | 293 | do-while (0) |
| 0 | 0 | - | 293 | do-while (0) |
| 294 | } | |||
| 295 | ||||
| 0 | 0 | - | 296 | static void wait_for_all_aios(struct kioctx *ctx) |
| 297 | { | |||
| 298 | struct task_struct *tsk = current; | |||
| 299 | DECLARE_WAITQUEUE(wait, tsk); | |||
| 300 | ||||
| 0 | 0 | - | 301 | if (!ctx->reqs_active) |
| 0 | - | 302 | return; | |
| 303 | ||||
| 304 | add_wait_queue(&ctx->wait, &wait); | |||
| 305 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | |||
| 0 | 0 | - | 305 | do-while (0) |
| 0 | 0 | - | 306 | while (ctx->reqs_active) { |
| 307 | schedule(); | |||
| 308 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | |||
| 0 | 0 | - | 308 | do-while (0) |
| 309 | } | |||
| 310 | __set_task_state(tsk, TASK_RUNNING); | |||
| 0 | 0 | - | 310 | do-while (0) |
| 311 | remove_wait_queue(&ctx->wait, &wait); | |||
| 312 | } | |||
| 313 | ||||
| 314 | /* wait_on_sync_kiocb: | |||
| 315 | * Waits on the given sync kiocb to complete. | |||
| 316 | */ | |||
| 0 | 0 | - | 317 | ssize_t fastcall wait_on_sync_kiocb(struct kiocb *iocb) |
| 318 | { | |||
| 0 | 0 | - | 319 | while (iocb->ki_users) { |
| 320 | set_current_state(TASK_UNINTERRUPTIBLE); | |||
| 0 | 0 | - | 320 | do-while (0) |
| 0 | 0 | - | 321 | if (!iocb->ki_users) |
| 0 | - | 322 | break; | |
| 323 | schedule(); | |||
| 324 | } | |||
| 325 | __set_current_state(TASK_RUNNING); | |||
| 0 | 0 | - | 325 | do-while (0) |
| 0 | - | 326 | return iocb->ki_user_data; | |
| 327 | } | |||
| 328 | ||||
| 329 | /* exit_aio: called when the last user of mm goes away. At this point, | |||
| 330 | * there is no way for any new requests to be submited or any of the | |||
| 331 | * io_* syscalls to be called on the context. However, there may be | |||
| 332 | * outstanding requests which hold references to the context; as they | |||
| 333 | * go away, they will call put_ioctx and release any pinned memory | |||
| 334 | * associated with the request (held via struct page * references). | |||
| 335 | */ | |||
| 184567 | 184567 | 336 | void fastcall exit_aio(struct mm_struct *mm) | |
| 337 | { | |||
| 338 | struct kioctx *ctx = mm->ioctx_list; | |||
| 339 | mm->ioctx_list = NULL; | |||
| 0 | 184567 | - | 340 | while (ctx) { |
| 341 | struct kioctx *next = ctx->next; | |||
| 342 | ctx->next = NULL; | |||
| 343 | aio_cancel_all(ctx); | |||
| 344 | ||||
| 345 | wait_for_all_aios(ctx); | |||
| 346 | /* | |||
| 347 | * this is an overkill, but ensures we don't leave | |||
| 348 | * the ctx on the aio_wq | |||
| 349 | */ | |||
| 350 | flush_workqueue(aio_wq); | |||
| 351 | ||||
| 0 | 0 | - | 352 | if (1 != atomic_read(&ctx->users)) |
| 353 | printk(KERN_DEBUG | |||
| 354 | "exit_aio:ioctx still alive: %d %d %d\n", | |||
| 355 | atomic_read(&ctx->users), ctx->dead, | |||
| 356 | ctx->reqs_active); | |||
| 357 | put_ioctx(ctx); | |||
| 357 | do | |||
| 0 | 0 | - | 357 | if (__builtin_expect ( ! ! ( ( __builtin.. |
| 0 | 0 | - | 357 | do-while (0) |
| 0 | 0 | - | 357 | if (__builtin_expect ( ! ! ( atomic_dec_an.. |
| 0 | 0 | - | 357 | do-while (0) |
| 358 | ctx = next; | |||
| 359 | } | |||
| 360 | } | |||
| 361 | ||||
| 362 | /* __put_ioctx | |||
| 363 | * Called when the last user of an aio context has gone away, | |||
| 364 | * and the struct needs to be freed. | |||
| 365 | */ | |||
| 0 | 0 | - | 366 | void fastcall __put_ioctx(struct kioctx *ctx) |
| 367 | { | |||
| 368 | unsigned nr_events = ctx->max_reqs; | |||
| 369 | ||||
| 0 | 0 | - | 370 | if (unlikely(ctx->reqs_active)) |
| 371 | BUG(); | |||
| 372 | ||||
| 373 | cancel_delayed_work(&ctx->wq); | |||
| 374 | flush_workqueue(aio_wq); | |||
| 375 | aio_free_ring(ctx); | |||
| 376 | mmdrop(ctx->mm); | |||
| 377 | ctx->mm = NULL; | |||
| 378 | pr_debug("__put_ioctx: freeing %p\n", ctx); | |||
| 0 | 0 | - | 378 | do-while (0) |
| 379 | kmem_cache_free(kioctx_cachep, ctx); | |||
| 380 | ||||
| 0 | 0 | - | 381 | if (nr_events) { |
| 382 | spin_lock(&aio_nr_lock); | |||
| 382 | do | |||
| 0 | 0 | - | 382 | do-while (0) |
| 0 | 0 | - | 382 | do-while (0) |
| 383 | BUG_ON(aio_nr - nr_events > aio_nr); | |||
| 0 | 0 | - | 383 | if (__builtin_expect ( ! ! ( ( aio_nr - nr.. |
| 0 | 0 | - | 383 | do-while (0) |
| 384 | aio_nr -= nr_events; | |||
| 385 | spin_unlock(&aio_nr_lock); | |||
| 385 | do | |||
| 0 | 0 | - | 385 | do-while (0) |
| 0 | 0 | - | 385 | do-while (0) |
| 386 | } | |||
| 387 | } | |||
| 388 | ||||
| 389 | /* aio_get_req | |||
| 390 | * Allocate a slot for an aio request. Increments the users count | |||
| 391 | * of the kioctx so that the kioctx stays around until all requests are | |||
| 392 | * complete. Returns NULL if no requests are free. | |||
| 393 | * | |||
| 394 | * Returns with kiocb->users set to 2. The io submit code path holds | |||
| 395 | * an extra reference while submitting the i/o. | |||
| 396 | * This prevents races between the aio code path referencing the | |||
| 397 | * req (after submitting it) and aio_complete() freeing the req. | |||
| 398 | */ | |||
| 399 | static struct kiocb *FASTCALL(__aio_get_req(struct kioctx *ctx)); | |||
| 0 | 0 | - | 400 | static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx) |
| 401 | { | |||
| 402 | struct kiocb *req = NULL; | |||
| 403 | struct aio_ring *ring; | |||
| 404 | int okay = 0; | |||
| 405 | ||||
| 406 | req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL); | |||
| 0 | 0 | - | 407 | if (unlikely(!req)) |
| 0 | - | 408 | return NULL; | |
| 409 | ||||
| 410 | req->ki_flags = 0; | |||
| 411 | req->ki_users = 2; | |||
| 412 | req->ki_key = 0; | |||
| 413 | req->ki_ctx = ctx; | |||
| 414 | req->ki_cancel = NULL; | |||
| 415 | req->ki_retry = NULL; | |||
| 416 | req->ki_dtor = NULL; | |||
| 417 | req->private = NULL; | |||
| 418 | INIT_LIST_HEAD(&req->ki_run_list); | |||
| 419 | ||||
| 420 | /* Check if the completion queue has enough free space to | |||
| 421 | * accept an event from this io. | |||
| 422 | */ | |||
| 423 | spin_lock_irq(&ctx->ctx_lock); | |||
| 423 | do | |||
| 423 | do | |||
| 0 | 0 | - | 423 | do-while (0) |
| 0 | 0 | - | 423 | do-while (0) |
| 0 | 0 | - | 423 | do-while (0) |
| 424 | ring = kmap_atomic(ctx->ring_info.ring_pages[0], KM_USER0); | |||
| 0 | 0 | - | 425 | if (ctx->reqs_active < aio_ring_avail(&ctx->ring_info, ring)) { |
| 426 | list_add(&req->ki_list, &ctx->active_reqs); | |||
| 427 | get_ioctx(ctx); | |||
| 427 | do | |||
| 0 | 0 | - | 427 | if (__builtin_expect ( ! ! ( ( __builtin.. |
| 0 | 0 | - | 427 | do-while (0) |
| 0 | 0 | - | 427 | do-while (0) |
| 428 | ctx->reqs_active++; | |||
| 429 | okay = 1; | |||
| 430 | } | |||
| 431 | kunmap_atomic(ring, KM_USER0); | |||
| 0 | 0 | - | 431 | do-while (0) |
| 432 | spin_unlock_irq(&ctx->ctx_lock); | |||
| 432 | do | |||
| 432 | do | |||
| 0 | 0 | - | 432 | do-while (0) |
| 0 | 0 | - | 432 | do-while (0) |
| 0 | 0 | - | 432 | do-while (0) |
| 433 | ||||
| 0 | 0 | - | 434 | if (!okay) { |
| 435 | kmem_cache_free(kiocb_cachep, req); | |||
| 436 | req = NULL; | |||
| 437 | } | |||
| 438 | ||||
| 0 | - | 439 | return req; | |
| 440 | } | |||
| 441 | ||||
| 0 | 0 | - | 442 | static inline struct kiocb *aio_get_req(struct&nbs |