2010-06-01 08:01:27

by Nitin Gupta

[permalink] [raw]
Subject: [PATCH 0/4] zram: generic RAM based compressed R/W block devices (v2)

* Changelog v1 vs v2
- Split file rename and code rename patches
- Removed useless swap related includes from zram_drv.c
- Various cleanups suggested by Minchan:
- Documented rzs->lock mutex in ramzswap_drv.h (see patch 1)
(this file is renamed to zram_drv.h in patch 2)
- remove useless 'index' argument in handle_zero_page()
- Edited comments/messages mentioning 'swap'
- Removed redundant return from void zram_slot_free_notify()

Creates RAM based block devices: /dev/zramX (X = 0, 1, ...).
Pages written to these disks are compressed and stored in memory
itself. These disks allow very fast I/O and compression provides
good amounts of memory savings.

This is enhancement over existing ramzswap driver which creates
virtual block devices (/dev/ramzswapX) which could be used only
as swap disks.

Now, with the ability to handle any kind of I/O request, zram
devices have lot more use cases:
- /tmp storage
- various caches under /var
- swap disks
- CacheFiles storage
- maybe even more! :)

Performance numbers can be found at:
http://code.google.com/p/compcache/wiki/zramperf

Stress testing results:
http://code.google.com/p/compcache/wiki/zramIOzone

Patch 1 makes core changes to support handling generic I/O
requests. Subsequent patches rename ramzswap* files to zram*
and similar changes in code and documentation.

Nitin Gupta (4):
Support generic I/O requests
Rename ramzswap files to zram
Rename ramzswap to zram in code
Rename ramzswap to zram in documentation

drivers/staging/Kconfig | 2 +-
drivers/staging/Makefile | 2 +-
drivers/staging/ramzswap/Kconfig | 21 -
drivers/staging/ramzswap/Makefile | 3 -
drivers/staging/ramzswap/ramzswap.txt | 51 --
drivers/staging/ramzswap/ramzswap_drv.c | 837 --------------------
drivers/staging/zram/Kconfig | 28 +
drivers/staging/zram/Makefile | 3 +
drivers/staging/{ramzswap => zram}/xvmalloc.c | 0
drivers/staging/{ramzswap => zram}/xvmalloc.h | 0
drivers/staging/{ramzswap => zram}/xvmalloc_int.h | 0
drivers/staging/zram/zram.txt | 62 ++
drivers/staging/zram/zram_drv.c | 804 +++++++++++++++++++
.../{ramzswap/ramzswap_drv.h => zram/zram_drv.h} | 71 +-
.../ramzswap_ioctl.h => zram/zram_ioctl.h} | 21 +-
15 files changed, 943 insertions(+), 962 deletions(-)
delete mode 100644 drivers/staging/ramzswap/Kconfig
delete mode 100644 drivers/staging/ramzswap/Makefile
delete mode 100644 drivers/staging/ramzswap/ramzswap.txt
delete mode 100644 drivers/staging/ramzswap/ramzswap_drv.c
create mode 100644 drivers/staging/zram/Kconfig
create mode 100644 drivers/staging/zram/Makefile
rename drivers/staging/{ramzswap => zram}/xvmalloc.c (100%)
rename drivers/staging/{ramzswap => zram}/xvmalloc.h (100%)
rename drivers/staging/{ramzswap => zram}/xvmalloc_int.h (100%)
create mode 100644 drivers/staging/zram/zram.txt
create mode 100644 drivers/staging/zram/zram_drv.c
rename drivers/staging/{ramzswap/ramzswap_drv.h => zram/zram_drv.h} (69%)
rename drivers/staging/{ramzswap/ramzswap_ioctl.h => zram/zram_ioctl.h} (68%)


2010-06-01 08:01:33

by Nitin Gupta

[permalink] [raw]
Subject: [PATCH 1/4] Support generic I/O requests

Currently, ramzwap devices (/dev/ramzswapX) can only
be used as swap disks since it was hard-coded to consider
only the first request in bio vector.

Now, we iterate over all the segments in an incoming
bio which allows us to handle all kinds of I/O requests.

ramzswap devices can still handle PAGE_SIZE aligned and
multiple of PAGE_SIZE sized I/O requests only. To ensure
that we get always get such requests only, we set following
request_queue attributes to PAGE_SIZE:
- physical_block_size
- logical_block_size
- io_min
- io_opt

Note: physical and logical block sizes were already set
equal to PAGE_SIZE and that seems to be sufficient to get
PAGE_SIZE aligned I/O.

Since we are no longer limited to handling swap requests
only, the next few patches rename ramzswap to zram. So,
the devices will then be called /dev/zram{0, 1, 2, ...}

Usage/Examples:
1) Use as /tmp storage
- mkfs.ext4 /dev/zram0
- mount /dev/zram0 /tmp

2) Use as swap:
- mkswap /dev/zram0
- swapon /dev/zram0 -p 10 # give highest priority to zram0

Performance:

- I/O benchamark done with 'dd' command. Details can be
found here:
http://code.google.com/p/compcache/wiki/zramperf
Summary:
- Maximum read speed (approx):
- ram disk: 1200 MB/sec
- zram disk: 600 MB/sec
- Maximum write speed (approx):
- ram disk: 500 MB/sec
- zram disk: 160 MB/sec

Issues:

- Double caching: We can potentially waste memory by having
two copies of a page -- one in page cache (uncompress) and
second in the device memory (compressed). However, during
reclaim, clean page cache pages are quickly freed, so this
does not seem to be a big problem.

- Stale data: Not all filesystems support issuing 'discard'
requests to underlying block devices. So, if such filesystems
are used over zram devices, we can accumulate lot of stale
data in memory. Even for filesystems to do support discard
(example, ext4), we need to see how effective it is.

- Scalability: There is only one (per-device) de/compression
buffer stats. This can lead to significant contention, especially
when used for generic (non-swap) purposes.

Signed-off-by: Nitin Gupta <[email protected]>
---
drivers/staging/ramzswap/ramzswap_drv.c | 326 ++++++++++++++-----------------
drivers/staging/ramzswap/ramzswap_drv.h | 3 +-
2 files changed, 149 insertions(+), 180 deletions(-)

diff --git a/drivers/staging/ramzswap/ramzswap_drv.c b/drivers/staging/ramzswap/ramzswap_drv.c
index d14bf91..7b5cc61 100644
--- a/drivers/staging/ramzswap/ramzswap_drv.c
+++ b/drivers/staging/ramzswap/ramzswap_drv.c
@@ -101,20 +101,6 @@ static void ramzswap_set_disksize(struct ramzswap *rzs, size_t totalram_bytes)
rzs->disksize &= PAGE_MASK;
}

-/*
- * Swap header (1st page of swap device) contains information
- * about a swap file/partition. Prepare such a header for the
- * given ramzswap device so that swapon can identify it as a
- * swap partition.
- */
-static void setup_swap_header(struct ramzswap *rzs, union swap_header *s)
-{
- s->info.version = 1;
- s->info.last_page = (rzs->disksize >> PAGE_SHIFT) - 1;
- s->info.nr_badpages = 0;
- memcpy(s->magic.magic, "SWAPSPACE2", 10);
-}
-
static void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
struct ramzswap_ioctl_stats *s)
{
@@ -202,31 +188,22 @@ out:
rzs->table[index].offset = 0;
}

-static int handle_zero_page(struct bio *bio)
+static void handle_zero_page(struct page *page)
{
void *user_mem;
- struct page *page = bio->bi_io_vec[0].bv_page;

user_mem = kmap_atomic(page, KM_USER0);
memset(user_mem, 0, PAGE_SIZE);
kunmap_atomic(user_mem, KM_USER0);

flush_dcache_page(page);
-
- set_bit(BIO_UPTODATE, &bio->bi_flags);
- bio_endio(bio, 0);
- return 0;
}

-static int handle_uncompressed_page(struct ramzswap *rzs, struct bio *bio)
+static void handle_uncompressed_page(struct ramzswap *rzs,
+ struct page *page, u32 index)
{
- u32 index;
- struct page *page;
unsigned char *user_mem, *cmem;

- page = bio->bi_io_vec[0].bv_page;
- index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
-
user_mem = kmap_atomic(page, KM_USER0);
cmem = kmap_atomic(rzs->table[index].page, KM_USER1) +
rzs->table[index].offset;
@@ -236,79 +213,71 @@ static int handle_uncompressed_page(struct ramzswap *rzs, struct bio *bio)
kunmap_atomic(cmem, KM_USER1);

flush_dcache_page(page);
-
- set_bit(BIO_UPTODATE, &bio->bi_flags);
- bio_endio(bio, 0);
- return 0;
-}
-
-/*
- * Called when request page is not present in ramzswap.
- * This is an attempt to read before any previous write
- * to this location - this happens due to readahead when
- * swap device is read from user-space (e.g. during swapon)
- */
-static int handle_ramzswap_fault(struct ramzswap *rzs, struct bio *bio)
-{
- pr_debug("Read before write on swap device: "
- "sector=%lu, size=%u, offset=%u\n",
- (ulong)(bio->bi_sector), bio->bi_size,
- bio->bi_io_vec[0].bv_offset);
-
- /* Do nothing. Just return success */
- set_bit(BIO_UPTODATE, &bio->bi_flags);
- bio_endio(bio, 0);
- return 0;
}

static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)
{
- int ret;
+
+ int i;
u32 index;
- size_t clen;
- struct page *page;
- struct zobj_header *zheader;
- unsigned char *user_mem, *cmem;
+ struct bio_vec *bvec;

rzs_stat64_inc(rzs, &rzs->stats.num_reads);

- page = bio->bi_io_vec[0].bv_page;
index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+ bio_for_each_segment(bvec, bio, i) {
+ int ret;
+ size_t clen;
+ struct page *page;
+ struct zobj_header *zheader;
+ unsigned char *user_mem, *cmem;

- if (rzs_test_flag(rzs, index, RZS_ZERO))
- return handle_zero_page(bio);
+ page = bvec->bv_page;

- /* Requested page is not present in compressed area */
- if (!rzs->table[index].page)
- return handle_ramzswap_fault(rzs, bio);
+ if (rzs_test_flag(rzs, index, RZS_ZERO)) {
+ handle_zero_page(page);
+ continue;
+ }

- /* Page is stored uncompressed since it's incompressible */
- if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)))
- return handle_uncompressed_page(rzs, bio);
+ /* Requested page is not present in compressed area */
+ if (unlikely(!rzs->table[index].page)) {
+ pr_debug("Read before write: sector=%lu, size=%u",
+ (ulong)(bio->bi_sector), bio->bi_size);
+ /* Do nothing */
+ continue;
+ }

- user_mem = kmap_atomic(page, KM_USER0);
- clen = PAGE_SIZE;
+ /* Page is stored uncompressed since it's incompressible */
+ if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) {
+ handle_uncompressed_page(rzs, page, index);
+ continue;
+ }

- cmem = kmap_atomic(rzs->table[index].page, KM_USER1) +
- rzs->table[index].offset;
+ user_mem = kmap_atomic(page, KM_USER0);
+ clen = PAGE_SIZE;

- ret = lzo1x_decompress_safe(
- cmem + sizeof(*zheader),
- xv_get_object_size(cmem) - sizeof(*zheader),
- user_mem, &clen);
+ cmem = kmap_atomic(rzs->table[index].page, KM_USER1) +
+ rzs->table[index].offset;

- kunmap_atomic(user_mem, KM_USER0);
- kunmap_atomic(cmem, KM_USER1);
+ ret = lzo1x_decompress_safe(
+ cmem + sizeof(*zheader),
+ xv_get_object_size(cmem) - sizeof(*zheader),
+ user_mem, &clen);

- /* should NEVER happen */
- if (unlikely(ret != LZO_E_OK)) {
- pr_err("Decompression failed! err=%d, page=%u\n",
- ret, index);
- rzs_stat64_inc(rzs, &rzs->stats.failed_reads);
- goto out;
- }
+ kunmap_atomic(user_mem, KM_USER0);
+ kunmap_atomic(cmem, KM_USER1);

- flush_dcache_page(page);
+ /* Should NEVER happen. Return bio error if it does. */
+ if (unlikely(ret != LZO_E_OK)) {
+ pr_err("Decompression failed! err=%d, page=%u\n",
+ ret, index);
+ rzs_stat64_inc(rzs, &rzs->stats.failed_reads);
+ goto out;
+ }
+
+ flush_dcache_page(page);
+ index++;
+ }

set_bit(BIO_UPTODATE, &bio->bi_flags);
bio_endio(bio, 0);
@@ -321,108 +290,120 @@ out:

static int ramzswap_write(struct ramzswap *rzs, struct bio *bio)
{
- int ret;
- u32 offset, index;
- size_t clen;
- struct zobj_header *zheader;
- struct page *page, *page_store;
- unsigned char *user_mem, *cmem, *src;
+ int i;
+ u32 index;
+ struct bio_vec *bvec;

rzs_stat64_inc(rzs, &rzs->stats.num_writes);

- page = bio->bi_io_vec[0].bv_page;
index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;

- src = rzs->compress_buffer;
+ bio_for_each_segment(bvec, bio, i) {
+ int ret;
+ u32 offset;
+ size_t clen;
+ struct zobj_header *zheader;
+ struct page *page, *page_store;
+ unsigned char *user_mem, *cmem, *src;

- mutex_lock(&rzs->lock);
+ page = bvec->bv_page;
+ src = rzs->compress_buffer;

- user_mem = kmap_atomic(page, KM_USER0);
- if (page_zero_filled(user_mem)) {
- kunmap_atomic(user_mem, KM_USER0);
- mutex_unlock(&rzs->lock);
- rzs_stat_inc(&rzs->stats.pages_zero);
- rzs_set_flag(rzs, index, RZS_ZERO);
+ /*
+ * System overwrites unused sectors. Free memory associated
+ * with this sector now.
+ */
+ if (rzs->table[index].page ||
+ rzs_test_flag(rzs, index, RZS_ZERO))
+ ramzswap_free_page(rzs, index);

- set_bit(BIO_UPTODATE, &bio->bi_flags);
- bio_endio(bio, 0);
- return 0;
- }
+ mutex_lock(&rzs->lock);

- ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen,
- rzs->compress_workmem);
+ user_mem = kmap_atomic(page, KM_USER0);
+ if (page_zero_filled(user_mem)) {
+ kunmap_atomic(user_mem, KM_USER0);
+ mutex_unlock(&rzs->lock);
+ rzs_stat_inc(&rzs->stats.pages_zero);
+ rzs_set_flag(rzs, index, RZS_ZERO);
+ continue;
+ }

- kunmap_atomic(user_mem, KM_USER0);
+ ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen,
+ rzs->compress_workmem);

- if (unlikely(ret != LZO_E_OK)) {
- mutex_unlock(&rzs->lock);
- pr_err("Compression failed! err=%d\n", ret);
- rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
- goto out;
- }
+ kunmap_atomic(user_mem, KM_USER0);

- /*
- * Page is incompressible. Store it as-is (uncompressed)
- * since we do not want to return too many swap write
- * errors which has side effect of hanging the system.
- */
- if (unlikely(clen > max_zpage_size)) {
- clen = PAGE_SIZE;
- page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
- if (unlikely(!page_store)) {
+ if (unlikely(ret != LZO_E_OK)) {
mutex_unlock(&rzs->lock);
- pr_info("Error allocating memory for incompressible "
- "page: %u\n", index);
+ pr_err("Compression failed! err=%d\n", ret);
rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
goto out;
}

- offset = 0;
- rzs_set_flag(rzs, index, RZS_UNCOMPRESSED);
- rzs_stat_inc(&rzs->stats.pages_expand);
- rzs->table[index].page = page_store;
- src = kmap_atomic(page, KM_USER0);
- goto memstore;
- }
+ /*
+ * Page is incompressible. Store it as-is (uncompressed)
+ * since we do not want to return too many swap write
+ * errors which has side effect of hanging the system.
+ */
+ if (unlikely(clen > max_zpage_size)) {
+ clen = PAGE_SIZE;
+ page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+ if (unlikely(!page_store)) {
+ mutex_unlock(&rzs->lock);
+ pr_info("Error allocating memory for "
+ "incompressible page: %u\n", index);
+ rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
+ goto out;
+ }
+
+ offset = 0;
+ rzs_set_flag(rzs, index, RZS_UNCOMPRESSED);
+ rzs_stat_inc(&rzs->stats.pages_expand);
+ rzs->table[index].page = page_store;
+ src = kmap_atomic(page, KM_USER0);
+ goto memstore;
+ }

- if (xv_malloc(rzs->mem_pool, clen + sizeof(*zheader),
- &rzs->table[index].page, &offset,
- GFP_NOIO | __GFP_HIGHMEM)) {
- mutex_unlock(&rzs->lock);
- pr_info("Error allocating memory for compressed "
- "page: %u, size=%zu\n", index, clen);
- rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
- goto out;
- }
+ if (xv_malloc(rzs->mem_pool, clen + sizeof(*zheader),
+ &rzs->table[index].page, &offset,
+ GFP_NOIO | __GFP_HIGHMEM)) {
+ mutex_unlock(&rzs->lock);
+ pr_info("Error allocating memory for compressed "
+ "page: %u, size=%zu\n", index, clen);
+ rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
+ goto out;
+ }

memstore:
- rzs->table[index].offset = offset;
+ rzs->table[index].offset = offset;

- cmem = kmap_atomic(rzs->table[index].page, KM_USER1) +
- rzs->table[index].offset;
+ cmem = kmap_atomic(rzs->table[index].page, KM_USER1) +
+ rzs->table[index].offset;

#if 0
- /* Back-reference needed for memory defragmentation */
- if (!rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)) {
- zheader = (struct zobj_header *)cmem;
- zheader->table_idx = index;
- cmem += sizeof(*zheader);
- }
+ /* Back-reference needed for memory defragmentation */
+ if (!rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)) {
+ zheader = (struct zobj_header *)cmem;
+ zheader->table_idx = index;
+ cmem += sizeof(*zheader);
+ }
#endif

- memcpy(cmem, src, clen);
+ memcpy(cmem, src, clen);

- kunmap_atomic(cmem, KM_USER1);
- if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)))
- kunmap_atomic(src, KM_USER0);
+ kunmap_atomic(cmem, KM_USER1);
+ if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)))
+ kunmap_atomic(src, KM_USER0);

- /* Update stats */
- rzs->stats.compr_size += clen;
- rzs_stat_inc(&rzs->stats.pages_stored);
- if (clen <= PAGE_SIZE / 2)
- rzs_stat_inc(&rzs->stats.good_compress);
+ /* Update stats */
+ rzs->stats.compr_size += clen;
+ rzs_stat_inc(&rzs->stats.pages_stored);
+ if (clen <= PAGE_SIZE / 2)
+ rzs_stat_inc(&rzs->stats.good_compress);

- mutex_unlock(&rzs->lock);
+ mutex_unlock(&rzs->lock);
+ index++;
+ }

set_bit(BIO_UPTODATE, &bio->bi_flags);
bio_endio(bio, 0);
@@ -436,19 +417,17 @@ out:
/*
* Check if request is within bounds and page aligned.
*/
-static inline int valid_swap_request(struct ramzswap *rzs, struct bio *bio)
+static inline int valid_io_request(struct ramzswap *rzs, struct bio *bio)
{
if (unlikely(
(bio->bi_sector >= (rzs->disksize >> SECTOR_SHIFT)) ||
(bio->bi_sector & (SECTORS_PER_PAGE - 1)) ||
- (bio->bi_vcnt != 1) ||
- (bio->bi_size != PAGE_SIZE) ||
- (bio->bi_io_vec[0].bv_offset != 0))) {
+ (bio->bi_size & (PAGE_SIZE - 1)))) {

return 0;
}

- /* swap request is valid */
+ /* I/O request is valid */
return 1;
}

@@ -465,7 +444,7 @@ static int ramzswap_make_request(struct request_queue *queue, struct bio *bio)
return 0;
}

- if (!valid_swap_request(rzs, bio)) {
+ if (!valid_io_request(rzs, bio)) {
rzs_stat64_inc(rzs, &rzs->stats.invalid_io);
bio_io_error(bio);
return 0;
@@ -531,8 +510,6 @@ static int ramzswap_ioctl_init_device(struct ramzswap *rzs)
{
int ret;
size_t num_pages;
- struct page *page;
- union swap_header *swap_header;

if (rzs->init_done) {
pr_info("Device already initialized!\n");
@@ -566,19 +543,6 @@ static int ramzswap_ioctl_init_device(struct ramzswap *rzs)
}
memset(rzs->table, 0, num_pages * sizeof(*rzs->table));

- page = alloc_page(__GFP_ZERO);
- if (!page) {
- pr_err("Error allocating swap header page\n");
- ret = -ENOMEM;
- goto fail;
- }
- rzs->table[0].page = page;
- rzs_set_flag(rzs, 0, RZS_UNCOMPRESSED);
-
- swap_header = kmap(page);
- setup_swap_header(rzs, swap_header);
- kunmap(page);
-
set_capacity(rzs->disk, rzs->disksize >> SECTOR_SHIFT);

/* ramzswap devices sort of resembles non-rotational disks */
@@ -689,11 +653,9 @@ void ramzswap_slot_free_notify(struct block_device *bdev, unsigned long index)
rzs = bdev->bd_disk->private_data;
ramzswap_free_page(rzs, index);
rzs_stat64_inc(rzs, &rzs->stats.notify_free);
-
- return;
}

-static struct block_device_operations ramzswap_devops = {
+static const struct block_device_operations ramzswap_devops = {
.ioctl = ramzswap_ioctl,
.swap_slot_free_notify = ramzswap_slot_free_notify,
.owner = THIS_MODULE
@@ -737,8 +699,14 @@ static int create_device(struct ramzswap *rzs, int device_id)
/* Actual capacity set using RZSIO_SET_DISKSIZE_KB ioctl */
set_capacity(rzs->disk, 0);

+ /*
+ * To ensure that we always get PAGE_SIZE aligned
+ * and n*PAGE_SIZED sized I/O requests.
+ */
blk_queue_physical_block_size(rzs->disk->queue, PAGE_SIZE);
blk_queue_logical_block_size(rzs->disk->queue, PAGE_SIZE);
+ blk_queue_io_min(rzs->disk->queue, PAGE_SIZE);
+ blk_queue_io_opt(rzs->disk->queue, PAGE_SIZE);

add_disk(rzs->disk);

diff --git a/drivers/staging/ramzswap/ramzswap_drv.h b/drivers/staging/ramzswap/ramzswap_drv.h
index 63c3042..ad91726 100644
--- a/drivers/staging/ramzswap/ramzswap_drv.h
+++ b/drivers/staging/ramzswap/ramzswap_drv.h
@@ -112,7 +112,8 @@ struct ramzswap {
void *compress_buffer;
struct table *table;
spinlock_t stat64_lock; /* protect 64-bit stats */
- struct mutex lock;
+ struct mutex lock; /* protect compression buffers against
+ * concurrent writes */
struct request_queue *queue;
struct gendisk *disk;
int init_done;
--
1.7.0.1

2010-06-01 08:01:38

by Nitin Gupta

[permalink] [raw]
Subject: [PATCH 2/4] Rename ramzswap files to zram

Related changes:
- Modify revelant Kconfig and Makefile accordingly.
- Change include filenames in code.
- Remove dependency on CONFIG_SWAP in Kconfig as zram usage
is no longer limited to swap disks.

Signed-off-by: Nitin Gupta <[email protected]>
---
drivers/staging/Kconfig | 2 +-
drivers/staging/Makefile | 2 +-
drivers/staging/ramzswap/Kconfig | 21 ---------------
drivers/staging/ramzswap/Makefile | 3 --
drivers/staging/zram/Kconfig | 28 ++++++++++++++++++++
drivers/staging/zram/Makefile | 3 ++
drivers/staging/{ramzswap => zram}/xvmalloc.c | 0
drivers/staging/{ramzswap => zram}/xvmalloc.h | 0
drivers/staging/{ramzswap => zram}/xvmalloc_int.h | 0
.../{ramzswap/ramzswap.txt => zram/zram.txt} | 0
.../{ramzswap/ramzswap_drv.c => zram/zram_drv.c} | 2 +-
.../{ramzswap/ramzswap_drv.h => zram/zram_drv.h} | 2 +-
.../ramzswap_ioctl.h => zram/zram_ioctl.h} | 0
13 files changed, 35 insertions(+), 28 deletions(-)
delete mode 100644 drivers/staging/ramzswap/Kconfig
delete mode 100644 drivers/staging/ramzswap/Makefile
create mode 100644 drivers/staging/zram/Kconfig
create mode 100644 drivers/staging/zram/Makefile
rename drivers/staging/{ramzswap => zram}/xvmalloc.c (100%)
rename drivers/staging/{ramzswap => zram}/xvmalloc.h (100%)
rename drivers/staging/{ramzswap => zram}/xvmalloc_int.h (100%)
rename drivers/staging/{ramzswap/ramzswap.txt => zram/zram.txt} (100%)
rename drivers/staging/{ramzswap/ramzswap_drv.c => zram/zram_drv.c} (99%)
rename drivers/staging/{ramzswap/ramzswap_drv.h => zram/zram_drv.h} (99%)
rename drivers/staging/{ramzswap/ramzswap_ioctl.h => zram/zram_ioctl.h} (100%)

diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index b5c3b30..32d5300 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -117,7 +117,7 @@ source "drivers/staging/sep/Kconfig"

source "drivers/staging/iio/Kconfig"

-source "drivers/staging/ramzswap/Kconfig"
+source "drivers/staging/zram/Kconfig"

source "drivers/staging/wlags49_h2/Kconfig"

diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index e330dd5..cec25b0 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -39,7 +39,7 @@ obj-$(CONFIG_RAR_REGISTER) += rar_register/
obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/
-obj-$(CONFIG_RAMZSWAP) += ramzswap/
+obj-$(CONFIG_ZRAM) += zram/
obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
obj-$(CONFIG_BATMAN_ADV) += batman-adv/
diff --git a/drivers/staging/ramzswap/Kconfig b/drivers/staging/ramzswap/Kconfig
deleted file mode 100644
index 127b3c6..0000000
--- a/drivers/staging/ramzswap/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-config RAMZSWAP
- tristate "Compressed in-memory swap device (ramzswap)"
- depends on SWAP
- select LZO_COMPRESS
- select LZO_DECOMPRESS
- default n
- help
- Creates virtual block devices which can (only) be used as swap
- disks. Pages swapped to these disks are compressed and stored in
- memory itself.
-
- See ramzswap.txt for more information.
- Project home: http://compcache.googlecode.com/
-
-config RAMZSWAP_STATS
- bool "Enable ramzswap stats"
- depends on RAMZSWAP
- default y
- help
- Enable statistics collection for ramzswap. This adds only a minimal
- overhead. In unsure, say Y.
diff --git a/drivers/staging/ramzswap/Makefile b/drivers/staging/ramzswap/Makefile
deleted file mode 100644
index 507d7dc..0000000
--- a/drivers/staging/ramzswap/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-ramzswap-objs := ramzswap_drv.o xvmalloc.o
-
-obj-$(CONFIG_RAMZSWAP) += ramzswap.o
diff --git a/drivers/staging/zram/Kconfig b/drivers/staging/zram/Kconfig
new file mode 100644
index 0000000..5bcfe16
--- /dev/null
+++ b/drivers/staging/zram/Kconfig
@@ -0,0 +1,28 @@
+config ZRAM
+ tristate "Compressed RAM block device support"
+ select LZO_COMPRESS
+ select LZO_DECOMPRESS
+ default n
+ help
+ Creates virtual block devices called /dev/zramX (X = 0, 1, ...).
+ Pages written to these disks are compressed and stored in memory
+ itself. These disks allow very fast I/O and compression provides
+ good amounts of memory savings.
+
+ It has several use cases, for example: /tmp storage, use as swap
+ disks and maybe many more.
+
+ See zram.txt for more information.
+ Project home: http://compcache.googlecode.com/
+
+config ZRAM_STATS
+ bool "Enable statistics for compressed RAM disks"
+ depends on ZRAM
+ default y
+ help
+ Enable statistics collection for compressed RAM devices. Statistics
+ are exported through ioctl interface, so you have to use zramconfig
+ program to get them. This adds only a minimal overhead.
+
+ If unsure, say Y.
+
diff --git a/drivers/staging/zram/Makefile b/drivers/staging/zram/Makefile
new file mode 100644
index 0000000..b2c087a
--- /dev/null
+++ b/drivers/staging/zram/Makefile
@@ -0,0 +1,3 @@
+zram-objs := zram_drv.o xvmalloc.o
+
+obj-$(CONFIG_ZRAM) += zram.o
diff --git a/drivers/staging/ramzswap/xvmalloc.c b/drivers/staging/zram/xvmalloc.c
similarity index 100%
rename from drivers/staging/ramzswap/xvmalloc.c
rename to drivers/staging/zram/xvmalloc.c
diff --git a/drivers/staging/ramzswap/xvmalloc.h b/drivers/staging/zram/xvmalloc.h
similarity index 100%
rename from drivers/staging/ramzswap/xvmalloc.h
rename to drivers/staging/zram/xvmalloc.h
diff --git a/drivers/staging/ramzswap/xvmalloc_int.h b/drivers/staging/zram/xvmalloc_int.h
similarity index 100%
rename from drivers/staging/ramzswap/xvmalloc_int.h
rename to drivers/staging/zram/xvmalloc_int.h
diff --git a/drivers/staging/ramzswap/ramzswap.txt b/drivers/staging/zram/zram.txt
similarity index 100%
rename from drivers/staging/ramzswap/ramzswap.txt
rename to drivers/staging/zram/zram.txt
diff --git a/drivers/staging/ramzswap/ramzswap_drv.c b/drivers/staging/zram/zram_drv.c
similarity index 99%
rename from drivers/staging/ramzswap/ramzswap_drv.c
rename to drivers/staging/zram/zram_drv.c
index 7b5cc61..e9b064c 100644
--- a/drivers/staging/ramzswap/ramzswap_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -30,7 +30,7 @@
#include <linux/swapops.h>
#include <linux/vmalloc.h>

-#include "ramzswap_drv.h"
+#include "zram_drv.h"

/* Globals */
static int ramzswap_major;
diff --git a/drivers/staging/ramzswap/ramzswap_drv.h b/drivers/staging/zram/zram_drv.h
similarity index 99%
rename from drivers/staging/ramzswap/ramzswap_drv.h
rename to drivers/staging/zram/zram_drv.h
index ad91726..4d2e48a 100644
--- a/drivers/staging/ramzswap/ramzswap_drv.h
+++ b/drivers/staging/zram/zram_drv.h
@@ -18,7 +18,7 @@
#include <linux/spinlock.h>
#include <linux/mutex.h>

-#include "ramzswap_ioctl.h"
+#include "zram_ioctl.h"
#include "xvmalloc.h"

/*
diff --git a/drivers/staging/ramzswap/ramzswap_ioctl.h b/drivers/staging/zram/zram_ioctl.h
similarity index 100%
rename from drivers/staging/ramzswap/ramzswap_ioctl.h
rename to drivers/staging/zram/zram_ioctl.h
--
1.7.0.1

2010-06-01 08:01:47

by Nitin Gupta

[permalink] [raw]
Subject: [PATCH 4/4] Rename ramzswap to zram in documentation

Related changes:
- Included example to show usage as generic
(non-swap) disk with ext4 filesystem.
- Renamed rzscontrol to zramconfig to match
with new device naming.

Signed-off-by: Nitin Gupta <[email protected]>
---
drivers/staging/zram/zram.txt | 113 ++++++++++++++++++++++------------------
1 files changed, 62 insertions(+), 51 deletions(-)
rewrite drivers/staging/zram/zram.txt (73%)

diff --git a/drivers/staging/zram/zram.txt b/drivers/staging/zram/zram.txt
dissimilarity index 73%
index 9694acf..520edc1 100644
--- a/drivers/staging/zram/zram.txt
+++ b/drivers/staging/zram/zram.txt
@@ -1,51 +1,62 @@
-ramzswap: Compressed RAM based swap device
--------------------------------------------
-
-Project home: http://compcache.googlecode.com/
-
-* Introduction
-
-The ramzswap module creates RAM based block devices which can (only) be used as
-swap disks. Pages swapped to these devices are compressed and stored in memory
-itself. See project home for use cases, performance numbers and a lot more.
-
-Individual ramzswap devices are configured and initialized using rzscontrol
-userspace utility as shown in examples below. See rzscontrol man page for more
-details.
-
-* Usage
-
-Following shows a typical sequence of steps for using ramzswap.
-
-1) Load Modules:
- modprobe ramzswap num_devices=4
- This creates 4 (uninitialized) devices: /dev/ramzswap{0,1,2,3}
- (num_devices parameter is optional. Default: 1)
-
-2) Initialize:
- Use rzscontrol utility to configure and initialize individual
- ramzswap devices. Example:
- rzscontrol /dev/ramzswap2 --init # uses default value of disksize_kb
-
- *See rzscontrol man page for more details and examples*
-
-3) Activate:
- swapon /dev/ramzswap2 # or any other initialized ramzswap device
-
-4) Stats:
- rzscontrol /dev/ramzswap2 --stats
-
-5) Deactivate:
- swapoff /dev/ramzswap2
-
-6) Reset:
- rzscontrol /dev/ramzswap2 --reset
- (This frees all the memory allocated for this device).
-
-
-Please report any problems at:
- - Mailing list: linux-mm-cc at laptop dot org
- - Issue tracker: http://code.google.com/p/compcache/issues/list
-
-Nitin Gupta
[email protected]
+zram: Compressed RAM based block devices
+----------------------------------------
+
+Project home: http://compcache.googlecode.com/
+
+* Introduction
+
+The zram module creates RAM based block devices: /dev/ramX (X = 0, 1, ...).
+Pages written to these disks are compressed and stored in memory itself.
+These disks allow very fast I/O and compression provides good amounts of
+memory savings.
+
+See project home for use cases, performance numbers and a lot more.
+
+Individual zram devices are configured and initialized using zramconfig
+userspace utility as shown in examples below. See zramconfig man page for
+more details.
+
+* Usage
+
+Following shows a typical sequence of steps for using zram.
+
+1) Load Modules:
+ modprobe zram num_devices=4
+ This creates 4 (uninitialized) devices: /dev/zram{0,1,2,3}
+ (num_devices parameter is optional. Default: 1)
+
+2) Initialize:
+ Use zramconfig utility to configure and initialize individual
+ zram devices. For example:
+ zramconfig /dev/zram0 --init # uses default value of disksize_kb
+ zramconfig /dev/zram1 --disksize_kb=102400 # 100MB /dev/zram1
+
+ *See zramconfig man page for more details and examples*
+
+3) Activate:
+ mkswap /dev/zram0
+ swapon /dev/zram0
+
+ mkfs.ext4 /dev/zram1
+ mount /dev/zram1 /tmp
+
+4) Stats:
+ zramconfig /dev/zram0 --stats
+ zramconfig /dev/zram1 --stats
+
+5) Deactivate:
+ swapoff /dev/zram0
+ umount /dev/zram1
+
+6) Reset:
+ zramconfig /dev/zram0 --reset
+ zramconfig /dev/zram1 --reset
+ (This frees memory allocated for the given device).
+
+
+Please report any problems at:
+ - Mailing list: linux-mm-cc at laptop dot org
+ - Issue tracker: http://code.google.com/p/compcache/issues/list
+
+Nitin Gupta
[email protected]
--
1.7.0.1

2010-06-01 08:03:44

by Nitin Gupta

[permalink] [raw]
Subject: [PATCH 3/4] Rename ramzswap to zram in code

Automated renames in code:
- rzs* -> zram*
- RZS* -> ZRAM*
- ramzswap* -> zram*

Manual changes:
- Edited comments/messages mentioning "swap"

Signed-off-by: Nitin Gupta <[email protected]>
---
drivers/staging/zram/zram_drv.c | 431 ++++++++++++++++++-------------------
drivers/staging/zram/zram_drv.h | 66 +++---
drivers/staging/zram/zram_ioctl.h | 21 +-
3 files changed, 256 insertions(+), 262 deletions(-)

diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index e9b064c..3f77843 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -1,5 +1,5 @@
/*
- * Compressed RAM based swap device
+ * Compressed RAM block device
*
* Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
@@ -12,7 +12,7 @@
* Project home: http://compcache.googlecode.com
*/

-#define KMSG_COMPONENT "ramzswap"
+#define KMSG_COMPONENT "zram"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

#include <linux/module.h>
@@ -26,35 +26,33 @@
#include <linux/slab.h>
#include <linux/lzo.h>
#include <linux/string.h>
-#include <linux/swap.h>
-#include <linux/swapops.h>
#include <linux/vmalloc.h>

#include "zram_drv.h"

/* Globals */
-static int ramzswap_major;
-static struct ramzswap *devices;
+static int zram_major;
+static struct zram *devices;

/* Module params (documentation at end) */
static unsigned int num_devices;

-static int rzs_test_flag(struct ramzswap *rzs, u32 index,
- enum rzs_pageflags flag)
+static int zram_test_flag(struct zram *zram, u32 index,
+ enum zram_pageflags flag)
{
- return rzs->table[index].flags & BIT(flag);
+ return zram->table[index].flags & BIT(flag);
}

-static void rzs_set_flag(struct ramzswap *rzs, u32 index,
- enum rzs_pageflags flag)
+static void zram_set_flag(struct zram *zram, u32 index,
+ enum zram_pageflags flag)
{
- rzs->table[index].flags |= BIT(flag);
+ zram->table[index].flags |= BIT(flag);
}

-static void rzs_clear_flag(struct ramzswap *rzs, u32 index,
- enum rzs_pageflags flag)
+static void zram_clear_flag(struct zram *zram, u32 index,
+ enum zram_pageflags flag)
{
- rzs->table[index].flags &= ~BIT(flag);
+ zram->table[index].flags &= ~BIT(flag);
}

static int page_zero_filled(void *ptr)
@@ -72,50 +70,50 @@ static int page_zero_filled(void *ptr)
return 1;
}

-static void ramzswap_set_disksize(struct ramzswap *rzs, size_t totalram_bytes)
+static void zram_set_disksize(struct zram *zram, size_t totalram_bytes)
{
- if (!rzs->disksize) {
+ if (!zram->disksize) {
pr_info(
"disk size not provided. You can use disksize_kb module "
"param to specify size.\nUsing default: (%u%% of RAM).\n",
default_disksize_perc_ram
);
- rzs->disksize = default_disksize_perc_ram *
+ zram->disksize = default_disksize_perc_ram *
(totalram_bytes / 100);
}

- if (rzs->disksize > 2 * (totalram_bytes)) {
+ if (zram->disksize > 2 * (totalram_bytes)) {
pr_info(
- "There is little point creating a ramzswap of greater than "
+ "There is little point creating a zram of greater than "
"twice the size of memory since we expect a 2:1 compression "
- "ratio. Note that ramzswap uses about 0.1%% of the size of "
- "the swap device when not in use so a huge ramzswap is "
+ "ratio. Note that zram uses about 0.1%% of the size of "
+ "the disk when not in use so a huge zram is "
"wasteful.\n"
"\tMemory Size: %zu kB\n"
"\tSize you selected: %zu kB\n"
"Continuing anyway ...\n",
- totalram_bytes >> 10, rzs->disksize
+ totalram_bytes >> 10, zram->disksize
);
}

- rzs->disksize &= PAGE_MASK;
+ zram->disksize &= PAGE_MASK;
}

-static void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
- struct ramzswap_ioctl_stats *s)
+static void zram_ioctl_get_stats(struct zram *zram,
+ struct zram_ioctl_stats *s)
{
- s->disksize = rzs->disksize;
+ s->disksize = zram->disksize;

-#if defined(CONFIG_RAMZSWAP_STATS)
+#if defined(CONFIG_ZRAM_STATS)
{
- struct ramzswap_stats *rs = &rzs->stats;
+ struct zram_stats *rs = &zram->stats;
size_t succ_writes, mem_used;
unsigned int good_compress_perc = 0, no_compress_perc = 0;

- mem_used = xv_get_total_size_bytes(rzs->mem_pool)
+ mem_used = xv_get_total_size_bytes(zram->mem_pool)
+ (rs->pages_expand << PAGE_SHIFT);
- succ_writes = rzs_stat64_read(rzs, &rs->num_writes) -
- rzs_stat64_read(rzs, &rs->failed_writes);
+ succ_writes = zram_stat64_read(zram, &rs->num_writes) -
+ zram_stat64_read(zram, &rs->failed_writes);

if (succ_writes && rs->pages_stored) {
good_compress_perc = rs->good_compress * 100
@@ -124,12 +122,12 @@ static void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
/ rs->pages_stored;
}

- s->num_reads = rzs_stat64_read(rzs, &rs->num_reads);
- s->num_writes = rzs_stat64_read(rzs, &rs->num_writes);
- s->failed_reads = rzs_stat64_read(rzs, &rs->failed_reads);
- s->failed_writes = rzs_stat64_read(rzs, &rs->failed_writes);
- s->invalid_io = rzs_stat64_read(rzs, &rs->invalid_io);
- s->notify_free = rzs_stat64_read(rzs, &rs->notify_free);
+ s->num_reads = zram_stat64_read(zram, &rs->num_reads);
+ s->num_writes = zram_stat64_read(zram, &rs->num_writes);
+ s->failed_reads = zram_stat64_read(zram, &rs->failed_reads);
+ s->failed_writes = zram_stat64_read(zram, &rs->failed_writes);
+ s->invalid_io = zram_stat64_read(zram, &rs->invalid_io);
+ s->notify_free = zram_stat64_read(zram, &rs->notify_free);
s->pages_zero = rs->pages_zero;

s->good_compress_pct = good_compress_perc;
@@ -141,34 +139,34 @@ static void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
s->compr_data_size = rs->compr_size;
s->mem_used_total = mem_used;
}
-#endif /* CONFIG_RAMZSWAP_STATS */
+#endif /* CONFIG_ZRAM_STATS */
}

-static void ramzswap_free_page(struct ramzswap *rzs, size_t index)
+static void zram_free_page(struct zram *zram, size_t index)
{
u32 clen;
void *obj;

- struct page *page = rzs->table[index].page;
- u32 offset = rzs->table[index].offset;
+ struct page *page = zram->table[index].page;
+ u32 offset = zram->table[index].offset;

if (unlikely(!page)) {
/*
* No memory is allocated for zero filled pages.
* Simply clear zero page flag.
*/
- if (rzs_test_flag(rzs, index, RZS_ZERO)) {
- rzs_clear_flag(rzs, index, RZS_ZERO);
- rzs_stat_dec(&rzs->stats.pages_zero);
+ if (zram_test_flag(zram, index, ZRAM_ZERO)) {
+ zram_clear_flag(zram, index, ZRAM_ZERO);
+ zram_stat_dec(&zram->stats.pages_zero);
}
return;
}

- if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) {
+ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
clen = PAGE_SIZE;
__free_page(page);
- rzs_clear_flag(rzs, index, RZS_UNCOMPRESSED);
- rzs_stat_dec(&rzs->stats.pages_expand);
+ zram_clear_flag(zram, index, ZRAM_UNCOMPRESSED);
+ zram_stat_dec(&zram->stats.pages_expand);
goto out;
}

@@ -176,16 +174,16 @@ static void ramzswap_free_page(struct ramzswap *rzs, size_t index)
clen = xv_get_object_size(obj) - sizeof(struct zobj_header);
kunmap_atomic(obj, KM_USER0);

- xv_free(rzs->mem_pool, page, offset);
+ xv_free(zram->mem_pool, page, offset);
if (clen <= PAGE_SIZE / 2)
- rzs_stat_dec(&rzs->stats.good_compress);
+ zram_stat_dec(&zram->stats.good_compress);

out:
- rzs->stats.compr_size -= clen;
- rzs_stat_dec(&rzs->stats.pages_stored);
+ zram->stats.compr_size -= clen;
+ zram_stat_dec(&zram->stats.pages_stored);

- rzs->table[index].page = NULL;
- rzs->table[index].offset = 0;
+ zram->table[index].page = NULL;
+ zram->table[index].offset = 0;
}

static void handle_zero_page(struct page *page)
@@ -199,14 +197,14 @@ static void handle_zero_page(struct page *page)
flush_dcache_page(page);
}

-static void handle_uncompressed_page(struct ramzswap *rzs,
+static void handle_uncompressed_page(struct zram *zram,
struct page *page, u32 index)
{
unsigned char *user_mem, *cmem;

user_mem = kmap_atomic(page, KM_USER0);
- cmem = kmap_atomic(rzs->table[index].page, KM_USER1) +
- rzs->table[index].offset;
+ cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
+ zram->table[index].offset;

memcpy(user_mem, cmem, PAGE_SIZE);
kunmap_atomic(user_mem, KM_USER0);
@@ -215,14 +213,14 @@ static void handle_uncompressed_page(struct ramzswap *rzs,
flush_dcache_page(page);
}

-static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)
+static int zram_read(struct zram *zram, struct bio *bio)
{

int i;
u32 index;
struct bio_vec *bvec;

- rzs_stat64_inc(rzs, &rzs->stats.num_reads);
+ zram_stat64_inc(zram, &zram->stats.num_reads);

index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
bio_for_each_segment(bvec, bio, i) {
@@ -234,13 +232,13 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)

page = bvec->bv_page;

- if (rzs_test_flag(rzs, index, RZS_ZERO)) {
+ if (zram_test_flag(zram, index, ZRAM_ZERO)) {
handle_zero_page(page);
continue;
}

/* Requested page is not present in compressed area */
- if (unlikely(!rzs->table[index].page)) {
+ if (unlikely(!zram->table[index].page)) {
pr_debug("Read before write: sector=%lu, size=%u",
(ulong)(bio->bi_sector), bio->bi_size);
/* Do nothing */
@@ -248,16 +246,16 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)
}

/* Page is stored uncompressed since it's incompressible */
- if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) {
- handle_uncompressed_page(rzs, page, index);
+ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
+ handle_uncompressed_page(zram, page, index);
continue;
}

user_mem = kmap_atomic(page, KM_USER0);
clen = PAGE_SIZE;

- cmem = kmap_atomic(rzs->table[index].page, KM_USER1) +
- rzs->table[index].offset;
+ cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
+ zram->table[index].offset;

ret = lzo1x_decompress_safe(
cmem + sizeof(*zheader),
@@ -271,7 +269,7 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)
if (unlikely(ret != LZO_E_OK)) {
pr_err("Decompression failed! err=%d, page=%u\n",
ret, index);
- rzs_stat64_inc(rzs, &rzs->stats.failed_reads);
+ zram_stat64_inc(zram, &zram->stats.failed_reads);
goto out;
}

@@ -288,13 +286,13 @@ out:
return 0;
}

-static int ramzswap_write(struct ramzswap *rzs, struct bio *bio)
+static int zram_write(struct zram *zram, struct bio *bio)
{
int i;
u32 index;
struct bio_vec *bvec;

- rzs_stat64_inc(rzs, &rzs->stats.num_writes);
+ zram_stat64_inc(zram, &zram->stats.num_writes);

index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;

@@ -307,82 +305,83 @@ static int ramzswap_write(struct ramzswap *rzs, struct bio *bio)
unsigned char *user_mem, *cmem, *src;

page = bvec->bv_page;
- src = rzs->compress_buffer;
+ src = zram->compress_buffer;

/*
* System overwrites unused sectors. Free memory associated
* with this sector now.
*/
- if (rzs->table[index].page ||
- rzs_test_flag(rzs, index, RZS_ZERO))
- ramzswap_free_page(rzs, index);
+ if (zram->table[index].page ||
+ zram_test_flag(zram, index, ZRAM_ZERO))
+ zram_free_page(zram, index);

- mutex_lock(&rzs->lock);
+ mutex_lock(&zram->lock);

user_mem = kmap_atomic(page, KM_USER0);
if (page_zero_filled(user_mem)) {
kunmap_atomic(user_mem, KM_USER0);
- mutex_unlock(&rzs->lock);
- rzs_stat_inc(&rzs->stats.pages_zero);
- rzs_set_flag(rzs, index, RZS_ZERO);
+ mutex_unlock(&zram->lock);
+ zram_stat_inc(&zram->stats.pages_zero);
+ zram_set_flag(zram, index, ZRAM_ZERO);
continue;
}

ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen,
- rzs->compress_workmem);
+ zram->compress_workmem);

kunmap_atomic(user_mem, KM_USER0);

if (unlikely(ret != LZO_E_OK)) {
- mutex_unlock(&rzs->lock);
+ mutex_unlock(&zram->lock);
pr_err("Compression failed! err=%d\n", ret);
- rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
+ zram_stat64_inc(zram, &zram->stats.failed_writes);
goto out;
}

/*
* Page is incompressible. Store it as-is (uncompressed)
- * since we do not want to return too many swap write
+ * since we do not want to return too many disk write
* errors which has side effect of hanging the system.
*/
if (unlikely(clen > max_zpage_size)) {
clen = PAGE_SIZE;
page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
if (unlikely(!page_store)) {
- mutex_unlock(&rzs->lock);
+ mutex_unlock(&zram->lock);
pr_info("Error allocating memory for "
"incompressible page: %u\n", index);
- rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
+ zram_stat64_inc(zram,
+ &zram->stats.failed_writes);
goto out;
}

offset = 0;
- rzs_set_flag(rzs, index, RZS_UNCOMPRESSED);
- rzs_stat_inc(&rzs->stats.pages_expand);
- rzs->table[index].page = page_store;
+ zram_set_flag(zram, index, ZRAM_UNCOMPRESSED);
+ zram_stat_inc(&zram->stats.pages_expand);
+ zram->table[index].page = page_store;
src = kmap_atomic(page, KM_USER0);
goto memstore;
}

- if (xv_malloc(rzs->mem_pool, clen + sizeof(*zheader),
- &rzs->table[index].page, &offset,
+ if (xv_malloc(zram->mem_pool, clen + sizeof(*zheader),
+ &zram->table[index].page, &offset,
GFP_NOIO | __GFP_HIGHMEM)) {
- mutex_unlock(&rzs->lock);
+ mutex_unlock(&zram->lock);
pr_info("Error allocating memory for compressed "
"page: %u, size=%zu\n", index, clen);
- rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
+ zram_stat64_inc(zram, &zram->stats.failed_writes);
goto out;
}

memstore:
- rzs->table[index].offset = offset;
+ zram->table[index].offset = offset;

- cmem = kmap_atomic(rzs->table[index].page, KM_USER1) +
- rzs->table[index].offset;
+ cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
+ zram->table[index].offset;

#if 0
/* Back-reference needed for memory defragmentation */
- if (!rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)) {
+ if (!zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)) {
zheader = (struct zobj_header *)cmem;
zheader->table_idx = index;
cmem += sizeof(*zheader);
@@ -392,16 +391,16 @@ memstore:
memcpy(cmem, src, clen);

kunmap_atomic(cmem, KM_USER1);
- if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)))
+ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)))
kunmap_atomic(src, KM_USER0);

/* Update stats */
- rzs->stats.compr_size += clen;
- rzs_stat_inc(&rzs->stats.pages_stored);
+ zram->stats.compr_size += clen;
+ zram_stat_inc(&zram->stats.pages_stored);
if (clen <= PAGE_SIZE / 2)
- rzs_stat_inc(&rzs->stats.good_compress);
+ zram_stat_inc(&zram->stats.good_compress);

- mutex_unlock(&rzs->lock);
+ mutex_unlock(&zram->lock);
index++;
}

@@ -417,10 +416,10 @@ out:
/*
* Check if request is within bounds and page aligned.
*/
-static inline int valid_io_request(struct ramzswap *rzs, struct bio *bio)
+static inline int valid_io_request(struct zram *zram, struct bio *bio)
{
if (unlikely(
- (bio->bi_sector >= (rzs->disksize >> SECTOR_SHIFT)) ||
+ (bio->bi_sector >= (zram->disksize >> SECTOR_SHIFT)) ||
(bio->bi_sector & (SECTORS_PER_PAGE - 1)) ||
(bio->bi_size & (PAGE_SIZE - 1)))) {

@@ -432,160 +431,160 @@ static inline int valid_io_request(struct ramzswap *rzs, struct bio *bio)
}

/*
- * Handler function for all ramzswap I/O requests.
+ * Handler function for all zram I/O requests.
*/
-static int ramzswap_make_request(struct request_queue *queue, struct bio *bio)
+static int zram_make_request(struct request_queue *queue, struct bio *bio)
{
int ret = 0;
- struct ramzswap *rzs = queue->queuedata;
+ struct zram *zram = queue->queuedata;

- if (unlikely(!rzs->init_done)) {
+ if (unlikely(!zram->init_done)) {
bio_io_error(bio);
return 0;
}

- if (!valid_io_request(rzs, bio)) {
- rzs_stat64_inc(rzs, &rzs->stats.invalid_io);
+ if (!valid_io_request(zram, bio)) {
+ zram_stat64_inc(zram, &zram->stats.invalid_io);
bio_io_error(bio);
return 0;
}

switch (bio_data_dir(bio)) {
case READ:
- ret = ramzswap_read(rzs, bio);
+ ret = zram_read(zram, bio);
break;

case WRITE:
- ret = ramzswap_write(rzs, bio);
+ ret = zram_write(zram, bio);
break;
}

return ret;
}

-static void reset_device(struct ramzswap *rzs)
+static void reset_device(struct zram *zram)
{
size_t index;

/* Do not accept any new I/O request */
- rzs->init_done = 0;
+ zram->init_done = 0;

/* Free various per-device buffers */
- kfree(rzs->compress_workmem);
- free_pages((unsigned long)rzs->compress_buffer, 1);
+ kfree(zram->compress_workmem);
+ free_pages((unsigned long)zram->compress_buffer, 1);

- rzs->compress_workmem = NULL;
- rzs->compress_buffer = NULL;
+ zram->compress_workmem = NULL;
+ zram->compress_buffer = NULL;

- /* Free all pages that are still in this ramzswap device */
- for (index = 0; index < rzs->disksize >> PAGE_SHIFT; index++) {
+ /* Free all pages that are still in this zram device */
+ for (index = 0; index < zram->disksize >> PAGE_SHIFT; index++) {
struct page *page;
u16 offset;

- page = rzs->table[index].page;
- offset = rzs->table[index].offset;
+ page = zram->table[index].page;
+ offset = zram->table[index].offset;

if (!page)
continue;

- if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)))
+ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)))
__free_page(page);
else
- xv_free(rzs->mem_pool, page, offset);
+ xv_free(zram->mem_pool, page, offset);
}

- vfree(rzs->table);
- rzs->table = NULL;
+ vfree(zram->table);
+ zram->table = NULL;

- xv_destroy_pool(rzs->mem_pool);
- rzs->mem_pool = NULL;
+ xv_destroy_pool(zram->mem_pool);
+ zram->mem_pool = NULL;

/* Reset stats */
- memset(&rzs->stats, 0, sizeof(rzs->stats));
+ memset(&zram->stats, 0, sizeof(zram->stats));

- rzs->disksize = 0;
+ zram->disksize = 0;
}

-static int ramzswap_ioctl_init_device(struct ramzswap *rzs)
+static int zram_ioctl_init_device(struct zram *zram)
{
int ret;
size_t num_pages;

- if (rzs->init_done) {
+ if (zram->init_done) {
pr_info("Device already initialized!\n");
return -EBUSY;
}

- ramzswap_set_disksize(rzs, totalram_pages << PAGE_SHIFT);
+ zram_set_disksize(zram, totalram_pages << PAGE_SHIFT);

- rzs->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
- if (!rzs->compress_workmem) {
+ zram->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+ if (!zram->compress_workmem) {
pr_err("Error allocating compressor working memory!\n");
ret = -ENOMEM;
goto fail;
}

- rzs->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1);
- if (!rzs->compress_buffer) {
+ zram->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1);
+ if (!zram->compress_buffer) {
pr_err("Error allocating compressor buffer space\n");
ret = -ENOMEM;
goto fail;
}

- num_pages = rzs->disksize >> PAGE_SHIFT;
- rzs->table = vmalloc(num_pages * sizeof(*rzs->table));
- if (!rzs->table) {
- pr_err("Error allocating ramzswap address table\n");
+ num_pages = zram->disksize >> PAGE_SHIFT;
+ zram->table = vmalloc(num_pages * sizeof(*zram->table));
+ if (!zram->table) {
+ pr_err("Error allocating zram address table\n");
/* To prevent accessing table entries during cleanup */
- rzs->disksize = 0;
+ zram->disksize = 0;
ret = -ENOMEM;
goto fail;
}
- memset(rzs->table, 0, num_pages * sizeof(*rzs->table));
+ memset(zram->table, 0, num_pages * sizeof(*zram->table));

- set_capacity(rzs->disk, rzs->disksize >> SECTOR_SHIFT);
+ set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);

- /* ramzswap devices sort of resembles non-rotational disks */
- queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rzs->disk->queue);
+ /* zram devices sort of resembles non-rotational disks */
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);

- rzs->mem_pool = xv_create_pool();
- if (!rzs->mem_pool) {
+ zram->mem_pool = xv_create_pool();
+ if (!zram->mem_pool) {
pr_err("Error creating memory pool\n");
ret = -ENOMEM;
goto fail;
}

- rzs->init_done = 1;
+ zram->init_done = 1;

pr_debug("Initialization done!\n");
return 0;

fail:
- reset_device(rzs);
+ reset_device(zram);

pr_err("Initialization failed: err=%d\n", ret);
return ret;
}

-static int ramzswap_ioctl_reset_device(struct ramzswap *rzs)
+static int zram_ioctl_reset_device(struct zram *zram)
{
- if (rzs->init_done)
- reset_device(rzs);
+ if (zram->init_done)
+ reset_device(zram);

return 0;
}

-static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode,
+static int zram_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
int ret = 0;
size_t disksize_kb;

- struct ramzswap *rzs = bdev->bd_disk->private_data;
+ struct zram *zram = bdev->bd_disk->private_data;

switch (cmd) {
- case RZSIO_SET_DISKSIZE_KB:
- if (rzs->init_done) {
+ case ZRAMIO_SET_DISKSIZE_KB:
+ if (zram->init_done) {
ret = -EBUSY;
goto out;
}
@@ -594,14 +593,14 @@ static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode,
ret = -EFAULT;
goto out;
}
- rzs->disksize = disksize_kb << 10;
+ zram->disksize = disksize_kb << 10;
pr_info("Disk size set to %zu kB\n", disksize_kb);
break;

- case RZSIO_GET_STATS:
+ case ZRAMIO_GET_STATS:
{
- struct ramzswap_ioctl_stats *stats;
- if (!rzs->init_done) {
+ struct zram_ioctl_stats *stats;
+ if (!zram->init_done) {
ret = -ENOTTY;
goto out;
}
@@ -610,7 +609,7 @@ static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode,
ret = -ENOMEM;
goto out;
}
- ramzswap_ioctl_get_stats(rzs, stats);
+ zram_ioctl_get_stats(zram, stats);
if (copy_to_user((void *)arg, stats, sizeof(*stats))) {
kfree(stats);
ret = -EFAULT;
@@ -619,11 +618,11 @@ static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode,
kfree(stats);
break;
}
- case RZSIO_INIT:
- ret = ramzswap_ioctl_init_device(rzs);
+ case ZRAMIO_INIT:
+ ret = zram_ioctl_init_device(zram);
break;

- case RZSIO_RESET:
+ case ZRAMIO_RESET:
/* Do not reset an active device! */
if (bdev->bd_holders) {
ret = -EBUSY;
@@ -634,7 +633,7 @@ static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode,
if (bdev)
fsync_bdev(bdev);

- ret = ramzswap_ioctl_reset_device(rzs);
+ ret = zram_ioctl_reset_device(zram);
break;

default:
@@ -646,88 +645,88 @@ out:
return ret;
}

-void ramzswap_slot_free_notify(struct block_device *bdev, unsigned long index)
+void zram_slot_free_notify(struct block_device *bdev, unsigned long index)
{
- struct ramzswap *rzs;
+ struct zram *zram;

- rzs = bdev->bd_disk->private_data;
- ramzswap_free_page(rzs, index);
- rzs_stat64_inc(rzs, &rzs->stats.notify_free);
+ zram = bdev->bd_disk->private_data;
+ zram_free_page(zram, index);
+ zram_stat64_inc(zram, &zram->stats.notify_free);
}

-static const struct block_device_operations ramzswap_devops = {
- .ioctl = ramzswap_ioctl,
- .swap_slot_free_notify = ramzswap_slot_free_notify,
+static const struct block_device_operations zram_devops = {
+ .ioctl = zram_ioctl,
+ .swap_slot_free_notify = zram_slot_free_notify,
.owner = THIS_MODULE
};

-static int create_device(struct ramzswap *rzs, int device_id)
+static int create_device(struct zram *zram, int device_id)
{
int ret = 0;

- mutex_init(&rzs->lock);
- spin_lock_init(&rzs->stat64_lock);
+ mutex_init(&zram->lock);
+ spin_lock_init(&zram->stat64_lock);

- rzs->queue = blk_alloc_queue(GFP_KERNEL);
- if (!rzs->queue) {
+ zram->queue = blk_alloc_queue(GFP_KERNEL);
+ if (!zram->queue) {
pr_err("Error allocating disk queue for device %d\n",
device_id);
ret = -ENOMEM;
goto out;
}

- blk_queue_make_request(rzs->queue, ramzswap_make_request);
- rzs->queue->queuedata = rzs;
+ blk_queue_make_request(zram->queue, zram_make_request);
+ zram->queue->queuedata = zram;

/* gendisk structure */
- rzs->disk = alloc_disk(1);
- if (!rzs->disk) {
- blk_cleanup_queue(rzs->queue);
+ zram->disk = alloc_disk(1);
+ if (!zram->disk) {
+ blk_cleanup_queue(zram->queue);
pr_warning("Error allocating disk structure for device %d\n",
device_id);
ret = -ENOMEM;
goto out;
}

- rzs->disk->major = ramzswap_major;
- rzs->disk->first_minor = device_id;
- rzs->disk->fops = &ramzswap_devops;
- rzs->disk->queue = rzs->queue;
- rzs->disk->private_data = rzs;
- snprintf(rzs->disk->disk_name, 16, "ramzswap%d", device_id);
+ zram->disk->major = zram_major;
+ zram->disk->first_minor = device_id;
+ zram->disk->fops = &zram_devops;
+ zram->disk->queue = zram->queue;
+ zram->disk->private_data = zram;
+ snprintf(zram->disk->disk_name, 16, "zram%d", device_id);

- /* Actual capacity set using RZSIO_SET_DISKSIZE_KB ioctl */
- set_capacity(rzs->disk, 0);
+ /* Actual capacity set using ZRAMIO_SET_DISKSIZE_KB ioctl */
+ set_capacity(zram->disk, 0);

/*
* To ensure that we always get PAGE_SIZE aligned
* and n*PAGE_SIZED sized I/O requests.
*/
- blk_queue_physical_block_size(rzs->disk->queue, PAGE_SIZE);
- blk_queue_logical_block_size(rzs->disk->queue, PAGE_SIZE);
- blk_queue_io_min(rzs->disk->queue, PAGE_SIZE);
- blk_queue_io_opt(rzs->disk->queue, PAGE_SIZE);
+ blk_queue_physical_block_size(zram->disk->queue, PAGE_SIZE);
+ blk_queue_logical_block_size(zram->disk->queue, PAGE_SIZE);
+ blk_queue_io_min(zram->disk->queue, PAGE_SIZE);
+ blk_queue_io_opt(zram->disk->queue, PAGE_SIZE);

- add_disk(rzs->disk);
+ add_disk(zram->disk);

- rzs->init_done = 0;
+ zram->init_done = 0;

out:
return ret;
}

-static void destroy_device(struct ramzswap *rzs)
+static void destroy_device(struct zram *zram)
{
- if (rzs->disk) {
- del_gendisk(rzs->disk);
- put_disk(rzs->disk);
+ if (zram->disk) {
+ del_gendisk(zram->disk);
+ put_disk(zram->disk);
}

- if (rzs->queue)
- blk_cleanup_queue(rzs->queue);
+ if (zram->queue)
+ blk_cleanup_queue(zram->queue);
}

-static int __init ramzswap_init(void)
+static int __init zram_init(void)
{
int ret, dev_id;

@@ -738,8 +737,8 @@ static int __init ramzswap_init(void)
goto out;
}

- ramzswap_major = register_blkdev(0, "ramzswap");
- if (ramzswap_major <= 0) {
+ zram_major = register_blkdev(0, "zram");
+ if (zram_major <= 0) {
pr_warning("Unable to get major number\n");
ret = -EBUSY;
goto out;
@@ -752,7 +751,7 @@ static int __init ramzswap_init(void)

/* Allocate the device array and initialize each one */
pr_info("Creating %u devices ...\n", num_devices);
- devices = kzalloc(num_devices * sizeof(struct ramzswap), GFP_KERNEL);
+ devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL);
if (!devices) {
ret = -ENOMEM;
goto unregister;
@@ -770,36 +769,36 @@ free_devices:
while (dev_id)
destroy_device(&devices[--dev_id]);
unregister:
- unregister_blkdev(ramzswap_major, "ramzswap");
+ unregister_blkdev(zram_major, "zram");
out:
return ret;
}

-static void __exit ramzswap_exit(void)
+static void __exit zram_exit(void)
{
int i;
- struct ramzswap *rzs;
+ struct zram *zram;

for (i = 0; i < num_devices; i++) {
- rzs = &devices[i];
+ zram = &devices[i];

- destroy_device(rzs);
- if (rzs->init_done)
- reset_device(rzs);
+ destroy_device(zram);
+ if (zram->init_done)
+ reset_device(zram);
}

- unregister_blkdev(ramzswap_major, "ramzswap");
+ unregister_blkdev(zram_major, "zram");

kfree(devices);
pr_debug("Cleanup done!\n");
}

module_param(num_devices, uint, 0);
-MODULE_PARM_DESC(num_devices, "Number of ramzswap devices");
+MODULE_PARM_DESC(num_devices, "Number of zram devices");

-module_init(ramzswap_init);
-module_exit(ramzswap_exit);
+module_init(zram_init);
+module_exit(zram_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Nitin Gupta <[email protected]>");
-MODULE_DESCRIPTION("Compressed RAM Based Swap Device");
+MODULE_DESCRIPTION("Compressed RAM Block Device");
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h
index 4d2e48a..945f974 100644
--- a/drivers/staging/zram/zram_drv.h
+++ b/drivers/staging/zram/zram_drv.h
@@ -1,5 +1,5 @@
/*
- * Compressed RAM based swap device
+ * Compressed RAM block device
*
* Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
@@ -12,8 +12,8 @@
* Project home: http://compcache.googlecode.com
*/

-#ifndef _RAMZSWAP_DRV_H_
-#define _RAMZSWAP_DRV_H_
+#ifndef _ZRAM_DRV_H_
+#define _ZRAM_DRV_H_

#include <linux/spinlock.h>
#include <linux/mutex.h>
@@ -41,7 +41,7 @@ struct zobj_header {

/*-- Configurable parameters */

-/* Default ramzswap disk size: 25% of total RAM */
+/* Default zram disk size: 25% of total RAM */
static const unsigned default_disksize_perc_ram = 25;

/*
@@ -63,23 +63,20 @@ static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3;
#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT)

-/* Flags for ramzswap pages (table[page_no].flags) */
-enum rzs_pageflags {
+/* Flags for zram pages (table[page_no].flags) */
+enum zram_pageflags {
/* Page is stored uncompressed */
- RZS_UNCOMPRESSED,
+ ZRAM_UNCOMPRESSED,

/* Page consists entirely of zeros */
- RZS_ZERO,
+ ZRAM_ZERO,

- __NR_RZS_PAGEFLAGS,
+ __NR_ZRAM_PAGEFLAGS,
};

/*-- Data structures */

-/*
- * Allocated for each swap slot, indexed by page no.
- * These table entries must fit exactly in a page.
- */
+/* Allocated for each disk page */
struct table {
struct page *page;
u16 offset;
@@ -87,17 +84,17 @@ struct table {
u8 flags;
} __attribute__((aligned(4)));

-struct ramzswap_stats {
+struct zram_stats {
/* basic stats */
size_t compr_size; /* compressed size of pages stored -
* needed to enforce memlimit */
/* more stats */
-#if defined(CONFIG_RAMZSWAP_STATS)
+#if defined(CONFIG_ZRAM_STATS)
u64 num_reads; /* failed + successful */
u64 num_writes; /* --do-- */
u64 failed_reads; /* should NEVER! happen */
u64 failed_writes; /* can happen when memory is too low */
- u64 invalid_io; /* non-swap I/O requests */
+ u64 invalid_io; /* non-page-aligned I/O requests */
u64 notify_free; /* no. of swap slot free notifications */
u32 pages_zero; /* no. of zero filled pages */
u32 pages_stored; /* no. of pages currently stored */
@@ -106,7 +103,7 @@ struct ramzswap_stats {
#endif
};

-struct ramzswap {
+struct zram {
struct xv_pool *mem_pool;
void *compress_workmem;
void *compress_buffer;
@@ -118,51 +115,50 @@ struct ramzswap {
struct gendisk *disk;
int init_done;
/*
- * This is limit on amount of *uncompressed* worth of data
- * we can hold. When backing swap device is provided, it is
- * set equal to device size.
+ * This is the limit on amount of *uncompressed* worth of data
+ * we can store in a disk.
*/
size_t disksize; /* bytes */

- struct ramzswap_stats stats;
+ struct zram_stats stats;
};

/*-- */

/* Debugging and Stats */
-#if defined(CONFIG_RAMZSWAP_STATS)
-static void rzs_stat_inc(u32 *v)
+#if defined(CONFIG_ZRAM_STATS)
+static void zram_stat_inc(u32 *v)
{
*v = *v + 1;
}

-static void rzs_stat_dec(u32 *v)
+static void zram_stat_dec(u32 *v)
{
*v = *v - 1;
}

-static void rzs_stat64_inc(struct ramzswap *rzs, u64 *v)
+static void zram_stat64_inc(struct zram *zram, u64 *v)
{
- spin_lock(&rzs->stat64_lock);
+ spin_lock(&zram->stat64_lock);
*v = *v + 1;
- spin_unlock(&rzs->stat64_lock);
+ spin_unlock(&zram->stat64_lock);
}

-static u64 rzs_stat64_read(struct ramzswap *rzs, u64 *v)
+static u64 zram_stat64_read(struct zram *zram, u64 *v)
{
u64 val;

- spin_lock(&rzs->stat64_lock);
+ spin_lock(&zram->stat64_lock);
val = *v;
- spin_unlock(&rzs->stat64_lock);
+ spin_unlock(&zram->stat64_lock);

return val;
}
#else
-#define rzs_stat_inc(v)
-#define rzs_stat_dec(v)
-#define rzs_stat64_inc(r, v)
-#define rzs_stat64_read(r, v)
-#endif /* CONFIG_RAMZSWAP_STATS */
+#define zram_stat_inc(v)
+#define zram_stat_dec(v)
+#define zram_stat64_inc(r, v)
+#define zram_stat64_read(r, v)
+#endif /* CONFIG_ZRAM_STATS */

#endif
diff --git a/drivers/staging/zram/zram_ioctl.h b/drivers/staging/zram/zram_ioctl.h
index db94bcb..5c415fa 100644
--- a/drivers/staging/zram/zram_ioctl.h
+++ b/drivers/staging/zram/zram_ioctl.h
@@ -1,5 +1,5 @@
/*
- * Compressed RAM based swap device
+ * Compressed RAM block device
*
* Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
@@ -12,17 +12,16 @@
* Project home: http://compcache.googlecode.com
*/

-#ifndef _RAMZSWAP_IOCTL_H_
-#define _RAMZSWAP_IOCTL_H_
+#ifndef _ZRAM_IOCTL_H_
+#define _ZRAM_IOCTL_H_

-struct ramzswap_ioctl_stats {
- u64 disksize; /* user specified or equal to backing swap
- * size (if present) */
+struct zram_ioctl_stats {
+ u64 disksize; /* disksize in bytes (user specifies in KB) */
u64 num_reads; /* failed + successful */
u64 num_writes; /* --do-- */
u64 failed_reads; /* should NEVER! happen */
u64 failed_writes; /* can happen when memory is too low */
- u64 invalid_io; /* non-swap I/O requests */
+ u64 invalid_io; /* non-page-aligned I/O requests */
u64 notify_free; /* no. of swap slot free notifications */
u32 pages_zero; /* no. of zero filled pages */
u32 good_compress_pct; /* no. of pages with compression ratio<=50% */
@@ -34,9 +33,9 @@ struct ramzswap_ioctl_stats {
u64 mem_used_total;
} __attribute__ ((packed, aligned(4)));

-#define RZSIO_SET_DISKSIZE_KB _IOW('z', 0, size_t)
-#define RZSIO_GET_STATS _IOR('z', 1, struct ramzswap_ioctl_stats)
-#define RZSIO_INIT _IO('z', 2)
-#define RZSIO_RESET _IO('z', 3)
+#define ZRAMIO_SET_DISKSIZE_KB _IOW('z', 0, size_t)
+#define ZRAMIO_GET_STATS _IOR('z', 1, struct zram_ioctl_stats)
+#define ZRAMIO_INIT _IO('z', 2)
+#define ZRAMIO_RESET _IO('z', 3)

#endif
--
1.7.0.1

2010-06-01 10:25:58

by Pekka Enberg

[permalink] [raw]
Subject: Re: [PATCH 0/4] zram: generic RAM based compressed R/W block devices (v2)

On 6/1/10 11:01 AM, Nitin Gupta wrote:
> Creates RAM based block devices: /dev/zramX (X = 0, 1, ...).
> Pages written to these disks are compressed and stored in memory
> itself. These disks allow very fast I/O and compression provides
> good amounts of memory savings.

Acked-by: Pekka Enberg <[email protected]>

2010-06-02 06:20:16

by Minchan Kim

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

On Tue, Jun 1, 2010 at 5:01 PM, Nitin Gupta <[email protected]> wrote:
> Currently, ramzwap devices (/dev/ramzswapX) can only
> be used as swap disks since it was hard-coded to consider
> only the first request in bio vector.
>
> Now, we iterate over all the segments in an incoming
> bio which allows us to handle all kinds of I/O requests.
>
> ramzswap devices can still handle PAGE_SIZE aligned and
> multiple of PAGE_SIZE sized I/O requests only. To ensure
> that we get always get such requests only, we set following
> request_queue attributes to PAGE_SIZE:
>  - physical_block_size
>  - logical_block_size
>  - io_min
>  - io_opt
>
> Note: physical and logical block sizes were already set
> equal to PAGE_SIZE and that seems to be sufficient to get
> PAGE_SIZE aligned I/O.
>
> Since we are no longer limited to handling swap requests
> only, the next few patches rename ramzswap to zram. So,
> the devices will then be called /dev/zram{0, 1, 2, ...}
>
> Usage/Examples:
>  1) Use as /tmp storage
>  - mkfs.ext4 /dev/zram0
>  - mount /dev/zram0 /tmp
>
>  2) Use as swap:
>  - mkswap /dev/zram0
>  - swapon /dev/zram0 -p 10 # give highest priority to zram0
>
> Performance:
>
>  - I/O benchamark done with 'dd' command. Details can be
> found here:
> http://code.google.com/p/compcache/wiki/zramperf
> Summary:
>  - Maximum read speed (approx):
>   - ram disk: 1200 MB/sec
>   - zram disk: 600 MB/sec
>  - Maximum write speed (approx):
>   - ram disk: 500 MB/sec
>   - zram disk: 160 MB/sec
>
> Issues:
>
>  - Double caching: We can potentially waste memory by having
> two copies of a page -- one in page cache (uncompress) and
> second in the device memory (compressed). However, during
> reclaim, clean page cache pages are quickly freed, so this
> does not seem to be a big problem.
>
>  - Stale data: Not all filesystems support issuing 'discard'
> requests to underlying block devices. So, if such filesystems
> are used over zram devices, we can accumulate lot of stale
> data in memory. Even for filesystems to do support discard
> (example, ext4), we need to see how effective it is.
>
>  - Scalability: There is only one (per-device) de/compression
> buffer stats. This can lead to significant contention, especially
> when used for generic (non-swap) purposes.
>
> Signed-off-by: Nitin Gupta <[email protected]>
Reviewed-by: Minchan Kim <[email protected]>

I saw mutex lock's usage as rather coarse-grained.
But I decides enhancing it with per-cpu stat after this series are merged.

Thanks for nice feature, Nitin.

P.S)
Why don't you send this series to -mm?
I don't know any patches have to go linux-next and any patches have to
go --mmotm.
I thought zram is related to memory management a little bit.

What's the criteria?

--
Kind regards,
Minchan Kim

2010-06-02 07:36:16

by Nitin Gupta

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

On 06/02/2010 11:50 AM, Minchan Kim wrote:
> On Tue, Jun 1, 2010 at 5:01 PM, Nitin Gupta <[email protected]> wrote:


> P.S)
> Why don't you send this series to -mm?

In general, zram is somewhat related to memory management but these zram
patches mainly deal with handling generic I/O requests. So, I just posted
them on linux-kernel. Even if changes were made to xvmalloc, I doubt
if anyone at -mm would be interested in a driver specific allocator.

> I don't know any patches have to go linux-next and any patches have to
> go --mmotm.
> I thought zram is related to memory management a little bit.
>
> What's the criteria?
>

I *guess* anything experimental goes to linux-next and if thats related
directly to core mm, it goes to --mmotm also.

Thanks,
Nitin

2010-06-04 19:11:37

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

On Tue, 1 Jun 2010 13:31:23 +0530
Nitin Gupta <[email protected]> wrote:

> Currently, ramzwap devices (/dev/ramzswapX) can only
> be used as swap disks since it was hard-coded to consider
> only the first request in bio vector.
>
> Now, we iterate over all the segments in an incoming
> bio which allows us to handle all kinds of I/O requests.
>
> ramzswap devices can still handle PAGE_SIZE aligned and
> multiple of PAGE_SIZE sized I/O requests only. To ensure
> that we get always get such requests only, we set following
> request_queue attributes to PAGE_SIZE:
> - physical_block_size
> - logical_block_size
> - io_min
> - io_opt
>
> Note: physical and logical block sizes were already set
> equal to PAGE_SIZE and that seems to be sufficient to get
> PAGE_SIZE aligned I/O.
>
> Since we are no longer limited to handling swap requests
> only, the next few patches rename ramzswap to zram. So,
> the devices will then be called /dev/zram{0, 1, 2, ...}

Thanks for doing this - I think it's for the best..

> Usage/Examples:
> 1) Use as /tmp storage
> - mkfs.ext4 /dev/zram0
> - mount /dev/zram0 /tmp

hm, how does that work? The "device" will only handle page-sized and
page-aligned requests, won't it? Can you walk us through what happens
when the fs does a 512-byte I/O?

> - Double caching: We can potentially waste memory by having
> two copies of a page -- one in page cache (uncompress) and
> second in the device memory (compressed). However, during
> reclaim, clean page cache pages are quickly freed, so this
> does not seem to be a big problem.

Yes, clean pagecache is cheap. But what happens when the pagecache
copy of the page gets modified?

Or is it the case that once a compressed page gets copied out to
pagecache, the compressed version is never used again? If so, the
memory could be synchronously freed, so I guess I don't understand what
you mean here.

> - Stale data: Not all filesystems support issuing 'discard'
> requests to underlying block devices. So, if such filesystems
> are used over zram devices, we can accumulate lot of stale
> data in memory. Even for filesystems to do support discard
> (example, ext4), we need to see how effective it is.

Can you walk us through how zram uses discard requests?

2010-06-04 19:20:20

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

On Wed, 2 Jun 2010 15:20:13 +0900
Minchan Kim <[email protected]> wrote:

> P.S)
> Why don't you send this series to -mm?
> I don't know any patches have to go linux-next and any patches have to
> go --mmotm.

The code lives in drivers/staging/ at present. That's Greg's tree.

> I thought zram is related to memory management a little bit.
>
> What's the criteria?

Yes, and this is something which bothers me a bit about the -staging
process. Code gets in there largely under the radar of the people who
work in that area. It gets "matured" for a while and the developer
thinks it's all ready to go into "mainline" and .... then what?
Someone needs to yank the code out of -staging and tell the interested
parties "hey, look at this". And at this stage, they might say "hell
no", or request large changes and the developer who thought everything
was all ready to go would be justifiably upset.

Obviously, this hasn't happened (much) with zram (partly because I
happened to notice it), but the potential is there.

I'm not sure what a good solution is, really. Obviously it would be
better if such code went straight into the subsystem maintainer's tree
on day one and got worked on there. But if that process was working
efficiently, we wouldn't have ever needed ./staging/.

So I suppose we (ie: Greg ;)) should identify the destination
maintainer at the outset and make sure that the maintainer(s) and the
subsystem mailing list are kept in the loop on all developments, and
that they're aware that this code is headed their way. Perhaps that's
already happening and I missed it.

2010-06-04 19:33:23

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH 2/4] Rename ramzswap files to zram

On Tue, 1 Jun 2010 13:31:24 +0530
Nitin Gupta <[email protected]> wrote:

> Related changes:
> - Modify revelant Kconfig and Makefile accordingly.
> - Change include filenames in code.
> - Remove dependency on CONFIG_SWAP in Kconfig as zram usage
> is no longer limited to swap disks.
>
> Signed-off-by: Nitin Gupta <[email protected]>
> ---
> drivers/staging/Kconfig | 2 +-
> drivers/staging/Makefile | 2 +-
> drivers/staging/ramzswap/Kconfig | 21 ---------------
> drivers/staging/ramzswap/Makefile | 3 --
> drivers/staging/zram/Kconfig | 28 ++++++++++++++++++++
> drivers/staging/zram/Makefile | 3 ++
> drivers/staging/{ramzswap => zram}/xvmalloc.c | 0
> drivers/staging/{ramzswap => zram}/xvmalloc.h | 0
> drivers/staging/{ramzswap => zram}/xvmalloc_int.h | 0
> .../{ramzswap/ramzswap.txt => zram/zram.txt} | 0
> .../{ramzswap/ramzswap_drv.c => zram/zram_drv.c} | 2 +-
> .../{ramzswap/ramzswap_drv.h => zram/zram_drv.h} | 2 +-
> .../ramzswap_ioctl.h => zram/zram_ioctl.h} | 0
> 13 files changed, 35 insertions(+), 28 deletions(-)
> delete mode 100644 drivers/staging/ramzswap/Kconfig
> delete mode 100644 drivers/staging/ramzswap/Makefile
> create mode 100644 drivers/staging/zram/Kconfig
> create mode 100644 drivers/staging/zram/Makefile
> rename drivers/staging/{ramzswap => zram}/xvmalloc.c (100%)
> rename drivers/staging/{ramzswap => zram}/xvmalloc.h (100%)
> rename drivers/staging/{ramzswap => zram}/xvmalloc_int.h (100%)
> rename drivers/staging/{ramzswap/ramzswap.txt => zram/zram.txt} (100%)
> rename drivers/staging/{ramzswap/ramzswap_drv.c => zram/zram_drv.c} (99%)
> rename drivers/staging/{ramzswap/ramzswap_drv.h => zram/zram_drv.h} (99%)
> rename drivers/staging/{ramzswap/ramzswap_ioctl.h => zram/zram_ioctl.h} (100%)

This is a git-specific thing and doesn't do anything useful for people
who use plain-old-patch(1) (eg: Greg and me).

Obviously we can manually type in the commands and put the massive
file-moving diff together, but it's a bit of a pain.

Maybe Greg has some magic automated way of turning these into regular
patches, but I don't.

2010-06-04 21:07:25

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 2/4] Rename ramzswap files to zram

On Fri, Jun 04, 2010 at 12:32:46PM -0700, Andrew Morton wrote:
> On Tue, 1 Jun 2010 13:31:24 +0530
> Nitin Gupta <[email protected]> wrote:
>
> > Related changes:
> > - Modify revelant Kconfig and Makefile accordingly.
> > - Change include filenames in code.
> > - Remove dependency on CONFIG_SWAP in Kconfig as zram usage
> > is no longer limited to swap disks.
> >
> > Signed-off-by: Nitin Gupta <[email protected]>
> > ---
> > drivers/staging/Kconfig | 2 +-
> > drivers/staging/Makefile | 2 +-
> > drivers/staging/ramzswap/Kconfig | 21 ---------------
> > drivers/staging/ramzswap/Makefile | 3 --
> > drivers/staging/zram/Kconfig | 28 ++++++++++++++++++++
> > drivers/staging/zram/Makefile | 3 ++
> > drivers/staging/{ramzswap => zram}/xvmalloc.c | 0
> > drivers/staging/{ramzswap => zram}/xvmalloc.h | 0
> > drivers/staging/{ramzswap => zram}/xvmalloc_int.h | 0
> > .../{ramzswap/ramzswap.txt => zram/zram.txt} | 0
> > .../{ramzswap/ramzswap_drv.c => zram/zram_drv.c} | 2 +-
> > .../{ramzswap/ramzswap_drv.h => zram/zram_drv.h} | 2 +-
> > .../ramzswap_ioctl.h => zram/zram_ioctl.h} | 0
> > 13 files changed, 35 insertions(+), 28 deletions(-)
> > delete mode 100644 drivers/staging/ramzswap/Kconfig
> > delete mode 100644 drivers/staging/ramzswap/Makefile
> > create mode 100644 drivers/staging/zram/Kconfig
> > create mode 100644 drivers/staging/zram/Makefile
> > rename drivers/staging/{ramzswap => zram}/xvmalloc.c (100%)
> > rename drivers/staging/{ramzswap => zram}/xvmalloc.h (100%)
> > rename drivers/staging/{ramzswap => zram}/xvmalloc_int.h (100%)
> > rename drivers/staging/{ramzswap/ramzswap.txt => zram/zram.txt} (100%)
> > rename drivers/staging/{ramzswap/ramzswap_drv.c => zram/zram_drv.c} (99%)
> > rename drivers/staging/{ramzswap/ramzswap_drv.h => zram/zram_drv.h} (99%)
> > rename drivers/staging/{ramzswap/ramzswap_ioctl.h => zram/zram_ioctl.h} (100%)
>
> This is a git-specific thing and doesn't do anything useful for people
> who use plain-old-patch(1) (eg: Greg and me).
>
> Obviously we can manually type in the commands and put the massive
> file-moving diff together, but it's a bit of a pain.
>
> Maybe Greg has some magic automated way of turning these into regular
> patches, but I don't.

No I don't :(

But for the staging tree, I've started to use git, so I should be able
to apply this. I'll try it out next week when I get to the "here's
what's going into .36" series of patches sent to me.

thanks,

greg k-h

2010-06-05 06:59:54

by Nitin Gupta

[permalink] [raw]
Subject: Re: [PATCH 2/4] Rename ramzswap files to zram

On 06/05/2010 01:02 AM, Andrew Morton wrote:
> On Tue, 1 Jun 2010 13:31:24 +0530
> Nitin Gupta <[email protected]> wrote:
>
>> Related changes:
>> - Modify revelant Kconfig and Makefile accordingly.
>> - Change include filenames in code.
>> - Remove dependency on CONFIG_SWAP in Kconfig as zram usage
>> is no longer limited to swap disks.
>>
>> Signed-off-by: Nitin Gupta <[email protected]>
>> ---
>> drivers/staging/Kconfig | 2 +-
>> drivers/staging/Makefile | 2 +-
>> drivers/staging/ramzswap/Kconfig | 21 ---------------
>> drivers/staging/ramzswap/Makefile | 3 --
>> drivers/staging/zram/Kconfig | 28 ++++++++++++++++++++
>> drivers/staging/zram/Makefile | 3 ++
>> drivers/staging/{ramzswap => zram}/xvmalloc.c | 0
>> drivers/staging/{ramzswap => zram}/xvmalloc.h | 0
>> drivers/staging/{ramzswap => zram}/xvmalloc_int.h | 0
>> .../{ramzswap/ramzswap.txt => zram/zram.txt} | 0
>> .../{ramzswap/ramzswap_drv.c => zram/zram_drv.c} | 2 +-
>> .../{ramzswap/ramzswap_drv.h => zram/zram_drv.h} | 2 +-
>> .../ramzswap_ioctl.h => zram/zram_ioctl.h} | 0
>> 13 files changed, 35 insertions(+), 28 deletions(-)
>> delete mode 100644 drivers/staging/ramzswap/Kconfig
>> delete mode 100644 drivers/staging/ramzswap/Makefile
>> create mode 100644 drivers/staging/zram/Kconfig
>> create mode 100644 drivers/staging/zram/Makefile
>> rename drivers/staging/{ramzswap => zram}/xvmalloc.c (100%)
>> rename drivers/staging/{ramzswap => zram}/xvmalloc.h (100%)
>> rename drivers/staging/{ramzswap => zram}/xvmalloc_int.h (100%)
>> rename drivers/staging/{ramzswap/ramzswap.txt => zram/zram.txt} (100%)
>> rename drivers/staging/{ramzswap/ramzswap_drv.c => zram/zram_drv.c} (99%)
>> rename drivers/staging/{ramzswap/ramzswap_drv.h => zram/zram_drv.h} (99%)
>> rename drivers/staging/{ramzswap/ramzswap_ioctl.h => zram/zram_ioctl.h} (100%)
>
> This is a git-specific thing and doesn't do anything useful for people
> who use plain-old-patch(1) (eg: Greg and me).
>
> Obviously we can manually type in the commands and put the massive
> file-moving diff together, but it's a bit of a pain.
>
> Maybe Greg has some magic automated way of turning these into regular
> patches, but I don't.
>
>

I used 'git-format-patch -M' as it should be easier to review
(as suggested by Arnd).

Anyways, I'm was not sure if I should be sending normal (non-git-specific)
version of these patches again. So, uploaded them here instead:

single monolithic patch:
http://compcache.googlecode.com/hg/sub-projects/mainline/zramv2_2.6.35-rc1.patch

or, if you prefer patch series:
http://compcache.googlecode.com/hg/sub-projects/mainline/zramv2_patch_series

Thanks,
Nitin


2010-06-05 07:44:20

by Nitin Gupta

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

On 06/05/2010 12:40 AM, Andrew Morton wrote:
> On Tue, 1 Jun 2010 13:31:23 +0530
> Nitin Gupta <[email protected]> wrote:
>

>> Usage/Examples:
>> 1) Use as /tmp storage
>> - mkfs.ext4 /dev/zram0
>> - mount /dev/zram0 /tmp
>
> hm, how does that work? The "device" will only handle page-sized and
> page-aligned requests, won't it? Can you walk us through what happens
> when the fs does a 512-byte I/O?
>

Yes, it still handles page-size aligned, n*page_size sized I/O requests.

Unfortunately, I don't know much of vfs/filesystem details, so I could not
trace out the exact path. But, given that we set logical and physical sector
size to PAGE_SIZE, the block layer (and filesytem) should make sure that we
get correctly aligned, correctly sized I/O requests. I just discovered this
fact through experimentation and didn't know making it a generic device is
actually this easy.

Given that I lack detailed knowledge in this area, there may be some corner
cases where we may get unaligned I/O requests (in which case we simply return
I/O error) but successful run of 'dd' and 'iozone' tests (links in patch 0/4)
increased my confidence in this :)

The only change that was needed to make it generic device was to
iterate over all bio segments (earlier it was hard-coded to handle
just the first one).

>> - Double caching: We can potentially waste memory by having
>> two copies of a page -- one in page cache (uncompress) and
>> second in the device memory (compressed). However, during
>> reclaim, clean page cache pages are quickly freed, so this
>> does not seem to be a big problem.
>
> Yes, clean pagecache is cheap. But what happens when the pagecache
> copy of the page gets modified?
>

Dirty pages are periodically flushed to disk (zram in this case) and
then it becomes clean again.

> Or is it the case that once a compressed page gets copied out to
> pagecache, the compressed version is never used again? If so, the
> memory could be synchronously freed, so I guess I don't understand what
> you mean here.

We cannot free a page as soon as it is decompressed and added to page cache.
When a clean page is reclaimed, it is simply freed and not written out to
disk and thus, we will end up losing this data.

The only opportunity to free a (compressed) disk page is when filesystem
issues a block discard request or, when used as a swap disk, we get a swap
slot free notification (a callback for this was recently added to
struct block_device_operations).

>
>> - Stale data: Not all filesystems support issuing 'discard'
>> requests to underlying block devices. So, if such filesystems
>> are used over zram devices, we can accumulate lot of stale
>> data in memory. Even for filesystems to do support discard
>> (example, ext4), we need to see how effective it is.
>
> Can you walk us through how zram uses discard requests?
>

I could not get discard working (yet), so support for this was
removed from these patches. I hope to include it soon.

Thanks for your feedback.
Nitin

2010-06-05 08:28:55

by Pekka Enberg

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

Andrew Morton wrote:
>> I thought zram is related to memory management a little bit.
>>
>> What's the criteria?
>
> Yes, and this is something which bothers me a bit about the -staging
> process. Code gets in there largely under the radar of the people who
> work in that area. It gets "matured" for a while and the developer
> thinks it's all ready to go into "mainline" and .... then what?
> Someone needs to yank the code out of -staging and tell the interested
> parties "hey, look at this". And at this stage, they might say "hell
> no", or request large changes and the developer who thought everything
> was all ready to go would be justifiably upset.

Yeah, that's what I assumed would happen here. When the code in -staging
is "good enough", Nitin would submit squashed patches for inclusion
review and when everyone is happy, we'd merge the code including full
history from -staging.

Btw, ramzswap and zram have been discussed openly on LKML. I guess Nitin
should have CC'd linux-mm as well for you to see it Andrew?

Pekka

2010-06-05 08:35:45

by Pekka Enberg

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

Hi Andrew,

On Fri, Jun 4, 2010 at 10:19 PM, Andrew Morton
<[email protected]> wrote:
>> I thought zram is related to memory management a little bit.
>>
>> What's the criteria?
>
> Yes, and this is something which bothers me a bit about the -staging
> process. ?Code gets in there largely under the radar of the people who
> work in that area. ?It gets "matured" for a while and the developer
> thinks it's all ready to go into "mainline" and .... ?then what?
> Someone needs to yank the code out of -staging and tell the interested
> parties "hey, look at this". ?And at this stage, they might say "hell
> no", or request large changes and the developer who thought everything
> was all ready to go would be justifiably upset.
>
> Obviously, this hasn't happened (much) with zram (partly because I
> happened to notice it), but the potential is there.
>
> I'm not sure what a good solution is, really. ?Obviously it would be
> better if such code went straight into the subsystem maintainer's tree
> on day one and got worked on there. ?But if that process was working
> efficiently, we wouldn't have ever needed ./staging/.

I thought the idea here is that when zram is "good enough", Nitin or
Greg would post squashed patches of it for review and if maintainers
are ready to take it, we'd merge the full history from -staging.

Not sure what Nitin's or Greg's plans are but I think it might be
realistic to try to get zram properly merged for 2.6.36.

> So I suppose we (ie: Greg ;)) should identify the destination
> maintainer at the outset and make sure that the maintainer(s) and the
> subsystem mailing list are kept in the loop on all developments, and
> that they're aware that this code is headed their way. ?Perhaps that's
> already happening and I missed it.

Ramzswap and zram have been discussed on LKML. I guess Nitin should
have CC'd linux-mm as well for you to see it? There hasn't been huge
interest in reviewing the code which is why I suggested -staging in
the first place. It ought to be a place where we can do in-tree
development while we wait for the busy maintainers to have the chance
to look at the code, no?

Pekka

2010-06-05 08:36:56

by Pekka Enberg

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

On Sat, Jun 5, 2010 at 11:28 AM, Pekka Enberg <[email protected]> wrote:
> Andrew Morton wrote:
>>>
>>> I thought zram is related to memory management a little bit.
>>>
>>> What's the criteria?
>>
>> Yes, and this is something which bothers me a bit about the -staging
>> process. ?Code gets in there largely under the radar of the people who
>> work in that area. ?It gets "matured" for a while and the developer
>> thinks it's all ready to go into "mainline" and .... ?then what? Someone
>> needs to yank the code out of -staging and tell the interested
>> parties "hey, look at this". ?And at this stage, they might say "hell
>> no", or request large changes and the developer who thought everything
>> was all ready to go would be justifiably upset.
>
> Yeah, that's what I assumed would happen here. When the code in -staging is
> "good enough", Nitin would submit squashed patches for inclusion review and
> when everyone is happy, we'd merge the code including full history from
> -staging.
>
> Btw, ramzswap and zram have been discussed openly on LKML. I guess Nitin
> should have CC'd linux-mm as well for you to see it Andrew?

Sorry for the duplicate mail. I thought I lost this to /dev/null.

2010-06-05 13:15:16

by Nitin Gupta

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

Hi Pekka,

On 06/05/2010 02:05 PM, Pekka Enberg wrote:
>
> On Fri, Jun 4, 2010 at 10:19 PM, Andrew Morton
> <[email protected]> wrote:
>>> I thought zram is related to memory management a little bit.
>>>
>>> What's the criteria?
>>
>> Yes, and this is something which bothers me a bit about the -staging
>> process. Code gets in there largely under the radar of the people who
>> work in that area. It gets "matured" for a while and the developer
>> thinks it's all ready to go into "mainline" and .... then what?
>> Someone needs to yank the code out of -staging and tell the interested
>> parties "hey, look at this". And at this stage, they might say "hell
>> no", or request large changes and the developer who thought everything
>> was all ready to go would be justifiably upset.
>>
>> Obviously, this hasn't happened (much) with zram (partly because I
>> happened to notice it), but the potential is there.
>>
>> I'm not sure what a good solution is, really. Obviously it would be
>> better if such code went straight into the subsystem maintainer's tree
>> on day one and got worked on there. But if that process was working
>> efficiently, we wouldn't have ever needed ./staging/.
>
> I thought the idea here is that when zram is "good enough", Nitin or
> Greg would post squashed patches of it for review and if maintainers
> are ready to take it, we'd merge the full history from -staging.
>
> Not sure what Nitin's or Greg's plans are but I think it might be
> realistic to try to get zram properly merged for 2.6.36.
>

Yes, I'm planning to move it to drivers proper in 2.6.36.

>> So I suppose we (ie: Greg ;)) should identify the destination
>> maintainer at the outset and make sure that the maintainer(s) and the
>> subsystem mailing list are kept in the loop on all developments, and
>> that they're aware that this code is headed their way. Perhaps that's
>> already happening and I missed it.
>
> Ramzswap and zram have been discussed on LKML. I guess Nitin should
> have CC'd linux-mm as well for you to see it? There hasn't been huge
> interest in reviewing the code which is why I suggested -staging in
> the first place. It ought to be a place where we can do in-tree
> development while we wait for the busy maintainers to have the chance
> to look at the code, no?
>

Its all somewhat related to "compressed caching", so maybe linux-mm
should be added. I will do so for future patches which makes non-trivial
changes.

Thanks for your reviews and ACKs.

Nitin

2010-06-06 23:32:53

by Minchan Kim

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

Hi, Pekka.

On Sat, Jun 5, 2010 at 5:35 PM, Pekka Enberg <[email protected]> wrote:
> Hi Andrew,
>
> On Fri, Jun 4, 2010 at 10:19 PM, Andrew Morton
> <[email protected]> wrote:
>>> I thought zram is related to memory management a little bit.
>>>
>>> What's the criteria?
>>
>> Yes, and this is something which bothers me a bit about the -staging
>> process.  Code gets in there largely under the radar of the people who
>> work in that area.  It gets "matured" for a while and the developer
>> thinks it's all ready to go into "mainline" and ....  then what?
>> Someone needs to yank the code out of -staging and tell the interested
>> parties "hey, look at this".  And at this stage, they might say "hell
>> no", or request large changes and the developer who thought everything
>> was all ready to go would be justifiably upset.
>>
>> Obviously, this hasn't happened (much) with zram (partly because I
>> happened to notice it), but the potential is there.
>>
>> I'm not sure what a good solution is, really.  Obviously it would be
>> better if such code went straight into the subsystem maintainer's tree
>> on day one and got worked on there.  But if that process was working
>> efficiently, we wouldn't have ever needed ./staging/.
>
> I thought the idea here is that when zram is "good enough", Nitin or
> Greg would post squashed patches of it for review and if maintainers
> are ready to take it, we'd merge the full history from -staging.
>
> Not sure what Nitin's or Greg's plans are but I think it might be
> realistic to try to get zram properly merged for 2.6.36.
>
>> So I suppose we (ie: Greg ;)) should identify the destination
>> maintainer at the outset and make sure that the maintainer(s) and the
>> subsystem mailing list are kept in the loop on all developments, and
>> that they're aware that this code is headed their way.  Perhaps that's
>> already happening and I missed it.
>
> Ramzswap and zram have been discussed on LKML. I guess Nitin should
> have CC'd linux-mm as well for you to see it? There hasn't been huge
> interest in reviewing the code which is why I suggested -staging in
> the first place. It ought to be a place where we can do in-tree
> development while we wait for the busy maintainers to have the chance
> to look at the code, no?

Fair enough.

AFAIR, mm forks haven't been interest in reviewing the code except
allocator at that time. but at least, Greg or someone should have Cced
one maintainer or mailing list related to patches to notice them.
"It's growing in here(ie, staging) and be ready to go to the
mainline". :)

--
Kind regards,
Minchan Kim

2010-06-07 05:35:41

by Pekka Enberg

[permalink] [raw]
Subject: Re: [PATCH 1/4] Support generic I/O requests

Hi Minchan,

On Mon, Jun 7, 2010 at 2:32 AM, Minchan Kim <[email protected]> wrote:
> AFAIR, mm forks haven't been interest in reviewing the code except
> allocator at that time. but at least, Greg or someone should have Cced
> one maintainer or mailing list related to patches to notice them.
> "It's growing in here(ie, staging) and be ready to go to the
> mainline". :)

Like I said, all patches have been discussed on LKML and Hugh Dickins
was CC'd because he's the swap maintainer. So the intent here was
always to make sure relevant people would see it but now looking back,
we ought to have CC'd linux-mm and maybe block maintainer(s) as well.

Pekka