]>
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" |
78125be9 | 9 | #include "display.h" |
f047219b | 10 | #include "log.h" |
f7a14956 | 11 | #include "fs.h" |
41b2fd5f | 12 | #include "lvm-string.h" |
b1713d28 | 13 | |
ab269099 JT |
14 | static void _build_lv_name(char *buffer, size_t s, struct logical_volume *lv) |
15 | { | |
16 | snprintf(buffer, s, "%s_%s", lv->vg->name, lv->name); | |
17 | } | |
18 | ||
2ba80b43 | 19 | static struct dm_task *_setup_task(struct logical_volume *lv, int task) |
37ed70b9 JT |
20 | { |
21 | char name[128]; | |
22 | struct dm_task *dmt; | |
23 | ||
24 | if (!(dmt = dm_task_create(task))) { | |
25 | stack; | |
26 | return NULL; | |
27 | } | |
28 | ||
29 | _build_lv_name(name, sizeof(name), lv); | |
30 | dm_task_set_name(dmt, name); | |
31 | ||
32 | return dmt; | |
33 | } | |
34 | ||
3080a754 | 35 | int lv_info(struct logical_volume *lv, struct dm_info *info) |
37ed70b9 | 36 | { |
ef8a0eae | 37 | int r = 0; |
37ed70b9 JT |
38 | struct dm_task *dmt; |
39 | ||
a299e388 | 40 | log_very_verbose("Getting device info for %s", lv->name); |
37ed70b9 JT |
41 | if (!(dmt = _setup_task(lv, DM_DEVICE_INFO))) { |
42 | stack; | |
43 | return 0; | |
44 | } | |
45 | ||
46 | if (!dm_task_run(dmt)) { | |
2ba80b43 | 47 | stack; |
ef8a0eae | 48 | goto out; |
2ba80b43 JT |
49 | } |
50 | ||
ef8a0eae JT |
51 | if (!dm_task_get_info(dmt, info)) { |
52 | stack; | |
53 | goto out; | |
54 | } | |
55 | r = 1; | |
2ba80b43 | 56 | |
ef8a0eae | 57 | out: |
2ba80b43 | 58 | dm_task_destroy(dmt); |
ef8a0eae | 59 | return r; |
2ba80b43 JT |
60 | } |
61 | ||
94b8220f | 62 | int lv_active(struct logical_volume *lv) |
2ba80b43 | 63 | { |
94b8220f | 64 | int r = -1; |
ef8a0eae | 65 | struct dm_info info; |
2ba80b43 | 66 | |
3080a754 | 67 | if (!lv_info(lv, &info)) { |
37ed70b9 | 68 | stack; |
94b8220f | 69 | return r; |
37ed70b9 JT |
70 | } |
71 | ||
a299e388 | 72 | log_very_verbose("%s is%s active", lv->name, info.exists ? "":" not"); |
ef8a0eae | 73 | return info.exists; |
37ed70b9 JT |
74 | } |
75 | ||
2bc25b54 AK |
76 | int lv_suspended(struct logical_volume *lv) |
77 | { | |
78 | int r = -1; | |
79 | struct dm_info info; | |
80 | ||
81 | if (!lv_info(lv, &info)) { | |
82 | stack; | |
83 | return r; | |
84 | } | |
85 | ||
86 | log_very_verbose("%s is%s suspended", lv->name, | |
87 | info.suspended ? "":" not"); | |
88 | return info.suspended; | |
89 | } | |
90 | ||
94b8220f | 91 | int lv_open_count(struct logical_volume *lv) |
2ba80b43 | 92 | { |
94b8220f | 93 | int r = -1; |
ef8a0eae | 94 | struct dm_info info; |
2ba80b43 | 95 | |
3080a754 | 96 | if (!lv_info(lv, &info)) { |
2ba80b43 | 97 | stack; |
94b8220f | 98 | return r; |
2ba80b43 JT |
99 | } |
100 | ||
a299e388 | 101 | log_very_verbose("%s is open %d time(s)", lv->name, info.open_count); |
ef8a0eae | 102 | return info.open_count; |
2ba80b43 JT |
103 | } |
104 | ||
80f9662b | 105 | /* |
0bab6591 | 106 | * Emit a target for a given segment. |
80f9662b | 107 | */ |
0bab6591 | 108 | static int _emit_target(struct dm_task *dmt, struct stripe_segment *seg) |
80f9662b JT |
109 | { |
110 | char params[1024]; | |
39497a44 | 111 | uint64_t esize = seg->lv->vg->extent_size; |
0bab6591 | 112 | uint32_t s, stripes = seg->stripes; |
b546cd6d | 113 | int w = 0, tw = 0; |
6c4ee296 JT |
114 | const char *no_space = |
115 | "Insufficient space to write target parameters."; | |
0bab6591 | 116 | |
6c4ee296 | 117 | if (stripes > 1) { |
41b2fd5f | 118 | tw = lvm_snprintf(params, sizeof(params), "%u %u ", |
6c4ee296 JT |
119 | stripes, seg->stripe_size); |
120 | ||
121 | if (tw < 0) { | |
122 | log_err(no_space); | |
123 | return 0; | |
124 | } | |
125 | ||
126 | w = tw; | |
127 | } | |
128 | ||
b546cd6d | 129 | |
6c4ee296 | 130 | for (s = 0; s < stripes; s++, w += tw) { |
41b2fd5f | 131 | tw = lvm_snprintf(params + w, sizeof(params) - w, |
0bab6591 JT |
132 | "%s %" PRIu64 "%s", |
133 | dev_name(seg->area[s].pv->dev), | |
134 | (seg->area[s].pv->pe_start + | |
135 | (esize * seg->area[s].pe)), | |
136 | s == (stripes - 1) ? "" : " "); | |
137 | ||
138 | if (tw < 0) { | |
6c4ee296 | 139 | log_err(no_space); |
0bab6591 JT |
140 | return 0; |
141 | } | |
80f9662b JT |
142 | } |
143 | ||
a299e388 AK |
144 | log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s", |
145 | esize * seg->le, esize * seg->len, | |
146 | stripes == 1 ? "linear" : "striped", | |
147 | params); | |
148 | ||
39497a44 | 149 | if (!dm_task_add_target(dmt, esize * seg->le, esize * seg->len, |
0bab6591 JT |
150 | stripes == 1 ? "linear" : "striped", |
151 | params)) { | |
80f9662b JT |
152 | stack; |
153 | return 0; | |
154 | } | |
155 | ||
80f9662b JT |
156 | return 1; |
157 | } | |
158 | ||
37ed70b9 | 159 | int _load(struct logical_volume *lv, int task) |
b1713d28 | 160 | { |
ae2bb665 | 161 | int r = 0; |
ae2bb665 | 162 | struct dm_task *dmt; |
0bab6591 JT |
163 | struct list *segh; |
164 | struct stripe_segment *seg; | |
e15559aa | 165 | |
a299e388 | 166 | log_very_verbose("Generating devmapper parameters for %s", lv->name); |
37ed70b9 | 167 | if (!(dmt = _setup_task(lv, task))) { |
ae2bb665 JT |
168 | stack; |
169 | return 0; | |
170 | } | |
b1713d28 | 171 | |
0bab6591 JT |
172 | list_iterate(segh, &lv->segments) { |
173 | seg = list_item(segh, struct stripe_segment); | |
174 | if (!_emit_target(dmt, seg)) { | |
cf4a4a1f | 175 | log_error("Unable to activate logical volume '%s'", |
80f9662b | 176 | lv->name); |
ae2bb665 JT |
177 | goto out; |
178 | } | |
ae2bb665 JT |
179 | } |
180 | ||
2bc25b54 AK |
181 | if (!(lv->status & LVM_WRITE) && !dm_task_set_ro(dmt)) |
182 | log_error("Failed to set %s read-only during activation.", | |
183 | lv->name); | |
184 | ||
185 | ||
f047219b | 186 | if (!(r = dm_task_run(dmt))) |
ae2bb665 JT |
187 | stack; |
188 | ||
b546cd6d AK |
189 | log_verbose("Logical volume %s%s activated", lv->name, |
190 | r == 1 ? "" : " not"); | |
3080a754 | 191 | |
ae2bb665 | 192 | out: |
f047219b | 193 | dm_task_destroy(dmt); |
ae2bb665 | 194 | return r; |
b1713d28 | 195 | } |
a381c45a | 196 | |
37ed70b9 | 197 | /* FIXME: Always display error msg */ |
37ed70b9 | 198 | int lv_activate(struct logical_volume *lv) |
0a5e4a14 | 199 | { |
c2d72fd4 AK |
200 | if (test_mode()) |
201 | return 0; | |
202 | ||
a299e388 | 203 | log_very_verbose("Activating %s", lv->name); |
f7a14956 | 204 | return _load(lv, DM_DEVICE_CREATE) && fs_add_lv(lv); |
37ed70b9 JT |
205 | } |
206 | ||
207 | int _suspend(struct logical_volume *lv, int sus) | |
208 | { | |
209 | int r; | |
210 | struct dm_task *dmt; | |
211 | int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME; | |
212 | ||
a299e388 | 213 | log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", lv->name); |
37ed70b9 JT |
214 | if (!(dmt = _setup_task(lv, task))) { |
215 | stack; | |
216 | return 0; | |
217 | } | |
218 | ||
219 | if (!(r = dm_task_run(dmt))) | |
220 | log_err("Couldn't %s device '%s'", sus ? "suspend" : "resume", | |
221 | lv->name); | |
222 | ||
223 | dm_task_destroy(dmt); | |
224 | return r; | |
225 | } | |
226 | ||
227 | int lv_reactivate(struct logical_volume *lv) | |
228 | { | |
229 | int r; | |
c2d72fd4 AK |
230 | |
231 | if (test_mode()) | |
232 | return 0; | |
233 | ||
2bc25b54 | 234 | if (!lv_suspended(lv) && !_suspend(lv, 1)) { |
37ed70b9 JT |
235 | stack; |
236 | return 0; | |
237 | } | |
0a5e4a14 | 238 | |
37ed70b9 | 239 | r = _load(lv, DM_DEVICE_RELOAD); |
ae2bb665 | 240 | |
37ed70b9 JT |
241 | if (!_suspend(lv, 0)) { |
242 | stack; | |
243 | return 0; | |
244 | } | |
0a5e4a14 | 245 | |
37ed70b9 | 246 | return r; |
0a5e4a14 AK |
247 | } |
248 | ||
ae2bb665 JT |
249 | int lv_deactivate(struct logical_volume *lv) |
250 | { | |
f047219b | 251 | int r; |
ab269099 JT |
252 | struct dm_task *dmt; |
253 | ||
a299e388 | 254 | log_very_verbose("Deactivating %s", lv->name); |
c2d72fd4 AK |
255 | if (test_mode()) |
256 | return 0; | |
257 | ||
37ed70b9 | 258 | if (!(dmt = _setup_task(lv, DM_DEVICE_REMOVE))) { |
ae2bb665 JT |
259 | stack; |
260 | return 0; | |
261 | } | |
262 | ||
f047219b | 263 | if (!(r = dm_task_run(dmt))) |
ae2bb665 JT |
264 | stack; |
265 | ||
ae2bb665 | 266 | dm_task_destroy(dmt); |
f7a14956 JT |
267 | |
268 | fs_del_lv(lv); | |
269 | ||
ae2bb665 JT |
270 | return r; |
271 | } | |
272 | ||
37ed70b9 JT |
273 | int activate_lvs_in_vg(struct volume_group *vg) |
274 | { | |
275 | struct list *lvh; | |
276 | struct logical_volume *lv; | |
94b8220f | 277 | int count = 0; |
37ed70b9 JT |
278 | |
279 | list_iterate(lvh, &vg->lvs) { | |
280 | lv = &(list_item(lvh, struct lv_list)->lv); | |
281 | ||
94b8220f | 282 | count += (!lv_active(lv) && lv_activate(lv)); |
37ed70b9 JT |
283 | } |
284 | ||
285 | return count; | |
286 | } | |
287 | ||
ae2bb665 JT |
288 | int lv_update_write_access(struct logical_volume *lv) |
289 | { | |
2bc25b54 AK |
290 | struct dm_info info; |
291 | ||
292 | if (!lv_info(lv, &info)) { | |
293 | stack; | |
294 | return 0; | |
295 | } | |
296 | ||
297 | if (!info.exists || info.suspended) | |
298 | /* Noop */ | |
299 | return 1; | |
300 | ||
301 | return lv_reactivate(lv); | |
ae2bb665 JT |
302 | } |
303 | ||
a381c45a AK |
304 | int deactivate_lvs_in_vg(struct volume_group *vg) |
305 | { | |
0a5e4a14 | 306 | struct list *lvh; |
37ed70b9 | 307 | struct logical_volume *lv; |
94b8220f | 308 | int count = 0; |
37ed70b9 JT |
309 | |
310 | list_iterate(lvh, &vg->lvs) { | |
311 | lv = &(list_item(lvh, struct lv_list)->lv); | |
0a5e4a14 | 312 | |
94b8220f | 313 | count += ((lv_active(lv) == 1) && lv_deactivate(lv)); |
37ed70b9 | 314 | } |
0a5e4a14 | 315 | |
37ed70b9 | 316 | return count; |
a381c45a | 317 | } |
f047219b AK |
318 | |
319 | int lvs_in_vg_activated(struct volume_group *vg) | |
320 | { | |
37ed70b9 JT |
321 | struct list *lvh; |
322 | struct logical_volume *lv; | |
94b8220f | 323 | int count = 0; |
37ed70b9 JT |
324 | |
325 | list_iterate(lvh, &vg->lvs) { | |
326 | lv = &(list_item(lvh, struct lv_list)->lv); | |
327 | ||
94b8220f | 328 | count += (lv_active(lv) == 1); |
37ed70b9 JT |
329 | } |
330 | ||
331 | return count; | |
f047219b | 332 | } |
2ba80b43 JT |
333 | |
334 | int lvs_in_vg_opened(struct volume_group *vg) | |
335 | { | |
336 | struct list *lvh; | |
337 | struct logical_volume *lv; | |
94b8220f | 338 | int count = 0; |
2ba80b43 JT |
339 | |
340 | list_iterate(lvh, &vg->lvs) { | |
341 | lv = &(list_item(lvh, struct lv_list)->lv); | |
342 | ||
94b8220f | 343 | count += (lv_open_count(lv) == 1); |
2ba80b43 JT |
344 | } |
345 | ||
346 | return count; | |
347 | } |