diff options
author | Sergey Senozhatsky <sergey.senozhatsky@gmail.com> | 2015-06-25 18:00:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-25 20:00:36 -0400 |
commit | 85508ec6cbc21645927b6ac05e3b2748119a3e23 (patch) | |
tree | 77eaa8003f4dd6f2aad867c5c54337ee9acc909d /drivers/block | |
parent | 3bca3ef7694166b86c91b515818cc5acecd357a7 (diff) |
zram: use idr instead of `zram_devices' array
This patch makes some preparations for on-demand device add/remove
functionality.
Remove `zram_devices' array and switch to id-to-pointer translation (idr).
idr doesn't bloat zram struct with additional members, f.e. list_head,
yet still provides ability to match the device_id with the device pointer.
No user-space visible changes.
[Julia.Lawall@lip6.fr: return -ENOMEM when `queue' alloc fails]
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Reported-by: Julia Lawall <Julia.Lawall@lip6.fr>
Acked-by: Minchan Kim <minchan@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/zram/zram_drv.c | 86 |
1 files changed, 49 insertions, 37 deletions
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 7814e686e23c..addb18d1b8d7 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c | |||
@@ -28,12 +28,12 @@ | |||
28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
29 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
30 | #include <linux/err.h> | 30 | #include <linux/err.h> |
31 | #include <linux/idr.h> | ||
31 | 32 | ||
32 | #include "zram_drv.h" | 33 | #include "zram_drv.h" |
33 | 34 | ||
34 | /* Globals */ | 35 | static DEFINE_IDR(zram_index_idr); |
35 | static int zram_major; | 36 | static int zram_major; |
36 | static struct zram *zram_devices; | ||
37 | static const char *default_compressor = "lzo"; | 37 | static const char *default_compressor = "lzo"; |
38 | 38 | ||
39 | /* Module params (documentation at end) */ | 39 | /* Module params (documentation at end) */ |
@@ -1154,10 +1154,20 @@ static struct attribute_group zram_disk_attr_group = { | |||
1154 | .attrs = zram_disk_attrs, | 1154 | .attrs = zram_disk_attrs, |
1155 | }; | 1155 | }; |
1156 | 1156 | ||
1157 | static int create_device(struct zram *zram, int device_id) | 1157 | static int zram_add(int device_id) |
1158 | { | 1158 | { |
1159 | struct zram *zram; | ||
1159 | struct request_queue *queue; | 1160 | struct request_queue *queue; |
1160 | int ret = -ENOMEM; | 1161 | int ret; |
1162 | |||
1163 | zram = kzalloc(sizeof(struct zram), GFP_KERNEL); | ||
1164 | if (!zram) | ||
1165 | return -ENOMEM; | ||
1166 | |||
1167 | ret = idr_alloc(&zram_index_idr, zram, device_id, | ||
1168 | device_id + 1, GFP_KERNEL); | ||
1169 | if (ret < 0) | ||
1170 | goto out_free_dev; | ||
1161 | 1171 | ||
1162 | init_rwsem(&zram->init_lock); | 1172 | init_rwsem(&zram->init_lock); |
1163 | 1173 | ||
@@ -1165,12 +1175,13 @@ static int create_device(struct zram *zram, int device_id) | |||
1165 | if (!queue) { | 1175 | if (!queue) { |
1166 | pr_err("Error allocating disk queue for device %d\n", | 1176 | pr_err("Error allocating disk queue for device %d\n", |
1167 | device_id); | 1177 | device_id); |
1168 | goto out; | 1178 | ret = -ENOMEM; |
1179 | goto out_free_idr; | ||
1169 | } | 1180 | } |
1170 | 1181 | ||
1171 | blk_queue_make_request(queue, zram_make_request); | 1182 | blk_queue_make_request(queue, zram_make_request); |
1172 | 1183 | ||
1173 | /* gendisk structure */ | 1184 | /* gendisk structure */ |
1174 | zram->disk = alloc_disk(1); | 1185 | zram->disk = alloc_disk(1); |
1175 | if (!zram->disk) { | 1186 | if (!zram->disk) { |
1176 | pr_warn("Error allocating disk structure for device %d\n", | 1187 | pr_warn("Error allocating disk structure for device %d\n", |
@@ -1235,34 +1246,42 @@ out_free_disk: | |||
1235 | put_disk(zram->disk); | 1246 | put_disk(zram->disk); |
1236 | out_free_queue: | 1247 | out_free_queue: |
1237 | blk_cleanup_queue(queue); | 1248 | blk_cleanup_queue(queue); |
1238 | out: | 1249 | out_free_idr: |
1250 | idr_remove(&zram_index_idr, device_id); | ||
1251 | out_free_dev: | ||
1252 | kfree(zram); | ||
1239 | return ret; | 1253 | return ret; |
1240 | } | 1254 | } |
1241 | 1255 | ||
1242 | static void destroy_devices(unsigned int nr) | 1256 | static void zram_remove(struct zram *zram) |
1243 | { | 1257 | { |
1244 | struct zram *zram; | 1258 | /* |
1245 | unsigned int i; | 1259 | * Remove sysfs first, so no one will perform a disksize |
1246 | 1260 | * store while we destroy the devices | |
1247 | for (i = 0; i < nr; i++) { | 1261 | */ |
1248 | zram = &zram_devices[i]; | 1262 | sysfs_remove_group(&disk_to_dev(zram->disk)->kobj, |
1249 | /* | 1263 | &zram_disk_attr_group); |
1250 | * Remove sysfs first, so no one will perform a disksize | ||
1251 | * store while we destroy the devices | ||
1252 | */ | ||
1253 | sysfs_remove_group(&disk_to_dev(zram->disk)->kobj, | ||
1254 | &zram_disk_attr_group); | ||
1255 | 1264 | ||
1256 | zram_reset_device(zram); | 1265 | zram_reset_device(zram); |
1266 | idr_remove(&zram_index_idr, zram->disk->first_minor); | ||
1267 | blk_cleanup_queue(zram->disk->queue); | ||
1268 | del_gendisk(zram->disk); | ||
1269 | put_disk(zram->disk); | ||
1270 | kfree(zram); | ||
1271 | } | ||
1257 | 1272 | ||
1258 | blk_cleanup_queue(zram->disk->queue); | 1273 | static int zram_remove_cb(int id, void *ptr, void *data) |
1259 | del_gendisk(zram->disk); | 1274 | { |
1260 | put_disk(zram->disk); | 1275 | zram_remove(ptr); |
1261 | } | 1276 | return 0; |
1277 | } | ||
1262 | 1278 | ||
1263 | kfree(zram_devices); | 1279 | static void destroy_devices(void) |
1280 | { | ||
1281 | idr_for_each(&zram_index_idr, &zram_remove_cb, NULL); | ||
1282 | idr_destroy(&zram_index_idr); | ||
1264 | unregister_blkdev(zram_major, "zram"); | 1283 | unregister_blkdev(zram_major, "zram"); |
1265 | pr_info("Destroyed %u device(s)\n", nr); | 1284 | pr_info("Destroyed device(s)\n"); |
1266 | } | 1285 | } |
1267 | 1286 | ||
1268 | static int __init zram_init(void) | 1287 | static int __init zram_init(void) |
@@ -1281,16 +1300,9 @@ static int __init zram_init(void) | |||
1281 | return -EBUSY; | 1300 | return -EBUSY; |
1282 | } | 1301 | } |
1283 | 1302 | ||
1284 | /* Allocate the device array and initialize each one */ | ||
1285 | zram_devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL); | ||
1286 | if (!zram_devices) { | ||
1287 | unregister_blkdev(zram_major, "zram"); | ||
1288 | return -ENOMEM; | ||
1289 | } | ||
1290 | |||
1291 | for (dev_id = 0; dev_id < num_devices; dev_id++) { | 1303 | for (dev_id = 0; dev_id < num_devices; dev_id++) { |
1292 | ret = create_device(&zram_devices[dev_id], dev_id); | 1304 | ret = zram_add(dev_id); |
1293 | if (ret) | 1305 | if (ret != 0) |
1294 | goto out_error; | 1306 | goto out_error; |
1295 | } | 1307 | } |
1296 | 1308 | ||
@@ -1298,13 +1310,13 @@ static int __init zram_init(void) | |||
1298 | return 0; | 1310 | return 0; |
1299 | 1311 | ||
1300 | out_error: | 1312 | out_error: |
1301 | destroy_devices(dev_id); | 1313 | destroy_devices(); |
1302 | return ret; | 1314 | return ret; |
1303 | } | 1315 | } |
1304 | 1316 | ||
1305 | static void __exit zram_exit(void) | 1317 | static void __exit zram_exit(void) |
1306 | { | 1318 | { |
1307 | destroy_devices(num_devices); | 1319 | destroy_devices(); |
1308 | } | 1320 | } |
1309 | 1321 | ||
1310 | module_init(zram_init); | 1322 | module_init(zram_init); |