Commit 8174dafb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull slab fixes from Vlastimil Babka:

 - Fix for a memory leak that can occur when already so low on memory
   that we can't allocate a new slab anymore (Qing Wang)

 - Fix for a case where slabobj_ext array for a slab might be allocated
   from the same slab, making it permanently non-freeable (Harry Yoo)

* tag 'slab-for-7.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab:
  slab: fix memory leak when refill_sheaf() fails
  mm/slab: fix an incorrect check in obj_exts_alloc_size()
parents 92e989ac 464b1c11
Loading
Loading
Loading
Loading
+4 −7
Original line number Diff line number Diff line
@@ -2119,13 +2119,6 @@ static inline size_t obj_exts_alloc_size(struct kmem_cache *s,
	size_t sz = sizeof(struct slabobj_ext) * slab->objects;
	struct kmem_cache *obj_exts_cache;

	/*
	 * slabobj_ext array for KMALLOC_CGROUP allocations
	 * are served from KMALLOC_NORMAL caches.
	 */
	if (!mem_alloc_profiling_enabled())
		return sz;

	if (sz > KMALLOC_MAX_CACHE_SIZE)
		return sz;

@@ -2797,6 +2790,7 @@ static void free_empty_sheaf(struct kmem_cache *s, struct slab_sheaf *sheaf)
	if (s->flags & SLAB_KMALLOC)
		mark_obj_codetag_empty(sheaf);

	VM_WARN_ON_ONCE(sheaf->size > 0);
	kfree(sheaf);

	stat(s, SHEAF_FREE);
@@ -2828,6 +2822,7 @@ static int refill_sheaf(struct kmem_cache *s, struct slab_sheaf *sheaf,
	return 0;
}

static void sheaf_flush_unused(struct kmem_cache *s, struct slab_sheaf *sheaf);

static struct slab_sheaf *alloc_full_sheaf(struct kmem_cache *s, gfp_t gfp)
{
@@ -2837,6 +2832,7 @@ static struct slab_sheaf *alloc_full_sheaf(struct kmem_cache *s, gfp_t gfp)
		return NULL;

	if (refill_sheaf(s, sheaf, gfp | __GFP_NOMEMALLOC | __GFP_NOWARN)) {
		sheaf_flush_unused(s, sheaf);
		free_empty_sheaf(s, sheaf);
		return NULL;
	}
@@ -4623,6 +4619,7 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
			 * we must be very low on memory so don't bother
			 * with the barn
			 */
			sheaf_flush_unused(s, empty);
			free_empty_sheaf(s, empty);
		}
	} else {