staging: zram: fix zram locking

Staging: zram: Replace mutex lock by a R/W semaphore
Staging: zram: Add a missing GFP_KERNEL specifier in zram_init_device()
This commit is contained in:
SecureCRT 2012-08-17 01:21:55 +08:00
parent cc0db50c33
commit c95ed3371a
9 changed files with 95 additions and 90 deletions

25
drivers/staging/zram/Kconfig Normal file → Executable file
View File

@ -21,23 +21,6 @@ config ZRAM
See zram.txt for more information.
Project home: http://compcache.googlecode.com/
config ZRAM_NUM_DEVICES
int "Default number of zram devices"
depends on ZRAM
range 1 32
default 1
help
Select default number of zram devices. You can override this value
using 'num_devices' module parameter.
config ZRAM_DEFAULT_PERCENTAGE
int "Default number of zram percentage"
depends on ZRAM
range 10 80
default 25
help
Select default zram disk size: percentage of total RAM
config ZRAM_DEBUG
bool "Compressed RAM block device debug support"
depends on ZRAM
@ -45,11 +28,3 @@ config ZRAM_DEBUG
help
This option adds additional debugging code to the compressed
RAM block device driver.
config ZRAM_DEFAULT_DISKSIZE
int "Default size of zram in bytes"
depends on ZRAM
default 100663296
help
Set default zram disk size (default ~ 96MB)

0
drivers/staging/zram/Makefile Normal file → Executable file
View File

0
drivers/staging/zram/xvmalloc.c Normal file → Executable file
View File

0
drivers/staging/zram/xvmalloc.h Normal file → Executable file
View File

0
drivers/staging/zram/xvmalloc_int.h Normal file → Executable file
View File

0
drivers/staging/zram/zram.txt Normal file → Executable file
View File

134
drivers/staging/zram/zram_drv.c Normal file → Executable file
View File

@ -104,19 +104,33 @@ static int page_zero_filled(void *ptr)
return 1;
}
static u64 zram_default_disksize_bytes(void)
static void zram_set_disksize(struct zram *zram, size_t totalram_bytes)
{
#if 0
return ((totalram_pages << PAGE_SHIFT) *
default_disksize_perc_ram / 100) & PAGE_MASK;
#endif
return CONFIG_ZRAM_DEFAULT_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
);
zram->disksize = default_disksize_perc_ram *
(totalram_bytes / 100);
}
static void zram_set_disksize(struct zram *zram, u64 size_bytes)
{
zram->disksize = size_bytes;
set_capacity(zram->disk, size_bytes >> SECTOR_SHIFT);
if (zram->disksize > 2 * (totalram_bytes)) {
pr_info(
"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 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: %llu kB\n"
"Continuing anyway ...\n",
totalram_bytes >> 10, zram->disksize
);
}
zram->disksize &= PAGE_MASK;
}
static void zram_free_page(struct zram *zram, size_t index)
@ -546,27 +560,35 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio)
{
struct zram *zram = queue->queuedata;
if (unlikely(!zram->init_done) && zram_init_device(zram))
goto error;
down_read(&zram->init_lock);
if (unlikely(!zram->init_done))
goto error_unlock;
if (!valid_io_request(zram, bio)) {
zram_stat64_inc(zram, &zram->stats.invalid_io);
bio_io_error(bio);
return 0;
}
if (unlikely(!zram->init_done) && zram_init_device(zram)) {
bio_io_error(bio);
return 0;
goto error_unlock;
}
__zram_make_request(zram, bio, bio_data_dir(bio));
up_read(&zram->init_lock);
return 0;
error_unlock:
up_read(&zram->init_lock);
error:
bio_io_error(bio);
return 0;
}
void zram_reset_device(struct zram *zram)
void __zram_reset_device(struct zram *zram)
{
size_t index;
mutex_lock(&zram->init_lock);
zram->init_done = 0;
/* Free various per-device buffers */
@ -602,8 +624,14 @@ void zram_reset_device(struct zram *zram)
/* Reset stats */
memset(&zram->stats, 0, sizeof(zram->stats));
zram_set_disksize(zram, zram_default_disksize_bytes());
mutex_unlock(&zram->init_lock);
zram->disksize = 0;
}
void zram_reset_device(struct zram *zram)
{
down_write(&zram->init_lock);
__zram_reset_device(zram);
up_write(&zram->init_lock);
}
int zram_init_device(struct zram *zram)
@ -611,37 +639,39 @@ int zram_init_device(struct zram *zram)
int ret;
size_t num_pages;
mutex_lock(&zram->init_lock);
down_write(&zram->init_lock);
if (zram->init_done) {
mutex_unlock(&zram->init_lock);
up_write(&zram->init_lock);
return 0;
}
zram_set_disksize(zram, totalram_pages << PAGE_SHIFT);
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;
goto fail_no_table;
}
zram->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1);
zram->compress_buffer =
(void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
if (!zram->compress_buffer) {
pr_err("Error allocating compressor buffer space\n");
ret = -ENOMEM;
goto fail;
goto fail_no_table;
}
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 */
zram->disksize = 0;
ret = -ENOMEM;
goto fail;
goto fail_no_table;
}
memset(zram->table, 0, num_pages * sizeof(*zram->table));
memset(zram->table, 0, num_pages * sizeof(*zram->table));
set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
/* zram devices sort of resembles non-rotational disks */
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);
@ -654,15 +684,17 @@ int zram_init_device(struct zram *zram)
}
zram->init_done = 1;
mutex_unlock(&zram->init_lock);
up_write(&zram->init_lock);
pr_debug("Initialization done!\n");
return 0;
fail_no_table:
/* To prevent accessing table entries during cleanup */
zram->disksize = 0;
fail:
mutex_unlock(&zram->init_lock);
zram_reset_device(zram);
__zram_reset_device(zram);
up_write(&zram->init_lock);
pr_err("Initialization failed: err=%d\n", ret);
return ret;
}
@ -687,7 +719,7 @@ static int create_device(struct zram *zram, int device_id)
int ret = 0;
init_rwsem(&zram->lock);
mutex_init(&zram->init_lock);
init_rwsem(&zram->init_lock);
spin_lock_init(&zram->stat64_lock);
zram->queue = blk_alloc_queue(GFP_KERNEL);
@ -718,12 +750,8 @@ static int create_device(struct zram *zram, int device_id)
zram->disk->private_data = zram;
snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
/*
* Set some default disksize. To set another disksize, user
* must reset the device and then write a new disksize to
* corresponding device's sysfs node.
*/
zram_set_disksize(zram, zram_default_disksize_bytes());
/* Actual capacity set using syfs (/sys/block/zram<id>/disksize */
set_capacity(zram->disk, 0);
/*
* To ensure that we always get PAGE_SIZE aligned
@ -768,13 +796,6 @@ static int __init zram_init(void)
{
int ret, dev_id;
/*
* Module parameter not specified by user. Use default
* value as defined during kernel config.
*/
if (zram_num_devices == 0)
zram_num_devices = CONFIG_ZRAM_NUM_DEVICES;
if (zram_num_devices > max_num_devices) {
pr_warning("Invalid value for num_devices: %u\n",
zram_num_devices);
@ -789,12 +810,15 @@ static int __init zram_init(void)
goto out;
}
if (!zram_num_devices) {
pr_info("num_devices not specified. Using default: 1\n");
zram_num_devices = 1;
}
/* Allocate the device array and initialize each one */
pr_info("Creating %u devices ...\n", zram_num_devices);
zram_devices = kzalloc(zram_num_devices * sizeof(struct zram),
GFP_KERNEL);
if (!zram_devices)
{
zram_devices = kzalloc(zram_num_devices * sizeof(struct zram), GFP_KERNEL);
if (!zram_devices) {
ret = -ENOMEM;
goto unregister;
}
@ -836,8 +860,8 @@ static void __exit zram_exit(void)
pr_debug("Cleanup done!\n");
}
module_param_named(num_devices, zram_num_devices, uint, 0);
MODULE_PARM_DESC(num_devices, "Number of zram devices");
module_param(zram_num_devices, uint, 0);
MODULE_PARM_DESC(zram_num_devices, "Number of zram devices");
module_init(zram_init);
module_exit(zram_exit);

8
drivers/staging/zram/zram_drv.h Normal file → Executable file
View File

@ -41,7 +41,7 @@ struct zobj_header {
/*-- Configurable parameters */
/* Default zram disk size: 25% of total RAM */
static const unsigned default_disksize_perc_ram = CONFIG_ZRAM_DEFAULT_PERCENTAGE;
static const unsigned default_disksize_perc_ram = 25;
/*
* Pages that compress to size greater than this are stored
@ -112,8 +112,8 @@ struct zram {
struct request_queue *queue;
struct gendisk *disk;
int init_done;
/* Prevent concurrent execution of device init and reset */
struct mutex init_lock;
/* Prevent concurrent execution of device init, reset and R/W request */
struct rw_semaphore init_lock;
/*
* This is the limit on amount of *uncompressed* worth of data
* we can store in a disk.
@ -130,7 +130,7 @@ extern struct attribute_group zram_disk_attr_group;
#endif
extern int zram_init_device(struct zram *zram);
extern void zram_reset_device(struct zram *zram);
extern void __zram_reset_device(struct zram *zram);
#endif

18
drivers/staging/zram/zram_sysfs.c Normal file → Executable file
View File

@ -55,19 +55,23 @@ static ssize_t disksize_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
int ret;
u64 disksize;
struct zram *zram = dev_to_zram(dev);
ret = strict_strtoull(buf, 10, &disksize);
if (ret)
return ret;
down_write(&zram->init_lock);
if (zram->init_done) {
up_write(&zram->init_lock);
pr_info("Cannot change disksize for initialized device\n");
return -EBUSY;
}
ret = strict_strtoull(buf, 10, &zram->disksize);
if (ret)
return ret;
zram->disksize = PAGE_ALIGN(zram->disksize);
zram->disksize = PAGE_ALIGN(disksize);
set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
up_write(&zram->init_lock);
return len;
}
@ -106,8 +110,10 @@ static ssize_t reset_store(struct device *dev,
if (bdev)
fsync_bdev(bdev);
down_write(&zram->init_lock);
if (zram->init_done)
zram_reset_device(zram);
__zram_reset_device(zram);
up_write(&zram->init_lock);
return len;
}