forked from Minki/linux
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>
This commit is contained in:
parent
fd68adec9d
commit
59e6ae5324
@ -349,20 +349,14 @@ static inline int ptr_ring_init(struct ptr_ring *r, int size, gfp_t gfp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
|
||||
void (*destroy)(void *))
|
||||
static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue,
|
||||
int size, gfp_t gfp,
|
||||
void (*destroy)(void *))
|
||||
{
|
||||
unsigned long flags;
|
||||
int producer = 0;
|
||||
void **queue = __ptr_ring_init_queue_alloc(size, gfp);
|
||||
void **old;
|
||||
void *ptr;
|
||||
|
||||
if (!queue)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&(r)->producer_lock, flags);
|
||||
|
||||
while ((ptr = ptr_ring_consume(r)))
|
||||
if (producer < size)
|
||||
queue[producer++] = ptr;
|
||||
@ -375,6 +369,23 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
|
||||
old = r->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);
|
||||
|
||||
kfree(old);
|
||||
@ -382,6 +393,48 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
|
||||
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 *))
|
||||
{
|
||||
void *ptr;
|
||||
|
@ -17,6 +17,11 @@
|
||||
typedef pthread_spinlock_t spinlock_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)
|
||||
{
|
||||
void *p = memalign(64, size);
|
||||
|
Loading…
Reference in New Issue
Block a user