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:
parent
cc0db50c33
commit
c95ed3371a
25
drivers/staging/zram/Kconfig
Normal file → Executable file
25
drivers/staging/zram/Kconfig
Normal file → Executable 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
0
drivers/staging/zram/Makefile
Normal file → Executable file
0
drivers/staging/zram/xvmalloc.c
Normal file → Executable file
0
drivers/staging/zram/xvmalloc.c
Normal file → Executable file
0
drivers/staging/zram/xvmalloc.h
Normal file → Executable file
0
drivers/staging/zram/xvmalloc.h
Normal file → Executable file
0
drivers/staging/zram/xvmalloc_int.h
Normal file → Executable file
0
drivers/staging/zram/xvmalloc_int.h
Normal file → Executable file
0
drivers/staging/zram/zram.txt
Normal file → Executable file
0
drivers/staging/zram/zram.txt
Normal file → Executable file
134
drivers/staging/zram/zram_drv.c
Normal file → Executable file
134
drivers/staging/zram/zram_drv.c
Normal file → Executable 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
8
drivers/staging/zram/zram_drv.h
Normal file → Executable 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
18
drivers/staging/zram/zram_sysfs.c
Normal file → Executable 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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user