diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-03-02 14:44:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-03-02 14:44:27 -0500 |
commit | 37cae6ad4c484030fa972241533c32730ec79b7d (patch) | |
tree | a01a13982af7b326af37c729a5ad83adbe99322d /drivers/md/dm-cache-policy.c | |
parent | 986248993d495aebffcdf0758ce28ab85aa4e9ff (diff) | |
parent | 8735a8134786fa4ef36dee65d7fa779b99ba5fe3 (diff) |
Merge tag 'dm-3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm
Pull device-mapper update from Alasdair G Kergon:
"The main addition here is a long-desired target framework to allow an
SSD to be used as a cache in front of a slower device. Cache tuning
is delegated to interchangeable policy modules so these can be
developed independently of the mechanics needed to shuffle the data
around.
Other than that, kcopyd users acquire a throttling parameter, ioctl
buffer usage gets streamlined, more mempool reliance is reduced and
there are a few other bug fixes and tidy-ups."
* tag 'dm-3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm: (30 commits)
dm cache: add cleaner policy
dm cache: add mq policy
dm: add cache target
dm persistent data: add bitset
dm persistent data: add transactional array
dm thin: remove cells from stack
dm bio prison: pass cell memory in
dm persistent data: add btree_walk
dm: add target num_write_bios fn
dm kcopyd: introduce configurable throttling
dm ioctl: allow message to return data
dm ioctl: optimize functions without variable params
dm ioctl: introduce ioctl_flags
dm: merge io_pool and tio_pool
dm: remove unused _rq_bio_info_cache
dm: fix limits initialization when there are no data devices
dm snapshot: add missing module aliases
dm persistent data: set some btree fn parms const
dm: refactor bio cloning
dm: rename bio cloning functions
...
Diffstat (limited to 'drivers/md/dm-cache-policy.c')
-rw-r--r-- | drivers/md/dm-cache-policy.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/drivers/md/dm-cache-policy.c b/drivers/md/dm-cache-policy.c new file mode 100644 index 000000000000..2cbf5fdaac52 --- /dev/null +++ b/drivers/md/dm-cache-policy.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Red Hat. All rights reserved. | ||
3 | * | ||
4 | * This file is released under the GPL. | ||
5 | */ | ||
6 | |||
7 | #include "dm-cache-policy-internal.h" | ||
8 | #include "dm.h" | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | |||
13 | /*----------------------------------------------------------------*/ | ||
14 | |||
15 | #define DM_MSG_PREFIX "cache-policy" | ||
16 | |||
17 | static DEFINE_SPINLOCK(register_lock); | ||
18 | static LIST_HEAD(register_list); | ||
19 | |||
20 | static struct dm_cache_policy_type *__find_policy(const char *name) | ||
21 | { | ||
22 | struct dm_cache_policy_type *t; | ||
23 | |||
24 | list_for_each_entry(t, ®ister_list, list) | ||
25 | if (!strcmp(t->name, name)) | ||
26 | return t; | ||
27 | |||
28 | return NULL; | ||
29 | } | ||
30 | |||
31 | static struct dm_cache_policy_type *__get_policy_once(const char *name) | ||
32 | { | ||
33 | struct dm_cache_policy_type *t = __find_policy(name); | ||
34 | |||
35 | if (t && !try_module_get(t->owner)) { | ||
36 | DMWARN("couldn't get module %s", name); | ||
37 | t = ERR_PTR(-EINVAL); | ||
38 | } | ||
39 | |||
40 | return t; | ||
41 | } | ||
42 | |||
43 | static struct dm_cache_policy_type *get_policy_once(const char *name) | ||
44 | { | ||
45 | struct dm_cache_policy_type *t; | ||
46 | |||
47 | spin_lock(®ister_lock); | ||
48 | t = __get_policy_once(name); | ||
49 | spin_unlock(®ister_lock); | ||
50 | |||
51 | return t; | ||
52 | } | ||
53 | |||
54 | static struct dm_cache_policy_type *get_policy(const char *name) | ||
55 | { | ||
56 | struct dm_cache_policy_type *t; | ||
57 | |||
58 | t = get_policy_once(name); | ||
59 | if (IS_ERR(t)) | ||
60 | return NULL; | ||
61 | |||
62 | if (t) | ||
63 | return t; | ||
64 | |||
65 | request_module("dm-cache-%s", name); | ||
66 | |||
67 | t = get_policy_once(name); | ||
68 | if (IS_ERR(t)) | ||
69 | return NULL; | ||
70 | |||
71 | return t; | ||
72 | } | ||
73 | |||
74 | static void put_policy(struct dm_cache_policy_type *t) | ||
75 | { | ||
76 | module_put(t->owner); | ||
77 | } | ||
78 | |||
79 | int dm_cache_policy_register(struct dm_cache_policy_type *type) | ||
80 | { | ||
81 | int r; | ||
82 | |||
83 | /* One size fits all for now */ | ||
84 | if (type->hint_size != 0 && type->hint_size != 4) { | ||
85 | DMWARN("hint size must be 0 or 4 but %llu supplied.", (unsigned long long) type->hint_size); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | spin_lock(®ister_lock); | ||
90 | if (__find_policy(type->name)) { | ||
91 | DMWARN("attempt to register policy under duplicate name %s", type->name); | ||
92 | r = -EINVAL; | ||
93 | } else { | ||
94 | list_add(&type->list, ®ister_list); | ||
95 | r = 0; | ||
96 | } | ||
97 | spin_unlock(®ister_lock); | ||
98 | |||
99 | return r; | ||
100 | } | ||
101 | EXPORT_SYMBOL_GPL(dm_cache_policy_register); | ||
102 | |||
103 | void dm_cache_policy_unregister(struct dm_cache_policy_type *type) | ||
104 | { | ||
105 | spin_lock(®ister_lock); | ||
106 | list_del_init(&type->list); | ||
107 | spin_unlock(®ister_lock); | ||
108 | } | ||
109 | EXPORT_SYMBOL_GPL(dm_cache_policy_unregister); | ||
110 | |||
111 | struct dm_cache_policy *dm_cache_policy_create(const char *name, | ||
112 | dm_cblock_t cache_size, | ||
113 | sector_t origin_size, | ||
114 | sector_t cache_block_size) | ||
115 | { | ||
116 | struct dm_cache_policy *p = NULL; | ||
117 | struct dm_cache_policy_type *type; | ||
118 | |||
119 | type = get_policy(name); | ||
120 | if (!type) { | ||
121 | DMWARN("unknown policy type"); | ||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | p = type->create(cache_size, origin_size, cache_block_size); | ||
126 | if (!p) { | ||
127 | put_policy(type); | ||
128 | return NULL; | ||
129 | } | ||
130 | p->private = type; | ||
131 | |||
132 | return p; | ||
133 | } | ||
134 | EXPORT_SYMBOL_GPL(dm_cache_policy_create); | ||
135 | |||
136 | void dm_cache_policy_destroy(struct dm_cache_policy *p) | ||
137 | { | ||
138 | struct dm_cache_policy_type *t = p->private; | ||
139 | |||
140 | p->destroy(p); | ||
141 | put_policy(t); | ||
142 | } | ||
143 | EXPORT_SYMBOL_GPL(dm_cache_policy_destroy); | ||
144 | |||
145 | const char *dm_cache_policy_get_name(struct dm_cache_policy *p) | ||
146 | { | ||
147 | struct dm_cache_policy_type *t = p->private; | ||
148 | |||
149 | return t->name; | ||
150 | } | ||
151 | EXPORT_SYMBOL_GPL(dm_cache_policy_get_name); | ||
152 | |||
153 | size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p) | ||
154 | { | ||
155 | struct dm_cache_policy_type *t = p->private; | ||
156 | |||
157 | return t->hint_size; | ||
158 | } | ||
159 | EXPORT_SYMBOL_GPL(dm_cache_policy_get_hint_size); | ||
160 | |||
161 | /*----------------------------------------------------------------*/ | ||