Messages in this thread Patch in this message | | | From | Dmitry Monakhov <> | Subject | [PATCH 6/6] blkdev: optimize discard payload utilization | Date | Mon, 29 Mar 2010 10:09:25 +0400 |
| |
Currently each discard bio require one page as payload storage But only one sector is actually used. Let's share allocated page with several requests. A bad thing about implementation is that it use global spinlock. But we may easily to switch to per-cpu buckets if it becomes a bottleneck.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> --- block/blk-lib.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/block/blk-lib.c b/block/blk-lib.c index 5326d91..ffa07ee 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -9,6 +9,8 @@ #include "blk.h" +static DEFINE_SPINLOCK(payload_mem_lock); + struct bio_batch { atomic_t done; @@ -135,15 +137,48 @@ static void blkdev_discard_end_io(struct bio *bio, int err) static int add_discard_payload(struct bio *bio, gfp_t gfp_mask, int len) { + static struct page *cur_page = NULL; + static int cur_offset = 0; struct page *page; + int offset; struct request_queue *q = bdev_get_queue(bio->bi_bdev); - - page = alloc_page(gfp_mask | __GFP_ZERO); - if (!page) +again: + spin_lock(&payload_mem_lock); + if (cur_offset + len > PAGE_SIZE) + /* There is no more space in the page */ + if (cur_page) { + put_page(cur_page); + cur_page = NULL; + cur_offset = 0; + } + if (!cur_page) { + spin_unlock(&payload_mem_lock); + page = alloc_page(gfp_mask | __GFP_ZERO); + if (!page) return -ENOMEM; - if (bio_add_pc_page(q, bio, page, len, 0) < len) - BUG(); + + spin_lock(&payload_mem_lock); + /* + * Check cur_page one more time after we reacquired the lock. + * Because it may be changed by other task. + */ + if (cur_page) { + spin_unlock(&payload_mem_lock); + put_page(page); + goto again; + } else + cur_page = page; + } + page = cur_page; get_page(page); + offset = cur_offset; + cur_offset += len; + + spin_unlock(&payload_mem_lock); + + if (bio_add_pc_page(q, bio, page, len, offset) < len) + BUG(); + return 0; } -- 1.6.6.1
| |