]>
Commit | Line | Data |
---|---|---|
b1713d28 JT |
1 | /* |
2 | * Copyright (C) 2001 Sistina Software (UK) Limited. | |
3 | * | |
1b9fcf48 | 4 | * This file is released under the LGPL. |
b1713d28 JT |
5 | */ |
6 | ||
a381c45a | 7 | #include "metadata.h" |
b1713d28 | 8 | #include "activate.h" |
f047219b | 9 | #include "log.h" |
b1713d28 | 10 | |
f047219b | 11 | #include <devmapper/libdevmapper.h> |
ae2bb665 | 12 | |
ab269099 JT |
13 | static void _build_lv_name(char *buffer, size_t s, struct logical_volume *lv) |
14 | { | |
15 | snprintf(buffer, s, "%s_%s", lv->vg->name, lv->name); | |
16 | } | |
17 | ||
2ba80b43 | 18 | static struct dm_task *_setup_task(struct logical_volume *lv, int task) |
37ed70b9 JT |
19 | { |
20 | char name[128]; | |
21 | struct dm_task *dmt; | |
22 | ||
23 | if (!(dmt = dm_task_create(task))) { | |
24 | stack; | |
25 | return NULL; | |
26 | } | |
27 | ||
28 | _build_lv_name(name, sizeof(name), lv); | |
29 | dm_task_set_name(dmt, name); | |
30 | ||
31 | return dmt; | |
32 | } | |
33 | ||
2ba80b43 | 34 | static struct dm_task *_info(struct logical_volume *lv) |
37ed70b9 | 35 | { |
37ed70b9 JT |
36 | struct dm_task *dmt; |
37 | ||
38 | if (!(dmt = _setup_task(lv, DM_DEVICE_INFO))) { | |
39 | stack; | |
40 | return 0; | |
41 | } | |
42 | ||
43 | if (!dm_task_run(dmt)) { | |
2ba80b43 JT |
44 | stack; |
45 | goto bad; | |
46 | } | |
47 | ||
48 | return dmt; | |
49 | ||
50 | bad: | |
51 | dm_task_destroy(dmt); | |
52 | return NULL; | |
53 | } | |
54 | ||
94b8220f | 55 | int lv_active(struct logical_volume *lv) |
2ba80b43 | 56 | { |
94b8220f | 57 | int r = -1; |
2ba80b43 JT |
58 | struct dm_task *dmt; |
59 | ||
60 | if (!(dmt = _info(lv))) { | |
37ed70b9 | 61 | stack; |
94b8220f | 62 | return r; |
37ed70b9 JT |
63 | } |
64 | ||
94b8220f | 65 | if (!dm_task_exists(dmt, &r)) { |
37ed70b9 JT |
66 | stack; |
67 | goto out; | |
68 | } | |
69 | ||
37ed70b9 JT |
70 | out: |
71 | dm_task_destroy(dmt); | |
72 | return r; | |
73 | } | |
74 | ||
94b8220f | 75 | int lv_open_count(struct logical_volume *lv) |
2ba80b43 | 76 | { |
94b8220f | 77 | int r = -1; |
2ba80b43 JT |
78 | struct dm_task *dmt; |
79 | ||
80 | if (!(dmt = _info(lv))) { | |
81 | stack; | |
94b8220f | 82 | return r; |
2ba80b43 JT |
83 | } |
84 | ||
94b8220f | 85 | if (!dm_task_open_count(dmt, &r)) { |
2ba80b43 JT |
86 | stack; |
87 | goto out; | |
88 | } | |
89 | ||
2ba80b43 JT |
90 | out: |
91 | dm_task_destroy(dmt); | |
92 | return r; | |
93 | } | |
94 | ||
80f9662b JT |
95 | /* |
96 | * Creates a target for the next contiguous run of | |
97 | * extents. | |
98 | */ | |
99 | static int _emit_target(struct dm_task *dmt, struct logical_volume *lv, | |
100 | unsigned int *ple) | |
101 | { | |
102 | char params[1024]; | |
103 | unsigned int le = *ple; | |
104 | uint64_t esize = lv->vg->extent_size; | |
105 | int i, count = 0; | |
106 | struct pe_specifier *pes, *first = NULL; | |
107 | ||
108 | for (i = le; i < lv->le_count; i++) { | |
109 | pes = lv->map + i; | |
110 | ||
111 | if (!first) | |
112 | first = pes; | |
113 | ||
114 | else if (first->pv != pes->pv || first->pe != pes->pe + 1) | |
115 | break; /* no longer contig. */ | |
116 | ||
117 | count++; | |
118 | } | |
119 | ||
120 | snprintf(params, sizeof(params), "%s %llu", | |
121 | dev_name(first->pv->dev), | |
122 | first->pv->pe_start + (esize * first->pe)); | |
123 | ||
124 | if (!dm_task_add_target(dmt, esize * le, esize * count, | |
125 | "linear", params)) { | |
126 | stack; | |
127 | return 0; | |
128 | } | |
129 | ||
130 | *ple = i; | |
131 | return 1; | |
132 | } | |
133 | ||
37ed70b9 | 134 | int _load(struct logical_volume *lv, int task) |
b1713d28 | 135 | { |
ae2bb665 | 136 | int r = 0; |
80f9662b | 137 | uint32_t le = 0; |
ae2bb665 | 138 | struct dm_task *dmt; |
e15559aa | 139 | |
37ed70b9 | 140 | if (!(dmt = _setup_task(lv, task))) { |
ae2bb665 JT |
141 | stack; |
142 | return 0; | |
143 | } | |
b1713d28 | 144 | |
80f9662b JT |
145 | /* |
146 | * Merge adjacent extents. | |
147 | */ | |
148 | while (le < lv->le_count) { | |
149 | if (!_emit_target(dmt, lv, &le)) { | |
150 | log_err("unable to activate logical volume '%s'", | |
151 | lv->name); | |
ae2bb665 JT |
152 | goto out; |
153 | } | |
ae2bb665 JT |
154 | } |
155 | ||
f047219b | 156 | if (!(r = dm_task_run(dmt))) |
ae2bb665 JT |
157 | stack; |
158 | ||
159 | out: | |
f047219b | 160 | dm_task_destroy(dmt); |
ae2bb665 | 161 | return r; |
b1713d28 | 162 | } |
a381c45a | 163 | |
37ed70b9 JT |
164 | /* FIXME: Always display error msg */ |
165 | /* FIXME: Create dev entry if required */ | |
166 | int lv_activate(struct logical_volume *lv) | |
0a5e4a14 | 167 | { |
37ed70b9 JT |
168 | return _load(lv, DM_DEVICE_CREATE); |
169 | } | |
170 | ||
171 | int _suspend(struct logical_volume *lv, int sus) | |
172 | { | |
173 | int r; | |
174 | struct dm_task *dmt; | |
175 | int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME; | |
176 | ||
177 | if (!(dmt = _setup_task(lv, task))) { | |
178 | stack; | |
179 | return 0; | |
180 | } | |
181 | ||
182 | if (!(r = dm_task_run(dmt))) | |
183 | log_err("Couldn't %s device '%s'", sus ? "suspend" : "resume", | |
184 | lv->name); | |
185 | ||
186 | dm_task_destroy(dmt); | |
187 | return r; | |
188 | } | |
189 | ||
190 | int lv_reactivate(struct logical_volume *lv) | |
191 | { | |
192 | int r; | |
193 | if (!_suspend(lv, 1)) { | |
194 | stack; | |
195 | return 0; | |
196 | } | |
0a5e4a14 | 197 | |
37ed70b9 | 198 | r = _load(lv, DM_DEVICE_RELOAD); |
ae2bb665 | 199 | |
37ed70b9 JT |
200 | if (!_suspend(lv, 0)) { |
201 | stack; | |
202 | return 0; | |
203 | } | |
0a5e4a14 | 204 | |
37ed70b9 | 205 | return r; |
0a5e4a14 AK |
206 | } |
207 | ||
ae2bb665 JT |
208 | int lv_deactivate(struct logical_volume *lv) |
209 | { | |
f047219b | 210 | int r; |
ab269099 JT |
211 | struct dm_task *dmt; |
212 | ||
37ed70b9 | 213 | if (!(dmt = _setup_task(lv, DM_DEVICE_REMOVE))) { |
ae2bb665 JT |
214 | stack; |
215 | return 0; | |
216 | } | |
217 | ||
f047219b | 218 | if (!(r = dm_task_run(dmt))) |
ae2bb665 JT |
219 | stack; |
220 | ||
ae2bb665 JT |
221 | dm_task_destroy(dmt); |
222 | return r; | |
223 | } | |
224 | ||
37ed70b9 JT |
225 | int activate_lvs_in_vg(struct volume_group *vg) |
226 | { | |
227 | struct list *lvh; | |
228 | struct logical_volume *lv; | |
94b8220f | 229 | int count = 0; |
37ed70b9 JT |
230 | |
231 | list_iterate(lvh, &vg->lvs) { | |
232 | lv = &(list_item(lvh, struct lv_list)->lv); | |
233 | ||
94b8220f | 234 | count += (!lv_active(lv) && lv_activate(lv)); |
37ed70b9 JT |
235 | } |
236 | ||
237 | return count; | |
238 | } | |
239 | ||
ae2bb665 JT |
240 | int lv_update_write_access(struct logical_volume *lv) |
241 | { | |
242 | return 0; | |
243 | } | |
244 | ||
a381c45a AK |
245 | int deactivate_lvs_in_vg(struct volume_group *vg) |
246 | { | |
0a5e4a14 | 247 | struct list *lvh; |
37ed70b9 | 248 | struct logical_volume *lv; |
94b8220f | 249 | int count = 0; |
37ed70b9 JT |
250 | |
251 | list_iterate(lvh, &vg->lvs) { | |
252 | lv = &(list_item(lvh, struct lv_list)->lv); | |
0a5e4a14 | 253 | |
94b8220f | 254 | count += ((lv_active(lv) == 1) && lv_deactivate(lv)); |
37ed70b9 | 255 | } |
0a5e4a14 | 256 | |
37ed70b9 | 257 | return count; |
a381c45a | 258 | } |
f047219b AK |
259 | |
260 | int lvs_in_vg_activated(struct volume_group *vg) | |
261 | { | |
37ed70b9 JT |
262 | struct list *lvh; |
263 | struct logical_volume *lv; | |
94b8220f | 264 | int count = 0; |
37ed70b9 JT |
265 | |
266 | list_iterate(lvh, &vg->lvs) { | |
267 | lv = &(list_item(lvh, struct lv_list)->lv); | |
268 | ||
94b8220f | 269 | count += (lv_active(lv) == 1); |
37ed70b9 JT |
270 | } |
271 | ||
272 | return count; | |
f047219b | 273 | } |
2ba80b43 JT |
274 | |
275 | int lvs_in_vg_opened(struct volume_group *vg) | |
276 | { | |
277 | struct list *lvh; | |
278 | struct logical_volume *lv; | |
94b8220f | 279 | int count = 0; |
2ba80b43 JT |
280 | |
281 | list_iterate(lvh, &vg->lvs) { | |
282 | lv = &(list_item(lvh, struct lv_list)->lv); | |
283 | ||
94b8220f | 284 | count += (lv_open_count(lv) == 1); |
2ba80b43 JT |
285 | } |
286 | ||
287 | return count; | |
288 | } | |
289 |