]>
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 | ||
39 | if (!(dmt = _setup_task(lv, DM_DEVICE_INFO))) { | |
40 | stack; | |
41 | return 0; | |
42 | } | |
43 | ||
44 | if (!dm_task_run(dmt)) { | |
2ba80b43 | 45 | stack; |
ef8a0eae | 46 | goto out; |
2ba80b43 JT |
47 | } |
48 | ||
ef8a0eae JT |
49 | if (!dm_task_get_info(dmt, info)) { |
50 | stack; | |
51 | goto out; | |
52 | } | |
53 | r = 1; | |
2ba80b43 | 54 | |
ef8a0eae | 55 | out: |
2ba80b43 | 56 | dm_task_destroy(dmt); |
ef8a0eae | 57 | return r; |
2ba80b43 JT |
58 | } |
59 | ||
94b8220f | 60 | int lv_active(struct logical_volume *lv) |
2ba80b43 | 61 | { |
94b8220f | 62 | int r = -1; |
ef8a0eae | 63 | struct dm_info info; |
2ba80b43 | 64 | |
3080a754 | 65 | if (!lv_info(lv, &info)) { |
37ed70b9 | 66 | stack; |
94b8220f | 67 | return r; |
37ed70b9 JT |
68 | } |
69 | ||
ef8a0eae | 70 | return info.exists; |
37ed70b9 JT |
71 | } |
72 | ||
94b8220f | 73 | int lv_open_count(struct logical_volume *lv) |
2ba80b43 | 74 | { |
94b8220f | 75 | int r = -1; |
ef8a0eae | 76 | struct dm_info info; |
2ba80b43 | 77 | |
3080a754 | 78 | if (!lv_info(lv, &info)) { |
2ba80b43 | 79 | stack; |
94b8220f | 80 | return r; |
2ba80b43 JT |
81 | } |
82 | ||
ef8a0eae | 83 | return info.open_count; |
2ba80b43 JT |
84 | } |
85 | ||
80f9662b | 86 | /* |
0bab6591 | 87 | * Emit a target for a given segment. |
80f9662b | 88 | */ |
0bab6591 | 89 | static int _emit_target(struct dm_task *dmt, struct stripe_segment *seg) |
80f9662b JT |
90 | { |
91 | char params[1024]; | |
39497a44 | 92 | uint64_t esize = seg->lv->vg->extent_size; |
0bab6591 JT |
93 | uint32_t s, stripes = seg->stripes; |
94 | int w, tw; | |
6c4ee296 JT |
95 | const char *no_space = |
96 | "Insufficient space to write target parameters."; | |
0bab6591 | 97 | |
6c4ee296 JT |
98 | if (stripes > 1) { |
99 | tw = snprintf(params, sizeof(params), "%u %u ", | |
100 | stripes, seg->stripe_size); | |
101 | ||
102 | if (tw < 0) { | |
103 | log_err(no_space); | |
104 | return 0; | |
105 | } | |
106 | ||
107 | w = tw; | |
108 | } | |
109 | ||
110 | for (s = 0; s < stripes; s++, w += tw) { | |
0bab6591 JT |
111 | tw = snprintf(params + w, sizeof(params) - w, |
112 | "%s %" PRIu64 "%s", | |
113 | dev_name(seg->area[s].pv->dev), | |
114 | (seg->area[s].pv->pe_start + | |
115 | (esize * seg->area[s].pe)), | |
116 | s == (stripes - 1) ? "" : " "); | |
117 | ||
118 | if (tw < 0) { | |
6c4ee296 | 119 | log_err(no_space); |
0bab6591 JT |
120 | return 0; |
121 | } | |
80f9662b JT |
122 | } |
123 | ||
39497a44 | 124 | if (!dm_task_add_target(dmt, esize * seg->le, esize * seg->len, |
0bab6591 JT |
125 | stripes == 1 ? "linear" : "striped", |
126 | params)) { | |
80f9662b JT |
127 | stack; |
128 | return 0; | |
129 | } | |
130 | ||
80f9662b JT |
131 | return 1; |
132 | } | |
133 | ||
37ed70b9 | 134 | int _load(struct logical_volume *lv, int task) |
b1713d28 | 135 | { |
ae2bb665 | 136 | int r = 0; |
ae2bb665 | 137 | struct dm_task *dmt; |
0bab6591 JT |
138 | struct list *segh; |
139 | struct stripe_segment *seg; | |
e15559aa | 140 | |
37ed70b9 | 141 | if (!(dmt = _setup_task(lv, task))) { |
ae2bb665 JT |
142 | stack; |
143 | return 0; | |
144 | } | |
b1713d28 | 145 | |
0bab6591 JT |
146 | list_iterate(segh, &lv->segments) { |
147 | seg = list_item(segh, struct stripe_segment); | |
148 | if (!_emit_target(dmt, seg)) { | |
cf4a4a1f | 149 | log_error("Unable to activate logical volume '%s'", |
80f9662b | 150 | lv->name); |
ae2bb665 JT |
151 | goto out; |
152 | } | |
ae2bb665 JT |
153 | } |
154 | ||
f047219b | 155 | if (!(r = dm_task_run(dmt))) |
ae2bb665 JT |
156 | stack; |
157 | ||
3080a754 AK |
158 | log_verbose("Logical volume %s activated", lv->name); |
159 | ||
ae2bb665 | 160 | out: |
f047219b | 161 | dm_task_destroy(dmt); |
ae2bb665 | 162 | return r; |
b1713d28 | 163 | } |
a381c45a | 164 | |
37ed70b9 | 165 | /* FIXME: Always display error msg */ |
37ed70b9 | 166 | int lv_activate(struct logical_volume *lv) |
0a5e4a14 | 167 | { |
f7a14956 | 168 | return _load(lv, DM_DEVICE_CREATE) && fs_add_lv(lv); |
37ed70b9 JT |
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 | 221 | dm_task_destroy(dmt); |
f7a14956 JT |
222 | |
223 | fs_del_lv(lv); | |
224 | ||
ae2bb665 JT |
225 | return r; |
226 | } | |
227 | ||
37ed70b9 JT |
228 | int activate_lvs_in_vg(struct volume_group *vg) |
229 | { | |
230 | struct list *lvh; | |
231 | struct logical_volume *lv; | |
94b8220f | 232 | int count = 0; |
37ed70b9 JT |
233 | |
234 | list_iterate(lvh, &vg->lvs) { | |
235 | lv = &(list_item(lvh, struct lv_list)->lv); | |
236 | ||
94b8220f | 237 | count += (!lv_active(lv) && lv_activate(lv)); |
37ed70b9 JT |
238 | } |
239 | ||
240 | return count; | |
241 | } | |
242 | ||
ae2bb665 JT |
243 | int lv_update_write_access(struct logical_volume *lv) |
244 | { | |
245 | return 0; | |
246 | } | |
247 | ||
a381c45a AK |
248 | int deactivate_lvs_in_vg(struct volume_group *vg) |
249 | { | |
0a5e4a14 | 250 | struct list *lvh; |
37ed70b9 | 251 | struct logical_volume *lv; |
94b8220f | 252 | int count = 0; |
37ed70b9 JT |
253 | |
254 | list_iterate(lvh, &vg->lvs) { | |
255 | lv = &(list_item(lvh, struct lv_list)->lv); | |
0a5e4a14 | 256 | |
94b8220f | 257 | count += ((lv_active(lv) == 1) && lv_deactivate(lv)); |
37ed70b9 | 258 | } |
0a5e4a14 | 259 | |
37ed70b9 | 260 | return count; |
a381c45a | 261 | } |
f047219b AK |
262 | |
263 | int lvs_in_vg_activated(struct volume_group *vg) | |
264 | { | |
37ed70b9 JT |
265 | struct list *lvh; |
266 | struct logical_volume *lv; | |
94b8220f | 267 | int count = 0; |
37ed70b9 JT |
268 | |
269 | list_iterate(lvh, &vg->lvs) { | |
270 | lv = &(list_item(lvh, struct lv_list)->lv); | |
271 | ||
94b8220f | 272 | count += (lv_active(lv) == 1); |
37ed70b9 JT |
273 | } |
274 | ||
275 | return count; | |
f047219b | 276 | } |
2ba80b43 JT |
277 | |
278 | int lvs_in_vg_opened(struct volume_group *vg) | |
279 | { | |
280 | struct list *lvh; | |
281 | struct logical_volume *lv; | |
94b8220f | 282 | int count = 0; |
2ba80b43 JT |
283 | |
284 | list_iterate(lvh, &vg->lvs) { | |
285 | lv = &(list_item(lvh, struct lv_list)->lv); | |
286 | ||
94b8220f | 287 | count += (lv_open_count(lv) == 1); |
2ba80b43 JT |
288 | } |
289 | ||
290 | return count; | |
291 | } |