Loading include/linux/vmalloc.h +1 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ extern void *__vmalloc_node_range(unsigned long size, unsigned long align, const void *caller); extern void vfree(const void *addr); extern void vfree_atomic(const void *addr); extern void *vmap(struct page **pages, unsigned int count, unsigned long flags, pgprot_t prot); Loading mm/vmalloc.c +36 −6 Original line number Diff line number Diff line Loading @@ -1554,6 +1554,38 @@ static void __vunmap(const void *addr, int deallocate_pages) return; } static inline void __vfree_deferred(const void *addr) { /* * Use raw_cpu_ptr() because this can be called from preemptible * context. Preemption is absolutely fine here, because the llist_add() * implementation is lockless, so it works even if we are adding to * nother cpu's list. schedule_work() should be fine with this too. */ struct vfree_deferred *p = raw_cpu_ptr(&vfree_deferred); if (llist_add((struct llist_node *)addr, &p->list)) schedule_work(&p->wq); } /** * vfree_atomic - release memory allocated by vmalloc() * @addr: memory base address * * This one is just like vfree() but can be called in any atomic context * except NMIs. */ void vfree_atomic(const void *addr) { BUG_ON(in_nmi()); kmemleak_free(addr); if (!addr) return; __vfree_deferred(addr); } /** * vfree - release memory allocated by vmalloc() * @addr: memory base address Loading @@ -1576,11 +1608,9 @@ void vfree(const void *addr) if (!addr) return; if (unlikely(in_interrupt())) { struct vfree_deferred *p = this_cpu_ptr(&vfree_deferred); if (llist_add((struct llist_node *)addr, &p->list)) schedule_work(&p->wq); } else if (unlikely(in_interrupt())) __vfree_deferred(addr); else __vunmap(addr, 1); } EXPORT_SYMBOL(vfree); Loading Loading
include/linux/vmalloc.h +1 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ extern void *__vmalloc_node_range(unsigned long size, unsigned long align, const void *caller); extern void vfree(const void *addr); extern void vfree_atomic(const void *addr); extern void *vmap(struct page **pages, unsigned int count, unsigned long flags, pgprot_t prot); Loading
mm/vmalloc.c +36 −6 Original line number Diff line number Diff line Loading @@ -1554,6 +1554,38 @@ static void __vunmap(const void *addr, int deallocate_pages) return; } static inline void __vfree_deferred(const void *addr) { /* * Use raw_cpu_ptr() because this can be called from preemptible * context. Preemption is absolutely fine here, because the llist_add() * implementation is lockless, so it works even if we are adding to * nother cpu's list. schedule_work() should be fine with this too. */ struct vfree_deferred *p = raw_cpu_ptr(&vfree_deferred); if (llist_add((struct llist_node *)addr, &p->list)) schedule_work(&p->wq); } /** * vfree_atomic - release memory allocated by vmalloc() * @addr: memory base address * * This one is just like vfree() but can be called in any atomic context * except NMIs. */ void vfree_atomic(const void *addr) { BUG_ON(in_nmi()); kmemleak_free(addr); if (!addr) return; __vfree_deferred(addr); } /** * vfree - release memory allocated by vmalloc() * @addr: memory base address Loading @@ -1576,11 +1608,9 @@ void vfree(const void *addr) if (!addr) return; if (unlikely(in_interrupt())) { struct vfree_deferred *p = this_cpu_ptr(&vfree_deferred); if (llist_add((struct llist_node *)addr, &p->list)) schedule_work(&p->wq); } else if (unlikely(in_interrupt())) __vfree_deferred(addr); else __vunmap(addr, 1); } EXPORT_SYMBOL(vfree); Loading