Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23b1223c authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mm: zbud: fix the locking scenarios with zcache"

parents ba808ae0 6f739662
Loading
Loading
Loading
Loading
+16 −13
Original line number Diff line number Diff line
@@ -342,6 +342,7 @@ int zbud_alloc(struct zbud_pool *pool, size_t size, gfp_t gfp,
	struct zbud_header *zhdr = NULL;
	enum buddy bud;
	struct page *page;
	unsigned long flags;
	int found = 0;

	if (!size || (gfp & __GFP_HIGHMEM))
@@ -349,7 +350,7 @@ int zbud_alloc(struct zbud_pool *pool, size_t size, gfp_t gfp,
	if (size > PAGE_SIZE - ZHDR_SIZE_ALIGNED - CHUNK_SIZE)
		return -ENOSPC;
	chunks = size_to_chunks(size);
	spin_lock_bh(&pool->lock);
	spin_lock_irqsave(&pool->lock, flags);

	/* First, try to find an unbuddied zbud page. */
	zhdr = NULL;
@@ -368,11 +369,11 @@ int zbud_alloc(struct zbud_pool *pool, size_t size, gfp_t gfp,
	}

	/* Couldn't find unbuddied zbud page, create new one */
	spin_unlock_bh(&pool->lock);
	spin_unlock_irqrestore(&pool->lock, flags);
	page = alloc_page(gfp);
	if (!page)
		return -ENOMEM;
	spin_lock_bh(&pool->lock);
	spin_lock_irqsave(&pool->lock, flags);
	pool->pages_nr++;
	zhdr = init_zbud_page(page);
	bud = FIRST;
@@ -400,7 +401,7 @@ found:
	*handle = encode_handle(zhdr, bud);
	if ((gfp & __GFP_ZERO) && found)
		memset((void *)*handle, 0, size);
	spin_unlock_bh(&pool->lock);
	spin_unlock_irqrestore(&pool->lock, flags);

	return 0;
}
@@ -419,8 +420,9 @@ void zbud_free(struct zbud_pool *pool, unsigned long handle)
{
	struct zbud_header *zhdr;
	int freechunks;
	unsigned long flags;

	spin_lock_bh(&pool->lock);
	spin_lock_irqsave(&pool->lock, flags);
	zhdr = handle_to_zbud_header(handle);

	/* If first buddy, handle will be page aligned */
@@ -431,7 +433,7 @@ void zbud_free(struct zbud_pool *pool, unsigned long handle)

	if (zhdr->under_reclaim) {
		/* zbud page is under reclaim, reclaim will free */
		spin_unlock_bh(&pool->lock);
		spin_unlock_irqrestore(&pool->lock, flags);
		return;
	}

@@ -449,7 +451,7 @@ void zbud_free(struct zbud_pool *pool, unsigned long handle)
		list_add(&zhdr->buddy, &pool->unbuddied[freechunks]);
	}

	spin_unlock_bh(&pool->lock);
	spin_unlock_irqrestore(&pool->lock, flags);
}

#define list_tail_entry(ptr, type, member) \
@@ -494,12 +496,13 @@ int zbud_reclaim_page(struct zbud_pool *pool, unsigned int retries)
{
	int i, ret, freechunks;
	struct zbud_header *zhdr;
	unsigned long flags;
	unsigned long first_handle = 0, last_handle = 0;

	spin_lock_bh(&pool->lock);
	spin_lock_irqsave(&pool->lock, flags);
	if (!pool->ops || !pool->ops->evict || list_empty(&pool->lru) ||
			retries == 0) {
		spin_unlock_bh(&pool->lock);
		spin_unlock_irqrestore(&pool->lock, flags);
		return -EINVAL;
	}
	for (i = 0; i < retries; i++) {
@@ -518,7 +521,7 @@ int zbud_reclaim_page(struct zbud_pool *pool, unsigned int retries)
			first_handle = encode_handle(zhdr, FIRST);
		if (zhdr->last_chunks)
			last_handle = encode_handle(zhdr, LAST);
		spin_unlock_bh(&pool->lock);
		spin_unlock_irqrestore(&pool->lock, flags);

		/* Issue the eviction callback(s) */
		if (first_handle) {
@@ -532,7 +535,7 @@ int zbud_reclaim_page(struct zbud_pool *pool, unsigned int retries)
				goto next;
		}
next:
		spin_lock_bh(&pool->lock);
		spin_lock_irqsave(&pool->lock, flags);
		zhdr->under_reclaim = false;
		if (zhdr->first_chunks == 0 && zhdr->last_chunks == 0) {
			/*
@@ -541,7 +544,7 @@ next:
			 */
			free_zbud_page(zhdr);
			pool->pages_nr--;
			spin_unlock_bh(&pool->lock);
			spin_unlock_irqrestore(&pool->lock, flags);
			return 0;
		} else if (zhdr->first_chunks == 0 ||
				zhdr->last_chunks == 0) {
@@ -556,7 +559,7 @@ next:
		/* add to beginning of LRU */
		list_add(&zhdr->lru, &pool->lru);
	}
	spin_unlock_bh(&pool->lock);
	spin_unlock_irqrestore(&pool->lock, flags);
	return -EAGAIN;
}