LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCHv2 0/7] introduce dynamic device creation/removal
@ 2015-03-01 8:42 Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 1/7] zram: cosmetic ZRAM_ATTR_RO code formatting tweak Sergey Senozhatsky
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Sergey Senozhatsky @ 2015-03-01 8:42 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim
Cc: Nitin Gupta, linux-kernel, Sergey Senozhatsky, Sergey Senozhatsky
Hello,
This patchset introduces zram-control sysfs class, which has two sysfs
attrs:
- zram_add -- add a new specific (device_id) zram device
- zram_remove -- remove a specific (device_id) zram device
Usage example:
# add a new specific zram device
echo 4 > /sys/class/zram-control/zram_add
# remove a specific zram device
echo 4 > /sys/class/zram-control/zram_remove
Patch set also does some cleanups and huge code reorganization.
v2:
switch to sysfs class, rather than using /dev/zram-control node and
doing IOCTL on it. we lose some features, though. like automatic
device_id generation.
Sergey Senozhatsky (7):
zram: cosmetic ZRAM_ATTR_RO code formatting tweak
zram: use idr instead of `zram_devices' array
zram: factor out device reset from reset_store()
zram: reorganize code layout
zram: add dynamic device add/remove functionality
zram: remove max_num_devices limitation
zram: report every added and removed device
Documentation/ABI/testing/sysfs-class-zram | 23 +
drivers/block/zram/zram_drv.c | 780 +++++++++++++++++------------
drivers/block/zram/zram_drv.h | 6 -
3 files changed, 474 insertions(+), 335 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-class-zram
--
2.3.1.167.g7f4ba4b
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCHv2 1/7] zram: cosmetic ZRAM_ATTR_RO code formatting tweak
2015-03-01 8:42 [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
@ 2015-03-01 8:42 ` Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 2/7] zram: use idr instead of `zram_devices' array Sergey Senozhatsky
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sergey Senozhatsky @ 2015-03-01 8:42 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim
Cc: Nitin Gupta, linux-kernel, Sergey Senozhatsky, Sergey Senozhatsky
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
drivers/block/zram/zram_drv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 871bd35..8fc2566 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -44,7 +44,7 @@ static const char *default_compressor = "lzo";
static unsigned int num_devices = 1;
#define ZRAM_ATTR_RO(name) \
-static ssize_t name##_show(struct device *d, \
+static ssize_t name##_show(struct device *d, \
struct device_attribute *attr, char *b) \
{ \
struct zram *zram = dev_to_zram(d); \
--
2.3.1.167.g7f4ba4b
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 2/7] zram: use idr instead of `zram_devices' array
2015-03-01 8:42 [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 1/7] zram: cosmetic ZRAM_ATTR_RO code formatting tweak Sergey Senozhatsky
@ 2015-03-01 8:42 ` Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 3/7] zram: factor out device reset from reset_store() Sergey Senozhatsky
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sergey Senozhatsky @ 2015-03-01 8:42 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim
Cc: Nitin Gupta, linux-kernel, Sergey Senozhatsky, Sergey Senozhatsky
This patch makes some preparations for dynamic device ADD/REMOVE functionality
via /dev/zram-control interface.
Remove `zram_devices' array and switch to id-to-pointer translation (idr).
idr doesn't bloat zram struct with additional members, f.e. list_head, yet
still provides ability to match the device_id with the device pointer.
No user-space visible changes.
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
drivers/block/zram/zram_drv.c | 81 ++++++++++++++++++++++++-------------------
1 file changed, 46 insertions(+), 35 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 8fc2566..6707b7b 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -32,12 +32,12 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/err.h>
+#include <linux/idr.h>
#include "zram_drv.h"
-/* Globals */
+static DEFINE_IDR(zram_index_idr);
static int zram_major;
-static struct zram *zram_devices;
static const char *default_compressor = "lzo";
/* Module params (documentation at end) */
@@ -1061,18 +1061,28 @@ static struct attribute_group zram_disk_attr_group = {
.attrs = zram_disk_attrs,
};
-static int create_device(struct zram *zram, int device_id)
+static int zram_add(int device_id)
{
+ struct zram *zram;
struct request_queue *queue;
int ret = -ENOMEM;
+ zram = kzalloc(sizeof(struct zram), GFP_KERNEL);
+ if (!zram)
+ return ret;
+
+ ret = idr_alloc(&zram_index_idr, zram, device_id,
+ device_id + 1, GFP_KERNEL);
+ if (ret < 0)
+ goto out_free_dev;
+
init_rwsem(&zram->init_lock);
queue = blk_alloc_queue(GFP_KERNEL);
if (!queue) {
pr_err("Error allocating disk queue for device %d\n",
device_id);
- goto out;
+ goto out_free_idr;
}
blk_queue_make_request(queue, zram_make_request);
@@ -1141,34 +1151,42 @@ out_free_disk:
put_disk(zram->disk);
out_free_queue:
blk_cleanup_queue(queue);
-out:
+out_free_idr:
+ idr_remove(&zram_index_idr, device_id);
+out_free_dev:
+ kfree(zram);
return ret;
}
-static void destroy_devices(unsigned int nr)
+static void zram_remove(struct zram *zram)
{
- struct zram *zram;
- unsigned int i;
-
- for (i = 0; i < nr; i++) {
- zram = &zram_devices[i];
- /*
- * Remove sysfs first, so no one will perform a disksize
- * store while we destroy the devices
- */
- sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
- &zram_disk_attr_group);
+ /*
+ * Remove sysfs first, so no one will perform a disksize
+ * store while we destroy the devices
+ */
+ sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
+ &zram_disk_attr_group);
- zram_reset_device(zram);
+ zram_reset_device(zram);
+ idr_remove(&zram_index_idr, zram->disk->first_minor);
+ blk_cleanup_queue(zram->disk->queue);
+ del_gendisk(zram->disk);
+ put_disk(zram->disk);
+ kfree(zram);
+}
- blk_cleanup_queue(zram->disk->queue);
- del_gendisk(zram->disk);
- put_disk(zram->disk);
- }
+static int zram_exit_cb(int id, void *ptr, void *data)
+{
+ zram_remove(ptr);
+ return 0;
+}
- kfree(zram_devices);
+static void destroy_devices(void)
+{
+ idr_for_each(&zram_index_idr, &zram_exit_cb, NULL);
+ idr_destroy(&zram_index_idr);
unregister_blkdev(zram_major, "zram");
- pr_info("Destroyed %u device(s)\n", nr);
+ pr_info("Destroyed device(s)\n");
}
static int __init zram_init(void)
@@ -1187,16 +1205,9 @@ static int __init zram_init(void)
return -EBUSY;
}
- /* Allocate the device array and initialize each one */
- zram_devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL);
- if (!zram_devices) {
- unregister_blkdev(zram_major, "zram");
- return -ENOMEM;
- }
-
for (dev_id = 0; dev_id < num_devices; dev_id++) {
- ret = create_device(&zram_devices[dev_id], dev_id);
- if (ret)
+ ret = zram_add(dev_id);
+ if (ret != 0)
goto out_error;
}
@@ -1204,13 +1215,13 @@ static int __init zram_init(void)
return 0;
out_error:
- destroy_devices(dev_id);
+ destroy_devices();
return ret;
}
static void __exit zram_exit(void)
{
- destroy_devices(num_devices);
+ destroy_devices();
}
module_init(zram_init);
--
2.3.1.167.g7f4ba4b
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 3/7] zram: factor out device reset from reset_store()
2015-03-01 8:42 [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 1/7] zram: cosmetic ZRAM_ATTR_RO code formatting tweak Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 2/7] zram: use idr instead of `zram_devices' array Sergey Senozhatsky
@ 2015-03-01 8:42 ` Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 4/7] zram: reorganize code layout Sergey Senozhatsky
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sergey Senozhatsky @ 2015-03-01 8:42 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim
Cc: Nitin Gupta, linux-kernel, Sergey Senozhatsky, Sergey Senozhatsky
Device reset currently consists of two steps:
a) holding ->bd_mutex we ensure that there are no device users
(bdev->bd_openers)
b) and internal part (executed under bdev->bd_mutex and partially
under zram->init_lock) that resets the device - frees allocated
memory and returns the device back to its initial (un-init) state.
Dynamic device removal requires the same amount of work and checks.
We can reuse internal cleanup part (b) zram_reset_device(), but step (a)
is done in sysfs ATTR reset_store() handler.
Rename step (b) from zram_reset_device() to zram_reset_device_internal()
and factor out step (a) to zram_reset_device(). Both reset_store() and
dynamic device removal will use zram_reset_device().
For readability let's keep them separated.
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
drivers/block/zram/zram_drv.c | 135 +++++++++++++++++++++---------------------
1 file changed, 67 insertions(+), 68 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 6707b7b..59662dc 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -729,48 +729,6 @@ static void zram_bio_discard(struct zram *zram, u32 index,
}
}
-static void zram_reset_device(struct zram *zram)
-{
- 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);
-
- 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)
{
@@ -829,16 +787,54 @@ out_free_meta:
return err;
}
-static ssize_t reset_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
+/* internal device reset part -- cleanup allocated memory and
+ * return back to initial state */
+static void zram_reset_device_internal(struct zram *zram)
{
- int ret;
- unsigned short do_reset;
- struct zram *zram;
- struct block_device *bdev;
+ struct zram_meta *meta;
+ struct zcomp *comp;
+ u64 disksize;
- zram = dev_to_zram(dev);
- bdev = bdget_disk(zram->disk, 0);
+ 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);
+
+ 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 int zram_reset_device(struct zram *zram)
+{
+ int ret = 0;
+ struct block_device *bdev = bdget_disk(zram->disk, 0);
if (!bdev)
return -ENOMEM;
@@ -850,31 +846,34 @@ static ssize_t reset_store(struct device *dev,
goto out;
}
- ret = kstrtou16(buf, 10, &do_reset);
- if (ret)
- 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;
-
+ zram_reset_device_internal(zram);
out:
mutex_unlock(&bdev->bd_mutex);
bdput(bdev);
return ret;
}
+static ssize_t reset_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ int ret;
+ unsigned short do_reset;
+ struct zram *zram;
+
+ zram = dev_to_zram(dev);
+ ret = kstrtou16(buf, 10, &do_reset);
+ if (ret)
+ return ret;
+
+ if (!do_reset)
+ return -EINVAL;
+
+ ret = zram_reset_device(zram);
+ return ret ? ret : len;
+}
+
static void __zram_make_request(struct zram *zram, struct bio *bio)
{
int offset, rw;
@@ -1167,7 +1166,7 @@ static void zram_remove(struct zram *zram)
sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
&zram_disk_attr_group);
- zram_reset_device(zram);
+ zram_reset_device_internal(zram);
idr_remove(&zram_index_idr, zram->disk->first_minor);
blk_cleanup_queue(zram->disk->queue);
del_gendisk(zram->disk);
--
2.3.1.167.g7f4ba4b
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 4/7] zram: reorganize code layout
2015-03-01 8:42 [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
` (2 preceding siblings ...)
2015-03-01 8:42 ` [PATCHv2 3/7] zram: factor out device reset from reset_store() Sergey Senozhatsky
@ 2015-03-01 8:42 ` Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 5/7] zram: add dynamic device add/remove functionality Sergey Senozhatsky
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sergey Senozhatsky @ 2015-03-01 8:42 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim
Cc: Nitin Gupta, linux-kernel, Sergey Senozhatsky, Sergey Senozhatsky
This patch looks big, but basically it just moves code blocks forward
and backward. No functional changes.
Our current code layout looks a bit 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 void zram_reset_device_internal
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: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
drivers/block/zram/zram_drv.c | 593 +++++++++++++++++++++---------------------
1 file changed, 296 insertions(+), 297 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 59662dc..bab8b20 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -63,6 +63,119 @@ static inline struct zram *dev_to_zram(struct device *dev)
return (struct zram *)dev_to_disk(dev)->private_data;
}
+/* flag operations needs meta->tb_lock */
+static int zram_test_flag(struct zram_meta *meta, u32 index,
+ enum zram_pageflags flag)
+{
+ return meta->table[index].value & BIT(flag);
+}
+
+static void zram_set_flag(struct zram_meta *meta, u32 index,
+ enum zram_pageflags flag)
+{
+ meta->table[index].value |= BIT(flag);
+}
+
+static void zram_clear_flag(struct zram_meta *meta, u32 index,
+ enum zram_pageflags flag)
+{
+ meta->table[index].value &= ~BIT(flag);
+}
+
+static size_t zram_get_obj_size(struct zram_meta *meta, u32 index)
+{
+ return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
+}
+
+static void zram_set_obj_size(struct zram_meta *meta,
+ u32 index, size_t size)
+{
+ unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT;
+
+ 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 disksize_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -246,65 +359,25 @@ static ssize_t comp_algorithm_store(struct device *dev,
return len;
}
-/* flag operations needs meta->tb_lock */
-static int zram_test_flag(struct zram_meta *meta, u32 index,
- enum zram_pageflags flag)
-{
- return meta->table[index].value & BIT(flag);
-}
-
-static void zram_set_flag(struct zram_meta *meta, u32 index,
- enum zram_pageflags flag)
-{
- meta->table[index].value |= BIT(flag);
-}
-
-static void zram_clear_flag(struct zram_meta *meta, u32 index,
- enum zram_pageflags flag)
-{
- meta->table[index].value &= ~BIT(flag);
-}
-
-static size_t zram_get_obj_size(struct zram_meta *meta, u32 index)
-{
- return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
-}
-
-static void zram_set_obj_size(struct zram_meta *meta,
- u32 index, size_t size)
-{
- unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT;
-
- meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
-}
+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 int is_partial_io(struct bio_vec *bvec)
+static inline bool zram_meta_get(struct zram *zram)
{
- return bvec->bv_len != PAGE_SIZE;
+ if (atomic_inc_not_zero(&zram->refcount))
+ return true;
+ return false;
}
-/*
- * 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)
+static inline void zram_meta_put(struct zram *zram)
{
- 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;
+ atomic_dec(&zram->refcount);
}
static void zram_meta_free(struct zram_meta *meta, u64 disksize)
@@ -358,56 +431,6 @@ out_error:
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,
* caller should hold this table index entry's bit_spinlock to
@@ -440,6 +463,7 @@ static void zram_free_page(struct zram *zram, size_t index)
zram_set_obj_size(meta, index, 0);
}
+
static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
{
int ret = 0;
@@ -525,21 +549,6 @@ out_cleanup:
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,
int offset)
{
@@ -667,36 +676,13 @@ out:
return ret;
}
-static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
- int offset, int rw)
-{
- int ret;
-
- 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);
- }
-
- 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
- * @index: physical block index in PAGE_SIZE units
- * @offset: byte offset within physical block
- */
-static void zram_bio_discard(struct zram *zram, u32 index,
- int offset, struct bio *bio)
+/*
+ * zram_bio_discard - handler on discard request
+ * @index: physical block index in PAGE_SIZE units
+ * @offset: byte offset within physical block
+ */
+static void zram_bio_discard(struct zram *zram, u32 index,
+ int offset, struct bio *bio)
{
size_t n = bio->bi_iter.bi_size;
struct zram_meta *meta = zram->meta;
@@ -729,151 +715,29 @@ static void zram_bio_discard(struct zram *zram, u32 index,
}
}
-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;
-}
-
-/* internal device reset part -- cleanup allocated memory and
- * return back to initial state */
-static void zram_reset_device_internal(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;
+ int ret;
- if (!init_done(zram)) {
- up_write(&zram->init_lock);
- return;
+ 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);
}
- 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);
-
- 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 int zram_reset_device(struct zram *zram)
-{
- int ret = 0;
- struct block_device *bdev = bdget_disk(zram->disk, 0);
-
- if (!bdev)
- return -ENOMEM;
-
- mutex_lock(&bdev->bd_mutex);
- /* Do not reset an active device! */
- if (bdev->bd_openers) {
- ret = -EBUSY;
- goto out;
+ if (unlikely(ret)) {
+ if (rw == READ)
+ 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_internal(zram);
-out:
- mutex_unlock(&bdev->bd_mutex);
- bdput(bdev);
return ret;
}
-static ssize_t reset_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- int ret;
- unsigned short do_reset;
- struct zram *zram;
-
- zram = dev_to_zram(dev);
- ret = kstrtou16(buf, 10, &do_reset);
- if (ret)
- return ret;
-
- if (!do_reset)
- return -EINVAL;
-
- ret = zram_reset_device(zram);
- return ret ? ret : len;
-}
-
static void __zram_make_request(struct zram *zram, struct bio *bio)
{
int offset, rw;
@@ -928,9 +792,7 @@ out:
bio_io_error(bio);
}
-/*
- * Handler function for all zram I/O requests.
- */
+/* Handler function for all zram I/O requests */
static void zram_make_request(struct request_queue *queue, struct bio *bio)
{
struct zram *zram = queue->queuedata;
@@ -1010,6 +872,152 @@ out:
return err;
}
+/* internal device reset part -- cleanup allocated memory and
+ * return back to initial state */
+static void zram_reset_device_internal(struct zram *zram)
+{
+ 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);
+
+ 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 int zram_reset_device(struct zram *zram)
+{
+ int ret = 0;
+ struct block_device *bdev = bdget_disk(zram->disk, 0);
+
+ if (!bdev)
+ return -ENOMEM;
+
+ mutex_lock(&bdev->bd_mutex);
+ /* Do not reset an active device! */
+ if (bdev->bd_openers) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Make sure all pending I/O is finished */
+ fsync_bdev(bdev);
+ zram_reset_device_internal(zram);
+out:
+ mutex_unlock(&bdev->bd_mutex);
+ bdput(bdev);
+ return ret;
+}
+
+static ssize_t reset_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ int ret;
+ unsigned short do_reset;
+ struct zram *zram;
+
+ zram = dev_to_zram(dev);
+ ret = kstrtou16(buf, 10, &do_reset);
+ if (ret)
+ return ret;
+
+ if (!do_reset)
+ return -EINVAL;
+
+ ret = zram_reset_device(zram);
+ return ret ? ret : len;
+}
+
+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;
+}
+
+/* per-device block device operations and sysfs attrs */
static const struct block_device_operations zram_devops = {
.swap_slot_free_notify = zram_slot_free_notify,
.rw_page = zram_rw_page,
@@ -1026,15 +1034,6 @@ static DEVICE_ATTR_RW(mem_used_max);
static DEVICE_ATTR_RW(max_comp_streams);
static DEVICE_ATTR_RW(comp_algorithm);
-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 struct attribute *zram_disk_attrs[] = {
&dev_attr_disksize.attr,
&dev_attr_initstate.attr,
--
2.3.1.167.g7f4ba4b
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 5/7] zram: add dynamic device add/remove functionality
2015-03-01 8:42 [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
` (3 preceding siblings ...)
2015-03-01 8:42 ` [PATCHv2 4/7] zram: reorganize code layout Sergey Senozhatsky
@ 2015-03-01 8:42 ` Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 6/7] zram: remove max_num_devices limitation Sergey Senozhatsky
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sergey Senozhatsky @ 2015-03-01 8:42 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim
Cc: Nitin Gupta, linux-kernel, Sergey Senozhatsky, Sergey Senozhatsky
Introduce zram-control sysfs class, which has two sysfs attrs:
- zram_add -- add a new specific (device_id) zram device
- zram_remove -- remove a specific (device_id) zram device
Usage example:
# add a new specific zram device
echo 4 > /sys/class/zram-control/zram_add
# remove a specific zram device
echo 4 > /sys/class/zram-control/zram_remove
There is no automatic device_id generation, so user is expected to
provide one.
NOTE, there might be users who already depend on the fact that at
least zram0 device gets always created by zram_init(). Thus, due to
compatibility reasons, along with requested device_id (f.e. 5) zram0
will also be created.
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
Documentation/ABI/testing/sysfs-class-zram | 23 ++++++
drivers/block/zram/zram_drv.c | 117 +++++++++++++++++++++++++++++
2 files changed, 140 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-class-zram
diff --git a/Documentation/ABI/testing/sysfs-class-zram b/Documentation/ABI/testing/sysfs-class-zram
new file mode 100644
index 0000000..4cbde8d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-zram
@@ -0,0 +1,23 @@
+What: /sys/class/zram-control/
+Date: March 2015
+KernelVersion: 4.0
+Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+ The zram-control/ class sub-directory belongs to zram
+ device class
+
+What: /sys/class/zram-control/zram_add
+Date: March 2015
+KernelVersion: 4.0
+Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+ Add a specific /dev/zramX device, where X is a device_id
+ provided by user
+
+ What: /sys/class/zram-control/zram_add
+Date: March 2015
+KernelVersion: 4.0
+Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+ Remove a specific /dev/zramX device, where X is a device_id
+ provided by user
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index bab8b20..8609c92 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -33,16 +33,23 @@
#include <linux/vmalloc.h>
#include <linux/err.h>
#include <linux/idr.h>
+#include <linux/sysfs.h>
#include "zram_drv.h"
static DEFINE_IDR(zram_index_idr);
+/* idr index must be protected */
+static DEFINE_MUTEX(zram_index_mutex);
+
static int zram_major;
static const char *default_compressor = "lzo";
/* Module params (documentation at end) */
static unsigned int num_devices = 1;
+#define ZRAM_CTL_ADD 1
+#define ZRAM_CTL_REMOVE 2
+
#define ZRAM_ATTR_RO(name) \
static ssize_t name##_show(struct device *d, \
struct device_attribute *attr, char *b) \
@@ -1173,6 +1180,107 @@ static void zram_remove(struct zram *zram)
kfree(zram);
}
+/* lookup if there is any device pointer that match the given device_id.
+ * return device pointer if so, or ERR_PTR() otherwise. */
+static struct zram *zram_lookup(int dev_id)
+{
+ struct zram *zram;
+
+ zram = idr_find(&zram_index_idr, dev_id);
+ if (zram)
+ return zram;
+ return ERR_PTR(-ENODEV);
+}
+
+/* common zram-control add/remove handler */
+static int zram_control(int cmd, const char *buf)
+{
+ struct zram *zram;
+ int ret = -ENOSYS, err, dev_id;
+
+ /* dev_id is gendisk->first_minor, which is `int' */
+ ret = kstrtoint(buf, 10, &dev_id);
+ if (ret || dev_id < 0)
+ return ret;
+
+ mutex_lock(&zram_index_mutex);
+ zram = zram_lookup(dev_id);
+
+ switch (cmd) {
+ case ZRAM_CTL_ADD:
+ if (!IS_ERR(zram)) {
+ ret = -EEXIST;
+ break;
+ }
+ ret = zram_add(dev_id);
+ break;
+ case ZRAM_CTL_REMOVE:
+ if (IS_ERR(zram)) {
+ ret = PTR_ERR(zram);
+ break;
+ }
+
+ /* First, make ->disksize device attr RO, closing
+ * ZRAM_CTL_REMOVE vs disksize_store() race window */
+ ret = sysfs_chmod_file(&disk_to_dev(zram->disk)->kobj,
+ &dev_attr_disksize.attr, S_IRUGO);
+ if (ret)
+ break;
+
+ ret = zram_reset_device(zram);
+ if (ret == 0) {
+ /* ->disksize is RO and there are no ->bd_openers */
+ zram_remove(zram);
+ break;
+ }
+
+ /* If there are still device bd_openers, try to make ->disksize
+ * RW again and return. even if we fail to make ->disksize RW,
+ * user still has RW ->reset attr. so it's possible to destroy
+ * that device */
+ err = sysfs_chmod_file(&disk_to_dev(zram->disk)->kobj,
+ &dev_attr_disksize.attr,
+ S_IWUSR | S_IRUGO);
+ if (err)
+ ret = err;
+ break;
+ }
+ mutex_unlock(&zram_index_mutex);
+
+ return ret;
+}
+
+/* zram module control sysfs attributes */
+static ssize_t zram_add_store(struct class *class,
+ struct class_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = zram_control(ZRAM_CTL_ADD, buf);
+ return ret ? ret : count;
+}
+
+static ssize_t zram_remove_store(struct class *class,
+ struct class_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = zram_control(ZRAM_CTL_REMOVE, buf);
+ return ret ? ret : count;
+}
+
+static struct class_attribute zram_control_class_attrs[] = {
+ __ATTR_WO(zram_add),
+ __ATTR_WO(zram_remove),
+ __ATTR_NULL,
+};
+
+static struct class zram_control_class = {
+ .name = "zram-control",
+ .owner = THIS_MODULE,
+ .class_attrs = zram_control_class_attrs,
+};
+
static int zram_exit_cb(int id, void *ptr, void *data)
{
zram_remove(ptr);
@@ -1181,6 +1289,7 @@ static int zram_exit_cb(int id, void *ptr, void *data)
static void destroy_devices(void)
{
+ class_destroy(&zram_control_class);
idr_for_each(&zram_index_idr, &zram_exit_cb, NULL);
idr_destroy(&zram_index_idr);
unregister_blkdev(zram_major, "zram");
@@ -1197,6 +1306,12 @@ static int __init zram_init(void)
return -EINVAL;
}
+ ret = class_register(&zram_control_class);
+ if (ret) {
+ pr_warn("Unable to register zram-control class\n");
+ return ret;
+ }
+
zram_major = register_blkdev(0, "zram");
if (zram_major <= 0) {
pr_warn("Unable to get major number\n");
@@ -1204,7 +1319,9 @@ static int __init zram_init(void)
}
for (dev_id = 0; dev_id < num_devices; dev_id++) {
+ mutex_lock(&zram_index_mutex);
ret = zram_add(dev_id);
+ mutex_unlock(&zram_index_mutex);
if (ret != 0)
goto out_error;
}
--
2.3.1.167.g7f4ba4b
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 6/7] zram: remove max_num_devices limitation
2015-03-01 8:42 [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
` (4 preceding siblings ...)
2015-03-01 8:42 ` [PATCHv2 5/7] zram: add dynamic device add/remove functionality Sergey Senozhatsky
@ 2015-03-01 8:42 ` Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 7/7] zram: report every added and removed device Sergey Senozhatsky
2015-03-03 6:51 ` [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
7 siblings, 0 replies; 9+ messages in thread
From: Sergey Senozhatsky @ 2015-03-01 8:42 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim
Cc: Nitin Gupta, linux-kernel, Sergey Senozhatsky, Sergey Senozhatsky
Limiting the number of zram devices to 32 (default max_num_devices value)
is confusing, let's drop it. A user with 2TB or 4TB of RAM, for example,
can request as many devices as he can handle.
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
drivers/block/zram/zram_drv.c | 8 +-------
drivers/block/zram/zram_drv.h | 6 ------
2 files changed, 1 insertion(+), 13 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 8609c92..5664b75 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -1300,12 +1300,6 @@ static int __init zram_init(void)
{
int ret, dev_id;
- if (num_devices > max_num_devices) {
- pr_warn("Invalid value for num_devices: %u\n",
- num_devices);
- return -EINVAL;
- }
-
ret = class_register(&zram_control_class);
if (ret) {
pr_warn("Unable to register zram-control class\n");
@@ -1343,7 +1337,7 @@ module_init(zram_init);
module_exit(zram_exit);
module_param(num_devices, uint, 0);
-MODULE_PARM_DESC(num_devices, "Number of zram devices");
+MODULE_PARM_DESC(num_devices, "Number of pre-created zram devices");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 17056e5..60d14bc 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -20,12 +20,6 @@
#include "zcomp.h"
-/*
- * Some arbitrary value. This is just to catch
- * invalid value for num_devices module parameter.
- */
-static const unsigned max_num_devices = 32;
-
/*-- Configurable parameters */
/*
--
2.3.1.167.g7f4ba4b
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 7/7] zram: report every added and removed device
2015-03-01 8:42 [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
` (5 preceding siblings ...)
2015-03-01 8:42 ` [PATCHv2 6/7] zram: remove max_num_devices limitation Sergey Senozhatsky
@ 2015-03-01 8:42 ` Sergey Senozhatsky
2015-03-03 6:51 ` [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
7 siblings, 0 replies; 9+ messages in thread
From: Sergey Senozhatsky @ 2015-03-01 8:42 UTC (permalink / raw)
To: Andrew Morton, Minchan Kim
Cc: Nitin Gupta, linux-kernel, Sergey Senozhatsky, Sergey Senozhatsky
With dynamic device creation/removal printing num_devices in zram_init()
doesn't make a lot of sense, as well as printing the number of destroyed
devices in destroy_devices(). Print per-device action (added/removed) in
zram_add() and zram_remove() instead.
Example:
[ 3645.259652] zram: Added device: zram5
[ 3646.152074] zram: Added device: zram6
[ 3650.585012] zram: Removed device: zram5
[ 3655.845584] zram: Added device: zram8
[ 3660.975223] zram: Removed device: zram6
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
drivers/block/zram/zram_drv.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 5664b75..b870916 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -1149,6 +1149,8 @@ static int zram_add(int device_id)
strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
zram->meta = NULL;
zram->max_comp_streams = 1;
+
+ pr_info("Added device: %s\n", zram->disk->disk_name);
return 0;
out_free_disk:
@@ -1175,6 +1177,8 @@ static void zram_remove(struct zram *zram)
zram_reset_device_internal(zram);
idr_remove(&zram_index_idr, zram->disk->first_minor);
blk_cleanup_queue(zram->disk->queue);
+
+ pr_info("Removed device: %s\n", zram->disk->disk_name);
del_gendisk(zram->disk);
put_disk(zram->disk);
kfree(zram);
@@ -1293,7 +1297,6 @@ static void destroy_devices(void)
idr_for_each(&zram_index_idr, &zram_exit_cb, NULL);
idr_destroy(&zram_index_idr);
unregister_blkdev(zram_major, "zram");
- pr_info("Destroyed device(s)\n");
}
static int __init zram_init(void)
@@ -1320,7 +1323,6 @@ static int __init zram_init(void)
goto out_error;
}
- pr_info("Created %u device(s)\n", num_devices);
return 0;
out_error:
--
2.3.1.167.g7f4ba4b
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCHv2 0/7] introduce dynamic device creation/removal
2015-03-01 8:42 [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
` (6 preceding siblings ...)
2015-03-01 8:42 ` [PATCHv2 7/7] zram: report every added and removed device Sergey Senozhatsky
@ 2015-03-03 6:51 ` Sergey Senozhatsky
7 siblings, 0 replies; 9+ messages in thread
From: Sergey Senozhatsky @ 2015-03-03 6:51 UTC (permalink / raw)
To: Sergey Senozhatsky
Cc: Andrew Morton, Minchan Kim, Nitin Gupta, linux-kernel,
Sergey Senozhatsky
On (03/01/15 17:42), Sergey Senozhatsky wrote:
> v2:
> switch to sysfs class, rather than using /dev/zram-control node and
> doing IOCTL on it. we lose some features, though. like automatic
> device_id generation.
>
Hello,
will submit v3 later today:
-- add missing add/remove documentation
-- fix kernel version typo in class documentation
-- add new trivial cleanup patch
-ss
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-03-03 6:51 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-01 8:42 [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 1/7] zram: cosmetic ZRAM_ATTR_RO code formatting tweak Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 2/7] zram: use idr instead of `zram_devices' array Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 3/7] zram: factor out device reset from reset_store() Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 4/7] zram: reorganize code layout Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 5/7] zram: add dynamic device add/remove functionality Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 6/7] zram: remove max_num_devices limitation Sergey Senozhatsky
2015-03-01 8:42 ` [PATCHv2 7/7] zram: report every added and removed device Sergey Senozhatsky
2015-03-03 6:51 ` [PATCHv2 0/7] introduce dynamic device creation/removal Sergey Senozhatsky
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).