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

Commit beb6602c authored by Minchan Kim's avatar Minchan Kim Committed by Linus Torvalds
Browse files

zram: remove zram_meta structure

It's redundant now.  Instead, remove it and use zram structure directly.

Link: http://lkml.kernel.org/r/1492052365-16169-5-git-send-email-minchan@kernel.org


Signed-off-by: default avatarMinchan Kim <minchan@kernel.org>
Cc: Hannes Reinecke <hare@suse.com>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 86c49814
Loading
Loading
Loading
Loading
+77 −112
Original line number Diff line number Diff line
@@ -58,46 +58,46 @@ static inline struct zram *dev_to_zram(struct device *dev)
}

/* flag operations require table entry bit_spin_lock() being held */
static int zram_test_flag(struct zram_meta *meta, u32 index,
static int zram_test_flag(struct zram *zram, u32 index,
			enum zram_pageflags flag)
{
	return meta->table[index].value & BIT(flag);
	return zram->table[index].value & BIT(flag);
}

static void zram_set_flag(struct zram_meta *meta, u32 index,
static void zram_set_flag(struct zram *zram, u32 index,
			enum zram_pageflags flag)
{
	meta->table[index].value |= BIT(flag);
	zram->table[index].value |= BIT(flag);
}

static void zram_clear_flag(struct zram_meta *meta, u32 index,
static void zram_clear_flag(struct zram *zram, u32 index,
			enum zram_pageflags flag)
{
	meta->table[index].value &= ~BIT(flag);
	zram->table[index].value &= ~BIT(flag);
}

static inline void zram_set_element(struct zram_meta *meta, u32 index,
static inline void zram_set_element(struct zram *zram, u32 index,
			unsigned long element)
{
	meta->table[index].element = element;
	zram->table[index].element = element;
}

static inline void zram_clear_element(struct zram_meta *meta, u32 index)
static inline void zram_clear_element(struct zram *zram, u32 index)
{
	meta->table[index].element = 0;
	zram->table[index].element = 0;
}

static size_t zram_get_obj_size(struct zram_meta *meta, u32 index)
static size_t zram_get_obj_size(struct zram *zram, u32 index)
{
	return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
	return zram->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
}

static void zram_set_obj_size(struct zram_meta *meta,
static void zram_set_obj_size(struct zram *zram,
					u32 index, size_t size)
{
	unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT;
	unsigned long flags = zram->table[index].value >> ZRAM_FLAG_SHIFT;

	meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
	zram->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
}

#if PAGE_SIZE != 4096
@@ -250,9 +250,8 @@ static ssize_t mem_used_max_store(struct device *dev,

	down_read(&zram->init_lock);
	if (init_done(zram)) {
		struct zram_meta *meta = zram->meta;
		atomic_long_set(&zram->stats.max_used_pages,
				zs_get_total_pages(meta->mem_pool));
				zs_get_total_pages(zram->mem_pool));
	}
	up_read(&zram->init_lock);

@@ -325,7 +324,6 @@ static ssize_t compact_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t len)
{
	struct zram *zram = dev_to_zram(dev);
	struct zram_meta *meta;

	down_read(&zram->init_lock);
	if (!init_done(zram)) {
@@ -333,8 +331,7 @@ static ssize_t compact_store(struct device *dev,
		return -EINVAL;
	}

	meta = zram->meta;
	zs_compact(meta->mem_pool);
	zs_compact(zram->mem_pool);
	up_read(&zram->init_lock);

	return len;
@@ -371,8 +368,8 @@ static ssize_t mm_stat_show(struct device *dev,

	down_read(&zram->init_lock);
	if (init_done(zram)) {
		mem_used = zs_get_total_pages(zram->meta->mem_pool);
		zs_pool_stats(zram->meta->mem_pool, &pool_stats);
		mem_used = zs_get_total_pages(zram->mem_pool);
		zs_pool_stats(zram->mem_pool, &pool_stats);
	}

	orig_size = atomic64_read(&zram->stats.pages_stored);
@@ -415,32 +412,26 @@ static DEVICE_ATTR_RO(debug_stat);

static void zram_slot_lock(struct zram *zram, u32 index)
{
	struct zram_meta *meta = zram->meta;

	bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
	bit_spin_lock(ZRAM_ACCESS, &zram->table[index].value);
}

static void zram_slot_unlock(struct zram *zram, u32 index)
{
	struct zram_meta *meta = zram->meta;

	bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
	bit_spin_unlock(ZRAM_ACCESS, &zram->table[index].value);
}

static bool zram_same_page_read(struct zram *zram, u32 index,
				struct page *page,
				unsigned int offset, unsigned int len)
{
	struct zram_meta *meta = zram->meta;

	zram_slot_lock(zram, index);
	if (unlikely(!meta->table[index].handle) ||
			zram_test_flag(meta, index, ZRAM_SAME)) {
	if (unlikely(!zram->table[index].handle) ||
			zram_test_flag(zram, index, ZRAM_SAME)) {
		void *mem;

		zram_slot_unlock(zram, index);
		mem = kmap_atomic(page);
		zram_fill_page(mem + offset, len, meta->table[index].element);
		zram_fill_page(mem + offset, len, zram->table[index].element);
		kunmap_atomic(mem);
		return true;
	}
@@ -456,14 +447,12 @@ static bool zram_same_page_write(struct zram *zram, u32 index,
	void *mem = kmap_atomic(page);

	if (page_same_filled(mem, &element)) {
		struct zram_meta *meta = zram->meta;

		kunmap_atomic(mem);
		/* Free memory associated with this sector now. */
		zram_slot_lock(zram, index);
		zram_free_page(zram, index);
		zram_set_flag(meta, index, ZRAM_SAME);
		zram_set_element(meta, index, element);
		zram_set_flag(zram, index, ZRAM_SAME);
		zram_set_element(zram, index, element);
		zram_slot_unlock(zram, index);

		atomic64_inc(&zram->stats.same_pages);
@@ -474,56 +463,44 @@ static bool zram_same_page_write(struct zram *zram, u32 index,
	return false;
}

static void zram_meta_free(struct zram_meta *meta, u64 disksize)
static void zram_meta_free(struct zram *zram, u64 disksize)
{
	size_t num_pages = disksize >> PAGE_SHIFT;
	size_t index;

	/* Free all pages that are still in this zram device */
	for (index = 0; index < num_pages; index++) {
		unsigned long handle = meta->table[index].handle;
		unsigned long handle = zram->table[index].handle;
		/*
		 * No memory is allocated for same element filled pages.
		 * Simply clear same page flag.
		 */
		if (!handle || zram_test_flag(meta, index, ZRAM_SAME))
		if (!handle || zram_test_flag(zram, index, ZRAM_SAME))
			continue;

		zs_free(meta->mem_pool, handle);
		zs_free(zram->mem_pool, handle);
	}

	zs_destroy_pool(meta->mem_pool);
	vfree(meta->table);
	kfree(meta);
	zs_destroy_pool(zram->mem_pool);
	vfree(zram->table);
}

static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize)
static bool zram_meta_alloc(struct zram *zram, u64 disksize)
{
	size_t num_pages;
	struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);

	if (!meta)
		return NULL;

	num_pages = disksize >> PAGE_SHIFT;
	meta->table = vzalloc(num_pages * sizeof(*meta->table));
	if (!meta->table) {
		pr_err("Error allocating zram address table\n");
		goto out_error;
	}
	zram->table = vzalloc(num_pages * sizeof(*zram->table));
	if (!zram->table)
		return false;

	meta->mem_pool = zs_create_pool(pool_name);
	if (!meta->mem_pool) {
		pr_err("Error creating memory pool\n");
		goto out_error;
	zram->mem_pool = zs_create_pool(zram->disk->disk_name);
	if (!zram->mem_pool) {
		vfree(zram->table);
		return false;
	}

	return meta;

out_error:
	vfree(meta->table);
	kfree(meta);
	return NULL;
	return true;
}

/*
@@ -533,16 +510,15 @@ static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize)
 */
static void zram_free_page(struct zram *zram, size_t index)
{
	struct zram_meta *meta = zram->meta;
	unsigned long handle = meta->table[index].handle;
	unsigned long handle = zram->table[index].handle;

	/*
	 * No memory is allocated for same element filled pages.
	 * Simply clear same page flag.
	 */
	if (zram_test_flag(meta, index, ZRAM_SAME)) {
		zram_clear_flag(meta, index, ZRAM_SAME);
		zram_clear_element(meta, index);
	if (zram_test_flag(zram, index, ZRAM_SAME)) {
		zram_clear_flag(zram, index, ZRAM_SAME);
		zram_clear_element(zram, index);
		atomic64_dec(&zram->stats.same_pages);
		return;
	}
@@ -550,14 +526,14 @@ static void zram_free_page(struct zram *zram, size_t index)
	if (!handle)
		return;

	zs_free(meta->mem_pool, handle);
	zs_free(zram->mem_pool, handle);

	atomic64_sub(zram_get_obj_size(meta, index),
	atomic64_sub(zram_get_obj_size(zram, index),
			&zram->stats.compr_data_size);
	atomic64_dec(&zram->stats.pages_stored);

	meta->table[index].handle = 0;
	zram_set_obj_size(meta, index, 0);
	zram->table[index].handle = 0;
	zram_set_obj_size(zram, index, 0);
}

static int zram_decompress_page(struct zram *zram, struct page *page, u32 index)
@@ -566,16 +542,15 @@ static int zram_decompress_page(struct zram *zram, struct page *page, u32 index)
	unsigned long handle;
	unsigned int size;
	void *src, *dst;
	struct zram_meta *meta = zram->meta;

	if (zram_same_page_read(zram, index, page, 0, PAGE_SIZE))
		return 0;

	zram_slot_lock(zram, index);
	handle = meta->table[index].handle;
	size = zram_get_obj_size(meta, index);
	handle = zram->table[index].handle;
	size = zram_get_obj_size(zram, index);

	src = zs_map_object(meta->mem_pool, handle, ZS_MM_RO);
	src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
	if (size == PAGE_SIZE) {
		dst = kmap_atomic(page);
		memcpy(dst, src, PAGE_SIZE);
@@ -589,7 +564,7 @@ static int zram_decompress_page(struct zram *zram, struct page *page, u32 index)
		kunmap_atomic(dst);
		zcomp_stream_put(zram->comp);
	}
	zs_unmap_object(meta->mem_pool, handle);
	zs_unmap_object(zram->mem_pool, handle);
	zram_slot_unlock(zram, index);

	/* Should NEVER happen. Return bio error if it does. */
@@ -641,7 +616,6 @@ static int zram_compress(struct zram *zram, struct zcomp_strm **zstrm,
	void *src;
	unsigned long alloced_pages;
	unsigned long handle = 0;
	struct zram_meta *meta = zram->meta;

compress_again:
	src = kmap_atomic(page);
@@ -651,7 +625,7 @@ static int zram_compress(struct zram *zram, struct zcomp_strm **zstrm,
	if (unlikely(ret)) {
		pr_err("Compression failed! err=%d\n", ret);
		if (handle)
			zs_free(meta->mem_pool, handle);
			zs_free(zram->mem_pool, handle);
		return ret;
	}

@@ -672,7 +646,7 @@ static int zram_compress(struct zram *zram, struct zcomp_strm **zstrm,
	 * from the slow path and handle has already been allocated.
	 */
	if (!handle)
		handle = zs_malloc(meta->mem_pool, comp_len,
		handle = zs_malloc(zram->mem_pool, comp_len,
				__GFP_KSWAPD_RECLAIM |
				__GFP_NOWARN |
				__GFP_HIGHMEM |
@@ -680,7 +654,7 @@ static int zram_compress(struct zram *zram, struct zcomp_strm **zstrm,
	if (!handle) {
		zcomp_stream_put(zram->comp);
		atomic64_inc(&zram->stats.writestall);
		handle = zs_malloc(meta->mem_pool, comp_len,
		handle = zs_malloc(zram->mem_pool, comp_len,
				GFP_NOIO | __GFP_HIGHMEM |
				__GFP_MOVABLE);
		*zstrm = zcomp_stream_get(zram->comp);
@@ -689,11 +663,11 @@ static int zram_compress(struct zram *zram, struct zcomp_strm **zstrm,
		return -ENOMEM;
	}

	alloced_pages = zs_get_total_pages(meta->mem_pool);
	alloced_pages = zs_get_total_pages(zram->mem_pool);
	update_used_max(zram, alloced_pages);

	if (zram->limit_pages && alloced_pages > zram->limit_pages) {
		zs_free(meta->mem_pool, handle);
		zs_free(zram->mem_pool, handle);
		return -ENOMEM;
	}

@@ -709,7 +683,6 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index)
	unsigned int comp_len;
	void *src, *dst;
	struct zcomp_strm *zstrm;
	struct zram_meta *meta = zram->meta;
	struct page *page = bvec->bv_page;

	if (zram_same_page_write(zram, index, page))
@@ -722,8 +695,7 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index)
		return ret;
	}


	dst = zs_map_object(meta->mem_pool, handle, ZS_MM_WO);
	dst = zs_map_object(zram->mem_pool, handle, ZS_MM_WO);

	src = zstrm->buffer;
	if (comp_len == PAGE_SIZE)
@@ -733,7 +705,7 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index)
		kunmap_atomic(src);

	zcomp_stream_put(zram->comp);
	zs_unmap_object(meta->mem_pool, handle);
	zs_unmap_object(zram->mem_pool, handle);

	/*
	 * Free memory associated with this sector
@@ -741,8 +713,8 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index)
	 */
	zram_slot_lock(zram, index);
	zram_free_page(zram, index);
	meta->table[index].handle = handle;
	zram_set_obj_size(meta, index, comp_len);
	zram->table[index].handle = handle;
	zram_set_obj_size(zram, index, comp_len);
	zram_slot_unlock(zram, index);

	/* Update stats */
@@ -932,10 +904,8 @@ static void zram_slot_free_notify(struct block_device *bdev,
				unsigned long index)
{
	struct zram *zram;
	struct zram_meta *meta;

	zram = bdev->bd_disk->private_data;
	meta = zram->meta;

	zram_slot_lock(zram, index);
	zram_free_page(zram, index);
@@ -983,7 +953,6 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,

static void zram_reset_device(struct zram *zram)
{
	struct zram_meta *meta;
	struct zcomp *comp;
	u64 disksize;

@@ -996,7 +965,6 @@ static void zram_reset_device(struct zram *zram)
		return;
	}

	meta = zram->meta;
	comp = zram->comp;
	disksize = zram->disksize;

@@ -1009,7 +977,7 @@ static void zram_reset_device(struct zram *zram)

	up_write(&zram->init_lock);
	/* I/O operation under all of CPU are done so let's free */
	zram_meta_free(meta, disksize);
	zram_meta_free(zram, disksize);
	zcomp_destroy(comp);
}

@@ -1018,7 +986,6 @@ static ssize_t disksize_store(struct device *dev,
{
	u64 disksize;
	struct zcomp *comp;
	struct zram_meta *meta;
	struct zram *zram = dev_to_zram(dev);
	int err;

@@ -1026,10 +993,18 @@ static ssize_t disksize_store(struct device *dev,
	if (!disksize)
		return -EINVAL;

	down_write(&zram->init_lock);
	if (init_done(zram)) {
		pr_info("Cannot change disksize for initialized device\n");
		err = -EBUSY;
		goto out_unlock;
	}

	disksize = PAGE_ALIGN(disksize);
	meta = zram_meta_alloc(zram->disk->disk_name, disksize);
	if (!meta)
		return -ENOMEM;
	if (!zram_meta_alloc(zram, disksize)) {
		err = -ENOMEM;
		goto out_unlock;
	}

	comp = zcomp_create(zram->compressor);
	if (IS_ERR(comp)) {
@@ -1039,14 +1014,6 @@ static ssize_t disksize_store(struct device *dev,
		goto out_free_meta;
	}

	down_write(&zram->init_lock);
	if (init_done(zram)) {
		pr_info("Cannot change disksize for initialized device\n");
		err = -EBUSY;
		goto out_destroy_comp;
	}

	zram->meta = meta;
	zram->comp = comp;
	zram->disksize = disksize;
	set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
@@ -1055,11 +1022,10 @@ static ssize_t disksize_store(struct device *dev,

	return len;

out_destroy_comp:
	up_write(&zram->init_lock);
	zcomp_destroy(comp);
out_free_meta:
	zram_meta_free(meta, disksize);
	zram_meta_free(zram, disksize);
out_unlock:
	up_write(&zram->init_lock);
	return err;
}

@@ -1245,7 +1211,6 @@ static int zram_add(void)
		goto out_free_disk;
	}
	strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
	zram->meta = NULL;

	pr_info("Added device: %s\n", zram->disk->disk_name);
	return device_id;
+1 −5
Original line number Diff line number Diff line
@@ -92,13 +92,9 @@ struct zram_stats {
	atomic64_t writestall;		/* no. of write slow paths */
};

struct zram_meta {
struct zram {
	struct zram_table_entry *table;
	struct zs_pool *mem_pool;
};

struct zram {
	struct zram_meta *meta;
	struct zcomp *comp;
	struct gendisk *disk;
	/* Prevent concurrent execution of device init */