forked from mirrors/linux
		
	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: syzbot+e4d4f9ddd4295539735d@syzkaller.appspotmail.com
Fixes: 2e0ab8ca83 ("ptr_ring: array based FIFO for pointers")
Signed-off-by: Jason Wang <jasowang@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									6e6e41c311
								
							
						
					
					
						commit
						0bf7800f17
					
				
					 1 changed files with 8 additions and 5 deletions
				
			
		|  | @ -464,11 +464,14 @@ static inline int ptr_ring_consume_batched_bh(struct ptr_ring *r, | |||
| 	__PTR_RING_PEEK_CALL_v; \ | ||||
| }) | ||||
| 
 | ||||
| /* Not all gfp_t flags (besides GFP_KERNEL) are allowed. See
 | ||||
|  * documentation for vmalloc for which of them are legal. | ||||
|  */ | ||||
| static inline void **__ptr_ring_init_queue_alloc(unsigned int size, gfp_t gfp) | ||||
| { | ||||
| 	if (size * sizeof(void *) > KMALLOC_MAX_SIZE) | ||||
| 		return NULL; | ||||
| 	return kcalloc(size, sizeof(void *), gfp); | ||||
| 	return kvmalloc_array(size, sizeof(void *), gfp | __GFP_ZERO); | ||||
| } | ||||
| 
 | ||||
| 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, | |||
| 	spin_unlock(&(r)->producer_lock); | ||||
| 	spin_unlock_irqrestore(&(r)->consumer_lock, flags); | ||||
| 
 | ||||
| 	kfree(old); | ||||
| 	kvfree(old); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -643,7 +646,7 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, | |||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < nrings; ++i) | ||||
| 		kfree(queues[i]); | ||||
| 		kvfree(queues[i]); | ||||
| 
 | ||||
| 	kfree(queues); | ||||
| 
 | ||||
|  | @ -651,7 +654,7 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, | |||
| 
 | ||||
| nomem: | ||||
| 	while (--i >= 0) | ||||
| 		kfree(queues[i]); | ||||
| 		kvfree(queues[i]); | ||||
| 
 | ||||
| 	kfree(queues); | ||||
| 
 | ||||
|  | @ -666,7 +669,7 @@ static inline void ptr_ring_cleanup(struct ptr_ring *r, void (*destroy)(void *)) | |||
| 	if (destroy) | ||||
| 		while ((ptr = ptr_ring_consume(r))) | ||||
| 			destroy(ptr); | ||||
| 	kfree(r->queue); | ||||
| 	kvfree(r->queue); | ||||
| } | ||||
| 
 | ||||
| #endif /* _LINUX_PTR_RING_H  */ | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Jason Wang
						Jason Wang