diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2016-06-30 02:45:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-01 05:32:17 -0400 |
commit | 59e6ae53248a72d83cec77dd704b6990b2394479 (patch) | |
tree | 6978c2c81e9c807a544304ea2c28ce49696d3ad4 /include/linux/ptr_ring.h | |
parent | fd68adec9de3104c236ffbcb3bd829d3e635a444 (diff) |
ptr_ring: support resizing multiple queues
Sometimes, we need support resizing multiple queues at once. This is
because it was not easy to recover to recover from a partial failure
of multiple queues resizing.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/ptr_ring.h')
-rw-r--r-- | include/linux/ptr_ring.h | 71 |
1 files changed, 62 insertions, 9 deletions
diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h index d78b8b89c707..2052011bf9fb 100644 --- a/include/linux/ptr_ring.h +++ b/include/linux/ptr_ring.h | |||
@@ -349,20 +349,14 @@ static inline int ptr_ring_init(struct ptr_ring *r, int size, gfp_t gfp) | |||
349 | return 0; | 349 | return 0; |
350 | } | 350 | } |
351 | 351 | ||
352 | static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, | 352 | static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue, |
353 | void (*destroy)(void *)) | 353 | int size, gfp_t gfp, |
354 | void (*destroy)(void *)) | ||
354 | { | 355 | { |
355 | unsigned long flags; | ||
356 | int producer = 0; | 356 | int producer = 0; |
357 | void **queue = __ptr_ring_init_queue_alloc(size, gfp); | ||
358 | void **old; | 357 | void **old; |
359 | void *ptr; | 358 | void *ptr; |
360 | 359 | ||
361 | if (!queue) | ||
362 | return -ENOMEM; | ||
363 | |||
364 | spin_lock_irqsave(&(r)->producer_lock, flags); | ||
365 | |||
366 | while ((ptr = ptr_ring_consume(r))) | 360 | while ((ptr = ptr_ring_consume(r))) |
367 | if (producer < size) | 361 | if (producer < size) |
368 | queue[producer++] = ptr; | 362 | queue[producer++] = ptr; |
@@ -375,6 +369,23 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, | |||
375 | old = r->queue; | 369 | old = r->queue; |
376 | r->queue = queue; | 370 | r->queue = queue; |
377 | 371 | ||
372 | return old; | ||
373 | } | ||
374 | |||
375 | static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, | ||
376 | void (*destroy)(void *)) | ||
377 | { | ||
378 | unsigned long flags; | ||
379 | void **queue = __ptr_ring_init_queue_alloc(size, gfp); | ||
380 | void **old; | ||
381 | |||
382 | if (!queue) | ||
383 | return -ENOMEM; | ||
384 | |||
385 | spin_lock_irqsave(&(r)->producer_lock, flags); | ||
386 | |||
387 | old = __ptr_ring_swap_queue(r, queue, size, gfp, destroy); | ||
388 | |||
378 | spin_unlock_irqrestore(&(r)->producer_lock, flags); | 389 | spin_unlock_irqrestore(&(r)->producer_lock, flags); |
379 | 390 | ||
380 | kfree(old); | 391 | kfree(old); |
@@ -382,6 +393,48 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, | |||
382 | return 0; | 393 | return 0; |
383 | } | 394 | } |
384 | 395 | ||
396 | static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings, | ||
397 | int size, | ||
398 | gfp_t gfp, void (*destroy)(void *)) | ||
399 | { | ||
400 | unsigned long flags; | ||
401 | void ***queues; | ||
402 | int i; | ||
403 | |||
404 | queues = kmalloc(nrings * sizeof *queues, gfp); | ||
405 | if (!queues) | ||
406 | goto noqueues; | ||
407 | |||
408 | for (i = 0; i < nrings; ++i) { | ||
409 | queues[i] = __ptr_ring_init_queue_alloc(size, gfp); | ||
410 | if (!queues[i]) | ||
411 | goto nomem; | ||
412 | } | ||
413 | |||
414 | for (i = 0; i < nrings; ++i) { | ||
415 | spin_lock_irqsave(&(rings[i])->producer_lock, flags); | ||
416 | queues[i] = __ptr_ring_swap_queue(rings[i], queues[i], | ||
417 | size, gfp, destroy); | ||
418 | spin_unlock_irqrestore(&(rings[i])->producer_lock, flags); | ||
419 | } | ||
420 | |||
421 | for (i = 0; i < nrings; ++i) | ||
422 | kfree(queues[i]); | ||
423 | |||
424 | kfree(queues); | ||
425 | |||
426 | return 0; | ||
427 | |||
428 | nomem: | ||
429 | while (--i >= 0) | ||
430 | kfree(queues[i]); | ||
431 | |||
432 | kfree(queues); | ||
433 | |||
434 | noqueues: | ||
435 | return -ENOMEM; | ||
436 | } | ||
437 | |||
385 | static inline void ptr_ring_cleanup(struct ptr_ring *r, void (*destroy)(void *)) | 438 | static inline void ptr_ring_cleanup(struct ptr_ring *r, void (*destroy)(void *)) |
386 | { | 439 | { |
387 | void *ptr; | 440 | void *ptr; |