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 | |
| 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>
| -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; |
