diff options
Diffstat (limited to 'drivers/md/persistent-data')
-rw-r--r-- | drivers/md/persistent-data/dm-array.c | 4 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-space-map-metadata.c | 8 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-transaction-manager.c | 77 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-transaction-manager.h | 7 |
4 files changed, 91 insertions, 5 deletions
diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c index 1d75b1dc1e2e..e64b61ad0ef3 100644 --- a/drivers/md/persistent-data/dm-array.c +++ b/drivers/md/persistent-data/dm-array.c | |||
@@ -645,8 +645,10 @@ static int array_resize(struct dm_array_info *info, dm_block_t root, | |||
645 | int r; | 645 | int r; |
646 | struct resize resize; | 646 | struct resize resize; |
647 | 647 | ||
648 | if (old_size == new_size) | 648 | if (old_size == new_size) { |
649 | *new_root = root; | ||
649 | return 0; | 650 | return 0; |
651 | } | ||
650 | 652 | ||
651 | resize.info = info; | 653 | resize.info = info; |
652 | resize.root = root; | 654 | resize.root = root; |
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 786b689bdfc7..e8a904298887 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c | |||
@@ -564,7 +564,9 @@ static int sm_bootstrap_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count | |||
564 | { | 564 | { |
565 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); | 565 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); |
566 | 566 | ||
567 | return smm->ll.nr_blocks; | 567 | *count = smm->ll.nr_blocks; |
568 | |||
569 | return 0; | ||
568 | } | 570 | } |
569 | 571 | ||
570 | static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count) | 572 | static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count) |
@@ -581,7 +583,9 @@ static int sm_bootstrap_get_count(struct dm_space_map *sm, dm_block_t b, | |||
581 | { | 583 | { |
582 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); | 584 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); |
583 | 585 | ||
584 | return b < smm->begin ? 1 : 0; | 586 | *result = (b < smm->begin) ? 1 : 0; |
587 | |||
588 | return 0; | ||
585 | } | 589 | } |
586 | 590 | ||
587 | static int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm, | 591 | static int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm, |
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 | * |