]>
Commit | Line | Data |
---|---|---|
9e300c84 | 1 | /* |
6606c3ae | 2 | * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
35216ca6 | 3 | * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved. |
9e300c84 | 4 | * |
6606c3ae | 5 | * This file is part of LVM2. |
9e300c84 | 6 | * |
6606c3ae AK |
7 | * This copyrighted material is made available to anyone wishing to use, |
8 | * modify, copy, or redistribute it subject to the terms and conditions | |
be684599 | 9 | * of the GNU Lesser General Public License v.2.1. |
9e300c84 | 10 | * |
be684599 | 11 | * You should have received a copy of the GNU Lesser General Public License |
6606c3ae | 12 | * along with this program; if not, write to the Free Software Foundation, |
fcbef05a | 13 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
9e300c84 AK |
14 | */ |
15 | ||
16 | #include "tools.h" | |
17 | ||
7f97c7ea | 18 | #include "lib/cache/lvmcache.h" |
db741e75 | 19 | #include "lib/metadata/metadata.h" |
5f102b34 | 20 | #include "lib/label/hints.h" |
f40fd883 | 21 | #include "lib/device/online.h" |
db741e75 DT |
22 | |
23 | #include <dirent.h> | |
24 | ||
83d47562 DT |
25 | struct pvscan_params { |
26 | int new_pvs_found; | |
27 | int pvs_found; | |
28 | uint64_t size_total; | |
29 | uint64_t size_new; | |
30 | unsigned pv_max_name_len; | |
31 | unsigned vg_max_name_len; | |
32 | unsigned pv_tmp_namelen; | |
33 | char *pv_tmp_name; | |
34 | }; | |
35 | ||
9b640c36 | 36 | struct pvscan_aa_params { |
9b640c36 | 37 | unsigned int activate_errors; |
9b640c36 DT |
38 | }; |
39 | ||
f3b723cd DT |
40 | /* |
41 | * Used by _pvscan_aa_quick() which is an optimization used | |
42 | * when one vg is being activated. | |
43 | */ | |
44 | static struct volume_group *saved_vg; | |
74a388cc | 45 | |
db741e75 | 46 | static int _pvscan_display_pv(struct cmd_context *cmd, |
83d47562 DT |
47 | struct physical_volume *pv, |
48 | struct pvscan_params *params) | |
5a52dca9 | 49 | { |
3d7eaf92 ZK |
50 | /* XXXXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXXXX */ |
51 | char uuid[40] __attribute__((aligned(8))); | |
83d47562 DT |
52 | const unsigned suffix_len = sizeof(uuid) + 10; |
53 | unsigned pv_len; | |
3d7eaf92 | 54 | const char *pvdevname = pv_dev_name(pv); |
5a52dca9 AK |
55 | |
56 | /* short listing? */ | |
7e671e5d | 57 | if (arg_is_set(cmd, short_ARG)) { |
852a2b98 | 58 | log_print_unless_silent("%s", pvdevname); |
83d47562 | 59 | return ECMD_PROCESSED; |
5a52dca9 AK |
60 | } |
61 | ||
83d47562 DT |
62 | if (!params->pv_max_name_len) { |
63 | lvmcache_get_max_name_lengths(cmd, ¶ms->pv_max_name_len, ¶ms->vg_max_name_len); | |
5a52dca9 | 64 | |
83d47562 DT |
65 | params->pv_max_name_len += 2; |
66 | params->vg_max_name_len += 2; | |
67 | params->pv_tmp_namelen = params->pv_max_name_len + suffix_len; | |
5a52dca9 | 68 | |
83d47562 DT |
69 | if (!(params->pv_tmp_name = dm_pool_alloc(cmd->mem, params->pv_tmp_namelen))) |
70 | return ECMD_FAILED; | |
5a52dca9 AK |
71 | } |
72 | ||
83d47562 DT |
73 | pv_len = params->pv_max_name_len; |
74 | memset(params->pv_tmp_name, 0, params->pv_tmp_namelen); | |
75 | ||
7e671e5d | 76 | if (arg_is_set(cmd, uuid_ARG)) { |
5a52dca9 AK |
77 | if (!id_write_format(&pv->id, uuid, sizeof(uuid))) { |
78 | stack; | |
83d47562 | 79 | return ECMD_FAILED; |
5a52dca9 AK |
80 | } |
81 | ||
83d47562 DT |
82 | if (dm_snprintf(params->pv_tmp_name, params->pv_tmp_namelen, "%-*s with UUID %s", |
83 | params->pv_max_name_len - 2, pvdevname, uuid) < 0) { | |
3d7eaf92 | 84 | log_error("Invalid PV name with uuid."); |
83d47562 | 85 | return ECMD_FAILED; |
3d7eaf92 | 86 | } |
83d47562 DT |
87 | pvdevname = params->pv_tmp_name; |
88 | pv_len += suffix_len; | |
5a52dca9 AK |
89 | } |
90 | ||
62228474 DT |
91 | if (arg_is_set(cmd, allpvs_ARG)) { |
92 | struct device *dev = pv->dev; | |
93 | if (!cmd->enable_devices_file) { | |
94 | if (is_orphan(pv)) { | |
95 | log_print_unless_silent("PV %-*s %-*s", | |
96 | pv_len, pvdevname, | |
97 | params->vg_max_name_len, " "); | |
98 | } else { | |
99 | log_print_unless_silent("PV %-*s VG %-*s", | |
100 | pv_len, pvdevname, | |
101 | params->vg_max_name_len, pv_vg_name(pv)); | |
102 | } | |
103 | } else if (!(dev->flags & DEV_MATCHED_USE_ID)) { | |
104 | if (is_orphan(pv)) { | |
105 | log_print_unless_silent("PV %-*s %-*s %-10s %s", | |
106 | pv_len, pvdevname, | |
107 | params->vg_max_name_len, " ", | |
108 | "-", "-"); | |
109 | } else { | |
110 | log_print_unless_silent("PV %-*s VG %-*s %-10s %s", | |
111 | pv_len, pvdevname, | |
112 | params->vg_max_name_len, pv_vg_name(pv), | |
113 | "-", "-"); | |
114 | } | |
115 | } else { | |
116 | if (is_orphan(pv)) { | |
117 | log_print_unless_silent("PV %-*s %-*s %-10s %s", | |
118 | pv_len, pvdevname, | |
119 | params->vg_max_name_len, " ", | |
120 | idtype_to_str(dev->id->idtype), | |
121 | dev->id->idname ?: "none"); | |
122 | } else { | |
123 | log_print_unless_silent("PV %-*s VG %-*s %-10s %s", | |
124 | pv_len, pvdevname, | |
125 | params->vg_max_name_len, pv_vg_name(pv), | |
126 | idtype_to_str(dev->id->idtype), | |
127 | dev->id->idname ?: "none"); | |
128 | } | |
129 | } | |
130 | } else if (is_orphan(pv)) | |
438e0050 | 131 | log_print_unless_silent("PV %-*s %-*s %s [%s]", |
3d7eaf92 | 132 | pv_len, pvdevname, |
83d47562 | 133 | params->vg_max_name_len, " ", |
438e0050 AK |
134 | pv->fmt ? pv->fmt->name : " ", |
135 | display_size(cmd, pv_size(pv))); | |
3d7eaf92 ZK |
136 | else if (pv_status(pv) & EXPORTED_VG) |
137 | log_print_unless_silent("PV %-*s is in exported VG %s [%s / %s free]", | |
138 | pv_len, pvdevname, pv_vg_name(pv), | |
139 | display_size(cmd, (uint64_t) pv_pe_count(pv) * pv_pe_size(pv)), | |
140 | display_size(cmd, (uint64_t) (pv_pe_count(pv) - pv_pe_alloc_count(pv)) * pv_pe_size(pv))); | |
141 | else | |
142 | log_print_unless_silent("PV %-*s VG %-*s %s [%s / %s free]", | |
143 | pv_len, pvdevname, | |
83d47562 | 144 | params->vg_max_name_len, pv_vg_name(pv), |
3d7eaf92 | 145 | pv->fmt ? pv->fmt->name : " ", |
438e0050 AK |
146 | display_size(cmd, (uint64_t) pv_pe_count(pv) * pv_pe_size(pv)), |
147 | display_size(cmd, (uint64_t) (pv_pe_count(pv) - pv_pe_alloc_count(pv)) * pv_pe_size(pv))); | |
83d47562 DT |
148 | return ECMD_PROCESSED; |
149 | } | |
150 | ||
db741e75 | 151 | static int _pvscan_display_single(struct cmd_context *cmd, struct volume_group *vg, |
83d47562 DT |
152 | struct physical_volume *pv, struct processing_handle *handle) |
153 | { | |
154 | struct pvscan_params *params = (struct pvscan_params *)handle->custom_handle; | |
155 | ||
7e671e5d AK |
156 | if ((arg_is_set(cmd, exported_ARG) && !(pv_status(pv) & EXPORTED_VG)) || |
157 | (arg_is_set(cmd, novolumegroup_ARG) && (!is_orphan(pv)))) { | |
83d47562 DT |
158 | return ECMD_PROCESSED; |
159 | ||
160 | } | |
161 | ||
162 | params->pvs_found++; | |
163 | ||
164 | if (is_orphan(pv)) { | |
165 | params->new_pvs_found++; | |
166 | params->size_new += pv_size(pv); | |
167 | params->size_total += pv_size(pv); | |
168 | } else { | |
169 | params->size_total += (uint64_t) pv_pe_count(pv) * pv_pe_size(pv); | |
170 | } | |
171 | ||
db741e75 | 172 | _pvscan_display_pv(cmd, pv, params); |
83d47562 | 173 | return ECMD_PROCESSED; |
5a52dca9 AK |
174 | } |
175 | ||
117160b2 | 176 | int pvscan_display_cmd(struct cmd_context *cmd, int argc, char **argv) |
9e300c84 | 177 | { |
83d47562 DT |
178 | struct pvscan_params params = { 0 }; |
179 | struct processing_handle *handle = NULL; | |
180 | int ret; | |
9e300c84 | 181 | |
7e671e5d | 182 | if (arg_is_set(cmd, novolumegroup_ARG) && arg_is_set(cmd, exported_ARG)) { |
b6c041d7 | 183 | log_error("Options -e and -n are incompatible"); |
ee1f91bf | 184 | return EINVALID_CMD_LINE; |
9e300c84 AK |
185 | } |
186 | ||
7e671e5d | 187 | if (arg_is_set(cmd, exported_ARG) || arg_is_set(cmd, novolumegroup_ARG)) |
e7ddf416 | 188 | log_warn("WARNING: only considering physical volumes %s", |
7e671e5d | 189 | arg_is_set(cmd, exported_ARG) ? |
9e300c84 AK |
190 | "of exported volume group(s)" : "in no volume group"); |
191 | ||
62228474 DT |
192 | if (arg_is_set(cmd, allpvs_ARG)) { |
193 | cmd->filter_deviceid_skip = 1; | |
194 | cmd->use_hints = 0; | |
195 | } | |
196 | ||
f752a953 | 197 | if (!(handle = init_processing_handle(cmd, NULL))) { |
83d47562 DT |
198 | log_error("Failed to initialize processing handle."); |
199 | ret = ECMD_FAILED; | |
200 | goto out; | |
9e300c84 AK |
201 | } |
202 | ||
83d47562 | 203 | handle->custom_handle = ¶ms; |
9e300c84 | 204 | |
db741e75 | 205 | ret = process_each_pv(cmd, argc, argv, NULL, 0, 0, handle, _pvscan_display_single); |
9e300c84 | 206 | |
83d47562 | 207 | if (!params.pvs_found) |
438e0050 | 208 | log_print_unless_silent("No matching physical volumes found"); |
852a2b98 ZK |
209 | else |
210 | log_print_unless_silent("Total: %d [%s] / in use: %d [%s] / in no VG: %d [%s]", | |
83d47562 DT |
211 | params.pvs_found, |
212 | display_size(cmd, params.size_total), | |
213 | params.pvs_found - params.new_pvs_found, | |
214 | display_size(cmd, (params.size_total - params.size_new)), | |
215 | params.new_pvs_found, display_size(cmd, params.size_new)); | |
9e300c84 | 216 | |
83d47562 | 217 | out: |
a23655ab | 218 | destroy_processing_handle(cmd, handle); |
e935d217 | 219 | |
83d47562 | 220 | return ret; |
9e300c84 | 221 | } |
db741e75 | 222 | |
db741e75 DT |
223 | /* |
224 | * When a device goes offline we only know its major:minor, not its PVID. | |
225 | * Since the dev isn't around, we can't read it to get its PVID, so we have to | |
226 | * read the PVID files to find the one containing this major:minor and remove | |
227 | * that one. This means that the PVID files need to contain the devno's they | |
228 | * were created from. | |
229 | */ | |
230 | ||
85e06366 | 231 | static void _online_pvid_file_remove_devno(unsigned major, unsigned minor) |
db741e75 DT |
232 | { |
233 | char path[PATH_MAX]; | |
25b58310 | 234 | char file_vgname[NAME_LEN]; |
db741e75 DT |
235 | DIR *dir; |
236 | struct dirent *de; | |
85e06366 | 237 | unsigned file_major, file_minor; |
db741e75 | 238 | |
85e06366 | 239 | log_debug("Remove pv online devno %u:%u", major, minor); |
db741e75 | 240 | |
f40fd883 | 241 | if (!(dir = opendir(PVS_ONLINE_DIR))) |
db741e75 DT |
242 | return; |
243 | ||
244 | while ((de = readdir(dir))) { | |
245 | if (de->d_name[0] == '.') | |
246 | continue; | |
247 | ||
248 | memset(path, 0, sizeof(path)); | |
f40fd883 | 249 | snprintf(path, sizeof(path), "%s/%s", PVS_ONLINE_DIR, de->d_name); |
db741e75 | 250 | |
25b58310 DT |
251 | file_major = 0; |
252 | file_minor = 0; | |
253 | memset(file_vgname, 0, sizeof(file_vgname)); | |
74a388cc | 254 | |
73b4602f | 255 | online_pvid_file_read(path, &file_major, &file_minor, file_vgname, NULL); |
db741e75 | 256 | |
25b58310 | 257 | if ((file_major == major) && (file_minor == minor)) { |
74a388cc | 258 | log_debug("Unlink pv online %s", path); |
87842119 | 259 | if (unlink(path) && (errno != ENOENT)) |
70950bbd | 260 | log_sys_debug("unlink", path); |
74a388cc | 261 | |
f3b723cd | 262 | if (file_vgname[0]) { |
0b6782fa | 263 | online_vg_file_remove(file_vgname); |
08878968 | 264 | online_lookup_file_remove(file_vgname); |
f3b723cd | 265 | } |
db741e75 DT |
266 | } |
267 | } | |
f1ac130d | 268 | if (closedir(dir)) |
f40fd883 | 269 | log_sys_debug("closedir", PVS_ONLINE_DIR); |
db741e75 DT |
270 | } |
271 | ||
74a388cc | 272 | static void _online_files_remove(const char *dirpath) |
db741e75 DT |
273 | { |
274 | char path[PATH_MAX]; | |
275 | DIR *dir; | |
276 | struct dirent *de; | |
277 | ||
74a388cc | 278 | if (!(dir = opendir(dirpath))) |
db741e75 DT |
279 | return; |
280 | ||
281 | while ((de = readdir(dir))) { | |
282 | if (de->d_name[0] == '.') | |
283 | continue; | |
284 | ||
285 | memset(path, 0, sizeof(path)); | |
74a388cc | 286 | snprintf(path, sizeof(path), "%s/%s", dirpath, de->d_name); |
87842119 | 287 | if (unlink(path) && (errno != ENOENT)) |
70950bbd | 288 | log_sys_debug("unlink", path); |
db741e75 | 289 | } |
f1ac130d | 290 | if (closedir(dir)) |
74a388cc | 291 | log_sys_debug("closedir", dirpath); |
db741e75 DT |
292 | } |
293 | ||
f3b723cd | 294 | static int _write_lookup_file(struct cmd_context *cmd, struct volume_group *vg) |
db741e75 | 295 | { |
f3b723cd DT |
296 | char path[PATH_MAX]; |
297 | char line[ID_LEN+2]; | |
db741e75 | 298 | struct pv_list *pvl; |
f3b723cd | 299 | int fd; |
db741e75 | 300 | |
f40fd883 DT |
301 | if (dm_snprintf(path, sizeof(path), "%s/%s", PVS_LOOKUP_DIR, vg->name) < 0) { |
302 | log_error_pvscan(cmd, "Path %s/%s is too long.", PVS_LOOKUP_DIR, vg->name); | |
f3b723cd DT |
303 | return 0; |
304 | } | |
db741e75 | 305 | |
f3b723cd DT |
306 | fd = open(path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); |
307 | if (fd < 0) { | |
308 | /* not a problem, can happen when multiple pvscans run at once */ | |
309 | log_debug("Did not create %s: %d", path, errno); | |
310 | return 0; | |
74a388cc | 311 | } |
db741e75 | 312 | |
f3b723cd | 313 | log_debug("write_lookup_file %s", path); |
db741e75 DT |
314 | |
315 | dm_list_iterate_items(pvl, &vg->pvs) { | |
f3b723cd DT |
316 | memcpy(&line, &pvl->pv->id.uuid, ID_LEN); |
317 | line[ID_LEN] = '\n'; | |
318 | line[ID_LEN+1] = '\0'; | |
db741e75 | 319 | |
f3b723cd | 320 | if (write(fd, &line, ID_LEN+1) < 0) |
5dbf316c | 321 | log_error_pvscan(cmd, "Failed to write lookup entry %s %s", path, line); |
74a388cc DT |
322 | } |
323 | ||
f3b723cd DT |
324 | if (close(fd)) |
325 | log_sys_debug("close", path); | |
db741e75 DT |
326 | |
327 | return 1; | |
328 | } | |
329 | ||
f3b723cd | 330 | static int _lookup_file_contains_pvid(FILE *fp, char *pvid) |
db741e75 | 331 | { |
f3b723cd | 332 | char line[64]; |
db741e75 | 333 | |
f3b723cd DT |
334 | while (fgets(line, sizeof(line), fp)) { |
335 | if (!memcmp(pvid, line, ID_LEN)) | |
336 | return 1; | |
1e9e21a1 | 337 | } |
f3b723cd | 338 | return 0; |
db741e75 DT |
339 | } |
340 | ||
f3b723cd | 341 | static void _lookup_file_count_pvid_files(FILE *fp, const char *vgname, int *pvs_online, int *pvs_offline) |
25b58310 | 342 | { |
f3b723cd | 343 | char line[64]; |
96b77716 | 344 | char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 }; |
25b58310 | 345 | |
f3b723cd | 346 | log_debug("checking all pvid files using lookup file for %s", vgname); |
25b58310 | 347 | |
f3b723cd | 348 | rewind(fp); |
db741e75 | 349 | |
f3b723cd | 350 | while (fgets(line, sizeof(line), fp)) { |
f3b723cd | 351 | memcpy(pvid, line, ID_LEN); |
db741e75 | 352 | |
f3b723cd DT |
353 | if (strlen(pvid) != ID_LEN) { |
354 | log_debug("ignore lookup file line %s", line); | |
355 | continue; | |
356 | } | |
db741e75 | 357 | |
f40fd883 | 358 | if (online_pvid_file_exists((const char *)pvid)) |
f3b723cd DT |
359 | (*pvs_online)++; |
360 | else | |
361 | (*pvs_offline)++; | |
db741e75 | 362 | } |
f3b723cd | 363 | } |
db741e75 | 364 | |
f3b723cd DT |
365 | /* |
366 | * There is no synchronization between the one doing write_lookup_file and the | |
367 | * other doing check_lookup_file. The pvscan doing write thinks the VG is | |
368 | * incomplete, and the pvscan doing check may also conclude the VG is | |
369 | * incomplete if it happens prior to the write. If neither pvscan thinks the | |
370 | * VG is complete then neither will activate it. To solve this race, the | |
371 | * pvscan doing write will recheck pvid online files after the write in which | |
372 | * case it would find the pvid online file from the pvscan doing check. | |
373 | */ | |
a0c848d4 | 374 | |
f3b723cd DT |
375 | /* |
376 | * The VG is not yet complete, more PVs need to arrive, and | |
377 | * some of those PVs may not have metadata on them. Without | |
378 | * metadata, pvscan for those PVs will be unable to determine | |
379 | * if the VG is complete. We don't know if other PVs will have | |
380 | * metadata or not. | |
381 | * | |
382 | * Save a temp file with a list of pvids in the vg, to be used | |
383 | * by a later pvscan on a PV without metadata. The later | |
384 | * pvscan will check for vg completeness using the temp file | |
385 | * since it has no vg metadata to use. | |
386 | * | |
387 | * Only the first pvscan for the VG creates the temp file. If | |
388 | * there are multiple pvscans for the same VG running at once, | |
389 | * they all race to create the lookup file, and only the first | |
390 | * to create the file will write it. | |
391 | * | |
392 | * After writing the temp file, we count pvid online files for | |
393 | * the VG again - the VG could now be complete since multiple | |
394 | * pvscans will run concurrently. We repeat this to cover a | |
395 | * race where another pvscan was running _check_lookup_file | |
396 | * during our _write_lookup_file. _write_lookup_file may not | |
397 | * have finished before _check_lookup_file, which would cause | |
398 | * the other pvscan to not find the pvid it's looking for, and | |
399 | * conclude the VG is incomplete, while we also think the VG is | |
400 | * incomplete. If we recheck online files after write_lookup, | |
401 | * we will see the pvid online file from the other pvscan and | |
402 | * see the VG is complete. | |
403 | */ | |
a0c848d4 | 404 | |
f3b723cd DT |
405 | static int _count_pvid_files_from_lookup_file(struct cmd_context *cmd, struct device *dev, |
406 | int *pvs_online, int *pvs_offline, | |
407 | const char **vgname_out) | |
408 | { | |
a9fd2071 | 409 | char path[PATH_MAX] = { 0 }; |
f3b723cd DT |
410 | FILE *fp; |
411 | DIR *dir; | |
412 | struct dirent *de; | |
413 | const char *vgname = NULL; | |
db741e75 | 414 | |
a9fd2071 | 415 | *vgname_out = NULL; |
f3b723cd DT |
416 | *pvs_online = 0; |
417 | *pvs_offline = 0; | |
db741e75 | 418 | |
f40fd883 DT |
419 | if (!(dir = opendir(PVS_LOOKUP_DIR))) { |
420 | log_sys_debug("opendir", PVS_LOOKUP_DIR); | |
a9fd2071 ZK |
421 | return 0; |
422 | } | |
db741e75 | 423 | |
f3b723cd DT |
424 | /* |
425 | * Read each file in pvs_lookup to find dev->pvid, and if it's | |
426 | * found save the vgname of the file it's found in. | |
427 | */ | |
a9fd2071 | 428 | while (!vgname && (de = readdir(dir))) { |
f3b723cd DT |
429 | if (de->d_name[0] == '.') |
430 | continue; | |
db741e75 | 431 | |
f40fd883 DT |
432 | if (dm_snprintf(path, sizeof(path), "%s/%s", PVS_LOOKUP_DIR, de->d_name) < 0) { |
433 | log_warn("WARNING: Path %s/%s is too long.", PVS_LOOKUP_DIR, de->d_name); | |
a9fd2071 ZK |
434 | continue; |
435 | } | |
db741e75 | 436 | |
f3b723cd | 437 | if (!(fp = fopen(path, "r"))) { |
a9fd2071 | 438 | log_warn("WARNING: Failed to open %s.", path); |
f3b723cd DT |
439 | continue; |
440 | } | |
b16abb38 | 441 | |
f3b723cd | 442 | if (_lookup_file_contains_pvid(fp, dev->pvid)) { |
a9fd2071 ZK |
443 | if ((vgname = dm_pool_strdup(cmd->mem, de->d_name))) |
444 | /* | |
445 | * stat pvid online file of each pvid listed in this file | |
446 | * the list of pvids from the file is the alternative to | |
447 | * using vg->pvs | |
448 | */ | |
449 | _lookup_file_count_pvid_files(fp, vgname, pvs_online, pvs_offline); | |
450 | else | |
451 | log_warn("WARNING: Failed to strdup vgname."); | |
f3b723cd | 452 | } |
4e20ebd6 | 453 | |
f3b723cd | 454 | if (fclose(fp)) |
a9fd2071 | 455 | log_sys_debug("fclose", path); |
4e20ebd6 | 456 | } |
f3b723cd | 457 | if (closedir(dir)) |
f40fd883 | 458 | log_sys_debug("closedir", PVS_LOOKUP_DIR); |
4e20ebd6 | 459 | |
f3b723cd | 460 | *vgname_out = vgname; |
a9fd2071 ZK |
461 | |
462 | return (vgname) ? 1 : 0; | |
db741e75 DT |
463 | } |
464 | ||
f3b723cd DT |
465 | static void _count_pvid_files(struct volume_group *vg, int *pvs_online, int *pvs_offline) |
466 | { | |
96b77716 | 467 | char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 }; |
f3b723cd DT |
468 | struct pv_list *pvl; |
469 | ||
470 | *pvs_online = 0; | |
471 | *pvs_offline = 0; | |
472 | ||
473 | dm_list_iterate_items(pvl, &vg->pvs) { | |
96b77716 | 474 | memcpy(pvid, &pvl->pv->id.uuid, ID_LEN); |
f40fd883 | 475 | if (online_pvid_file_exists(pvid)) |
f3b723cd DT |
476 | (*pvs_online)++; |
477 | else | |
478 | (*pvs_offline)++; | |
479 | } | |
db741e75 DT |
480 | } |
481 | ||
482 | static int _pvscan_aa_single(struct cmd_context *cmd, const char *vg_name, | |
483 | struct volume_group *vg, struct processing_handle *handle) | |
484 | { | |
485 | struct pvscan_aa_params *pp = (struct pvscan_aa_params *)handle->custom_handle; | |
486 | ||
487 | if (vg_is_clustered(vg)) | |
488 | return ECMD_PROCESSED; | |
489 | ||
490 | if (vg_is_exported(vg)) | |
491 | return ECMD_PROCESSED; | |
492 | ||
493 | if (vg_is_shared(vg)) | |
494 | return ECMD_PROCESSED; | |
495 | ||
496 | log_debug("pvscan autoactivating VG %s.", vg_name); | |
497 | ||
c609dedc | 498 | if (!vgchange_activate(cmd, vg, CHANGE_AAY, 1, NULL)) { |
0b6782fa | 499 | log_error_pvscan(cmd, "%s: autoactivation failed.", vg->name); |
db741e75 DT |
500 | pp->activate_errors++; |
501 | } | |
502 | ||
503 | return ECMD_PROCESSED; | |
504 | } | |
505 | ||
25b58310 DT |
506 | /* |
507 | * This is a very unconventional way of doing things because | |
508 | * we want to figure out which devices to read the VG from | |
509 | * without first scanning devices. It's usually the reverse; | |
510 | * we have to scan all devs, which tells us which devs we | |
511 | * need to read to get the VG. | |
512 | * | |
513 | * We can do it this way only by cheating and using the pvid | |
514 | * online files for devs that have been scanned by prior pvscan | |
515 | * instances. | |
516 | * | |
517 | * This is similar to the hints file, but the hints file is | |
518 | * always a full picture of PV state, and is only ever created | |
519 | * by scanning all devs, whereas the online files are only | |
520 | * created incrementally by scanning one device at a time. | |
521 | * The online files are only used for determining complete VGs | |
522 | * for the purpose of autoactivation, and no attempt is made | |
523 | * to keep them in sync with lvm state once autoactivation | |
524 | * is complete, but much effort is made to always ensure hints | |
525 | * will accurately reflect PV state. | |
526 | * | |
527 | * The saved VG metadata tells us which PVIDs are needed to | |
528 | * complete the VG. The pv online files tell us which of those | |
529 | * PVIDs are online, and the content of those pv online files | |
530 | * tells us which major:minor number holds that PVID. The | |
531 | * dev_cache tell us which struct device has the major:minor. | |
532 | * We end up with a list of struct devices that we need to | |
533 | * scan/read in order to process/activate the VG. | |
534 | */ | |
535 | ||
0c23d3fc | 536 | static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname, |
25b58310 DT |
537 | struct dm_list *devs) |
538 | { | |
539 | char path[PATH_MAX]; | |
540 | char file_vgname[NAME_LEN]; | |
73b4602f | 541 | char file_devname[NAME_LEN]; |
96b77716 | 542 | char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 }; |
0c23d3fc | 543 | char uuidstr[64] __attribute__((aligned(8))); |
25b58310 DT |
544 | struct pv_list *pvl; |
545 | struct device_list *devl; | |
546 | struct device *dev; | |
547 | struct volume_group *vg; | |
0c23d3fc | 548 | const char *name1, *name2; |
25b58310 | 549 | dev_t devno; |
85e06366 | 550 | unsigned file_major = 0, file_minor = 0; |
25b58310 DT |
551 | |
552 | /* | |
553 | * We previously saved the metadata (as a struct vg) from the device | |
554 | * arg that was scanned. Now use that metadata to put together a list | |
555 | * of devices for this VG. (This could alternatively be worked out by | |
556 | * reading all the pvid online files, see which have a matching vg | |
557 | * name, and getting the device numbers from those files.) | |
558 | */ | |
f3b723cd DT |
559 | if (!(vg = saved_vg)) |
560 | goto_bad; | |
25b58310 DT |
561 | |
562 | dm_list_iterate_items(pvl, &vg->pvs) { | |
96b77716 | 563 | memcpy(pvid, &pvl->pv->id.uuid, ID_LEN); |
25b58310 DT |
564 | |
565 | memset(path, 0, sizeof(path)); | |
f40fd883 | 566 | snprintf(path, sizeof(path), "%s/%s", PVS_ONLINE_DIR, pvid); |
25b58310 DT |
567 | |
568 | file_major = 0; | |
569 | file_minor = 0; | |
570 | memset(file_vgname, 0, sizeof(file_vgname)); | |
73b4602f | 571 | memset(file_devname, 0, sizeof(file_devname)); |
25b58310 | 572 | |
73b4602f | 573 | online_pvid_file_read(path, &file_major, &file_minor, file_vgname, file_devname); |
25b58310 DT |
574 | |
575 | if (file_vgname[0] && strcmp(vgname, file_vgname)) { | |
0b6782fa DT |
576 | log_error_pvscan(cmd, "Wrong VG found for %d:%d PVID %s: %s vs %s", |
577 | file_major, file_minor, pvid, vgname, file_vgname); | |
f3b723cd | 578 | goto bad; |
25b58310 DT |
579 | } |
580 | ||
581 | devno = MKDEV(file_major, file_minor); | |
582 | ||
73b4602f DT |
583 | if (!(dev = setup_dev_in_dev_cache(cmd, devno, file_devname[0] ? file_devname : NULL))) { |
584 | log_error_pvscan(cmd, "No device set up for online PV %d:%d %s PVID %s", file_major, file_minor, file_devname, pvid); | |
f3b723cd | 585 | goto bad; |
25b58310 DT |
586 | } |
587 | ||
33e47182 DT |
588 | /* |
589 | * Do not need to match device_id here, see comment after | |
590 | * get_devs_from_saved_vg about relying on pvid online file. | |
591 | */ | |
592 | ||
0c23d3fc DT |
593 | name1 = dev_name(dev); |
594 | name2 = pvl->pv->device_hint; | |
595 | ||
470b967b DT |
596 | /* Probably pointless since dev is from online file which was already checked. */ |
597 | if (!strncmp(name2, "/dev/md", 7) && strncmp(name1, "/dev/md", 7)) { | |
0c23d3fc DT |
598 | if (!id_write_format((const struct id *)pvid, uuidstr, sizeof(uuidstr))) |
599 | uuidstr[0] = '\0'; | |
0b6782fa | 600 | log_print_pvscan(cmd, "PVID %s read from %s last written to %s.", uuidstr, name1, name2); |
f3b723cd | 601 | goto bad; |
0c23d3fc DT |
602 | } |
603 | ||
65c4f81d | 604 | if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl)))) |
f3b723cd | 605 | goto_bad; |
25b58310 DT |
606 | |
607 | devl->dev = dev; | |
608 | dm_list_add(devs, &devl->list); | |
609 | log_debug("pvscan using %s for PVID %s in VG %s", dev_name(dev), pvid, vgname); | |
610 | } | |
611 | ||
612 | return 1; | |
f3b723cd DT |
613 | |
614 | bad: | |
615 | if (saved_vg) { | |
616 | release_vg(saved_vg); | |
617 | saved_vg = NULL; | |
618 | } | |
619 | return 0; | |
25b58310 DT |
620 | } |
621 | ||
622 | /* | |
623 | * When there's a single VG to activate (the common case), | |
624 | * optimize things by cutting out the process_each_vg(). | |
625 | * | |
626 | * The main point of this optimization is to avoid extra | |
627 | * device scanning in the common case where we're | |
628 | * activating a completed VG after scanning a single PV. | |
629 | * The scanning overhead of hundreds of concurrent | |
630 | * activations from hundreds of PVs appearing together | |
631 | * can be overwhelming, and scanning needs to be reduced | |
632 | * as much as possible. | |
633 | * | |
634 | * The common process_each_vg will generally do: | |
635 | * label scan all devs | |
636 | * vg_read | |
637 | * lock vg | |
638 | * label rescan of only vg devs (often skipped) | |
639 | * read metadata | |
640 | * set pv devices (find devs for each PVID) | |
641 | * do command (vgchange_activate) | |
642 | * unlock vg | |
643 | * | |
644 | * In this optimized version with process_each we do: | |
645 | * lock vg | |
646 | * label scan of only vg devs | |
647 | * vg_read | |
648 | * read metadata | |
649 | * set pv devices (find devs for each PVID) | |
650 | * do command (vgchange_activate) | |
651 | * unlock vg | |
652 | * | |
653 | * The optimized version avoids scanning all devs, which | |
654 | * is important when there are many devs. | |
655 | */ | |
656 | ||
0c23d3fc | 657 | static int _pvscan_aa_quick(struct cmd_context *cmd, struct pvscan_aa_params *pp, const char *vgname, |
f3b723cd | 658 | int *no_quick) |
25b58310 DT |
659 | { |
660 | struct dm_list devs; /* device_list */ | |
661 | struct volume_group *vg; | |
662 | struct pv_list *pvl; | |
663 | const char *vgid; | |
664 | uint32_t lockd_state = 0; | |
665 | uint32_t error_flags = 0; | |
666 | int ret = ECMD_PROCESSED; | |
667 | ||
668 | dm_list_init(&devs); | |
669 | ||
670 | /* | |
671 | * Get list of devices for this VG so we can label scan them. | |
672 | * The saved VG struct gives the list of PVIDs in the VG. | |
673 | * The pvs_online/PVID files gives us the devnums for PVIDs. | |
674 | * The dev_cache gives us struct devices from the devnums. | |
675 | */ | |
f3b723cd | 676 | if (!_get_devs_from_saved_vg(cmd, vgname, &devs)) { |
0b6782fa | 677 | log_print_pvscan(cmd, "VG %s not using quick activation.", vgname); |
0c23d3fc | 678 | *no_quick = 1; |
25b58310 DT |
679 | return ECMD_FAILED; |
680 | } | |
681 | ||
d0ab5bf7 DT |
682 | /* |
683 | * The list of devs do not need to be filtered or checked | |
684 | * against the devices file because a dev is only returned | |
685 | * that has a pv online file, and a dev will only have a | |
686 | * pv online file if it's been processed by a previous | |
687 | * pvscan, which did the filtering and devices file check. | |
688 | */ | |
689 | ||
25b58310 DT |
690 | /* |
691 | * Lock the VG before scanning so we don't need to | |
692 | * rescan in _vg_read. (The lock_vol and the | |
693 | * label rescan are then disabled in vg_read.) | |
694 | */ | |
695 | if (!lock_vol(cmd, vgname, LCK_VG_WRITE, NULL)) { | |
0b6782fa | 696 | log_error_pvscan(cmd, "activation for VG %s failed to lock VG.", vgname); |
25b58310 DT |
697 | return ECMD_FAILED; |
698 | } | |
699 | ||
700 | /* | |
701 | * Drop lvmcache info about the PV/VG that was saved | |
702 | * when originally identifying the PV. | |
703 | */ | |
704 | lvmcache_destroy(cmd, 1, 1); | |
705 | ||
706 | label_scan_devs(cmd, NULL, &devs); | |
707 | ||
708 | if (!(vgid = lvmcache_vgid_from_vgname(cmd, vgname))) { | |
0b6782fa | 709 | log_error_pvscan(cmd, "activation for VG %s failed to find vgid.", vgname); |
25b58310 DT |
710 | return ECMD_FAILED; |
711 | } | |
712 | ||
713 | /* | |
714 | * can_use_one_scan and READ_WITHOUT_LOCK are both important key | |
715 | * changes made to vg_read that are possible because the VG is locked | |
716 | * above (lock_vol). | |
717 | */ | |
718 | ||
719 | cmd->can_use_one_scan = 1; | |
720 | ||
721 | vg = vg_read(cmd, vgname, vgid, READ_WITHOUT_LOCK | READ_FOR_ACTIVATE, lockd_state, &error_flags, NULL); | |
722 | ||
723 | if (!vg) { | |
724 | /* | |
725 | * The common cases would already have been caught during the | |
726 | * original device arg scan. There will be very few and unusual | |
727 | * cases that would be caught here. | |
728 | */ | |
0b6782fa | 729 | log_error_pvscan(cmd, "activation for VG %s cannot read (%x).", vgname, error_flags); |
25b58310 DT |
730 | return ECMD_FAILED; |
731 | } | |
732 | ||
733 | /* | |
734 | * These cases would already have been caught during the original | |
735 | * device arg scan. | |
736 | */ | |
737 | if (vg_is_clustered(vg)) | |
738 | goto_out; | |
739 | if (vg_is_exported(vg)) | |
740 | goto_out; | |
741 | if (vg_is_shared(vg)) | |
742 | goto_out; | |
743 | ||
744 | /* | |
745 | * Verify that the devices we scanned above for the VG are in fact the | |
746 | * devices used by the VG we read. | |
747 | */ | |
748 | dm_list_iterate_items(pvl, &vg->pvs) { | |
c98617c5 | 749 | if (device_list_find_dev(&devs, pvl->pv->dev)) |
25b58310 | 750 | continue; |
0b6782fa | 751 | log_error_pvscan(cmd, "activation for VG %s found different devices.", vgname); |
25b58310 DT |
752 | ret = ECMD_FAILED; |
753 | goto out; | |
754 | } | |
755 | ||
756 | log_debug("pvscan autoactivating VG %s.", vgname); | |
757 | ||
c609dedc | 758 | if (!vgchange_activate(cmd, vg, CHANGE_AAY, 1, NULL)) { |
0b6782fa | 759 | log_error_pvscan(cmd, "%s: autoactivation failed.", vg->name); |
25b58310 DT |
760 | pp->activate_errors++; |
761 | } | |
762 | ||
763 | out: | |
764 | unlock_vg(cmd, vg, vgname); | |
765 | release_vg(vg); | |
766 | return ret; | |
767 | } | |
768 | ||
db741e75 | 769 | static int _pvscan_aa(struct cmd_context *cmd, struct pvscan_aa_params *pp, |
f3b723cd | 770 | int do_all, struct dm_list *vgnames) |
db741e75 DT |
771 | { |
772 | struct processing_handle *handle = NULL; | |
74a388cc | 773 | struct dm_str_list *sl, *sl2; |
0c23d3fc | 774 | int no_quick = 0; |
5485ec10 | 775 | int ret = ECMD_FAILED; |
db741e75 | 776 | |
db741e75 | 777 | if (!(handle = init_processing_handle(cmd, NULL))) { |
0b6782fa | 778 | log_error_pvscan(cmd, "Failed to initialize processing handle."); |
f3b723cd | 779 | goto out; |
db741e75 DT |
780 | } |
781 | ||
782 | handle->custom_handle = pp; | |
783 | ||
74a388cc DT |
784 | /* |
785 | * For each complete vg that can be autoactivated, see if this | |
786 | * particular pvscan command should activate the vg. There can be | |
787 | * multiple concurrent pvscans for the same completed vg (when all the | |
788 | * PVs for the VG appear at once), and we want only one of the pvscans | |
789 | * to run the activation. The first to create the file will do it. | |
790 | */ | |
791 | dm_list_iterate_items_safe(sl, sl2, vgnames) { | |
f40fd883 | 792 | if (!online_vg_file_create(cmd, sl->str)) { |
0b6782fa | 793 | log_print_pvscan(cmd, "VG %s skip autoactivation.", sl->str); |
74a388cc DT |
794 | str_list_del(vgnames, sl->str); |
795 | continue; | |
796 | } | |
0b6782fa | 797 | log_print_pvscan(cmd, "VG %s run autoactivation.", sl->str); |
74a388cc DT |
798 | } |
799 | ||
800 | if (dm_list_empty(vgnames)) { | |
801 | destroy_processing_handle(cmd, handle); | |
f3b723cd DT |
802 | ret = ECMD_PROCESSED; |
803 | goto out; | |
74a388cc DT |
804 | } |
805 | ||
f3b723cd DT |
806 | /* |
807 | * When saved_vg is set there should only be one vgname. | |
808 | * If the optimized "quick" function finds something amiss | |
809 | * it will set no_quick and return so that the slow version | |
810 | * can be used. | |
811 | */ | |
812 | if (!do_all && saved_vg && (dm_list_size(vgnames) == 1)) { | |
813 | log_debug("autoactivate quick"); | |
814 | ret = _pvscan_aa_quick(cmd, pp, saved_vg->name, &no_quick); | |
25b58310 | 815 | } |
db741e75 | 816 | |
f3b723cd DT |
817 | /* |
818 | * do_all indicates 'pvscan --cache' in which case | |
819 | * pvscan_cache_all() has already done lvmcache_label_scan | |
820 | * which does not need to be repeated by process_each_vg. | |
821 | */ | |
822 | if (!saved_vg || (dm_list_size(vgnames) > 1) || no_quick) { | |
823 | uint32_t read_flags = READ_FOR_ACTIVATE; | |
d0ab5bf7 DT |
824 | |
825 | log_debug("autoactivate slow"); | |
826 | ||
827 | /* | |
828 | * PROCESS_SKIP_SCAN: we have already done lvmcache_label_scan | |
829 | * so tell process_each to skip it. | |
830 | */ | |
d0ab5bf7 | 831 | |
d0ab5bf7 | 832 | if (!do_all) |
33e47182 DT |
833 | lvmcache_label_scan(cmd); |
834 | ||
835 | read_flags |= PROCESS_SKIP_SCAN; | |
d0ab5bf7 | 836 | |
f3b723cd DT |
837 | ret = process_each_vg(cmd, 0, NULL, NULL, vgnames, read_flags, 0, handle, _pvscan_aa_single); |
838 | } | |
0c23d3fc | 839 | |
db741e75 | 840 | destroy_processing_handle(cmd, handle); |
f3b723cd DT |
841 | out: |
842 | if (saved_vg) { | |
843 | release_vg(saved_vg); | |
844 | saved_vg = NULL; | |
845 | } | |
db741e75 DT |
846 | return ret; |
847 | } | |
848 | ||
f3b723cd DT |
849 | struct pvscan_arg { |
850 | struct dm_list list; | |
851 | const char *devname; | |
852 | dev_t devno; | |
db741e75 | 853 | struct device *dev; |
f3b723cd DT |
854 | }; |
855 | ||
856 | static int _get_args(struct cmd_context *cmd, int argc, char **argv, | |
857 | struct dm_list *pvscan_args) | |
858 | { | |
db741e75 | 859 | struct arg_value_group_list *current_group; |
f3b723cd DT |
860 | struct pvscan_arg *arg; |
861 | const char *arg_name; | |
8a036752 | 862 | int major = -1, minor = -1; |
db741e75 | 863 | |
f3b723cd | 864 | /* Process position args, which can be /dev/name or major:minor */ |
f0089472 | 865 | |
f3b723cd DT |
866 | while (argc) { |
867 | argc--; | |
868 | arg_name = *argv++; | |
0534cd9c | 869 | |
f3b723cd DT |
870 | if (arg_name[0] == '/') { |
871 | if (!(arg = dm_pool_zalloc(cmd->mem, sizeof(*arg)))) | |
872 | return_0; | |
873 | arg->devname = arg_name; | |
874 | dm_list_add(pvscan_args, &arg->list); | |
875 | continue; | |
876 | } | |
db741e75 | 877 | |
f3b723cd DT |
878 | if (sscanf(arg_name, "%d:%d", &major, &minor) != 2) { |
879 | log_warn("WARNING: Failed to parse major:minor from %s, skipping.", arg_name); | |
880 | continue; | |
881 | } | |
db741e75 | 882 | |
ee496f28 ZK |
883 | if ((major < 0) || (minor < 0)) { |
884 | log_warn("WARNING: Invalid major:minor %d:%d, skipping.", major, minor); | |
885 | continue; | |
886 | } | |
887 | ||
f3b723cd DT |
888 | if (!(arg = dm_pool_zalloc(cmd->mem, sizeof(*arg)))) |
889 | return_0; | |
890 | arg->devno = MKDEV(major, minor); | |
891 | dm_list_add(pvscan_args, &arg->list); | |
db741e75 DT |
892 | } |
893 | ||
f3b723cd DT |
894 | /* Process any grouped --major --minor args */ |
895 | ||
896 | dm_list_iterate_items(current_group, &cmd->arg_value_groups) { | |
897 | major = grouped_arg_int_value(current_group->arg_values, major_ARG, major); | |
898 | minor = grouped_arg_int_value(current_group->arg_values, minor_ARG, minor); | |
899 | ||
900 | if (major < 0 || minor < 0) | |
901 | continue; | |
902 | ||
903 | if (!(arg = dm_pool_zalloc(cmd->mem, sizeof(*arg)))) | |
904 | return_0; | |
905 | arg->devno = MKDEV(major, minor); | |
906 | dm_list_add(pvscan_args, &arg->list); | |
417724ef DT |
907 | } |
908 | ||
f3b723cd DT |
909 | return 1; |
910 | } | |
74460f70 | 911 | |
f3b723cd DT |
912 | static int _get_args_devs(struct cmd_context *cmd, struct dm_list *pvscan_args, |
913 | struct dm_list *pvscan_devs) | |
914 | { | |
915 | struct pvscan_arg *arg; | |
916 | struct device_list *devl; | |
db741e75 | 917 | |
f3b723cd DT |
918 | /* pass NULL filter when getting devs from dev-cache, filtering is done separately */ |
919 | ||
920 | /* in common usage, no dev will be found for a devno */ | |
921 | ||
922 | dm_list_iterate_items(arg, pvscan_args) { | |
73b4602f | 923 | if (!arg->devname && !arg->devno) |
f3b723cd | 924 | return_0; |
73b4602f | 925 | if (!(arg->dev = setup_dev_in_dev_cache(cmd, arg->devno, arg->devname))) { |
85e06366 ZK |
926 | log_error_pvscan(cmd, "No device set up for arg %s %u:%u.", |
927 | arg->devname ?: "", MAJOR(arg->devno), MINOR(arg->devno)); | |
73b4602f | 928 | } |
4567c6a2 DT |
929 | } |
930 | ||
f3b723cd DT |
931 | dm_list_iterate_items(arg, pvscan_args) { |
932 | if (!arg->dev) | |
933 | continue; | |
f0089472 | 934 | |
f3b723cd DT |
935 | if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl)))) |
936 | return_0; | |
937 | devl->dev = arg->dev; | |
938 | dm_list_add(pvscan_devs, &devl->list); | |
939 | } | |
db741e75 | 940 | |
f3b723cd DT |
941 | return 1; |
942 | } | |
943 | ||
0b6782fa DT |
944 | static void _set_pv_devices_online(struct cmd_context *cmd, struct volume_group *vg) |
945 | { | |
946 | char path[PATH_MAX]; | |
947 | char file_vgname[NAME_LEN]; | |
73b4602f | 948 | char file_devname[NAME_LEN]; |
0b6782fa DT |
949 | char pvid[ID_LEN+1] = { 0 }; |
950 | struct pv_list *pvl; | |
951 | struct device *dev; | |
85e06366 | 952 | unsigned major, minor; |
0b6782fa DT |
953 | dev_t devno; |
954 | ||
955 | dm_list_iterate_items(pvl, &vg->pvs) { | |
956 | memcpy(&pvid, &pvl->pv->id.uuid, ID_LEN); | |
957 | ||
958 | if (pvl->pv->status & MISSING_PV) { | |
959 | log_debug("set_pv_devices_online vg %s pv %s missing flag already set", | |
960 | vg->name, pvid); | |
961 | continue; | |
962 | } | |
963 | ||
f40fd883 | 964 | if (!online_pvid_file_exists(pvid)) { |
0b6782fa DT |
965 | log_debug("set_pv_devices_online vg %s pv %s no online file", |
966 | vg->name, pvid); | |
967 | pvl->pv->status |= MISSING_PV; | |
968 | continue; | |
969 | } | |
970 | ||
971 | memset(path, 0, sizeof(path)); | |
f40fd883 | 972 | snprintf(path, sizeof(path), "%s/%s", PVS_ONLINE_DIR, pvid); |
0b6782fa DT |
973 | |
974 | major = 0; | |
975 | minor = 0; | |
73b4602f DT |
976 | memset(file_vgname, 0, sizeof(file_vgname)); |
977 | memset(file_devname, 0, sizeof(file_devname)); | |
0b6782fa | 978 | |
73b4602f | 979 | online_pvid_file_read(path, &major, &minor, file_vgname, file_devname); |
0b6782fa DT |
980 | |
981 | if (file_vgname[0] && strcmp(vg->name, file_vgname)) { | |
982 | log_warn("WARNING: VG %s PV %s wrong vgname in online file %s", | |
983 | vg->name, pvid, file_vgname); | |
984 | pvl->pv->status |= MISSING_PV; | |
985 | continue; | |
986 | } | |
987 | ||
988 | devno = MKDEV(major, minor); | |
989 | ||
73b4602f DT |
990 | if (!(dev = setup_dev_in_dev_cache(cmd, devno, file_devname[0] ? file_devname : NULL))) { |
991 | log_print_pvscan(cmd, "VG %s PV %s no device found for online PV %d:%d %s", | |
992 | vg->name, pvid, major, minor, file_devname); | |
0b6782fa DT |
993 | pvl->pv->status |= MISSING_PV; |
994 | continue; | |
995 | } | |
996 | ||
997 | log_debug("set_pv_devices_online vg %s pv %s is online %s", | |
998 | vg->name, pvid, dev_name(dev)); | |
999 | ||
1000 | pvl->pv->dev = dev; | |
1001 | } | |
1002 | } | |
1003 | ||
f3b723cd DT |
1004 | static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvscan_devs, |
1005 | int *pv_count, struct dm_list *complete_vgnames) | |
1006 | { | |
1007 | struct device_list *devl, *devl2; | |
1008 | struct device *dev; | |
1009 | struct lvmcache_info *info; | |
1010 | const struct format_type *fmt; | |
1011 | struct format_instance_ctx fic = { .type = 0 }; | |
1012 | struct format_instance *fid; | |
1013 | struct metadata_area *mda1, *mda2; | |
1014 | struct volume_group *vg; | |
87ee401e | 1015 | struct physical_volume *pv; |
0b6782fa | 1016 | const char *vgname = NULL; |
87ee401e | 1017 | uint64_t devsize; |
0b6782fa DT |
1018 | uint32_t ext_version, ext_flags; |
1019 | int do_cache = arg_is_set(cmd, cache_long_ARG); | |
f3b723cd | 1020 | int do_activate = arg_is_set(cmd, activate_ARG); |
0b6782fa DT |
1021 | int do_list_lvs = arg_is_set(cmd, listlvs_ARG); |
1022 | int do_list_vg = arg_is_set(cmd, listvg_ARG); | |
1023 | int do_check_complete = arg_is_set(cmd, checkcomplete_ARG); | |
1024 | int do_vgonline = arg_is_set(cmd, vgonline_ARG); | |
f3b723cd DT |
1025 | int pvs_online; |
1026 | int pvs_offline; | |
1027 | int pvs_unknown; | |
04725763 | 1028 | int vg_complete = 0; |
0b6782fa | 1029 | int do_full_check; |
f3b723cd DT |
1030 | int ret = 1; |
1031 | ||
1032 | dm_list_iterate_items_safe(devl, devl2, pvscan_devs) { | |
1033 | dev = devl->dev; | |
1034 | ||
1035 | log_debug("online_devs %s %s", dev_name(dev), dev->pvid); | |
1036 | ||
f3b723cd DT |
1037 | if (!(info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) { |
1038 | if (!do_all) | |
0b6782fa | 1039 | log_print_pvscan(cmd, "ignore %s with no lvm info.", dev_name(dev)); |
f3b723cd DT |
1040 | continue; |
1041 | } | |
db741e75 | 1042 | |
f3b723cd DT |
1043 | ext_version = lvmcache_ext_version(info); |
1044 | ext_flags = lvmcache_ext_flags(info); | |
1045 | if ((ext_version >= 2) && !(ext_flags & PV_EXT_USED)) { | |
0b6782fa | 1046 | log_print_pvscan(cmd, "PV %s not used.", dev_name(dev)); |
f3b723cd | 1047 | (*pv_count)++; |
db741e75 | 1048 | continue; |
f3b723cd | 1049 | } |
db741e75 | 1050 | |
f3b723cd | 1051 | fmt = lvmcache_fmt(info); |
f4100351 ZK |
1052 | if (!(fid = fmt->ops->create_instance(fmt, &fic))) { |
1053 | log_error("pvscan[%d] failed to create format instance.", getpid()); | |
1054 | ret = 0; | |
1055 | continue; | |
1056 | } | |
1057 | ||
f3b723cd | 1058 | vg = NULL; |
db741e75 | 1059 | |
f3b723cd DT |
1060 | mda1 = lvmcache_get_dev_mda(dev, 1); |
1061 | mda2 = lvmcache_get_dev_mda(dev, 2); | |
6f18186b | 1062 | |
f3b723cd DT |
1063 | if (mda1 && !mda_is_ignored(mda1)) |
1064 | vg = mda1->ops->vg_read(cmd, fid, "", mda1, NULL, NULL); | |
1065 | ||
1066 | if (!vg && mda2 && !mda_is_ignored(mda2)) | |
1067 | vg = mda2->ops->vg_read(cmd, fid, "", mda2, NULL, NULL); | |
1068 | ||
1069 | if (!vg) { | |
0b6782fa | 1070 | log_print_pvscan(cmd, "PV %s has no VG metadata.", dev_name(dev)); |
e1287c3b ZK |
1071 | if (fid) |
1072 | fmt->ops->destroy_instance(fid); | |
f3b723cd DT |
1073 | goto online; |
1074 | } | |
1075 | ||
87ee401e | 1076 | set_pv_devices(fid, vg); |
f3b723cd | 1077 | |
87ee401e | 1078 | if (!(pv = find_pv(vg, dev))) { |
0b6782fa | 1079 | log_print_pvscan(cmd, "PV %s not found in VG %s.", dev_name(dev), vg->name); |
87ee401e DT |
1080 | release_vg(vg); |
1081 | continue; | |
1082 | } | |
f3b723cd | 1083 | |
87ee401e | 1084 | devsize = dev->size; |
e6d35874 ZK |
1085 | if (!devsize && |
1086 | !dev_get_size(dev, &devsize)) { | |
ae355ffc | 1087 | log_print_pvscan(cmd, "PV %s missing device size.", dev_name(dev)); |
e6d35874 ZK |
1088 | release_vg(vg); |
1089 | continue; | |
1090 | } | |
87ee401e DT |
1091 | do_full_check = 0; |
1092 | ||
1093 | /* If use_full_md_check is set then this has already been done by filter. */ | |
470b967b | 1094 | if (!cmd->use_full_md_check && (cmd->dev_types->md_major != MAJOR(dev->dev))) { |
87ee401e DT |
1095 | if (devsize && (pv->size != devsize)) |
1096 | do_full_check = 1; | |
1097 | if (pv->device_hint && !strncmp(pv->device_hint, "/dev/md", 7)) | |
1098 | do_full_check = 1; | |
1099 | } | |
0b6782fa | 1100 | |
90485650 | 1101 | if (do_full_check && dev_is_md_component(cmd, dev, NULL, 1)) { |
0b6782fa | 1102 | log_print_pvscan(cmd, "ignore md component %s.", dev_name(dev)); |
f3b723cd DT |
1103 | release_vg(vg); |
1104 | continue; | |
1105 | } | |
1106 | ||
1107 | if (vg_is_shared(vg)) { | |
0b6782fa | 1108 | log_print_pvscan(cmd, "PV %s ignore shared VG.", dev_name(dev)); |
f3b723cd DT |
1109 | release_vg(vg); |
1110 | continue; | |
1111 | } | |
1112 | ||
1113 | if (vg->system_id && vg->system_id[0] && | |
1114 | cmd->system_id && cmd->system_id[0] && | |
1115 | vg_is_foreign(vg)) { | |
1116 | log_verbose("Ignore PV %s with VG system id %s with our system id %s", | |
1117 | dev_name(dev), vg->system_id, cmd->system_id); | |
0b6782fa DT |
1118 | log_print_pvscan(cmd, "PV %s ignore foreign VG.", dev_name(dev)); |
1119 | release_vg(vg); | |
1120 | continue; | |
1121 | } | |
1122 | ||
1123 | if (vg_is_exported(vg)) { | |
1124 | log_print_pvscan(cmd, "PV %s ignore exported VG.", dev_name(dev)); | |
f3b723cd DT |
1125 | release_vg(vg); |
1126 | continue; | |
1127 | } | |
1128 | ||
1129 | /* | |
1130 | * online file phase | |
1131 | * create pvs_online/<pvid> | |
1132 | * check if vg is complete: stat pvs_online/<pvid> for each vg->pvs | |
1133 | * if vg is complete, save vg name in list for activation phase | |
1134 | * if vg not complete, create pvs_lookup/<vgname> listing all pvids from vg->pvs | |
1135 | * (only if pvs_lookup/<vgname> does not yet exist) | |
1136 | * if no vg metadata, read pvs_lookup files for pvid, use that list to check if complete | |
1137 | */ | |
1138 | online: | |
1139 | (*pv_count)++; | |
1140 | ||
1141 | /* | |
1142 | * Create file named for pvid to record this PV is online. | |
0b6782fa | 1143 | * The command creates/checks online files only when --cache is used. |
f3b723cd | 1144 | */ |
f40fd883 | 1145 | if (do_cache && !online_pvid_file_create(cmd, dev, vg ? vg->name : NULL)) { |
0b6782fa | 1146 | log_error_pvscan(cmd, "PV %s failed to create online file.", dev_name(dev)); |
f3b723cd DT |
1147 | release_vg(vg); |
1148 | ret = 0; | |
1149 | continue; | |
1150 | } | |
1151 | ||
1152 | /* | |
0b6782fa | 1153 | * A plain pvscan --cache <dev> just creates the online file. |
f3b723cd | 1154 | */ |
0b6782fa DT |
1155 | if (!do_activate && !do_list_lvs && !do_list_vg) { |
1156 | log_print_pvscan(cmd, "PV %s online.", dev_name(dev)); | |
f3b723cd DT |
1157 | release_vg(vg); |
1158 | continue; | |
1159 | } | |
1160 | ||
1161 | /* | |
1162 | * Check if all the PVs for this VG are online. If the arrival | |
1163 | * of this dev completes the VG, then save the vgname in | |
0b6782fa DT |
1164 | * complete_vgnames (activation phase will want to know which |
1165 | * VGs to activate.) | |
f3b723cd | 1166 | */ |
0b6782fa DT |
1167 | if (do_activate || do_check_complete) { |
1168 | pvs_online = 0; | |
1169 | pvs_offline = 0; | |
1170 | pvs_unknown = 0; | |
1171 | vg_complete = 0; | |
f3b723cd | 1172 | |
0b6782fa DT |
1173 | if (vg) { |
1174 | /* | |
5dbf316c DT |
1175 | * Check if the VG is complete by checking that |
1176 | * pvs_online/<pvid> files exist for all vg->pvs. | |
0b6782fa DT |
1177 | */ |
1178 | log_debug("checking all pvid files from vg %s", vg->name); | |
f3b723cd | 1179 | _count_pvid_files(vg, &pvs_online, &pvs_offline); |
5dbf316c DT |
1180 | |
1181 | /* | |
1182 | * When there is more than one PV in the VG, write | |
1183 | * /run/lvm/pvs_lookup/<vgname> with a list of PVIDs in | |
1184 | * the VG. This is used in case a later PV comes | |
1185 | * online that has no metadata, in which case pvscan | |
1186 | * for that PV needs to use the lookup file to check if | |
1187 | * the VG is complete. The lookup file is also used by | |
1188 | * vgchange -aay --autoactivation event <vgname> | |
1189 | * to check if all pvs_online files for the VG exist. | |
1190 | * | |
1191 | * For multiple concurrent pvscan's, they will race to | |
1192 | * create the lookup file and the first will succeed. | |
1193 | * | |
1194 | * After writing the lookup file, recheck pvid files to | |
1195 | * resolve a possible race with another pvscan reading | |
1196 | * the lookup file that missed it. | |
1197 | */ | |
1198 | if (dm_list_size(&vg->pvs) > 1) { | |
1199 | if (_write_lookup_file(cmd, vg)) { | |
1200 | if (pvs_offline) { | |
1201 | log_debug("rechecking all pvid files from vg %s", vg->name); | |
1202 | _count_pvid_files(vg, &pvs_online, &pvs_offline); | |
1203 | if (!pvs_offline) | |
1204 | log_print_pvscan(cmd, "VG %s complete after recheck.", vg->name); | |
1205 | } | |
1206 | } | |
0b6782fa | 1207 | } |
0b6782fa DT |
1208 | vgname = vg->name; |
1209 | } else { | |
1210 | /* | |
1211 | * No VG metadata on this PV, so try to use a lookup | |
1212 | * file written by a prior pvscan for a list of all | |
1213 | * PVIDs. A lookup file may not exist for this PV if | |
1214 | * it's the first to appear from the VG. | |
1215 | */ | |
1216 | log_debug("checking all pvid files from lookup file"); | |
1217 | if (!_count_pvid_files_from_lookup_file(cmd, dev, &pvs_online, &pvs_offline, &vgname)) | |
1218 | pvs_unknown = 1; | |
1219 | } | |
1220 | ||
1221 | if (pvs_unknown) { | |
1222 | log_print_pvscan(cmd, "PV %s online, VG unknown.", dev_name(dev)); | |
1223 | vg_complete = 0; | |
1224 | ||
1225 | } else if (pvs_offline) { | |
1226 | log_print_pvscan(cmd, "PV %s online, VG %s incomplete (need %d).", | |
1227 | dev_name(dev), vgname, pvs_offline); | |
1228 | vg_complete = 0; | |
1229 | ||
1230 | } else { | |
1231 | log_print_pvscan(cmd, "PV %s online, VG %s is complete.", dev_name(dev), vgname); | |
1232 | if (!str_list_add(cmd->mem, complete_vgnames, dm_pool_strdup(cmd->mem, vgname))) | |
1233 | stack; | |
1234 | vg_complete = 1; | |
f3b723cd | 1235 | } |
0b6782fa | 1236 | } |
f3b723cd | 1237 | |
0b6782fa | 1238 | if (!vgname && vg) |
f3b723cd | 1239 | vgname = vg->name; |
0b6782fa DT |
1240 | |
1241 | if (do_list_vg || do_list_lvs) { | |
1242 | if (!vgname) { | |
1243 | log_print("VG unknown"); | |
1244 | } else if (!do_check_complete) { | |
1245 | log_print("VG %s", vgname); | |
1246 | } else if (vg_complete) { | |
f40fd883 | 1247 | if (do_vgonline && !online_vg_file_create(cmd, vgname)) { |
0b6782fa DT |
1248 | log_print("VG %s finished", vgname); |
1249 | } else { | |
1250 | /* | |
1251 | * A udev rule imports KEY=val from a program's stdout. | |
1252 | * Other output causes udev to ignore everything. | |
1253 | * Run pvscan from udev rule using --udevoutput to | |
1254 | * enable this printf, and suppress all log output | |
1255 | */ | |
1256 | if (arg_is_set(cmd, udevoutput_ARG)) | |
1257 | printf("LVM_VG_NAME_COMPLETE='%s'\n", vgname); | |
1258 | else | |
1259 | log_print("VG %s complete", vgname); | |
1260 | } | |
1261 | } else { | |
1262 | if (arg_is_set(cmd, udevoutput_ARG)) | |
1263 | printf("LVM_VG_NAME_INCOMPLETE='%s'\n", vgname); | |
1264 | else | |
1265 | log_print("VG %s incomplete", vgname); | |
1266 | } | |
1267 | ||
f3b723cd | 1268 | /* |
0b6782fa DT |
1269 | * When the VG is complete|finished, we could print |
1270 | * a list of devices in the VG, by reading the pvid files | |
1271 | * that were counted, which provides major:minor of each | |
1272 | * device and using that to get the struct dev and dev_name. | |
1273 | * The user could pass this list of devices to --devices | |
1274 | * to optimize a subsequent command (activation) on the VG. | |
1275 | * Just call set_pv_devices_online (if not done othewise) | |
1276 | * since that finds the devs. | |
f3b723cd | 1277 | */ |
f3b723cd | 1278 | } |
db741e75 | 1279 | |
0b6782fa DT |
1280 | if (do_list_lvs && !vg) { |
1281 | /* require all PVs used for booting have metadata */ | |
1282 | log_print_pvscan(cmd, "Cannot list LVs from device without metadata."); | |
1283 | } | |
1284 | ||
1285 | if (do_list_lvs && vg) { | |
1286 | struct dm_list lvs_list; | |
1287 | struct lv_list *lvl; | |
1288 | ||
1289 | dm_list_init(&lvs_list); | |
1290 | ||
1291 | /* | |
1292 | * For each vg->pvs entry, get the dev based on the online file | |
1293 | * for the pvid and set pv->dev or pv->status MISSING_PV. | |
1294 | */ | |
1295 | _set_pv_devices_online(cmd, vg); | |
1296 | ||
1297 | /* | |
1298 | * lvs_list are LVs that use dev. | |
1299 | */ | |
1300 | if (!get_visible_lvs_using_pv(cmd, vg, dev, &lvs_list)) | |
1301 | log_print_pvscan(cmd, "Failed to find LVs using %s.", dev_name(dev)); | |
1302 | ||
1303 | if (!do_check_complete) { | |
1304 | dm_list_iterate_items(lvl, &lvs_list) | |
1305 | log_print("LV %s", display_lvname(lvl->lv)); | |
1306 | } else if (vg_complete) { | |
1307 | /* | |
1308 | * A shortcut; the vg complete implies all lvs are complete. | |
1309 | */ | |
1310 | dm_list_iterate_items(lvl, &lvs_list) | |
1311 | log_print("LV %s complete", display_lvname(lvl->lv)); | |
1312 | } else { | |
1313 | /* | |
1314 | * For each LV in VG, check if all devs are present. | |
1315 | * Sets the PARTIAL flag on LVs that are not complete. | |
1316 | */ | |
1317 | if (!vg_mark_partial_lvs(vg, 1)) | |
1318 | log_print_pvscan(cmd, "Failed to check partial lvs."); | |
1319 | ||
1320 | dm_list_iterate_items(lvl, &lvs_list) { | |
1321 | if (!lv_is_partial(lvl->lv)) | |
1322 | log_print("LV %s complete", display_lvname(lvl->lv)); | |
1323 | else | |
1324 | log_print("LV %s incomplete", display_lvname(lvl->lv)); | |
1325 | } | |
1326 | } | |
db741e75 | 1327 | } |
f3b723cd | 1328 | |
0b6782fa DT |
1329 | /* |
1330 | * When "pvscan --cache -aay <dev>" completes the vg, save the | |
1331 | * struct vg to use for quick activation function. | |
1332 | */ | |
1333 | if (do_activate && !saved_vg && vg && vg_complete && !do_all && (dm_list_size(pvscan_devs) == 1)) | |
f3b723cd DT |
1334 | saved_vg = vg; |
1335 | else | |
1336 | release_vg(vg); | |
417724ef | 1337 | } |
db741e75 | 1338 | |
f3b723cd DT |
1339 | return ret; |
1340 | } | |
1341 | ||
1342 | static int _pvscan_cache_all(struct cmd_context *cmd, int argc, char **argv, | |
1343 | struct dm_list *complete_vgnames) | |
1344 | { | |
1345 | struct dm_list pvscan_devs; | |
1346 | struct dev_iter *iter; | |
1347 | struct device_list *devl; | |
1348 | struct device *dev; | |
1349 | int pv_count = 0; | |
1350 | ||
1351 | dm_list_init(&pvscan_devs); | |
1352 | ||
f40fd883 DT |
1353 | _online_files_remove(PVS_ONLINE_DIR); |
1354 | _online_files_remove(VGS_ONLINE_DIR); | |
1355 | _online_files_remove(PVS_LOOKUP_DIR); | |
f3b723cd | 1356 | |
83fe6e72 DT |
1357 | unlink_searched_devnames(cmd); |
1358 | ||
417724ef | 1359 | /* |
f3b723cd DT |
1360 | * pvscan --cache removes existing hints and recreates new ones. |
1361 | * We begin by clearing hints at the start of the command. | |
1362 | * The pvscan_recreate_hints flag is used to enable the | |
1363 | * special case hint recreation in label_scan. | |
417724ef | 1364 | */ |
f3b723cd DT |
1365 | cmd->pvscan_recreate_hints = 1; |
1366 | pvscan_recreate_hints_begin(cmd); | |
417724ef | 1367 | |
f3b723cd | 1368 | log_debug("pvscan_cache_all: label scan all"); |
417724ef | 1369 | |
f3b723cd DT |
1370 | /* |
1371 | * use lvmcache_label_scan() instead of just label_scan_devs() | |
1372 | * because label_scan() has the ability to update hints, | |
1373 | * which we want 'pvscan --cache' to do, and that uses | |
1374 | * info from lvmcache, e.g. duplicate pv info. | |
1375 | */ | |
92b4fcf5 DT |
1376 | if (!lvmcache_label_scan(cmd)) |
1377 | return_0; | |
f3b723cd DT |
1378 | |
1379 | cmd->pvscan_recreate_hints = 0; | |
1380 | cmd->use_hints = 0; | |
1381 | ||
1382 | log_debug("pvscan_cache_all: create list of devices"); | |
1383 | ||
1384 | /* | |
1385 | * The use of filter here will just reuse the existing | |
1386 | * (persistent) filter info label_scan has already set up. | |
1387 | */ | |
f8aa073a | 1388 | if (!(iter = dev_iter_create(cmd->filter, 1))) |
f3b723cd | 1389 | return_0; |
417724ef | 1390 | |
f3b723cd DT |
1391 | while ((dev = dev_iter_get(cmd, iter))) { |
1392 | if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl)))) { | |
1393 | dev_iter_destroy(iter); | |
1394 | return_0; | |
1395 | } | |
1396 | devl->dev = dev; | |
1397 | dm_list_add(&pvscan_devs, &devl->list); | |
db741e75 | 1398 | } |
f3b723cd | 1399 | dev_iter_destroy(iter); |
db741e75 | 1400 | |
f3b723cd DT |
1401 | _online_devs(cmd, 1, &pvscan_devs, &pv_count, complete_vgnames); |
1402 | ||
1403 | return 1; | |
1404 | } | |
1405 | ||
1406 | static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv, | |
1407 | struct dm_list *complete_vgnames) | |
1408 | { | |
1409 | struct dm_list pvscan_args; /* struct pvscan_arg */ | |
1410 | struct dm_list pvscan_devs; /* struct device_list */ | |
1411 | struct pvscan_arg *arg; | |
1412 | struct device_list *devl, *devl2; | |
83fe6e72 | 1413 | int relax_deviceid_filter = 0; |
f3b723cd DT |
1414 | int pv_count = 0; |
1415 | int ret; | |
1416 | ||
1417 | dm_list_init(&pvscan_args); | |
1418 | dm_list_init(&pvscan_devs); | |
1419 | ||
594f6ca9 | 1420 | cmd->expect_missing_vg_device = 1; |
f3b723cd | 1421 | |
d0ab5bf7 | 1422 | /* |
33e47182 DT |
1423 | * Special pvscan-specific setup steps to avoid looking |
1424 | * at any devices except for device args. | |
1425 | * Read devices file and determine if devices file will be used. | |
1426 | * Does not do dev_cache_scan (adds nothing to dev-cache), and | |
1427 | * does not do any device id matching. | |
d0ab5bf7 | 1428 | */ |
62533ae3 | 1429 | if (!setup_devices_for_online_autoactivation(cmd)) { |
0b6782fa | 1430 | log_error_pvscan(cmd, "Failed to set up devices."); |
5f7a7af7 | 1431 | return 0; |
83fe6e72 | 1432 | } |
417724ef DT |
1433 | |
1434 | /* | |
f3b723cd | 1435 | * Get list of args. Do not use filters. |
417724ef | 1436 | */ |
f3b723cd DT |
1437 | if (!_get_args(cmd, argc, argv, &pvscan_args)) |
1438 | return_0; | |
417724ef DT |
1439 | |
1440 | /* | |
f3b723cd | 1441 | * Get list of devs for args. Do not use filters. |
417724ef | 1442 | */ |
f3b723cd DT |
1443 | if (!_get_args_devs(cmd, &pvscan_args, &pvscan_devs)) |
1444 | return_0; | |
db741e75 | 1445 | |
f3b723cd DT |
1446 | /* |
1447 | * Remove pvid online files for major/minor args for which the dev has | |
1448 | * been removed. | |
1449 | */ | |
1450 | dm_list_iterate_items(arg, &pvscan_args) { | |
1451 | if (arg->dev || !arg->devno) | |
1452 | continue; | |
85e06366 | 1453 | _online_pvid_file_remove_devno(MAJOR(arg->devno), MINOR(arg->devno)); |
f3b723cd | 1454 | } |
db741e75 | 1455 | |
f3b723cd DT |
1456 | /* |
1457 | * A common pvscan removal of a single dev is done here. | |
1458 | */ | |
1459 | if (dm_list_empty(&pvscan_devs)) | |
1460 | return 1; | |
1461 | ||
1462 | if (cmd->md_component_detection && !cmd->use_full_md_check && | |
1463 | !strcmp(cmd->md_component_checks, "auto") && | |
f8aa073a | 1464 | dev_cache_has_md_with_end_superblock(cmd->dev_types)) { |
f3b723cd DT |
1465 | log_debug("Enable full md component check."); |
1466 | cmd->use_full_md_check = 1; | |
1467 | } | |
db741e75 | 1468 | |
f3b723cd DT |
1469 | /* |
1470 | * Apply nodata filters. | |
83fe6e72 DT |
1471 | * |
1472 | * We want pvscan autoactivation to work when using a devices file | |
1473 | * containing idtype=devname, in cases when the devname changes | |
1474 | * after reboot. To make this work, we have to relax the devices | |
1475 | * file restrictions somewhat here in cases where the devices file | |
1476 | * contains entries with idtype=devname: disable filter-deviceid | |
1477 | * when applying the nodata filters here, and read the label header. | |
1478 | * Once the label header is read, check if the label header pvid | |
1479 | * is in the devices file, and ignore the device if it's not. | |
1480 | * The downside of this is that pvscans from the system will read | |
1481 | * devs belonging to other devices files. | |
1482 | * Enable/disable this behavior with a config setting? | |
f3b723cd | 1483 | */ |
83fe6e72 | 1484 | |
f3b723cd DT |
1485 | log_debug("pvscan_cache_args: filter devs nodata"); |
1486 | ||
d0ab5bf7 | 1487 | /* |
33e47182 DT |
1488 | * Match dev args with the devices file because special/optimized |
1489 | * device setup was used above which does not check the devices file. | |
1490 | * If a match fails here do not exclude it, that will be done below by | |
1491 | * passes_filter() which runs filter-deviceid. The | |
1492 | * relax_deviceid_filter case needs to be able to work around | |
88aa285a DT |
1493 | * unmatching devs, or unmatching product_uuid/hostname which means |
1494 | * we can ignore the device ID and use any device with a PVID listed | |
1495 | * in system.devices. | |
d0ab5bf7 | 1496 | */ |
33e47182 | 1497 | |
d0ab5bf7 | 1498 | if (cmd->enable_devices_file) { |
33e47182 | 1499 | dm_list_iterate_items(devl, &pvscan_devs) |
d0ab5bf7 DT |
1500 | device_ids_match_dev(cmd, devl->dev); |
1501 | } | |
33e47182 DT |
1502 | if (cmd->enable_devices_list) |
1503 | device_ids_match_device_list(cmd); | |
d0ab5bf7 | 1504 | |
88aa285a DT |
1505 | if (cmd->enable_devices_file && |
1506 | (device_ids_use_devname(cmd) || cmd->device_ids_refresh_trigger)) { | |
83fe6e72 DT |
1507 | relax_deviceid_filter = 1; |
1508 | cmd->filter_deviceid_skip = 1; | |
1509 | } | |
1510 | ||
f3b723cd | 1511 | cmd->filter_nodata_only = 1; |
5f102b34 | 1512 | |
17a3585c DT |
1513 | /* |
1514 | * Hack to handle regex filter that contains a symlink name for dev arg. | |
1515 | * pvscan --cache <dev> is called by our udev rule at a time when the | |
1516 | * symlinks for <dev> may not all be created yet (by other udev rules.) | |
1517 | * The regex filter in lvm.conf may refer to <dev> using a symlink name, | |
1518 | * so we need to know all the symlinks for <dev> in order for the filter | |
1519 | * to work correctly. Scanning /dev with dev_cache_scan() would usually | |
1520 | * find all the symlink names for <dev>, adding them to dev->aliases, | |
1521 | * which would let the filter work, but all symlinks aren't created yet. | |
1522 | * But, the DEVLINKS env var, set by udev, contains all the symlink | |
1523 | * names for <dev> that have been or *will be* created. So, we add all | |
1524 | * these symlink names to dev->aliases, as if we had found them in /dev. | |
1525 | * This allows <dev> to be recognized by a regex filter containing a | |
1526 | * symlink for <dev>. We have to tell filter-regex to not set the | |
1527 | * preferred name for <dev> to a symlink name since the <dev> may not | |
1528 | * be usable by that symlink name yet. | |
1529 | */ | |
1530 | if ((dm_list_size(&pvscan_devs) == 1) && | |
c9fdc828 | 1531 | !cmd->enable_devices_file && |
bd05318b | 1532 | !cmd->enable_devices_list) { |
17a3585c DT |
1533 | char *env_str; |
1534 | struct dm_list *env_aliases; | |
1535 | devl = dm_list_item(dm_list_first(&pvscan_devs), struct device_list); | |
1536 | if ((env_str = getenv("DEVLINKS"))) { | |
1537 | log_debug("Finding symlink names from DEVLINKS for filter regex."); | |
1538 | log_debug("DEVLINKS %s", env_str); | |
1539 | env_aliases = str_to_str_list(cmd->mem, env_str, " ", 0); | |
1540 | dm_list_splice(&devl->dev->aliases, env_aliases); | |
1541 | } else { | |
1542 | log_debug("Finding symlink names from /dev for filter regex."); | |
1543 | dev_cache_scan(cmd); | |
1544 | } | |
1545 | cmd->filter_regex_set_preferred_name_disable = 1; | |
1546 | } | |
1547 | ||
f3b723cd DT |
1548 | dm_list_iterate_items_safe(devl, devl2, &pvscan_devs) { |
1549 | if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL)) { | |
8db3b11e | 1550 | log_print_pvscan(cmd, "%s excluded: %s.", |
0b6782fa | 1551 | dev_name(devl->dev), dev_filtered_reason(devl->dev)); |
f3b723cd | 1552 | dm_list_del(&devl->list); |
db741e75 DT |
1553 | } |
1554 | } | |
1555 | ||
f3b723cd DT |
1556 | cmd->filter_nodata_only = 0; |
1557 | ||
1558 | /* | |
1559 | * Clear the results of nodata filters that were saved by the | |
1560 | * persistent filter so that the complete set of filters will | |
1561 | * be checked by passes_filter below. | |
1562 | */ | |
1563 | dm_list_iterate_items(devl, &pvscan_devs) | |
1564 | cmd->filter->wipe(cmd, cmd->filter, devl->dev, NULL); | |
1565 | ||
417724ef | 1566 | /* |
f3b723cd DT |
1567 | * Read header from each dev. |
1568 | * Eliminate non-lvm devs. | |
1569 | * Apply all filters. | |
417724ef | 1570 | */ |
f3b723cd DT |
1571 | |
1572 | log_debug("pvscan_cache_args: read and filter devs"); | |
1573 | ||
39e65c8f | 1574 | label_scan_setup_bcache(); |
f3b723cd DT |
1575 | |
1576 | dm_list_iterate_items_safe(devl, devl2, &pvscan_devs) { | |
4dc5d4ac DT |
1577 | int has_pvid; |
1578 | ||
1579 | if (!label_read_pvid(devl->dev, &has_pvid)) { | |
ae355ffc | 1580 | log_print_pvscan(cmd, "%s cannot read label.", dev_name(devl->dev)); |
4dc5d4ac DT |
1581 | dm_list_del(&devl->list); |
1582 | continue; | |
1583 | } | |
1584 | ||
1585 | if (!has_pvid) { | |
f3b723cd | 1586 | /* Not an lvm device */ |
0b6782fa | 1587 | log_print_pvscan(cmd, "%s not an lvm device.", dev_name(devl->dev)); |
f3b723cd DT |
1588 | dm_list_del(&devl->list); |
1589 | continue; | |
1590 | } | |
1591 | ||
83fe6e72 DT |
1592 | /* |
1593 | * filter-deviceid is not being used because of unstable devnames, | |
1594 | * so in place of that check if the pvid is in the devices file. | |
1595 | */ | |
1596 | if (relax_deviceid_filter) { | |
1597 | if (!get_du_for_pvid(cmd, devl->dev->pvid)) { | |
0b6782fa DT |
1598 | log_print_pvscan(cmd, "%s excluded by devices file (checking PVID).", |
1599 | dev_name(devl->dev)); | |
83fe6e72 DT |
1600 | dm_list_del(&devl->list); |
1601 | continue; | |
1602 | } | |
1603 | } | |
1604 | ||
f3b723cd DT |
1605 | /* Applies all filters, including those that need data from dev. */ |
1606 | if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL)) { | |
8db3b11e | 1607 | log_print_pvscan(cmd, "%s excluded: %s.", |
0b6782fa | 1608 | dev_name(devl->dev), dev_filtered_reason(devl->dev)); |
f3b723cd DT |
1609 | dm_list_del(&devl->list); |
1610 | } | |
417724ef DT |
1611 | } |
1612 | ||
83fe6e72 DT |
1613 | if (relax_deviceid_filter) |
1614 | cmd->filter_deviceid_skip = 0; | |
1615 | ||
f3b723cd DT |
1616 | if (dm_list_empty(&pvscan_devs)) |
1617 | return 1; | |
1618 | ||
1619 | log_debug("pvscan_cache_args: label scan devs"); | |
1620 | ||
1621 | /* | |
1622 | * Scan devs to populate lvmcache info, which includes the mda info that's | |
1623 | * needed to read vg metadata in the next step. The _cached variant of | |
1624 | * label_scan is used so the exsting bcache data from label_read_pvid above | |
1625 | * can be reused (although more data may need to be read depending on how | |
1626 | * much of the metadata was covered by reading the pvid.) | |
1627 | */ | |
1628 | label_scan_devs_cached(cmd, NULL, &pvscan_devs); | |
1629 | ||
1630 | ret = _online_devs(cmd, 0, &pvscan_devs, &pv_count, complete_vgnames); | |
1631 | ||
5f102b34 DT |
1632 | /* |
1633 | * When a new PV appears, the system runs pvscan --cache dev. | |
1634 | * This also means that existing hints are invalid, and | |
1635 | * we can force hints to be refreshed here. There may be | |
1636 | * cases where this detects a change that the other methods | |
1637 | * of detecting invalid hints doesn't catch. | |
1638 | */ | |
83fe6e72 | 1639 | if (pv_count) { |
5f102b34 | 1640 | invalidate_hints(cmd); |
83fe6e72 DT |
1641 | unlink_searched_devnames(cmd); |
1642 | } | |
5f102b34 | 1643 | |
f3b723cd DT |
1644 | return ret; |
1645 | } | |
1646 | ||
d558b3ad DT |
1647 | static int _get_autoactivation(struct cmd_context *cmd, int event_activation, int *skip_command) |
1648 | { | |
1649 | const char *aa_str; | |
1650 | ||
1651 | if (!(aa_str = arg_str_value(cmd, autoactivation_ARG, NULL))) | |
1652 | return 1; | |
1653 | ||
1654 | if (strcmp(aa_str, "event")) { | |
1655 | log_print_pvscan(cmd, "Skip pvscan for unknown autoactivation value."); | |
1656 | *skip_command = 1; | |
1657 | return 1; | |
1658 | } | |
1659 | ||
1660 | if (!event_activation) { | |
1661 | log_print_pvscan(cmd, "Skip pvscan for event with event_activation=0."); | |
1662 | *skip_command = 1; | |
1663 | return 1; | |
1664 | } | |
1665 | ||
1666 | return 1; | |
1667 | } | |
1668 | ||
f3b723cd DT |
1669 | int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) |
1670 | { | |
1671 | struct pvscan_aa_params pp = { 0 }; | |
1672 | struct dm_list complete_vgnames; | |
1673 | int do_activate = arg_is_set(cmd, activate_ARG); | |
e33c2e03 | 1674 | int event_activation; |
d558b3ad | 1675 | int skip_command = 0; |
f3b723cd DT |
1676 | int devno_args = 0; |
1677 | int do_all; | |
1678 | int ret; | |
1679 | ||
1680 | dm_list_init(&complete_vgnames); | |
1681 | ||
d5a06f9a DT |
1682 | cmd->check_devs_used = 0; |
1683 | ||
d3d6a0e8 DT |
1684 | cmd->print_device_id_not_found = 0; |
1685 | ||
87714a13 DT |
1686 | cmd->ignore_device_name_mismatch = 1; |
1687 | ||
e33c2e03 DT |
1688 | event_activation = find_config_tree_bool(cmd, global_event_activation_CFG, NULL); |
1689 | ||
1690 | if (do_activate && !event_activation) { | |
1691 | log_verbose("Ignoring pvscan --cache -aay because event_activation is disabled."); | |
1692 | return ECMD_PROCESSED; | |
1693 | } | |
1694 | ||
0b6782fa DT |
1695 | /* |
1696 | * lvm udev rules call: | |
1697 | * pvscan --cache --listvg|--listlvs --checkcomplete PV | |
1698 | * when PVs appear, even if event_activation=0 in lvm.conf. | |
1699 | * | |
1700 | * The udev rules will do autoactivation if they see complete | |
1701 | * VGs/LVs reported from the pvscan. | |
1702 | * | |
1703 | * When event_activation=0 we do not want to do autoactivation | |
1704 | * from udev events, so we need the pvscan to not report any | |
1705 | * complete VGs/LVs when event_activation=0 so that the udev | |
1706 | * rules do not attempt to autoactivate. | |
1707 | */ | |
1708 | ||
1709 | if (arg_is_set(cmd, checkcomplete_ARG) && !event_activation) { | |
1710 | if (arg_is_set(cmd, udevoutput_ARG)) | |
1711 | printf("LVM_EVENT_ACTIVATION=0\n"); | |
1712 | else | |
1713 | log_print_pvscan(cmd, "Ignoring pvscan with --checkcomplete because event_activation is disabled."); | |
1714 | return ECMD_PROCESSED; | |
1715 | } | |
1716 | ||
1717 | /* | |
c7a5b5cc DT |
1718 | * Do not use udev for device listing or device info because pvscan |
1719 | * is used to populate udev info. | |
0b6782fa DT |
1720 | */ |
1721 | init_obtain_device_list_from_udev(0); | |
c7a5b5cc | 1722 | init_external_device_info_source(DEV_EXT_NONE); |
0b6782fa | 1723 | |
f3b723cd DT |
1724 | if (arg_is_set(cmd, major_ARG) + arg_is_set(cmd, minor_ARG)) |
1725 | devno_args = 1; | |
1726 | ||
1727 | if (devno_args && (!arg_is_set(cmd, major_ARG) || !arg_is_set(cmd, minor_ARG))) { | |
1728 | log_error("Both --major and --minor required to identify devices."); | |
1729 | return EINVALID_CMD_LINE; | |
1730 | } | |
1731 | ||
1732 | do_all = !argc && !devno_args; | |
1733 | ||
f40fd883 | 1734 | online_dir_setup(cmd); |
f3b723cd DT |
1735 | |
1736 | if (do_all) { | |
1737 | if (!_pvscan_cache_all(cmd, argc, argv, &complete_vgnames)) | |
1738 | return ECMD_FAILED; | |
1739 | } else { | |
0b6782fa | 1740 | if (!arg_is_set(cmd, checkcomplete_ARG) && !event_activation) { |
e33c2e03 DT |
1741 | /* Avoid doing anything for device removal: pvscan --cache <devno> */ |
1742 | log_verbose("Ignoring pvscan --cache because event_activation is disabled."); | |
1743 | return ECMD_PROCESSED; | |
1744 | } | |
d558b3ad DT |
1745 | |
1746 | if (!_get_autoactivation(cmd, event_activation, &skip_command)) | |
1747 | return_ECMD_FAILED; | |
1748 | ||
1749 | if (skip_command) | |
1750 | return ECMD_PROCESSED; | |
1751 | ||
f3b723cd DT |
1752 | if (!_pvscan_cache_args(cmd, argc, argv, &complete_vgnames)) |
1753 | return ECMD_FAILED; | |
1754 | } | |
1755 | ||
1756 | if (!do_activate) | |
1757 | return ECMD_PROCESSED; | |
1758 | ||
1759 | if (dm_list_empty(&complete_vgnames)) { | |
1760 | log_debug("No VGs to autoactivate."); | |
1761 | return ECMD_PROCESSED; | |
1762 | } | |
db741e75 DT |
1763 | |
1764 | /* | |
f3b723cd DT |
1765 | * When the PV was recorded online, we check if all the PVs for the VG |
1766 | * are online. If so, the vgname was added to the list, and we can | |
1767 | * attempt to autoactivate LVs in the VG. | |
db741e75 | 1768 | */ |
f3b723cd | 1769 | ret = _pvscan_aa(cmd, &pp, do_all, &complete_vgnames); |
db741e75 | 1770 | |
f3b723cd | 1771 | if (pp.activate_errors) |
db741e75 DT |
1772 | ret = ECMD_FAILED; |
1773 | ||
1774 | if (!sync_local_dev_names(cmd)) | |
1775 | stack; | |
db741e75 DT |
1776 | return ret; |
1777 | } | |
1778 | ||
117160b2 DT |
1779 | int pvscan(struct cmd_context *cmd, int argc, char **argv) |
1780 | { | |
1781 | log_error(INTERNAL_ERROR "Missing function for command definition %d:%s.", | |
bebbb1e6 | 1782 | cmd->command->command_index, command_enum(cmd->command->command_enum)); |
117160b2 DT |
1783 | return ECMD_FAILED; |
1784 | } | |
1785 |