diff options
author | Nitin Gupta <ngupta@vflare.org> | 2010-06-01 13:31:24 +0530 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-06-18 12:46:42 -0700 |
commit | 16a4bfb9e9dfefbd28ee170fa3e259bc88d81eb5 (patch) | |
tree | fc8cdc97f97b699c7ed0e0a08eacd5a3b1f3058f /drivers/staging/ramzswap | |
parent | a1dd52afa94238d361d70502b219409ea115e235 (diff) |
Staging: 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 <ngupta@vflare.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/ramzswap')
-rw-r--r-- | drivers/staging/ramzswap/Kconfig | 21 | ||||
-rw-r--r-- | drivers/staging/ramzswap/Makefile | 3 | ||||
-rw-r--r-- | drivers/staging/ramzswap/ramzswap.txt | 51 | ||||
-rw-r--r-- | drivers/staging/ramzswap/ramzswap_drv.c | 805 | ||||
-rw-r--r-- | drivers/staging/ramzswap/ramzswap_drv.h | 168 | ||||
-rw-r--r-- | drivers/staging/ramzswap/ramzswap_ioctl.h | 42 | ||||
-rw-r--r-- | drivers/staging/ramzswap/xvmalloc.c | 507 | ||||
-rw-r--r-- | drivers/staging/ramzswap/xvmalloc.h | 30 | ||||
-rw-r--r-- | drivers/staging/ramzswap/xvmalloc_int.h | 86 |
9 files changed, 0 insertions, 1713 deletions
diff --git a/drivers/staging/ramzswap/Kconfig b/drivers/staging/ramzswap/Kconfig deleted file mode 100644 index 127b3c6c959..00000000000 --- 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 507d7dc3b86..00000000000 --- 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/ramzswap/ramzswap.txt b/drivers/staging/ramzswap/ramzswap.txt deleted file mode 100644 index 9694acfeb43..00000000000 --- a/drivers/staging/ramzswap/ramzswap.txt +++ /dev/null @@ -1,51 +0,0 @@ -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 -ngupta@vflare.org diff --git a/drivers/staging/ramzswap/ramzswap_drv.c b/drivers/staging/ramzswap/ramzswap_drv.c deleted file mode 100644 index 7b5cc61b3d6..00000000000 --- a/drivers/staging/ramzswap/ramzswap_drv.c +++ /dev/null @@ -1,805 +0,0 @@ -/* - * Compressed RAM based swap device - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - * - * Project home: http://compcache.googlecode.com - */ - -#define KMSG_COMPONENT "ramzswap" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/bitops.h> -#include <linux/blkdev.h> -#include <linux/buffer_head.h> -#include <linux/device.h> -#include <linux/genhd.h> -#include <linux/highmem.h> -#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 "ramzswap_drv.h" - -/* Globals */ -static int ramzswap_major; -static struct ramzswap *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) -{ - return rzs->table[index].flags & BIT(flag); -} - -static void rzs_set_flag(struct ramzswap *rzs, u32 index, - enum rzs_pageflags flag) -{ - rzs->table[index].flags |= BIT(flag); -} - -static void rzs_clear_flag(struct ramzswap *rzs, u32 index, - enum rzs_pageflags flag) -{ - rzs->table[index].flags &= ~BIT(flag); -} - -static int page_zero_filled(void *ptr) -{ - unsigned int pos; - unsigned long *page; - - page = (unsigned long *)ptr; - - for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) { - if (page[pos]) - return 0; - } - - return 1; -} - -static void ramzswap_set_disksize(struct ramzswap *rzs, size_t totalram_bytes) -{ - if (!rzs->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 * - (totalram_bytes / 100); - } - - if (rzs->disksize > 2 * (totalram_bytes)) { - pr_info( - "There is little point creating a ramzswap 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 " - "wasteful.\n" - "\tMemory Size: %zu kB\n" - "\tSize you selected: %zu kB\n" - "Continuing anyway ...\n", - totalram_bytes >> 10, rzs->disksize - ); - } - - rzs->disksize &= PAGE_MASK; -} - -static void ramzswap_ioctl_get_stats(struct ramzswap *rzs, - struct ramzswap_ioctl_stats *s) -{ - s->disksize = rzs->disksize; - -#if defined(CONFIG_RAMZSWAP_STATS) - { - struct ramzswap_stats *rs = &rzs->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) - + (rs->pages_expand << PAGE_SHIFT); - succ_writes = rzs_stat64_read(rzs, &rs->num_writes) - - rzs_stat64_read(rzs, &rs->failed_writes); - - if (succ_writes && rs->pages_stored) { - good_compress_perc = rs->good_compress * 100 - / rs->pages_stored; - no_compress_perc = rs->pages_expand * 100 - / 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->pages_zero = rs->pages_zero; - - s->good_compress_pct = good_compress_perc; - s->pages_expand_pct = no_compress_perc; - - s->pages_stored = rs->pages_stored; - s->pages_used = mem_used >> PAGE_SHIFT; - s->orig_data_size = rs->pages_stored << PAGE_SHIFT; - s->compr_data_size = rs->compr_size; - s->mem_used_total = mem_used; - } -#endif /* CONFIG_RAMZSWAP_STATS */ -} - -static void ramzswap_free_page(struct ramzswap *rzs, size_t index) -{ - u32 clen; - void *obj; - - struct page *page = rzs->table[index].page; - u32 offset = rzs->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); - } - return; - } - - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { - clen = PAGE_SIZE; - __free_page(page); - rzs_clear_flag(rzs, index, RZS_UNCOMPRESSED); - rzs_stat_dec(&rzs->stats.pages_expand); - goto out; - } - - obj = kmap_atomic(page, KM_USER0) + offset; - clen = xv_get_object_size(obj) - sizeof(struct zobj_header); - kunmap_atomic(obj, KM_USER0); - - xv_free(rzs->mem_pool, page, offset); - if (clen <= PAGE_SIZE / 2) - rzs_stat_dec(&rzs->stats.good_compress); - -out: - rzs->stats.compr_size -= clen; - rzs_stat_dec(&rzs->stats.pages_stored); - - rzs->table[index].page = NULL; - rzs->table[index].offset = 0; -} - -static void handle_zero_page(struct page *page) -{ - void *user_mem; - - user_mem = kmap_atomic(page, KM_USER0); - memset(user_mem, 0, PAGE_SIZE); - kunmap_atomic(user_mem, KM_USER0); - - flush_dcache_page(page); -} - -static void handle_uncompressed_page(struct ramzswap *rzs, - 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; - - memcpy(user_mem, cmem, PAGE_SIZE); - kunmap_atomic(user_mem, KM_USER0); - kunmap_atomic(cmem, KM_USER1); - - flush_dcache_page(page); -} - -static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) -{ - - int i; - u32 index; - struct bio_vec *bvec; - - rzs_stat64_inc(rzs, &rzs->stats.num_reads); - - 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; - - page = bvec->bv_page; - - if (rzs_test_flag(rzs, index, RZS_ZERO)) { - handle_zero_page(page); - continue; - } - - /* 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; - } - - /* Page is stored uncompressed since it's incompressible */ - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { - handle_uncompressed_page(rzs, 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; - - ret = lzo1x_decompress_safe( - cmem + sizeof(*zheader), - xv_get_object_size(cmem) - sizeof(*zheader), - user_mem, &clen); - - kunmap_atomic(user_mem, KM_USER0); - kunmap_atomic(cmem, KM_USER1); - - /* 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); - return 0; - -out: - bio_io_error(bio); - return 0; -} - -static int ramzswap_write(struct ramzswap *rzs, struct bio *bio) -{ - int i; - u32 index; - struct bio_vec *bvec; - - rzs_stat64_inc(rzs, &rzs->stats.num_writes); - - index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; - - 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; - - page = bvec->bv_page; - src = rzs->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); - - mutex_lock(&rzs->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); - continue; - } - - ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen, - rzs->compress_workmem); - - kunmap_atomic(user_mem, KM_USER0); - - 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; - } - - /* - * 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; - } - -memstore: - rzs->table[index].offset = 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); - } -#endif - - memcpy(cmem, src, clen); - - 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); - - mutex_unlock(&rzs->lock); - index++; - } - - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio_endio(bio, 0); - return 0; - -out: - bio_io_error(bio); - return 0; -} - -/* - * Check if request is within bounds and page aligned. - */ -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_size & (PAGE_SIZE - 1)))) { - - return 0; - } - - /* I/O request is valid */ - return 1; -} - -/* - * Handler function for all ramzswap I/O requests. - */ -static int ramzswap_make_request(struct request_queue *queue, struct bio *bio) -{ - int ret = 0; - struct ramzswap *rzs = queue->queuedata; - - if (unlikely(!rzs->init_done)) { - bio_io_error(bio); - return 0; - } - - if (!valid_io_request(rzs, bio)) { - rzs_stat64_inc(rzs, &rzs->stats.invalid_io); - bio_io_error(bio); - return 0; - } - - switch (bio_data_dir(bio)) { - case READ: - ret = ramzswap_read(rzs, bio); - break; - - case WRITE: - ret = ramzswap_write(rzs, bio); - break; - } - - return ret; -} - -static void reset_device(struct ramzswap *rzs) -{ - size_t index; - - /* Do not accept any new I/O request */ - rzs->init_done = 0; - - /* Free various per-device buffers */ - kfree(rzs->compress_workmem); - free_pages((unsigned long)rzs->compress_buffer, 1); - - rzs->compress_workmem = NULL; - rzs->compress_buffer = NULL; - - /* Free all pages that are still in this ramzswap device */ - for (index = 0; index < rzs->disksize >> PAGE_SHIFT; index++) { - struct page *page; - u16 offset; - - page = rzs->table[index].page; - offset = rzs->table[index].offset; - - if (!page) - continue; - - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) - __free_page(page); - else - xv_free(rzs->mem_pool, page, offset); - } - - vfree(rzs->table); - rzs->table = NULL; - - xv_destroy_pool(rzs->mem_pool); - rzs->mem_pool = NULL; - - /* Reset stats */ - memset(&rzs->stats, 0, sizeof(rzs->stats)); - - rzs->disksize = 0; -} - -static int ramzswap_ioctl_init_device(struct ramzswap *rzs) -{ - int ret; - size_t num_pages; - - if (rzs->init_done) { - pr_info("Device already initialized!\n"); - return -EBUSY; - } - - ramzswap_set_disksize(rzs, totalram_pages << PAGE_SHIFT); - - rzs->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); - if (!rzs->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) { - 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"); - /* To prevent accessing table entries during cleanup */ - rzs->disksize = 0; - ret = -ENOMEM; - goto fail; - } - memset(rzs->table, 0, num_pages * sizeof(*rzs->table)); - - set_capacity(rzs->disk, rzs->disksize >> SECTOR_SHIFT); - - /* ramzswap devices sort of resembles non-rotational disks */ - queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rzs->disk->queue); - - rzs->mem_pool = xv_create_pool(); - if (!rzs->mem_pool) { - pr_err("Error creating memory pool\n"); - ret = -ENOMEM; - goto fail; - } - - rzs->init_done = 1; - - pr_debug("Initialization done!\n"); - return 0; - -fail: - reset_device(rzs); - - pr_err("Initialization failed: err=%d\n", ret); - return ret; -} - -static int ramzswap_ioctl_reset_device(struct ramzswap *rzs) -{ - if (rzs->init_done) - reset_device(rzs); - - return 0; -} - -static int ramzswap_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; - - switch (cmd) { - case RZSIO_SET_DISKSIZE_KB: - if (rzs->init_done) { - ret = -EBUSY; - goto out; - } - if (copy_from_user(&disksize_kb, (void *)arg, - _IOC_SIZE(cmd))) { - ret = -EFAULT; - goto out; - } - rzs->disksize = disksize_kb << 10; - pr_info("Disk size set to %zu kB\n", disksize_kb); - break; - - case RZSIO_GET_STATS: - { - struct ramzswap_ioctl_stats *stats; - if (!rzs->init_done) { - ret = -ENOTTY; - goto out; - } - stats = kzalloc(sizeof(*stats), GFP_KERNEL); - if (!stats) { - ret = -ENOMEM; - goto out; - } - ramzswap_ioctl_get_stats(rzs, stats); - if (copy_to_user((void *)arg, stats, sizeof(*stats))) { - kfree(stats); - ret = -EFAULT; - goto out; - } - kfree(stats); - break; - } - case RZSIO_INIT: - ret = ramzswap_ioctl_init_device(rzs); - break; - - case RZSIO_RESET: - /* Do not reset an active device! */ - if (bdev->bd_holders) { - ret = -EBUSY; - goto out; - } - - /* Make sure all pending I/O is finished */ - if (bdev) - fsync_bdev(bdev); - - ret = ramzswap_ioctl_reset_device(rzs); - break; - - default: - pr_info("Invalid ioctl %u\n", cmd); - ret = -ENOTTY; - } - -out: - return ret; -} - -void ramzswap_slot_free_notify(struct block_device *bdev, unsigned long index) -{ - struct ramzswap *rzs; - - rzs = bdev->bd_disk->private_data; - ramzswap_free_page(rzs, index); - rzs_stat64_inc(rzs, &rzs->stats.notify_free); -} - -static const struct block_device_operations ramzswap_devops = { - .ioctl = ramzswap_ioctl, - .swap_slot_free_notify = ramzswap_slot_free_notify, - .owner = THIS_MODULE -}; - -static int create_device(struct ramzswap *rzs, int device_id) -{ - int ret = 0; - - mutex_init(&rzs->lock); - spin_lock_init(&rzs->stat64_lock); - - rzs->queue = blk_alloc_queue(GFP_KERNEL); - if (!rzs->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; - - /* gendisk structure */ - rzs->disk = alloc_disk(1); - if (!rzs->disk) { - blk_cleanup_queue(rzs->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); - - /* 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); - - rzs->init_done = 0; - -out: - return ret; -} - -static void destroy_device(struct ramzswap *rzs) -{ - if (rzs->disk) { - del_gendisk(rzs->disk); - put_disk(rzs->disk); - } - - if (rzs->queue) - blk_cleanup_queue(rzs->queue); -} - -static int __init ramzswap_init(void) -{ - int ret, dev_id; - - if (num_devices > max_num_devices) { - pr_warning("Invalid value for num_devices: %u\n", - num_devices); - ret = -EINVAL; - goto out; - } - - ramzswap_major = register_blkdev(0, "ramzswap"); - if (ramzswap_major <= 0) { - pr_warning("Unable to get major number\n"); - ret = -EBUSY; - goto out; - } - - if (!num_devices) { - pr_info("num_devices not specified. Using default: 1\n"); - num_devices = 1; - } - - /* 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); - if (!devices) { - ret = -ENOMEM; - goto unregister; - } - - for (dev_id = 0; dev_id < num_devices; dev_id++) { - ret = create_device(&devices[dev_id], dev_id); - if (ret) - goto free_devices; - } - - return 0; - -free_devices: - while (dev_id) - destroy_device(&devices[--dev_id]); -unregister: - unregister_blkdev(ramzswap_major, "ramzswap"); -out: - return ret; -} - -static void __exit ramzswap_exit(void) -{ - int i; - struct ramzswap *rzs; - - for (i = 0; i < num_devices; i++) { - rzs = &devices[i]; - - destroy_device(rzs); - if (rzs->init_done) - reset_device(rzs); - } - - unregister_blkdev(ramzswap_major, "ramzswap"); - - kfree(devices); - pr_debug("Cleanup done!\n"); -} - -module_param(num_devices, uint, 0); -MODULE_PARM_DESC(num_devices, "Number of ramzswap devices"); - -module_init(ramzswap_init); -module_exit(ramzswap_exit); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>"); -MODULE_DESCRIPTION("Compressed RAM Based Swap Device"); diff --git a/drivers/staging/ramzswap/ramzswap_drv.h b/drivers/staging/ramzswap/ramzswap_drv.h deleted file mode 100644 index ad91726013b..00000000000 --- a/drivers/staging/ramzswap/ramzswap_drv.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Compressed RAM based swap device - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - * - * Project home: http://compcache.googlecode.com - */ - -#ifndef _RAMZSWAP_DRV_H_ -#define _RAMZSWAP_DRV_H_ - -#include <linux/spinlock.h> -#include <linux/mutex.h> - -#include "ramzswap_ioctl.h" -#include "xvmalloc.h" - -/* - * Some arbitrary value. This is just to catch - * invalid value for num_devices module parameter. - */ -static const unsigned max_num_devices = 32; - -/* - * Stored at beginning of each compressed object. - * - * It stores back-reference to table entry which points to this - * object. This is required to support memory defragmentation. - */ -struct zobj_header { -#if 0 - u32 table_idx; -#endif -}; - -/*-- Configurable parameters */ - -/* Default ramzswap disk size: 25% of total RAM */ -static const unsigned default_disksize_perc_ram = 25; - -/* - * Pages that compress to size greater than this are stored - * uncompressed in memory. - */ -static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3; - -/* - * NOTE: max_zpage_size must be less than or equal to: - * XV_MAX_ALLOC_SIZE - sizeof(struct zobj_header) - * otherwise, xv_malloc() would always return failure. - */ - -/*-- End of configurable params */ - -#define SECTOR_SHIFT 9 -#define SECTOR_SIZE (1 << SECTOR_SHIFT) -#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 { - /* Page is stored uncompressed */ - RZS_UNCOMPRESSED, - - /* Page consists entirely of zeros */ - RZS_ZERO, - - __NR_RZS_PAGEFLAGS, -}; - -/*-- Data structures */ - -/* - * Allocated for each swap slot, indexed by page no. - * These table entries must fit exactly in a page. - */ -struct table { - struct page *page; - u16 offset; - u8 count; /* object ref count (not yet used) */ - u8 flags; -} __attribute__((aligned(4))); - -struct ramzswap_stats { - /* basic stats */ - size_t compr_size; /* compressed size of pages stored - - * needed to enforce memlimit */ - /* more stats */ -#if defined(CONFIG_RAMZSWAP_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 notify_free; /* no. of swap slot free notifications */ - u32 pages_zero; /* no. of zero filled pages */ - u32 pages_stored; /* no. of pages currently stored */ - u32 good_compress; /* % of pages with compression ratio<=50% */ - u32 pages_expand; /* % of incompressible pages */ -#endif -}; - -struct ramzswap { - struct xv_pool *mem_pool; - void *compress_workmem; - void *compress_buffer; - struct table *table; - spinlock_t stat64_lock; /* protect 64-bit stats */ - struct mutex lock; /* protect compression buffers against - * concurrent writes */ - struct request_queue *queue; - 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. - */ - size_t disksize; /* bytes */ - - struct ramzswap_stats stats; -}; - -/*-- */ - -/* Debugging and Stats */ -#if defined(CONFIG_RAMZSWAP_STATS) -static void rzs_stat_inc(u32 *v) -{ - *v = *v + 1; -} - -static void rzs_stat_dec(u32 *v) -{ - *v = *v - 1; -} - -static void rzs_stat64_inc(struct ramzswap *rzs, u64 *v) -{ - spin_lock(&rzs->stat64_lock); - *v = *v + 1; - spin_unlock(&rzs->stat64_lock); -} - -static u64 rzs_stat64_read(struct ramzswap *rzs, u64 *v) -{ - u64 val; - - spin_lock(&rzs->stat64_lock); - val = *v; - spin_unlock(&rzs->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 */ - -#endif diff --git a/drivers/staging/ramzswap/ramzswap_ioctl.h b/drivers/staging/ramzswap/ramzswap_ioctl.h deleted file mode 100644 index db94bcb4296..00000000000 --- a/drivers/staging/ramzswap/ramzswap_ioctl.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Compressed RAM based swap device - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - * - * Project home: http://compcache.googlecode.com - */ - -#ifndef _RAMZSWAP_IOCTL_H_ -#define _RAMZSWAP_IOCTL_H_ - -struct ramzswap_ioctl_stats { - u64 disksize; /* user specified or equal to backing swap - * size (if present) */ - 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 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% */ - u32 pages_expand_pct; /* no. of incompressible pages */ - u32 pages_stored; - u32 pages_used; - u64 orig_data_size; - u64 compr_data_size; - 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) - -#endif diff --git a/drivers/staging/ramzswap/xvmalloc.c b/drivers/staging/ramzswap/xvmalloc.c deleted file mode 100644 index 3fdbb8ada82..00000000000 --- a/drivers/staging/ramzswap/xvmalloc.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * xvmalloc memory allocator - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - */ - -#include <linux/bitops.h> -#include <linux/errno.h> -#include <linux/highmem.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/slab.h> - -#include "xvmalloc.h" -#include "xvmalloc_int.h" - -static void stat_inc(u64 *value) -{ - *value = *value + 1; -} - -static void stat_dec(u64 *value) -{ - *value = *value - 1; -} - -static int test_flag(struct block_header *block, enum blockflags flag) -{ - return block->prev & BIT(flag); -} - -static void set_flag(struct block_header *block, enum blockflags flag) -{ - block->prev |= BIT(flag); -} - -static void clear_flag(struct block_header *block, enum blockflags flag) -{ - block->prev &= ~BIT(flag); -} - -/* - * Given <page, offset> pair, provide a derefrencable pointer. - * This is called from xv_malloc/xv_free path, so it - * needs to be fast. - */ -static void *get_ptr_atomic(struct page *page, u16 offset, enum km_type type) -{ - unsigned char *base; - - base = kmap_atomic(page, type); - return base + offset; -} - -static void put_ptr_atomic(void *ptr, enum km_type type) -{ - kunmap_atomic(ptr, type); -} - -static u32 get_blockprev(struct block_header *block) -{ - return block->prev & PREV_MASK; -} - -static void set_blockprev(struct block_header *block, u16 new_offset) -{ - block->prev = new_offset | (block->prev & FLAGS_MASK); -} - -static struct block_header *BLOCK_NEXT(struct block_header *block) -{ - return (struct block_header *) - ((char *)block + block->size + XV_ALIGN); -} - -/* - * Get index of free list containing blocks of maximum size - * which is less than or equal to given size. - */ -static u32 get_index_for_insert(u32 size) -{ - if (unlikely(size > XV_MAX_ALLOC_SIZE)) - size = XV_MAX_ALLOC_SIZE; - size &= ~FL_DELTA_MASK; - return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; -} - -/* - * Get index of free list having blocks of size greater than - * or equal to requested size. - */ -static u32 get_index(u32 size) -{ - if (unlikely(size < XV_MIN_ALLOC_SIZE)) - size = XV_MIN_ALLOC_SIZE; - size = ALIGN(size, FL_DELTA); - return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; -} - -/** - * find_block - find block of at least given size - * @pool: memory pool to search from - * @size: size of block required - * @page: page containing required block - * @offset: offset within the page where block is located. - * - * Searches two level bitmap to locate block of at least - * the given size. If such a block is found, it provides - * <page, offset> to identify this block and returns index - * in freelist where we found this block. - * Otherwise, returns 0 and <page, offset> params are not touched. - */ -static u32 find_block(struct xv_pool *pool, u32 size, - struct page **page, u32 *offset) -{ - ulong flbitmap, slbitmap; - u32 flindex, slindex, slbitstart; - - /* There are no free blocks in this pool */ - if (!pool->flbitmap) - return 0; - - /* Get freelist index correspoding to this size */ - slindex = get_index(size); - slbitmap = pool->slbitmap[slindex / BITS_PER_LONG]; - slbitstart = slindex % BITS_PER_LONG; - - /* - * If freelist is not empty at this index, we found the - * block - head of this list. This is approximate best-fit match. - */ - if (test_bit(slbitstart, &slbitmap)) { - *page = pool->freelist[slindex].page; - *offset = pool->freelist[slindex].offset; - return slindex; - } - - /* - * No best-fit found. Search a bit further in bitmap for a free block. - * Second level bitmap consists of series of 32-bit chunks. Search - * further in the chunk where we expected a best-fit, starting from - * index location found above. - */ - slbitstart++; - slbitmap >>= slbitstart; - - /* Skip this search if we were already at end of this bitmap chunk */ - if ((slbitstart != BITS_PER_LONG) && slbitmap) { - slindex += __ffs(slbitmap) + 1; - *page = pool->freelist[slindex].page; - *offset = pool->freelist[slindex].offset; - return slindex; - } - - /* Now do a full two-level bitmap search to find next nearest fit */ - flindex = slindex / BITS_PER_LONG; - - flbitmap = (pool->flbitmap) >> (flindex + 1); - if (!flbitmap) - return 0; - - flindex += __ffs(flbitmap) + 1; - slbitmap = pool->slbitmap[flindex]; - slindex = (flindex * BITS_PER_LONG) + __ffs(slbitmap); - *page = pool->freelist[slindex].page; - *offset = pool->freelist[slindex].offset; - - return slindex; -} - -/* - * Insert block at <page, offset> in freelist of given pool. - * freelist used depends on block size. - */ -static void insert_block(struct xv_pool *pool, struct page *page, u32 offset, - struct block_header *block) -{ - u32 flindex, slindex; - struct block_header *nextblock; - - slindex = get_index_for_insert(block->size); - flindex = slindex / BITS_PER_LONG; - - block->link.prev_page = 0; - block->link.prev_offset = 0; - block->link.next_page = pool->freelist[slindex].page; - block->link.next_offset = pool->freelist[slindex].offset; - pool->freelist[slindex].page = page; - pool->freelist[slindex].offset = offset; - - if (block->link.next_page) { - nextblock = get_ptr_atomic(block->link.next_page, - block->link.next_offset, KM_USER1); - nextblock->link.prev_page = page; - nextblock->link.prev_offset = offset; - put_ptr_atomic(nextblock, KM_USER1); - } - - __set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); - __set_bit(flindex, &pool->flbitmap); -} - -/* - * Remove block from head of freelist. Index 'slindex' identifies the freelist. - */ -static void remove_block_head(struct xv_pool *pool, - struct block_header *block, u32 slindex) -{ - struct block_header *tmpblock; - u32 flindex = slindex / BITS_PER_LONG; - - pool->freelist[slindex].page = block->link.next_page; - pool->freelist[slindex].offset = block->link.next_offset; - block->link.prev_page = 0; - block->link.prev_offset = 0; - - if (!pool->freelist[slindex].page) { - __clear_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); - if (!pool->slbitmap[flindex]) - __clear_bit(flindex, &pool->flbitmap); - } else { - /* - * DEBUG ONLY: We need not reinitialize freelist head previous - * pointer to 0 - we never depend on its value. But just for - * sanity, lets do it. - */ - tmpblock = get_ptr_atomic(pool->freelist[slindex].page, - pool->freelist[slindex].offset, KM_USER1); - tmpblock->link.prev_page = 0; - tmpblock->link.prev_offset = 0; - put_ptr_atomic(tmpblock, KM_USER1); - } -} - -/* - * Remove block from freelist. Index 'slindex' identifies the freelist. - */ -static void remove_block(struct xv_pool *pool, struct page *page, u32 offset, - struct block_header *block, u32 slindex) -{ - u32 flindex; - struct block_header *tmpblock; - - if (pool->freelist[slindex].page == page - && pool->freelist[slindex].offset == offset) { - remove_block_head(pool, block, slindex); - return; - } - - flindex = slindex / BITS_PER_LONG; - - if (block->link.prev_page) { - tmpblock = get_ptr_atomic(block->link.prev_page, - block->link.prev_offset, KM_USER1); - tmpblock->link.next_page = block->link.next_page; - tmpblock->link.next_offset = block->link.next_offset; - put_ptr_atomic(tmpblock, KM_USER1); - } - - if (block->link.next_page) { - tmpblock = get_ptr_atomic(block->link.next_page, - block->link.next_offset, KM_USER1); - tmpblock->link.prev_page = block->link.prev_page; - tmpblock->link.prev_offset = block->link.prev_offset; - put_ptr_atomic(tmpblock, KM_USER1); - } -} - -/* - * Allocate a page and add it to freelist of given pool. - */ -static int grow_pool(struct xv_pool *pool, gfp_t flags) -{ - struct page *page; - struct block_header *block; - - page = alloc_page(flags); - if (unlikely(!page)) - return -ENOMEM; - - stat_inc(&pool->total_pages); - - spin_lock(&pool->lock); - block = get_ptr_atomic(page, 0, KM_USER0); - - block->size = PAGE_SIZE - XV_ALIGN; - set_flag(block, BLOCK_FREE); - clear_flag(block, PREV_FREE); - set_blockprev(block, 0); - - insert_block(pool, page, 0, block); - - put_ptr_atomic(block, KM_USER0); - spin_unlock(&pool->lock); - - return 0; -} - -/* - * Create a memory pool. Allocates freelist, bitmaps and other - * per-pool metadata. - */ -struct xv_pool *xv_create_pool(void) -{ - u32 ovhd_size; - struct xv_pool *pool; - - ovhd_size = roundup(sizeof(*pool), PAGE_SIZE); - pool = kzalloc(ovhd_size, GFP_KERNEL); - if (!pool) - return NULL; - - spin_lock_init(&pool->lock); - - return pool; -} - -void xv_destroy_pool(struct xv_pool *pool) -{ - kfree(pool); -} - -/** - * xv_malloc - Allocate block of given size from pool. - * @pool: pool to allocate from - * @size: size of block to allocate - * @page: page no. that holds the object - * @offset: location of object within page - * - * On success, <page, offset> identifies block allocated - * and 0 is returned. On failure, <page, offset> is set to - * 0 and -ENOMEM is returned. - * - * Allocation requests with size > XV_MAX_ALLOC_SIZE will fail. - */ -int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, - u32 *offset, gfp_t flags) -{ - int error; - u32 index, tmpsize, origsize, tmpoffset; - struct block_header *block, *tmpblock; - - *page = NULL; - *offset = 0; - origsize = size; - - if (unlikely(!size || size > XV_MAX_ALLOC_SIZE)) - return -ENOMEM; - - size = ALIGN(size, XV_ALIGN); - - spin_lock(&pool->lock); - - index = find_block(pool, size, page, offset); - - if (!*page) { - spin_unlock(&pool->lock); - if (flags & GFP_NOWAIT) - return -ENOMEM; - error = grow_pool(pool, flags); - if (unlikely(error)) - return error; - - spin_lock(&pool->lock); - index = find_block(pool, size, page, offset); - } - - if (!*page) { - spin_unlock(&pool->lock); - return -ENOMEM; - } - - block = get_ptr_atomic(*page, *offset, KM_USER0); - - remove_block_head(pool, block, index); - - /* Split the block if required */ - tmpoffset = *offset + size + XV_ALIGN; - tmpsize = block->size - size; - tmpblock = (struct block_header *)((char *)block + size + XV_ALIGN); - if (tmpsize) { - tmpblock->size = tmpsize - XV_ALIGN; - set_flag(tmpblock, BLOCK_FREE); - clear_flag(tmpblock, PREV_FREE); - - set_blockprev(tmpblock, *offset); - if (tmpblock->size >= XV_MIN_ALLOC_SIZE) - insert_block(pool, *page, tmpoffset, tmpblock); - - if (tmpoffset + XV_ALIGN + tmpblock->size != PAGE_SIZE) { - tmpblock = BLOCK_NEXT(tmpblock); - set_blockprev(tmpblock, tmpoffset); - } - } else { - /* This block is exact fit */ - if (tmpoffset != PAGE_SIZE) - clear_flag(tmpblock, PREV_FREE); - } - - block->size = origsize; - clear_flag(block, BLOCK_FREE); - - put_ptr_atomic(block, KM_USER0); - spin_unlock(&pool->lock); - - *offset += XV_ALIGN; - - return 0; -} - -/* - * Free block identified with <page, offset> - */ -void xv_free(struct xv_pool *pool, struct page *page, u32 offset) -{ - void *page_start; - struct block_header *block, *tmpblock; - - offset -= XV_ALIGN; - - spin_lock(&pool->lock); - - page_start = get_ptr_atomic(page, 0, KM_USER0); - block = (struct block_header *)((char *)page_start + offset); - - /* Catch double free bugs */ - BUG_ON(test_flag(block, BLOCK_FREE)); - - block->size = ALIGN(block->size, XV_ALIGN); - - tmpblock = BLOCK_NEXT(block); - if (offset + block->size + XV_ALIGN == PAGE_SIZE) - tmpblock = NULL; - - /* Merge next block if its free */ - if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) { - /* - * Blocks smaller than XV_MIN_ALLOC_SIZE - * are not inserted in any free list. - */ - if (tmpblock->size >= XV_MIN_ALLOC_SIZE) { - remove_block(pool, page, - offset + block->size + XV_ALIGN, tmpblock, - get_index_for_insert(tmpblock->size)); - } - block->size += tmpblock->size + XV_ALIGN; - } - - /* Merge previous block if its free */ - if (test_flag(block, PREV_FREE)) { - tmpblock = (struct block_header *)((char *)(page_start) + - get_blockprev(block)); - offset = offset - tmpblock->size - XV_ALIGN; - - if (tmpblock->size >= XV_MIN_ALLOC_SIZE) - remove_block(pool, page, offset, tmpblock, - get_index_for_insert(tmpblock->size)); - - tmpblock->size += block->size + XV_ALIGN; - block = tmpblock; - } - - /* No used objects in this page. Free it. */ - if (block->size == PAGE_SIZE - XV_ALIGN) { - put_ptr_atomic(page_start, KM_USER0); - spin_unlock(&pool->lock); - - __free_page(page); - stat_dec(&pool->total_pages); - return; - } - - set_flag(block, BLOCK_FREE); - if (block->size >= XV_MIN_ALLOC_SIZE) - insert_block(pool, page, offset, block); - - if (offset + block->size + XV_ALIGN != PAGE_SIZE) { - tmpblock = BLOCK_NEXT(block); - set_flag(tmpblock, PREV_FREE); - set_blockprev(tmpblock, offset); - } - - put_ptr_atomic(page_start, KM_USER0); - spin_unlock(&pool->lock); -} - -u32 xv_get_object_size(void *obj) -{ - struct block_header *blk; - - blk = (struct block_header *)((char *)(obj) - XV_ALIGN); - return blk->size; -} - -/* - * Returns total memory used by allocator (userdata + metadata) - */ -u64 xv_get_total_size_bytes(struct xv_pool *pool) -{ - return pool->total_pages << PAGE_SHIFT; -} diff --git a/drivers/staging/ramzswap/xvmalloc.h b/drivers/staging/ramzswap/xvmalloc.h deleted file mode 100644 index 5b1a81aa5fa..00000000000 --- a/drivers/staging/ramzswap/xvmalloc.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * xvmalloc memory allocator - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - */ - -#ifndef _XV_MALLOC_H_ -#define _XV_MALLOC_H_ - -#include <linux/types.h> - -struct xv_pool; - -struct xv_pool *xv_create_pool(void); -void xv_destroy_pool(struct xv_pool *pool); - -int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, - u32 *offset, gfp_t flags); -void xv_free(struct xv_pool *pool, struct page *page, u32 offset); - -u32 xv_get_object_size(void *obj); -u64 xv_get_total_size_bytes(struct xv_pool *pool); - -#endif diff --git a/drivers/staging/ramzswap/xvmalloc_int.h b/drivers/staging/ramzswap/xvmalloc_int.h deleted file mode 100644 index e23ed5c8b8e..00000000000 --- a/drivers/staging/ramzswap/xvmalloc_int.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * xvmalloc memory allocator - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - */ - -#ifndef _XV_MALLOC_INT_H_ -#define _XV_MALLOC_INT_H_ - -#include <linux/kernel.h> -#include <linux/types.h> - -/* User configurable params */ - -/* Must be power of two */ -#define XV_ALIGN_SHIFT 2 -#define XV_ALIGN (1 << XV_ALIGN_SHIFT) -#define XV_ALIGN_MASK (XV_ALIGN - 1) - -/* This must be greater than sizeof(link_free) */ -#define XV_MIN_ALLOC_SIZE 32 -#define XV_MAX_ALLOC_SIZE (PAGE_SIZE - XV_ALIGN) - -/* Free lists are separated by FL_DELTA bytes */ -#define FL_DELTA_SHIFT 3 -#define FL_DELTA (1 << FL_DELTA_SHIFT) -#define FL_DELTA_MASK (FL_DELTA - 1) -#define NUM_FREE_LISTS ((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \ - / FL_DELTA + 1) - -#define MAX_FLI DIV_ROUND_UP(NUM_FREE_LISTS, BITS_PER_LONG) - -/* End of user params */ - -enum blockflags { - BLOCK_FREE, - PREV_FREE, - __NR_BLOCKFLAGS, -}; - -#define FLAGS_MASK XV_ALIGN_MASK -#define PREV_MASK (~FLAGS_MASK) - -struct freelist_entry { - struct page *page; - u16 offset; - u16 pad; -}; - -struct link_free { - struct page *prev_page; - struct page *next_page; - u16 prev_offset; - u16 next_offset; -}; - -struct block_header { - union { - /* This common header must be XV_ALIGN bytes */ - u8 common[XV_ALIGN]; - struct { - u16 size; - u16 prev; - }; - }; - struct link_free link; -}; - -struct xv_pool { - ulong flbitmap; - ulong slbitmap[MAX_FLI]; - spinlock_t lock; - - struct freelist_entry freelist[NUM_FREE_LISTS]; - - /* stats */ - u64 total_pages; -}; - -#endif |