Commit 59e6ae53 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by David S. Miller

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: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarJason Wang <jasowang@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fd68adec
...@@ -349,20 +349,14 @@ static inline int ptr_ring_init(struct ptr_ring *r, int size, gfp_t gfp) ...@@ -349,20 +349,14 @@ static inline int ptr_ring_init(struct ptr_ring *r, int size, gfp_t gfp)
return 0; return 0;
} }
static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue,
void (*destroy)(void *)) int size, gfp_t gfp,
void (*destroy)(void *))
{ {
unsigned long flags;
int producer = 0; int producer = 0;
void **queue = __ptr_ring_init_queue_alloc(size, gfp);
void **old; void **old;
void *ptr; void *ptr;
if (!queue)
return -ENOMEM;
spin_lock_irqsave(&(r)->producer_lock, flags);
while ((ptr = ptr_ring_consume(r))) while ((ptr = ptr_ring_consume(r)))
if (producer < size) if (producer < size)
queue[producer++] = ptr; queue[producer++] = ptr;
...@@ -375,6 +369,23 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, ...@@ -375,6 +369,23 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
old = r->queue; old = r->queue;
r->queue = queue; r->queue = queue;
return old;
}
static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
void (*destroy)(void *))
{
unsigned long flags;
void **queue = __ptr_ring_init_queue_alloc(size, gfp);
void **old;
if (!queue)
return -ENOMEM;
spin_lock_irqsave(&(r)->producer_lock, flags);
old = __ptr_ring_swap_queue(r, queue, size, gfp, destroy);
spin_unlock_irqrestore(&(r)->producer_lock, flags); spin_unlock_irqrestore(&(r)->producer_lock, flags);
kfree(old); kfree(old);
...@@ -382,6 +393,48 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, ...@@ -382,6 +393,48 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
return 0; return 0;
} }
static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings,
int size,
gfp_t gfp, void (*destroy)(void *))
{
unsigned long flags;
void ***queues;
int i;
queues = kmalloc(nrings * sizeof *queues, gfp);
if (!queues)
goto noqueues;
for (i = 0; i < nrings; ++i) {
queues[i] = __ptr_ring_init_queue_alloc(size, gfp);
if (!queues[i])
goto nomem;
}
for (i = 0; i < nrings; ++i) {
spin_lock_irqsave(&(rings[i])->producer_lock, flags);
queues[i] = __ptr_ring_swap_queue(rings[i], queues[i],
size, gfp, destroy);
spin_unlock_irqrestore(&(rings[i])->producer_lock, flags);
}
for (i = 0; i < nrings; ++i)
kfree(queues[i]);
kfree(queues);
return 0;
nomem:
while (--i >= 0)
kfree(queues[i]);
kfree(queues);
noqueues:
return -ENOMEM;
}
static inline void ptr_ring_cleanup(struct ptr_ring *r, void (*destroy)(void *)) static inline void ptr_ring_cleanup(struct ptr_ring *r, void (*destroy)(void *))
{ {
void *ptr; void *ptr;
......
...@@ -17,6 +17,11 @@ ...@@ -17,6 +17,11 @@
typedef pthread_spinlock_t spinlock_t; typedef pthread_spinlock_t spinlock_t;
typedef int gfp_t; typedef int gfp_t;
static void *kmalloc(unsigned size, gfp_t gfp)
{
return memalign(64, size);
}
static void *kzalloc(unsigned size, gfp_t gfp) static void *kzalloc(unsigned size, gfp_t gfp)
{ {
void *p = memalign(64, size); void *p = memalign(64, size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment