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