mirror of https://gitee.com/openkylin/linux.git
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;
|
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,
|
||||||
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,
|
||||||
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 @@
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue