diff options
author | Minchan Kim <minchan@kernel.org> | 2014-01-30 18:46:06 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 19:56:56 -0500 |
commit | e46e33152eb82b8e2db7ffb3790a2a2653c34513 (patch) | |
tree | a55cd8329dcb0f30b11ff75605b3f4f7bbd790de /drivers/block | |
parent | f614a9f48dedd2b80d1dc8bae8094842fcdb39dd (diff) |
zram: remove zram->lock in read path and change it with mutex
Finally, we separated zram->lock dependency from 32bit stat/ table
handling so there is no reason to use rw_semaphore between read and
write path so this patch removes the lock from read path totally and
changes rw_semaphore with mutex. So, we could do
old:
read-read: OK
read-write: NO
write-write: NO
Now:
read-read: OK
read-write: OK
write-write: NO
The below data proves mixed workload performs well 11 times and there is
also enhance on write-write path because current rw-semaphore doesn't
support SPIN_ON_OWNER. It's side effect but anyway good thing for us.
Write-related tests perform better (from 61% to 1058%) but read path has
good/bad(from -2.22% to 1.45%) but they are all marginal within stddev.
CPU 12
iozone -t -T -l 12 -u 12 -r 16K -s 60M -I +Z -V 0
==Initial write ==Initial write
records: 10 records: 10
avg: 516189.16 avg: 839907.96
std: 22486.53 (4.36%) std: 47902.17 (5.70%)
max: 546970.60 max: 909910.35
min: 481131.54 min: 751148.38
==Rewrite ==Rewrite
records: 10 records: 10
avg: 509527.98 avg: 1050156.37
std: 45799.94 (8.99%) std: 40695.44 (3.88%)
max: 611574.27 max: 1111929.26
min: 443679.95 min: 980409.62
==Read ==Read
records: 10 records: 10
avg: 4408624.17 avg: 4472546.76
std: 281152.61 (6.38%) std: 163662.78 (3.66%)
max: 4867888.66 max: 4727351.03
min: 4058347.69 min: 4126520.88
==Re-read ==Re-read
records: 10 records: 10
avg: 4462147.53 avg: 4363257.75
std: 283546.11 (6.35%) std: 247292.63 (5.67%)
max: 4912894.44 max: 4677241.75
min: 4131386.50 min: 4035235.84
==Reverse Read ==Reverse Read
records: 10 records: 10
avg: 4565865.97 avg: 4485818.08
std: 313395.63 (6.86%) std: 248470.10 (5.54%)
max: 5232749.16 max: 4789749.94
min: 4185809.62 min: 3963081.34
==Stride read ==Stride read
records: 10 records: 10
avg: 4515981.80 avg: 4418806.01
std: 211192.32 (4.68%) std: 212837.97 (4.82%)
max: 4889287.28 max: 4686967.22
min: 4210362.00 min: 4083041.84
==Random read ==Random read
records: 10 records: 10
avg: 4410525.23 avg: 4387093.18
std: 236693.22 (5.37%) std: 235285.23 (5.36%)
max: 4713698.47 max: 4669760.62
min: 4057163.62 min: 3952002.16
==Mixed workload ==Mixed workload
records: 10 records: 10
avg: 243234.25 avg: 2818677.27
std: 28505.07 (11.72%) std: 195569.70 (6.94%)
max: 288905.23 max: 3126478.11
min: 212473.16 min: 2484150.69
==Random write ==Random write
records: 10 records: 10
avg: 555887.07 avg: 1053057.79
std: 70841.98 (12.74%) std: 35195.36 (3.34%)
max: 683188.28 max: 1096125.73
min: 437299.57 min: 992481.93
==Pwrite ==Pwrite
records: 10 records: 10
avg: 501745.93 avg: 810363.09
std: 16373.54 (3.26%) std: 19245.01 (2.37%)
max: 518724.52 max: 833359.70
min: 464208.73 min: 765501.87
==Pread ==Pread
records: 10 records: 10
avg: 4539894.60 avg: 4457680.58
std: 197094.66 (4.34%) std: 188965.60 (4.24%)
max: 4877170.38 max: 4689905.53
min: 4226326.03 min: 4095739.72
Signed-off-by: Minchan Kim <minchan@kernel.org>
Cc: Nitin Gupta <ngupta@vflare.org>
Tested-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Cc: Jerome Marchand <jmarchan@redhat.com>
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 | 17 | ||||
-rw-r--r-- | drivers/block/zram/zram_drv.h | 4 |
2 files changed, 9 insertions, 12 deletions
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index f1a3c958d84b..011e55d820b1 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c | |||
@@ -230,6 +230,7 @@ static struct zram_meta *zram_meta_alloc(u64 disksize) | |||
230 | } | 230 | } |
231 | 231 | ||
232 | rwlock_init(&meta->tb_lock); | 232 | rwlock_init(&meta->tb_lock); |
233 | mutex_init(&meta->buffer_lock); | ||
233 | return meta; | 234 | return meta; |
234 | 235 | ||
235 | free_table: | 236 | free_table: |
@@ -412,6 +413,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
412 | struct page *page; | 413 | struct page *page; |
413 | unsigned char *user_mem, *cmem, *src, *uncmem = NULL; | 414 | unsigned char *user_mem, *cmem, *src, *uncmem = NULL; |
414 | struct zram_meta *meta = zram->meta; | 415 | struct zram_meta *meta = zram->meta; |
416 | bool locked = false; | ||
415 | 417 | ||
416 | page = bvec->bv_page; | 418 | page = bvec->bv_page; |
417 | src = meta->compress_buffer; | 419 | src = meta->compress_buffer; |
@@ -431,6 +433,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
431 | goto out; | 433 | goto out; |
432 | } | 434 | } |
433 | 435 | ||
436 | mutex_lock(&meta->buffer_lock); | ||
437 | locked = true; | ||
434 | user_mem = kmap_atomic(page); | 438 | user_mem = kmap_atomic(page); |
435 | 439 | ||
436 | if (is_partial_io(bvec)) { | 440 | if (is_partial_io(bvec)) { |
@@ -457,7 +461,6 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
457 | 461 | ||
458 | ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, | 462 | ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, |
459 | meta->compress_workmem); | 463 | meta->compress_workmem); |
460 | |||
461 | if (!is_partial_io(bvec)) { | 464 | if (!is_partial_io(bvec)) { |
462 | kunmap_atomic(user_mem); | 465 | kunmap_atomic(user_mem); |
463 | user_mem = NULL; | 466 | user_mem = NULL; |
@@ -514,6 +517,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
514 | atomic_inc(&zram->stats.good_compress); | 517 | atomic_inc(&zram->stats.good_compress); |
515 | 518 | ||
516 | out: | 519 | out: |
520 | if (locked) | ||
521 | mutex_unlock(&meta->buffer_lock); | ||
517 | if (is_partial_io(bvec)) | 522 | if (is_partial_io(bvec)) |
518 | kfree(uncmem); | 523 | kfree(uncmem); |
519 | 524 | ||
@@ -527,15 +532,10 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
527 | { | 532 | { |
528 | int ret; | 533 | int ret; |
529 | 534 | ||
530 | if (rw == READ) { | 535 | if (rw == READ) |
531 | down_read(&zram->lock); | ||
532 | ret = zram_bvec_read(zram, bvec, index, offset, bio); | 536 | ret = zram_bvec_read(zram, bvec, index, offset, bio); |
533 | up_read(&zram->lock); | 537 | else |
534 | } else { | ||
535 | down_write(&zram->lock); | ||
536 | ret = zram_bvec_write(zram, bvec, index, offset); | 538 | ret = zram_bvec_write(zram, bvec, index, offset); |
537 | up_write(&zram->lock); | ||
538 | } | ||
539 | 539 | ||
540 | return ret; | 540 | return ret; |
541 | } | 541 | } |
@@ -808,7 +808,6 @@ static int create_device(struct zram *zram, int device_id) | |||
808 | { | 808 | { |
809 | int ret = -ENOMEM; | 809 | int ret = -ENOMEM; |
810 | 810 | ||
811 | init_rwsem(&zram->lock); | ||
812 | init_rwsem(&zram->init_lock); | 811 | init_rwsem(&zram->init_lock); |
813 | 812 | ||
814 | zram->queue = blk_alloc_queue(GFP_KERNEL); | 813 | zram->queue = blk_alloc_queue(GFP_KERNEL); |
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h index d876300da6c9..ad8aa35bae00 100644 --- a/drivers/block/zram/zram_drv.h +++ b/drivers/block/zram/zram_drv.h | |||
@@ -88,13 +88,11 @@ struct zram_meta { | |||
88 | void *compress_buffer; | 88 | void *compress_buffer; |
89 | struct table *table; | 89 | struct table *table; |
90 | struct zs_pool *mem_pool; | 90 | struct zs_pool *mem_pool; |
91 | struct mutex buffer_lock; /* protect compress buffers */ | ||
91 | }; | 92 | }; |
92 | 93 | ||
93 | struct zram { | 94 | struct zram { |
94 | struct zram_meta *meta; | 95 | struct zram_meta *meta; |
95 | struct rw_semaphore lock; /* protect compression buffers, | ||
96 | * reads and writes | ||
97 | */ | ||
98 | struct request_queue *queue; | 96 | struct request_queue *queue; |
99 | struct gendisk *disk; | 97 | struct gendisk *disk; |
100 | int init_done; | 98 | int init_done; |