diff options
author | Joe Thornber <ejt@redhat.com> | 2014-10-06 10:27:26 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2014-11-10 15:25:26 -0500 |
commit | 4646015d7e4ca5a4dc19427fb0a0aeff15a4fd91 (patch) | |
tree | 5afe82e874f9eff6eeb70e77db458b22dcea3307 /drivers/md | |
parent | e5cfc69a513cdc9d9e753c5ce07f0cc6b496bfd3 (diff) |
dm transaction manager: add support for prefetching blocks of metadata
Introduce the dm_tm_issue_prefetches interface. If you're using a
non-blocking clone the tm will build up a list of requested blocks that
weren't in core. dm_tm_issue_prefetches will request those blocks to be
prefetched.
Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/persistent-data/dm-transaction-manager.c | 77 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-transaction-manager.h | 7 |
2 files changed, 82 insertions, 2 deletions
diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c index 3bc30a0ae3d6..9cb797d800cf 100644 --- a/drivers/md/persistent-data/dm-transaction-manager.c +++ b/drivers/md/persistent-data/dm-transaction-manager.c | |||
@@ -10,6 +10,8 @@ | |||
10 | #include "dm-persistent-data-internal.h" | 10 | #include "dm-persistent-data-internal.h" |
11 | 11 | ||
12 | #include <linux/export.h> | 12 | #include <linux/export.h> |
13 | #include <linux/mutex.h> | ||
14 | #include <linux/hash.h> | ||
13 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
14 | #include <linux/device-mapper.h> | 16 | #include <linux/device-mapper.h> |
15 | 17 | ||
@@ -17,6 +19,61 @@ | |||
17 | 19 | ||
18 | /*----------------------------------------------------------------*/ | 20 | /*----------------------------------------------------------------*/ |
19 | 21 | ||
22 | #define PREFETCH_SIZE 128 | ||
23 | #define PREFETCH_BITS 7 | ||
24 | #define PREFETCH_SENTINEL ((dm_block_t) -1ULL) | ||
25 | |||
26 | struct prefetch_set { | ||
27 | struct mutex lock; | ||
28 | dm_block_t blocks[PREFETCH_SIZE]; | ||
29 | }; | ||
30 | |||
31 | static unsigned prefetch_hash(dm_block_t b) | ||
32 | { | ||
33 | return hash_64(b, PREFETCH_BITS); | ||
34 | } | ||
35 | |||
36 | static void prefetch_wipe(struct prefetch_set *p) | ||
37 | { | ||
38 | unsigned i; | ||
39 | for (i = 0; i < PREFETCH_SIZE; i++) | ||
40 | p->blocks[i] = PREFETCH_SENTINEL; | ||
41 | } | ||
42 | |||
43 | static void prefetch_init(struct prefetch_set *p) | ||
44 | { | ||
45 | mutex_init(&p->lock); | ||
46 | prefetch_wipe(p); | ||
47 | } | ||
48 | |||
49 | static void prefetch_add(struct prefetch_set *p, dm_block_t b) | ||
50 | { | ||
51 | unsigned h = prefetch_hash(b); | ||
52 | |||
53 | mutex_lock(&p->lock); | ||
54 | if (p->blocks[h] == PREFETCH_SENTINEL) | ||
55 | p->blocks[h] = b; | ||
56 | |||
57 | mutex_unlock(&p->lock); | ||
58 | } | ||
59 | |||
60 | static void prefetch_issue(struct prefetch_set *p, struct dm_block_manager *bm) | ||
61 | { | ||
62 | unsigned i; | ||
63 | |||
64 | mutex_lock(&p->lock); | ||
65 | |||
66 | for (i = 0; i < PREFETCH_SIZE; i++) | ||
67 | if (p->blocks[i] != PREFETCH_SENTINEL) { | ||
68 | dm_bm_prefetch(bm, p->blocks[i]); | ||
69 | p->blocks[i] = PREFETCH_SENTINEL; | ||
70 | } | ||
71 | |||
72 | mutex_unlock(&p->lock); | ||
73 | } | ||
74 | |||
75 | /*----------------------------------------------------------------*/ | ||
76 | |||
20 | struct shadow_info { | 77 | struct shadow_info { |
21 | struct hlist_node hlist; | 78 | struct hlist_node hlist; |
22 | dm_block_t where; | 79 | dm_block_t where; |
@@ -37,6 +94,8 @@ struct dm_transaction_manager { | |||
37 | 94 | ||
38 | spinlock_t lock; | 95 | spinlock_t lock; |
39 | struct hlist_head buckets[DM_HASH_SIZE]; | 96 | struct hlist_head buckets[DM_HASH_SIZE]; |
97 | |||
98 | struct prefetch_set prefetches; | ||
40 | }; | 99 | }; |
41 | 100 | ||
42 | /*----------------------------------------------------------------*/ | 101 | /*----------------------------------------------------------------*/ |
@@ -117,6 +176,8 @@ static struct dm_transaction_manager *dm_tm_create(struct dm_block_manager *bm, | |||
117 | for (i = 0; i < DM_HASH_SIZE; i++) | 176 | for (i = 0; i < DM_HASH_SIZE; i++) |
118 | INIT_HLIST_HEAD(tm->buckets + i); | 177 | INIT_HLIST_HEAD(tm->buckets + i); |
119 | 178 | ||
179 | prefetch_init(&tm->prefetches); | ||
180 | |||
120 | return tm; | 181 | return tm; |
121 | } | 182 | } |
122 | 183 | ||
@@ -268,8 +329,14 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b, | |||
268 | struct dm_block_validator *v, | 329 | struct dm_block_validator *v, |
269 | struct dm_block **blk) | 330 | struct dm_block **blk) |
270 | { | 331 | { |
271 | if (tm->is_clone) | 332 | if (tm->is_clone) { |
272 | return dm_bm_read_try_lock(tm->real->bm, b, v, blk); | 333 | int r = dm_bm_read_try_lock(tm->real->bm, b, v, blk); |
334 | |||
335 | if (r == -EWOULDBLOCK) | ||
336 | prefetch_add(&tm->real->prefetches, b); | ||
337 | |||
338 | return r; | ||
339 | } | ||
273 | 340 | ||
274 | return dm_bm_read_lock(tm->bm, b, v, blk); | 341 | return dm_bm_read_lock(tm->bm, b, v, blk); |
275 | } | 342 | } |
@@ -317,6 +384,12 @@ struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm) | |||
317 | return tm->bm; | 384 | return tm->bm; |
318 | } | 385 | } |
319 | 386 | ||
387 | void dm_tm_issue_prefetches(struct dm_transaction_manager *tm) | ||
388 | { | ||
389 | prefetch_issue(&tm->prefetches, tm->bm); | ||
390 | } | ||
391 | EXPORT_SYMBOL_GPL(dm_tm_issue_prefetches); | ||
392 | |||
320 | /*----------------------------------------------------------------*/ | 393 | /*----------------------------------------------------------------*/ |
321 | 394 | ||
322 | static int dm_tm_create_internal(struct dm_block_manager *bm, | 395 | static int dm_tm_create_internal(struct dm_block_manager *bm, |
diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h index 2772ed2a781a..2e0d4d66fb1b 100644 --- a/drivers/md/persistent-data/dm-transaction-manager.h +++ b/drivers/md/persistent-data/dm-transaction-manager.h | |||
@@ -109,6 +109,13 @@ int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b, | |||
109 | struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm); | 109 | struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm); |
110 | 110 | ||
111 | /* | 111 | /* |
112 | * If you're using a non-blocking clone the tm will build up a list of | ||
113 | * requested blocks that weren't in core. This call will request those | ||
114 | * blocks to be prefetched. | ||
115 | */ | ||
116 | void dm_tm_issue_prefetches(struct dm_transaction_manager *tm); | ||
117 | |||
118 | /* | ||
112 | * A little utility that ties the knot by producing a transaction manager | 119 | * A little utility that ties the knot by producing a transaction manager |
113 | * that has a space map managed by the transaction manager... | 120 | * that has a space map managed by the transaction manager... |
114 | * | 121 | * |