Commit 522698d7 authored by Sergey Senozhatsky's avatar Sergey Senozhatsky Committed by Linus Torvalds

zram: reorganize code layout

This patch looks big, but basically it just moves code blocks.
No functional changes.

Our current code layout looks like a sandwitch.

For example,
a) between read/write handlers, we have update_used_max() helper function:

static int zram_decompress_page
static int zram_bvec_read
static inline void update_used_max
static int zram_bvec_write
static int zram_bvec_rw

b) RW request handlers __zram_make_request/zram_bio_discard are divided by
sysfs attr reset_store() function and corresponding zram_reset_device()
handler:

static void zram_bio_discard
static void zram_reset_device
static ssize_t disksize_store
static ssize_t reset_store
static void __zram_make_request

c) we first a bunch of sysfs read/store functions. then a number of
one-liners, then helper functions, RW functions, sysfs functions, helper
functions again, and so on.

Reorganize layout to be more logically grouped (a brief description,
`cat zram_drv.c | grep static` gives a bigger picture):

-- one-liners: zram_test_flag/etc.

-- helpers: is_partial_io/update_position/etc

-- sysfs attr show/store functions + ZRAM_ATTR_RO() generated stats
show() functions
exception: reset and disksize store functions are required to be after
meta() functions. because we do device create/destroy actions in these
sysfs handlers.

-- "mm" functions: meta get/put, meta alloc/free, page free
static inline bool zram_meta_get
static inline void zram_meta_put
static void zram_meta_free
static struct zram_meta *zram_meta_alloc
static void zram_free_page

-- a block of I/O functions
static int zram_decompress_page
static int zram_bvec_read
static int zram_bvec_write
static void zram_bio_discard
static int zram_bvec_rw
static void __zram_make_request
static void zram_make_request
static void zram_slot_free_notify
static int zram_rw_page

-- device contol: add/remove/init/reset functions (+zram-control class
will sit here)
static int zram_reset_device
static ssize_t reset_store
static ssize_t disksize_store
static int zram_add
static void zram_remove
static int __init zram_init
static void __exit zram_exit
Signed-off-by: default avatarSergey Senozhatsky <sergey.senozhatsky@gmail.com>
Acked-by: default avatarMinchan Kim <minchan@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 85508ec6
...@@ -70,33 +70,117 @@ static inline struct zram *dev_to_zram(struct device *dev) ...@@ -70,33 +70,117 @@ static inline struct zram *dev_to_zram(struct device *dev)
return (struct zram *)dev_to_disk(dev)->private_data; return (struct zram *)dev_to_disk(dev)->private_data;
} }
static ssize_t compact_store(struct device *dev, /* flag operations needs meta->tb_lock */
struct device_attribute *attr, const char *buf, size_t len) static int zram_test_flag(struct zram_meta *meta, u32 index,
enum zram_pageflags flag)
{ {
unsigned long nr_migrated; return meta->table[index].value & BIT(flag);
struct zram *zram = dev_to_zram(dev); }
struct zram_meta *meta;
down_read(&zram->init_lock); static void zram_set_flag(struct zram_meta *meta, u32 index,
if (!init_done(zram)) { enum zram_pageflags flag)
up_read(&zram->init_lock); {
return -EINVAL; meta->table[index].value |= BIT(flag);
} }
meta = zram->meta; static void zram_clear_flag(struct zram_meta *meta, u32 index,
nr_migrated = zs_compact(meta->mem_pool); enum zram_pageflags flag)
atomic64_add(nr_migrated, &zram->stats.num_migrated); {
up_read(&zram->init_lock); meta->table[index].value &= ~BIT(flag);
}
return len; static size_t zram_get_obj_size(struct zram_meta *meta, u32 index)
{
return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
} }
static ssize_t disksize_show(struct device *dev, static void zram_set_obj_size(struct zram_meta *meta,
struct device_attribute *attr, char *buf) u32 index, size_t size)
{ {
struct zram *zram = dev_to_zram(dev); unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT;
return scnprintf(buf, PAGE_SIZE, "%llu\n", zram->disksize); meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
}
static inline int is_partial_io(struct bio_vec *bvec)
{
return bvec->bv_len != PAGE_SIZE;
}
/*
* Check if request is within bounds and aligned on zram logical blocks.
*/
static inline int valid_io_request(struct zram *zram,
sector_t start, unsigned int size)
{
u64 end, bound;
/* unaligned request */
if (unlikely(start & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
return 0;
if (unlikely(size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
return 0;
end = start + (size >> SECTOR_SHIFT);
bound = zram->disksize >> SECTOR_SHIFT;
/* out of range range */
if (unlikely(start >= bound || end > bound || start > end))
return 0;
/* I/O request is valid */
return 1;
}
static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
{
if (*offset + bvec->bv_len >= PAGE_SIZE)
(*index)++;
*offset = (*offset + bvec->bv_len) % PAGE_SIZE;
}
static inline void update_used_max(struct zram *zram,
const unsigned long pages)
{
unsigned long old_max, cur_max;
old_max = atomic_long_read(&zram->stats.max_used_pages);
do {
cur_max = old_max;
if (pages > cur_max)
old_max = atomic_long_cmpxchg(
&zram->stats.max_used_pages, cur_max, pages);
} while (old_max != cur_max);
}
static int page_zero_filled(void *ptr)
{
unsigned int pos;
unsigned long *page;
page = (unsigned long *)ptr;
for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) {
if (page[pos])
return 0;
}
return 1;
}
static void handle_zero_page(struct bio_vec *bvec)
{
struct page *page = bvec->bv_page;
void *user_mem;
user_mem = kmap_atomic(page);
if (is_partial_io(bvec))
memset(user_mem + bvec->bv_offset, 0, bvec->bv_len);
else
clear_page(user_mem);
kunmap_atomic(user_mem);
flush_dcache_page(page);
} }
static ssize_t initstate_show(struct device *dev, static ssize_t initstate_show(struct device *dev,
...@@ -112,6 +196,14 @@ static ssize_t initstate_show(struct device *dev, ...@@ -112,6 +196,14 @@ static ssize_t initstate_show(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%u\n", val); return scnprintf(buf, PAGE_SIZE, "%u\n", val);
} }
static ssize_t disksize_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct zram *zram = dev_to_zram(dev);
return scnprintf(buf, PAGE_SIZE, "%llu\n", zram->disksize);
}
static ssize_t orig_data_size_show(struct device *dev, static ssize_t orig_data_size_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -139,19 +231,6 @@ static ssize_t mem_used_total_show(struct device *dev, ...@@ -139,19 +231,6 @@ static ssize_t mem_used_total_show(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT); return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT);
} }
static ssize_t max_comp_streams_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int val;
struct zram *zram = dev_to_zram(dev);
down_read(&zram->init_lock);
val = zram->max_comp_streams;
up_read(&zram->init_lock);
return scnprintf(buf, PAGE_SIZE, "%d\n", val);
}
static ssize_t mem_limit_show(struct device *dev, static ssize_t mem_limit_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -221,6 +300,19 @@ static ssize_t mem_used_max_store(struct device *dev, ...@@ -221,6 +300,19 @@ static ssize_t mem_used_max_store(struct device *dev,
return len; return len;
} }
static ssize_t max_comp_streams_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int val;
struct zram *zram = dev_to_zram(dev);
down_read(&zram->init_lock);
val = zram->max_comp_streams;
up_read(&zram->init_lock);
return scnprintf(buf, PAGE_SIZE, "%d\n", val);
}
static ssize_t max_comp_streams_store(struct device *dev, static ssize_t max_comp_streams_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len) struct device_attribute *attr, const char *buf, size_t len)
{ {
...@@ -278,71 +370,101 @@ static ssize_t comp_algorithm_store(struct device *dev, ...@@ -278,71 +370,101 @@ static ssize_t comp_algorithm_store(struct device *dev,
return len; return len;
} }
/* flag operations needs meta->tb_lock */ static ssize_t compact_store(struct device *dev,
static int zram_test_flag(struct zram_meta *meta, u32 index, struct device_attribute *attr, const char *buf, size_t len)
enum zram_pageflags flag)
{ {
return meta->table[index].value & BIT(flag); unsigned long nr_migrated;
} struct zram *zram = dev_to_zram(dev);
struct zram_meta *meta;
static void zram_set_flag(struct zram_meta *meta, u32 index, down_read(&zram->init_lock);
enum zram_pageflags flag) if (!init_done(zram)) {
{ up_read(&zram->init_lock);
meta->table[index].value |= BIT(flag); return -EINVAL;
} }
static void zram_clear_flag(struct zram_meta *meta, u32 index, meta = zram->meta;
enum zram_pageflags flag) nr_migrated = zs_compact(meta->mem_pool);
{ atomic64_add(nr_migrated, &zram->stats.num_migrated);
meta->table[index].value &= ~BIT(flag); up_read(&zram->init_lock);
}
static size_t zram_get_obj_size(struct zram_meta *meta, u32 index) return len;
{
return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
} }
static void zram_set_obj_size(struct zram_meta *meta, static ssize_t io_stat_show(struct device *dev,
u32 index, size_t size) struct device_attribute *attr, char *buf)
{ {
unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT; struct zram *zram = dev_to_zram(dev);
ssize_t ret;
meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size; down_read(&zram->init_lock);
} ret = scnprintf(buf, PAGE_SIZE,
"%8llu %8llu %8llu %8llu\n",
(u64)atomic64_read(&zram->stats.failed_reads),
(u64)atomic64_read(&zram->stats.failed_writes),
(u64)atomic64_read(&zram->stats.invalid_io),
(u64)atomic64_read(&zram->stats.notify_free));
up_read(&zram->init_lock);
static inline int is_partial_io(struct bio_vec *bvec) return ret;
{
return bvec->bv_len != PAGE_SIZE;
} }
/* static ssize_t mm_stat_show(struct device *dev,
* Check if request is within bounds and aligned on zram logical blocks. struct device_attribute *attr, char *buf)
*/
static inline int valid_io_request(struct zram *zram,
sector_t start, unsigned int size)
{ {
u64 end, bound; struct zram *zram = dev_to_zram(dev);
u64 orig_size, mem_used = 0;
long max_used;
ssize_t ret;
/* unaligned request */ down_read(&zram->init_lock);
if (unlikely(start & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1))) if (init_done(zram))
return 0; mem_used = zs_get_total_pages(zram->meta->mem_pool);
if (unlikely(size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
return 0;
end = start + (size >> SECTOR_SHIFT); orig_size = atomic64_read(&zram->stats.pages_stored);
bound = zram->disksize >> SECTOR_SHIFT; max_used = atomic_long_read(&zram->stats.max_used_pages);
/* out of range range */
if (unlikely(start >= bound || end > bound || start > end))
return 0;
/* I/O request is valid */ ret = scnprintf(buf, PAGE_SIZE,
return 1; "%8llu %8llu %8llu %8lu %8ld %8llu %8llu\n",
} orig_size << PAGE_SHIFT,
(u64)atomic64_read(&zram->stats.compr_data_size),
mem_used << PAGE_SHIFT,
zram->limit_pages << PAGE_SHIFT,
max_used << PAGE_SHIFT,
(u64)atomic64_read(&zram->stats.zero_pages),
(u64)atomic64_read(&zram->stats.num_migrated));
up_read(&zram->init_lock);
static void zram_meta_free(struct zram_meta *meta, u64 disksize) return ret;
{ }
size_t num_pages = disksize >> PAGE_SHIFT;
size_t index; static DEVICE_ATTR_RO(io_stat);
static DEVICE_ATTR_RO(mm_stat);
ZRAM_ATTR_RO(num_reads);
ZRAM_ATTR_RO(num_writes);
ZRAM_ATTR_RO(failed_reads);
ZRAM_ATTR_RO(failed_writes);
ZRAM_ATTR_RO(invalid_io);
ZRAM_ATTR_RO(notify_free);
ZRAM_ATTR_RO(zero_pages);
ZRAM_ATTR_RO(compr_data_size);
static inline bool zram_meta_get(struct zram *zram)
{
if (atomic_inc_not_zero(&zram->refcount))
return true;
return false;
}
static inline void zram_meta_put(struct zram *zram)
{
atomic_dec(&zram->refcount);
}
static void zram_meta_free(struct zram_meta *meta, u64 disksize)
{
size_t num_pages = disksize >> PAGE_SHIFT;
size_t index;
/* Free all pages that are still in this zram device */ /* Free all pages that are still in this zram device */
for (index = 0; index < num_pages; index++) { for (index = 0; index < num_pages; index++) {
...@@ -390,56 +512,6 @@ static struct zram_meta *zram_meta_alloc(int device_id, u64 disksize) ...@@ -390,56 +512,6 @@ static struct zram_meta *zram_meta_alloc(int device_id, u64 disksize)
return NULL; return NULL;
} }
static inline bool zram_meta_get(struct zram *zram)
{
if (atomic_inc_not_zero(&zram->refcount))
return true;
return false;
}
static inline void zram_meta_put(struct zram *zram)
{
atomic_dec(&zram->refcount);
}
static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
{
if (*offset + bvec->bv_len >= PAGE_SIZE)
(*index)++;
*offset = (*offset + bvec->bv_len) % PAGE_SIZE;
}
static int page_zero_filled(void *ptr)
{
unsigned int pos;
unsigned long *page;
page = (unsigned long *)ptr;
for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) {
if (page[pos])
return 0;
}
return 1;
}
static void handle_zero_page(struct bio_vec *bvec)
{
struct page *page = bvec->bv_page;
void *user_mem;
user_mem = kmap_atomic(page);
if (is_partial_io(bvec))
memset(user_mem + bvec->bv_offset, 0, bvec->bv_len);
else
clear_page(user_mem);
kunmap_atomic(user_mem);
flush_dcache_page(page);
}
/* /*
* To protect concurrent access to the same index entry, * To protect concurrent access to the same index entry,
* caller should hold this table index entry's bit_spinlock to * caller should hold this table index entry's bit_spinlock to
...@@ -557,21 +629,6 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, ...@@ -557,21 +629,6 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
return ret; return ret;
} }
static inline void update_used_max(struct zram *zram,
const unsigned long pages)
{
unsigned long old_max, cur_max;
old_max = atomic_long_read(&zram->stats.max_used_pages);
do {
cur_max = old_max;
if (pages > cur_max)
old_max = atomic_long_cmpxchg(
&zram->stats.max_used_pages, cur_max, pages);
} while (old_max != cur_max);
}
static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
int offset) int offset)
{ {
...@@ -699,35 +756,6 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, ...@@ -699,35 +756,6 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
return ret; return ret;
} }
static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
int offset, int rw)
{
unsigned long start_time = jiffies;
int ret;
generic_start_io_acct(rw, bvec->bv_len >> SECTOR_SHIFT,
&zram->disk->part0);
if (rw == READ) {
atomic64_inc(&zram->stats.num_reads);
ret = zram_bvec_read(zram, bvec, index, offset);
} else {
atomic64_inc(&zram->stats.num_writes);
ret = zram_bvec_write(zram, bvec, index, offset);
}
generic_end_io_acct(rw, &zram->disk->part0, start_time);
if (unlikely(ret)) {
if (rw == READ)
atomic64_inc(&zram->stats.failed_reads);
else
atomic64_inc(&zram->stats.failed_writes);
}
return ret;
}
/* /*
* zram_bio_discard - handler on discard request * zram_bio_discard - handler on discard request
* @index: physical block index in PAGE_SIZE units * @index: physical block index in PAGE_SIZE units
...@@ -767,151 +795,32 @@ static void zram_bio_discard(struct zram *zram, u32 index, ...@@ -767,151 +795,32 @@ static void zram_bio_discard(struct zram *zram, u32 index,
} }
} }
static void zram_reset_device(struct zram *zram) static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
{ int offset, int rw)
struct zram_meta *meta;
struct zcomp *comp;
u64 disksize;
down_write(&zram->init_lock);
zram->limit_pages = 0;
if (!init_done(zram)) {
up_write(&zram->init_lock);
return;
}
meta = zram->meta;
comp = zram->comp;
disksize = zram->disksize;
/*
* Refcount will go down to 0 eventually and r/w handler
* cannot handle further I/O so it will bail out by
* check zram_meta_get.
*/
zram_meta_put(zram);
/*
* We want to free zram_meta in process context to avoid
* deadlock between reclaim path and any other locks.
*/
wait_event(zram->io_done, atomic_read(&zram->refcount) == 0);
/* Reset stats */
memset(&zram->stats, 0, sizeof(zram->stats));
zram->disksize = 0;
zram->max_comp_streams = 1;
set_capacity(zram->disk, 0);
part_stat_set_all(&zram->disk->part0, 0);
up_write(&zram->init_lock);
/* I/O operation under all of CPU are done so let's free */
zram_meta_free(meta, disksize);
zcomp_destroy(comp);
}
static ssize_t disksize_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
u64 disksize;
struct zcomp *comp;
struct zram_meta *meta;
struct zram *zram = dev_to_zram(dev);
int err;
disksize = memparse(buf, NULL);
if (!disksize)
return -EINVAL;
disksize = PAGE_ALIGN(disksize);
meta = zram_meta_alloc(zram->disk->first_minor, disksize);
if (!meta)
return -ENOMEM;
comp = zcomp_create(zram->compressor, zram->max_comp_streams);
if (IS_ERR(comp)) {
pr_info("Cannot initialise %s compressing backend\n",
zram->compressor);
err = PTR_ERR(comp);
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;
}
init_waitqueue_head(&zram->io_done);
atomic_set(&zram->refcount, 1);
zram->meta = meta;
zram->comp = comp;
zram->disksize = disksize;
set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
up_write(&zram->init_lock);
/*
* Revalidate disk out of the init_lock to avoid lockdep splat.
* It's okay because disk's capacity is protected by init_lock
* so that revalidate_disk always sees up-to-date capacity.
*/
revalidate_disk(zram->disk);
return len;
out_destroy_comp:
up_write(&zram->init_lock);
zcomp_destroy(comp);
out_free_meta:
zram_meta_free(meta, disksize);
return err;
}
static ssize_t reset_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{ {
unsigned long start_time = jiffies;
int ret; int ret;
unsigned short do_reset;
struct zram *zram;
struct block_device *bdev;
zram = dev_to_zram(dev); generic_start_io_acct(rw, bvec->bv_len >> SECTOR_SHIFT,
bdev = bdget_disk(zram->disk, 0); &zram->disk->part0);
if (!bdev)
return -ENOMEM;
mutex_lock(&bdev->bd_mutex); if (rw == READ) {
/* Do not reset an active device! */ atomic64_inc(&zram->stats.num_reads);
if (bdev->bd_openers) { ret = zram_bvec_read(zram, bvec, index, offset);
ret = -EBUSY; } else {
goto out; atomic64_inc(&zram->stats.num_writes);
ret = zram_bvec_write(zram, bvec, index, offset);
} }
ret = kstrtou16(buf, 10, &do_reset); generic_end_io_acct(rw, &zram->disk->part0, start_time);
if (ret)
goto out;
if (!do_reset) { if (unlikely(ret)) {
ret = -EINVAL; if (rw == READ)
goto out; atomic64_inc(&zram->stats.failed_reads);
else
atomic64_inc(&zram->stats.failed_writes);
} }
/* Make sure all pending I/O is finished */
fsync_bdev(bdev);
zram_reset_device(zram);
mutex_unlock(&bdev->bd_mutex);
revalidate_disk(zram->disk);
bdput(bdev);
return len;
out:
mutex_unlock(&bdev->bd_mutex);
bdput(bdev);
return ret; return ret;
} }
...@@ -1051,80 +960,170 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector, ...@@ -1051,80 +960,170 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
return err; return err;
} }
static const struct block_device_operations zram_devops = { static void zram_reset_device(struct zram *zram)
.swap_slot_free_notify = zram_slot_free_notify, {
.rw_page = zram_rw_page, struct zram_meta *meta;
.owner = THIS_MODULE struct zcomp *comp;
}; u64 disksize;
static DEVICE_ATTR_WO(compact); down_write(&zram->init_lock);
static DEVICE_ATTR_RW(disksize);
static DEVICE_ATTR_RO(initstate);
static DEVICE_ATTR_WO(reset);
static DEVICE_ATTR_RO(orig_data_size);
static DEVICE_ATTR_RO(mem_used_total);
static DEVICE_ATTR_RW(mem_limit);
static DEVICE_ATTR_RW(mem_used_max);
static DEVICE_ATTR_RW(max_comp_streams);
static DEVICE_ATTR_RW(comp_algorithm);
static ssize_t io_stat_show(struct device *dev, zram->limit_pages = 0;
struct device_attribute *attr, char *buf)
if (!init_done(zram)) {
up_write(&zram->init_lock);
return;
}
meta = zram->meta;
comp = zram->comp;
disksize = zram->disksize;
/*
* Refcount will go down to 0 eventually and r/w handler
* cannot handle further I/O so it will bail out by
* check zram_meta_get.
*/
zram_meta_put(zram);
/*
* We want to free zram_meta in process context to avoid
* deadlock between reclaim path and any other locks.
*/
wait_event(zram->io_done, atomic_read(&zram->refcount) == 0);
/* Reset stats */
memset(&zram->stats, 0, sizeof(zram->stats));
zram->disksize = 0;
zram->max_comp_streams = 1;
set_capacity(zram->disk, 0);
part_stat_set_all(&zram->disk->part0, 0);
up_write(&zram->init_lock);
/* I/O operation under all of CPU are done so let's free */
zram_meta_free(meta, disksize);
zcomp_destroy(comp);
}
static ssize_t disksize_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{ {
u64 disksize;
struct zcomp *comp;
struct zram_meta *meta;
struct zram *zram = dev_to_zram(dev); struct zram *zram = dev_to_zram(dev);
ssize_t ret; int err;
down_read(&zram->init_lock); disksize = memparse(buf, NULL);
ret = scnprintf(buf, PAGE_SIZE, if (!disksize)
"%8llu %8llu %8llu %8llu\n", return -EINVAL;
(u64)atomic64_read(&zram->stats.failed_reads),
(u64)atomic64_read(&zram->stats.failed_writes),
(u64)atomic64_read(&zram->stats.invalid_io),
(u64)atomic64_read(&zram->stats.notify_free));
up_read(&zram->init_lock);
return ret; disksize = PAGE_ALIGN(disksize);
meta = zram_meta_alloc(zram->disk->first_minor, disksize);
if (!meta)
return -ENOMEM;
comp = zcomp_create(zram->compressor, zram->max_comp_streams);
if (IS_ERR(comp)) {
pr_info("Cannot initialise %s compressing backend\n",
zram->compressor);
err = PTR_ERR(comp);
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;
}
init_waitqueue_head(&zram->io_done);
atomic_set(&zram->refcount, 1);
zram->meta = meta;
zram->comp = comp;
zram->disksize = disksize;
set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
up_write(&zram->init_lock);
/*
* Revalidate disk out of the init_lock to avoid lockdep splat.
* It's okay because disk's capacity is protected by init_lock
* so that revalidate_disk always sees up-to-date capacity.
*/
revalidate_disk(zram->disk);
return len;
out_destroy_comp:
up_write(&zram->init_lock);
zcomp_destroy(comp);
out_free_meta:
zram_meta_free(meta, disksize);
return err;
} }
static ssize_t mm_stat_show(struct device *dev, static ssize_t reset_store(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, const char *buf, size_t len)
{ {
struct zram *zram = dev_to_zram(dev); int ret;
u64 orig_size, mem_used = 0; unsigned short do_reset;
long max_used; struct zram *zram;
ssize_t ret; struct block_device *bdev;
down_read(&zram->init_lock); zram = dev_to_zram(dev);
if (init_done(zram)) bdev = bdget_disk(zram->disk, 0);
mem_used = zs_get_total_pages(zram->meta->mem_pool);
orig_size = atomic64_read(&zram->stats.pages_stored); if (!bdev)
max_used = atomic_long_read(&zram->stats.max_used_pages); return -ENOMEM;
ret = scnprintf(buf, PAGE_SIZE, mutex_lock(&bdev->bd_mutex);
"%8llu %8llu %8llu %8lu %8ld %8llu %8llu\n", /* Do not reset an active device! */
orig_size << PAGE_SHIFT, if (bdev->bd_openers) {
(u64)atomic64_read(&zram->stats.compr_data_size), ret = -EBUSY;
mem_used << PAGE_SHIFT, goto out;
zram->limit_pages << PAGE_SHIFT, }
max_used << PAGE_SHIFT,
(u64)atomic64_read(&zram->stats.zero_pages), ret = kstrtou16(buf, 10, &do_reset);
(u64)atomic64_read(&zram->stats.num_migrated)); if (ret)
up_read(&zram->init_lock); goto out;
if (!do_reset) {
ret = -EINVAL;
goto out;
}
/* Make sure all pending I/O is finished */
fsync_bdev(bdev);
zram_reset_device(zram);
mutex_unlock(&bdev->bd_mutex);
revalidate_disk(zram->disk);
bdput(bdev);
return len;
out:
mutex_unlock(&bdev->bd_mutex);
bdput(bdev);
return ret; return ret;
} }
static DEVICE_ATTR_RO(io_stat); static const struct block_device_operations zram_devops = {
static DEVICE_ATTR_RO(mm_stat); .swap_slot_free_notify = zram_slot_free_notify,
ZRAM_ATTR_RO(num_reads); .rw_page = zram_rw_page,
ZRAM_ATTR_RO(num_writes); .owner = THIS_MODULE
ZRAM_ATTR_RO(failed_reads); };
ZRAM_ATTR_RO(failed_writes);
ZRAM_ATTR_RO(invalid_io); static DEVICE_ATTR_WO(compact);
ZRAM_ATTR_RO(notify_free); static DEVICE_ATTR_RW(disksize);
ZRAM_ATTR_RO(zero_pages); static DEVICE_ATTR_RO(initstate);
ZRAM_ATTR_RO(compr_data_size); static DEVICE_ATTR_WO(reset);
static DEVICE_ATTR_RO(orig_data_size);
static DEVICE_ATTR_RO(mem_used_total);
static DEVICE_ATTR_RW(mem_limit);
static DEVICE_ATTR_RW(mem_used_max);
static DEVICE_ATTR_RW(max_comp_streams);
static DEVICE_ATTR_RW(comp_algorithm);
static struct attribute *zram_disk_attrs[] = { static struct attribute *zram_disk_attrs[] = {
&dev_attr_disksize.attr, &dev_attr_disksize.attr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment