diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2014-01-13 19:13:05 -0500 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2014-01-14 23:23:03 -0500 |
commit | 55b082e614e219fb5199a6f93e648ed35d3c96d5 (patch) | |
tree | a2707e62bdd914e9651e78cde6cb55a5f0b88d7f /drivers/md | |
parent | 55494bf2947dccdf2d98b62374fea7365dfead84 (diff) |
dm snapshot: use dm-bufio prefetch
This patch modifies dm-snapshot so that it prefetches the buffers when
loading the exceptions.
The number of buffers read ahead is specified in the DM_PREFETCH_CHUNKS
macro. The current value for DM_PREFETCH_CHUNKS (12) was found to
provide the best performance on a single 15k SCSI spindle. In the
future we may modify this default or make it configurable.
Also, introduce the function dm_bufio_set_minimum_buffers to setup
bufio's number of internal buffers before freeing happens. dm-bufio may
hold more buffers if enough memory is available. There is no guarantee
that the specified number of buffers will be available - if you need a
guarantee, use the argument reserved_buffers for
dm_bufio_client_create.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-bufio.c | 14 | ||||
-rw-r--r-- | drivers/md/dm-bufio.h | 5 | ||||
-rw-r--r-- | drivers/md/dm-snap-persistent.c | 25 |
3 files changed, 41 insertions, 3 deletions
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index d86593721915..9ed42125514b 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c | |||
@@ -104,6 +104,8 @@ struct dm_bufio_client { | |||
104 | struct list_head reserved_buffers; | 104 | struct list_head reserved_buffers; |
105 | unsigned need_reserved_buffers; | 105 | unsigned need_reserved_buffers; |
106 | 106 | ||
107 | unsigned minimum_buffers; | ||
108 | |||
107 | struct hlist_head *cache_hash; | 109 | struct hlist_head *cache_hash; |
108 | wait_queue_head_t free_buffer_wait; | 110 | wait_queue_head_t free_buffer_wait; |
109 | 111 | ||
@@ -861,8 +863,8 @@ static void __get_memory_limit(struct dm_bufio_client *c, | |||
861 | buffers = dm_bufio_cache_size_per_client >> | 863 | buffers = dm_bufio_cache_size_per_client >> |
862 | (c->sectors_per_block_bits + SECTOR_SHIFT); | 864 | (c->sectors_per_block_bits + SECTOR_SHIFT); |
863 | 865 | ||
864 | if (buffers < DM_BUFIO_MIN_BUFFERS) | 866 | if (buffers < c->minimum_buffers) |
865 | buffers = DM_BUFIO_MIN_BUFFERS; | 867 | buffers = c->minimum_buffers; |
866 | 868 | ||
867 | *limit_buffers = buffers; | 869 | *limit_buffers = buffers; |
868 | *threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100; | 870 | *threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100; |
@@ -1372,6 +1374,12 @@ void dm_bufio_forget(struct dm_bufio_client *c, sector_t block) | |||
1372 | } | 1374 | } |
1373 | EXPORT_SYMBOL(dm_bufio_forget); | 1375 | EXPORT_SYMBOL(dm_bufio_forget); |
1374 | 1376 | ||
1377 | void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n) | ||
1378 | { | ||
1379 | c->minimum_buffers = n; | ||
1380 | } | ||
1381 | EXPORT_SYMBOL(dm_bufio_set_minimum_buffers); | ||
1382 | |||
1375 | unsigned dm_bufio_get_block_size(struct dm_bufio_client *c) | 1383 | unsigned dm_bufio_get_block_size(struct dm_bufio_client *c) |
1376 | { | 1384 | { |
1377 | return c->block_size; | 1385 | return c->block_size; |
@@ -1568,6 +1576,8 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign | |||
1568 | INIT_LIST_HEAD(&c->reserved_buffers); | 1576 | INIT_LIST_HEAD(&c->reserved_buffers); |
1569 | c->need_reserved_buffers = reserved_buffers; | 1577 | c->need_reserved_buffers = reserved_buffers; |
1570 | 1578 | ||
1579 | c->minimum_buffers = DM_BUFIO_MIN_BUFFERS; | ||
1580 | |||
1571 | init_waitqueue_head(&c->free_buffer_wait); | 1581 | init_waitqueue_head(&c->free_buffer_wait); |
1572 | c->async_write_error = 0; | 1582 | c->async_write_error = 0; |
1573 | 1583 | ||
diff --git a/drivers/md/dm-bufio.h b/drivers/md/dm-bufio.h index 3dac37627ba4..c096779a7292 100644 --- a/drivers/md/dm-bufio.h +++ b/drivers/md/dm-bufio.h | |||
@@ -115,6 +115,11 @@ void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block); | |||
115 | */ | 115 | */ |
116 | void dm_bufio_forget(struct dm_bufio_client *c, sector_t block); | 116 | void dm_bufio_forget(struct dm_bufio_client *c, sector_t block); |
117 | 117 | ||
118 | /* | ||
119 | * Set the minimum number of buffers before cleanup happens. | ||
120 | */ | ||
121 | void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n); | ||
122 | |||
118 | unsigned dm_bufio_get_block_size(struct dm_bufio_client *c); | 123 | unsigned dm_bufio_get_block_size(struct dm_bufio_client *c); |
119 | sector_t dm_bufio_get_device_size(struct dm_bufio_client *c); | 124 | sector_t dm_bufio_get_device_size(struct dm_bufio_client *c); |
120 | sector_t dm_bufio_get_block_number(struct dm_buffer *b); | 125 | sector_t dm_bufio_get_block_number(struct dm_buffer *b); |
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 169275050c0b..afc3d017de4c 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #define DM_MSG_PREFIX "persistent snapshot" | 18 | #define DM_MSG_PREFIX "persistent snapshot" |
19 | #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */ | 19 | #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */ |
20 | 20 | ||
21 | #define DM_PREFETCH_CHUNKS 12 | ||
22 | |||
21 | /*----------------------------------------------------------------- | 23 | /*----------------------------------------------------------------- |
22 | * Persistent snapshots, by persistent we mean that the snapshot | 24 | * Persistent snapshots, by persistent we mean that the snapshot |
23 | * will survive a reboot. | 25 | * will survive a reboot. |
@@ -497,6 +499,7 @@ static int read_exceptions(struct pstore *ps, | |||
497 | { | 499 | { |
498 | int r, full = 1; | 500 | int r, full = 1; |
499 | struct dm_bufio_client *client; | 501 | struct dm_bufio_client *client; |
502 | chunk_t prefetch_area = 0; | ||
500 | 503 | ||
501 | client = dm_bufio_client_create(dm_snap_cow(ps->store->snap)->bdev, | 504 | client = dm_bufio_client_create(dm_snap_cow(ps->store->snap)->bdev, |
502 | ps->store->chunk_size << SECTOR_SHIFT, | 505 | ps->store->chunk_size << SECTOR_SHIFT, |
@@ -506,13 +509,33 @@ static int read_exceptions(struct pstore *ps, | |||
506 | return PTR_ERR(client); | 509 | return PTR_ERR(client); |
507 | 510 | ||
508 | /* | 511 | /* |
512 | * Setup for one current buffer + desired readahead buffers. | ||
513 | */ | ||
514 | dm_bufio_set_minimum_buffers(client, 1 + DM_PREFETCH_CHUNKS); | ||
515 | |||
516 | /* | ||
509 | * Keeping reading chunks and inserting exceptions until | 517 | * Keeping reading chunks and inserting exceptions until |
510 | * we find a partially full area. | 518 | * we find a partially full area. |
511 | */ | 519 | */ |
512 | for (ps->current_area = 0; full; ps->current_area++) { | 520 | for (ps->current_area = 0; full; ps->current_area++) { |
513 | struct dm_buffer *bp; | 521 | struct dm_buffer *bp; |
514 | void *area; | 522 | void *area; |
515 | chunk_t chunk = area_location(ps, ps->current_area); | 523 | chunk_t chunk; |
524 | |||
525 | if (unlikely(prefetch_area < ps->current_area)) | ||
526 | prefetch_area = ps->current_area; | ||
527 | |||
528 | if (DM_PREFETCH_CHUNKS) do { | ||
529 | chunk_t pf_chunk = area_location(ps, prefetch_area); | ||
530 | if (unlikely(pf_chunk >= dm_bufio_get_device_size(client))) | ||
531 | break; | ||
532 | dm_bufio_prefetch(client, pf_chunk, 1); | ||
533 | prefetch_area++; | ||
534 | if (unlikely(!prefetch_area)) | ||
535 | break; | ||
536 | } while (prefetch_area <= ps->current_area + DM_PREFETCH_CHUNKS); | ||
537 | |||
538 | chunk = area_location(ps, ps->current_area); | ||
516 | 539 | ||
517 | area = dm_bufio_read(client, chunk, &bp); | 540 | area = dm_bufio_read(client, chunk, &bp); |
518 | if (unlikely(IS_ERR(area))) { | 541 | if (unlikely(IS_ERR(area))) { |