Merge branch 'for-3.2/core' of git://git.kernel.dk/linux-block
[pandora-kernel.git] / drivers / staging / zram / zram_drv.c
index 02589ca..09de99f 100644 (file)
 
 /* Globals */
 static int zram_major;
-struct zram *devices;
+struct zram *zram_devices;
 
 /* Module params (documentation at end) */
-unsigned int num_devices;
+unsigned int zram_num_devices;
 
 static void zram_stat_inc(u32 *v)
 {
@@ -560,25 +560,33 @@ static void 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;
-       }
-
-       if (unlikely(!zram->init_done) && zram_init_device(zram)) {
-               bio_io_error(bio);
-               return;
+               goto error_unlock;
        }
 
        __zram_make_request(zram, bio, bio_data_dir(bio));
+       up_read(&zram->init_lock);
+
+       return;
+
+error_unlock:
+       up_read(&zram->init_lock);
+error:
+       bio_io_error(bio);
 }
 
-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 */
@@ -615,7 +623,13 @@ void zram_reset_device(struct zram *zram)
        memset(&zram->stats, 0, sizeof(zram->stats));
 
        zram->disksize = 0;
-       mutex_unlock(&zram->init_lock);
+}
+
+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)
@@ -623,10 +637,10 @@ 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;
        }
 
@@ -636,24 +650,22 @@ int zram_init_device(struct zram *zram)
        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);
        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 = vzalloc(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;
        }
 
        set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
@@ -669,20 +681,23 @@ 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;
 }
 
-void zram_slot_free_notify(struct block_device *bdev, unsigned long index)
+static void zram_slot_free_notify(struct block_device *bdev,
+                               unsigned long index)
 {
        struct zram *zram;
 
@@ -701,7 +716,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);
@@ -778,9 +793,9 @@ static int __init zram_init(void)
 {
        int ret, dev_id;
 
-       if (num_devices > max_num_devices) {
+       if (zram_num_devices > max_num_devices) {
                pr_warning("Invalid value for num_devices: %u\n",
-                               num_devices);
+                               zram_num_devices);
                ret = -EINVAL;
                goto out;
        }
@@ -792,21 +807,21 @@ static int __init zram_init(void)
                goto out;
        }
 
-       if (!num_devices) {
+       if (!zram_num_devices) {
                pr_info("num_devices not specified. Using default: 1\n");
-               num_devices = 1;
+               zram_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 zram), GFP_KERNEL);
-       if (!devices) {
+       pr_info("Creating %u devices ...\n", zram_num_devices);
+       zram_devices = kzalloc(zram_num_devices * sizeof(struct zram), GFP_KERNEL);
+       if (!zram_devices) {
                ret = -ENOMEM;
                goto unregister;
        }
 
-       for (dev_id = 0; dev_id < num_devices; dev_id++) {
-               ret = create_device(&devices[dev_id], dev_id);
+       for (dev_id = 0; dev_id < zram_num_devices; dev_id++) {
+               ret = create_device(&zram_devices[dev_id], dev_id);
                if (ret)
                        goto free_devices;
        }
@@ -815,8 +830,8 @@ static int __init zram_init(void)
 
 free_devices:
        while (dev_id)
-               destroy_device(&devices[--dev_id]);
-       kfree(devices);
+               destroy_device(&zram_devices[--dev_id]);
+       kfree(zram_devices);
 unregister:
        unregister_blkdev(zram_major, "zram");
 out:
@@ -828,8 +843,8 @@ static void __exit zram_exit(void)
        int i;
        struct zram *zram;
 
-       for (i = 0; i < num_devices; i++) {
-               zram = &devices[i];
+       for (i = 0; i < zram_num_devices; i++) {
+               zram = &zram_devices[i];
 
                destroy_device(zram);
                if (zram->init_done)
@@ -838,12 +853,12 @@ static void __exit zram_exit(void)
 
        unregister_blkdev(zram_major, "zram");
 
-       kfree(devices);
+       kfree(zram_devices);
        pr_debug("Cleanup done!\n");
 }
 
-module_param(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);