Ejemplo n.º 1
0
static void *zcache_pampd_eph_create(char *data, size_t size, bool raw,
					struct tmem_handle *th)
{
	void *pampd = NULL, *cdata = data;
	unsigned clen = size;
	bool zero_filled = false;
	struct page *page = (struct page *)(data), *newpage;

	if (page_is_zero_filled(page)) {
		clen = 0;
		zero_filled = true;
		inc_zcache_zero_filled_pages();
		goto got_pampd;
	}

	if (!raw) {
		zcache_compress(page, &cdata, &clen);
		if (clen > zbud_max_buddy_size()) {
			inc_zcache_compress_poor();
			goto out;
		}
	} else {
		BUG_ON(clen > zbud_max_buddy_size());
	}

	/* look for space via an existing match first */
	pampd = (void *)zbud_match_prep(th, true, cdata, clen);
	if (pampd != NULL)
		goto got_pampd;

	/* no match, now we need to find (or free up) a full page */
	newpage = zcache_alloc_page();
	if (newpage != NULL)
		goto create_in_new_page;

	inc_zcache_failed_getfreepages();
	/* can't allocate a page, evict an ephemeral page via LRU */
	newpage = zcache_evict_eph_pageframe();
	if (newpage == NULL) {
		inc_zcache_eph_ate_tail_failed();
		goto out;
	}
	inc_zcache_eph_ate_tail();

create_in_new_page:
	pampd = (void *)zbud_create_prep(th, true, cdata, clen, newpage);
	BUG_ON(pampd == NULL);
	inc_zcache_eph_pageframes();

got_pampd:
	inc_zcache_eph_zbytes(clen);
	inc_zcache_eph_zpages();
	if (ramster_enabled && raw && !zero_filled)
		ramster_count_foreign_pages(true, 1);
	if (zero_filled)
		pampd = (void *)ZERO_FILLED;
out:
	return pampd;
}
Ejemplo n.º 2
0
static char *zbud_data(struct zbud_hdr *zh, unsigned size)
{
	struct zbud_page *zbpg;
	char *p;
	unsigned budnum;
    
	ASSERT_SENTINEL(zh, ZBH);
	budnum = zbud_budnum(zh);
	BUG_ON(size == 0 || size > zbud_max_buddy_size());
	zbpg = container_of(zh, struct zbud_page, buddy[budnum]);
	ASSERT_SPINLOCK(&zbpg->lock);
	p = (char *)zbpg;
	if (budnum == 0)
		p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) &
              CHUNK_MASK);
	else if (budnum == 1)
		p += PAGE_SIZE - ((size + CHUNK_SIZE - 1) & CHUNK_MASK);
	return p;
}
Ejemplo n.º 3
0
static inline unsigned zbud_size_to_chunks(unsigned size)
{
	BUG_ON(size == 0 || size > zbud_max_buddy_size());
	return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT;
}