Skip to content

Commit 0bf7800

Browse files
jasowangdavem330
authored andcommitted
ptr_ring: try vmalloc() when kmalloc() fails
This patch switch to use kvmalloc_array() for using a vmalloc() fallback to help in case kmalloc() fails. Reported-by: [email protected] Fixes: 2e0ab8c ("ptr_ring: array based FIFO for pointers") Signed-off-by: Jason Wang <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6e6e41c commit 0bf7800

File tree

1 file changed

+8
-5
lines changed

1 file changed

+8
-5
lines changed

include/linux/ptr_ring.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -464,11 +464,14 @@ static inline int ptr_ring_consume_batched_bh(struct ptr_ring *r,
464464
__PTR_RING_PEEK_CALL_v; \
465465
})
466466

467+
/* Not all gfp_t flags (besides GFP_KERNEL) are allowed. See
468+
* documentation for vmalloc for which of them are legal.
469+
*/
467470
static inline void **__ptr_ring_init_queue_alloc(unsigned int size, gfp_t gfp)
468471
{
469472
if (size * sizeof(void *) > KMALLOC_MAX_SIZE)
470473
return NULL;
471-
return kcalloc(size, sizeof(void *), gfp);
474+
return kvmalloc_array(size, sizeof(void *), gfp | __GFP_ZERO);
472475
}
473476

474477
static inline void __ptr_ring_set_size(struct ptr_ring *r, int size)
@@ -603,7 +606,7 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
603606
spin_unlock(&(r)->producer_lock);
604607
spin_unlock_irqrestore(&(r)->consumer_lock, flags);
605608

606-
kfree(old);
609+
kvfree(old);
607610

608611
return 0;
609612
}
@@ -643,15 +646,15 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings,
643646
}
644647

645648
for (i = 0; i < nrings; ++i)
646-
kfree(queues[i]);
649+
kvfree(queues[i]);
647650

648651
kfree(queues);
649652

650653
return 0;
651654

652655
nomem:
653656
while (--i >= 0)
654-
kfree(queues[i]);
657+
kvfree(queues[i]);
655658

656659
kfree(queues);
657660

@@ -666,7 +669,7 @@ static inline void ptr_ring_cleanup(struct ptr_ring *r, void (*destroy)(void *))
666669
if (destroy)
667670
while ((ptr = ptr_ring_consume(r)))
668671
destroy(ptr);
669-
kfree(r->queue);
672+
kvfree(r->queue);
670673
}
671674

672675
#endif /* _LINUX_PTR_RING_H */

0 commit comments

Comments
 (0)