aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/persistent-data
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-09 00:10:03 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-09 00:10:03 -0500
commit140dfc9299c33bbfc9350fa061f5ab65cb83df13 (patch)
tree09508691964e277f4835d30f7b9c3962e8cac596 /drivers/md/persistent-data
parentf94784bdb114439eb3a5e62343826887bbf3f37c (diff)
parent1a71d6ffe18c0d0f03fc8531949cc8ed41d702ee (diff)
Merge tag 'dm-3.19-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper updates from Mike Snitzer: - Significant DM thin-provisioning performance improvements to meet performance requirements that were requested by the Gluster distributed filesystem. Specifically, dm-thinp now takes care to aggregate IO that will be issued to the same thinp block before issuing IO to the underlying devices. This really helps improve performance on HW RAID6 devices that have a writeback cache because it avoids RMW in the HW RAID controller. - Some stable fixes: fix leak in DM bufio if integrity profiles were enabled, use memzero_explicit in DM crypt to avoid any potential for information leak, and a DM cache fix to properly mark a cache block dirty if it was promoted to the cache via the overwrite optimization. - A few simple DM persistent data library fixes - DM cache multiqueue policy block promotion improvements. - DM cache discard improvements that take advantage of range (multiblock) discard support in the DM bio-prison. This allows for much more efficient bulk discard processing (e.g. when mkfs.xfs discards the entire device). - Some small optimizations in DM core and RCU deference cleanups - DM core changes to suspend/resume code to introduce the new internal suspend/resume interface that the DM thin-pool target now uses to suspend/resume active thin devices when the thin-pool must suspend/resume. This avoids forcing userspace to track all active thin volumes in a thin-pool when the thin-pool is suspended for the purposes of metadata or data space resize. * tag 'dm-3.19-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: (49 commits) dm crypt: use memzero_explicit for on-stack buffer dm space map metadata: fix sm_bootstrap_get_count() dm space map metadata: fix sm_bootstrap_get_nr_blocks() dm bufio: fix memleak when using a dm_buffer's inline bio dm cache: fix spurious cell_defer when dealing with partial block at end of device dm cache: dirty flag was mistakenly being cleared when promoting via overwrite dm cache: only use overwrite optimisation for promotion when in writeback mode dm cache: discard block size must be a multiple of cache block size dm cache: fix a harmless race when working out if a block is discarded dm cache: when reloading a discard bitset allow for a different discard block size dm cache: fix some issues with the new discard range support dm array: if resizing the array is a noop set the new root to the old one dm: use rcu_dereference_protected instead of rcu_dereference dm thin: fix pool_io_hints to avoid looking at max_hw_sectors dm thin: suspend/resume active thin devices when reloading thin-pool dm: enhance internal suspend and resume interface dm thin: do not allow thin device activation while pool is suspended dm: add presuspend_undo hook to target_type dm: return earlier from dm_blk_ioctl if target doesn't implement .ioctl dm thin: remove stale 'trim' message in block comment above pool_message ...
Diffstat (limited to 'drivers/md/persistent-data')
-rw-r--r--drivers/md/persistent-data/dm-array.c4
-rw-r--r--drivers/md/persistent-data/dm-space-map-metadata.c8
-rw-r--r--drivers/md/persistent-data/dm-transaction-manager.c77
-rw-r--r--drivers/md/persistent-data/dm-transaction-manager.h7
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
570static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count) 572static 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
587static int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm, 591static 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
26struct prefetch_set {
27 struct mutex lock;
28 dm_block_t blocks[PREFETCH_SIZE];
29};
30
31static unsigned prefetch_hash(dm_block_t b)
32{
33 return hash_64(b, PREFETCH_BITS);
34}
35
36static 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
43static void prefetch_init(struct prefetch_set *p)
44{
45 mutex_init(&p->lock);
46 prefetch_wipe(p);
47}
48
49static 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
60static 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
20struct shadow_info { 77struct 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
387void dm_tm_issue_prefetches(struct dm_transaction_manager *tm)
388{
389 prefetch_issue(&tm->prefetches, tm->bm);
390}
391EXPORT_SYMBOL_GPL(dm_tm_issue_prefetches);
392
320/*----------------------------------------------------------------*/ 393/*----------------------------------------------------------------*/
321 394
322static int dm_tm_create_internal(struct dm_block_manager *bm, 395static 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,
109struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm); 109struct 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 */
116void 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 *