1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3 * This file and its contents are supplied under the terms of the
4 * Common Development and Distribution License ("CDDL"), version 1.0.
5 * You may only use this file in accordance with the terms of version
6 * 1.0 of the CDDL.
7 *
8 * A full copy of the text of the CDDL should have accompanied this
9 * source. A copy of the CDDL is also available via the Internet at
10 * https://opensource.org/license/CDDL-1.0.
11 */
12 /*
13 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
14 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
15 * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
16 * Copyright 2015 RackTop Systems.
17 * Copyright (c) 2016, Intel Corporation.
18 */
19
20 /*
21 * Pool import support functions.
22 *
23 * Used by zpool, ztest, zdb, and zhack to locate importable configs. Since
24 * these commands are expected to run in the global zone, we can assume
25 * that the devices are all readable when called.
26 *
27 * To import a pool, we rely on reading the configuration information from the
28 * ZFS label of each device. If we successfully read the label, then we
29 * organize the configuration information in the following hierarchy:
30 *
31 * pool guid -> toplevel vdev guid -> label txg
32 *
33 * Duplicate entries matching this same tuple will be discarded. Once we have
34 * examined every device, we pick the best label txg config for each toplevel
35 * vdev. We then arrange these toplevel vdevs into a complete pool config, and
36 * update any paths that have changed. Finally, we attempt to import the pool
37 * using our derived config, and record the results.
38 */
39
40 #include <ctype.h>
41 #include <dirent.h>
42 #include <errno.h>
43 #include <libintl.h>
44 #include <libgen.h>
45 #include <stddef.h>
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <sys/stat.h>
50 #include <unistd.h>
51 #include <fcntl.h>
52 #include <sys/dktp/fdisk.h>
53 #include <sys/vdev_impl.h>
54 #include <sys/fs/zfs.h>
55
56 #include <libzutil.h>
57 #include <libnvpair.h>
58 #include <libzfs.h>
59
60 #include "zutil_import.h"
61
62 #ifdef HAVE_LIBUDEV
63 #include <libudev.h>
64 #include <sched.h>
65 #endif
66 #include <blkid/blkid.h>
67
68 #define DEV_BYID_PATH "/dev/disk/by-id/"
69
70 /*
71 * Skip devices with well known prefixes:
72 * there can be side effects when opening devices which need to be avoided.
73 *
74 * hpet - High Precision Event Timer
75 * watchdog[N] - Watchdog must be closed in a special way.
76 */
77 static boolean_t
should_skip_dev(const char * dev)78 should_skip_dev(const char *dev)
79 {
80 return ((strcmp(dev, "watchdog") == 0) ||
81 (strncmp(dev, "watchdog", 8) == 0 && isdigit(dev[8])) ||
82 (strcmp(dev, "hpet") == 0));
83 }
84
85 /*
86 * Common predicate for zpool_dev_probe_ok() and its fd variant: only a
87 * block device, or a regular file large enough to hold a label, may be
88 * probed. Anything else is refused.
89 */
90 static boolean_t
dev_stat_probe_ok(const struct stat64 * statbuf)91 dev_stat_probe_ok(const struct stat64 *statbuf)
92 {
93 return (S_ISBLK(statbuf->st_mode) ||
94 (S_ISREG(statbuf->st_mode) && statbuf->st_size >= SPA_MINDEVSIZE));
95 }
96
97 /*
98 * Determine if a path may be safely opened to probe for a vdev label.
99 * Only regular files large enough to hold a label and block devices are
100 * acceptable. Anything else is refused: opening other device nodes can
101 * have side effects (e.g. arming a watchdog) and opening a FIFO blocks
102 * indefinitely. stat64() never blocks, even on a FIFO.
103 */
104 boolean_t
zpool_dev_probe_ok(const char * path)105 zpool_dev_probe_ok(const char *path)
106 {
107 struct stat64 statbuf;
108
109 if (should_skip_dev(zfs_basename(path)))
110 return (B_FALSE);
111
112 /* Ignore failed stats. */
113 if (stat64(path, &statbuf) != 0)
114 return (B_FALSE);
115
116 return (dev_stat_probe_ok(&statbuf));
117 }
118
119 /*
120 * As zpool_dev_probe_ok(), but re-check the type of an object already
121 * opened. A path naming a symlink may have been repointed at a different
122 * node between the stat64() above and the open(), so only trust a
123 * descriptor which is still a block device or a large enough regular file.
124 */
125 boolean_t
zpool_dev_probe_ok_fd(int fd)126 zpool_dev_probe_ok_fd(int fd)
127 {
128 struct stat64 statbuf;
129
130 if (fstat64(fd, &statbuf) != 0)
131 return (B_FALSE);
132
133 return (dev_stat_probe_ok(&statbuf));
134 }
135
136 int
zfs_dev_flush(int fd)137 zfs_dev_flush(int fd)
138 {
139 return (ioctl(fd, BLKFLSBUF));
140 }
141
142 void
zpool_open_func(void * arg)143 zpool_open_func(void *arg)
144 {
145 rdsk_node_t *rn = arg;
146 libpc_handle_t *hdl = rn->rn_hdl;
147 nvlist_t *config;
148 uint64_t vdev_guid = 0;
149 int error;
150 int num_labels = 0;
151 int fd;
152
153 if (!zpool_dev_probe_ok(rn->rn_name))
154 return;
155
156 /*
157 * Preferentially open using O_DIRECT to bypass the block device
158 * cache which may be stale for multipath devices. An EINVAL errno
159 * indicates O_DIRECT is unsupported so fallback to just O_RDONLY.
160 */
161 fd = open(rn->rn_name, O_RDONLY | O_DIRECT | O_CLOEXEC);
162 if ((fd < 0) && (errno == EINVAL))
163 fd = open(rn->rn_name, O_RDONLY | O_CLOEXEC);
164 if ((fd < 0) && (errno == EACCES))
165 hdl->lpc_open_access_error = B_TRUE;
166 if (fd < 0)
167 return;
168
169 error = zpool_read_label(fd, &config, &num_labels);
170 if (error != 0) {
171 (void) close(fd);
172 return;
173 }
174
175 if (num_labels == 0) {
176 (void) close(fd);
177 nvlist_free(config);
178 return;
179 }
180
181 /*
182 * Check that the vdev is for the expected guid. Additional entries
183 * are speculatively added based on the paths stored in the labels.
184 * Entries with valid paths but incorrect guids must be removed.
185 */
186 error = nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, &vdev_guid);
187 if (error || (rn->rn_vdev_guid && rn->rn_vdev_guid != vdev_guid)) {
188 (void) close(fd);
189 nvlist_free(config);
190 return;
191 }
192
193 (void) close(fd);
194
195 rn->rn_config = config;
196 rn->rn_num_labels = num_labels;
197
198 /*
199 * Add additional entries for paths described by this label.
200 */
201 if (rn->rn_labelpaths) {
202 const char *path = NULL;
203 const char *devid = NULL;
204 rdsk_node_t *slice;
205 avl_index_t where;
206 int error;
207
208 if (label_paths(rn->rn_hdl, rn->rn_config, &path, &devid))
209 return;
210
211 /*
212 * Allow devlinks to stabilize so all paths are available.
213 */
214 zpool_disk_wait(rn->rn_name);
215
216 if (path != NULL) {
217 slice = zutil_alloc(hdl, sizeof (rdsk_node_t));
218 slice->rn_name = zutil_strdup(hdl, path);
219 slice->rn_vdev_guid = vdev_guid;
220 slice->rn_avl = rn->rn_avl;
221 slice->rn_hdl = hdl;
222 slice->rn_order = IMPORT_ORDER_PREFERRED_1;
223 slice->rn_labelpaths = B_FALSE;
224 pthread_mutex_lock(rn->rn_lock);
225 if (avl_find(rn->rn_avl, slice, &where)) {
226 pthread_mutex_unlock(rn->rn_lock);
227 free(slice->rn_name);
228 free(slice);
229 } else {
230 avl_insert(rn->rn_avl, slice, where);
231 pthread_mutex_unlock(rn->rn_lock);
232 zpool_open_func(slice);
233 }
234 }
235
236 if (devid != NULL) {
237 slice = zutil_alloc(hdl, sizeof (rdsk_node_t));
238 error = asprintf(&slice->rn_name, "%s%s",
239 DEV_BYID_PATH, devid);
240 if (error == -1) {
241 free(slice);
242 return;
243 }
244
245 slice->rn_vdev_guid = vdev_guid;
246 slice->rn_avl = rn->rn_avl;
247 slice->rn_hdl = hdl;
248 slice->rn_order = IMPORT_ORDER_PREFERRED_2;
249 slice->rn_labelpaths = B_FALSE;
250 pthread_mutex_lock(rn->rn_lock);
251 if (avl_find(rn->rn_avl, slice, &where)) {
252 pthread_mutex_unlock(rn->rn_lock);
253 free(slice->rn_name);
254 free(slice);
255 } else {
256 avl_insert(rn->rn_avl, slice, where);
257 pthread_mutex_unlock(rn->rn_lock);
258 zpool_open_func(slice);
259 }
260 }
261 }
262 }
263
264 static const char * const
265 zpool_default_import_path[] = {
266 "/dev/disk/by-vdev", /* Custom rules, use first if they exist */
267 "/dev/mapper", /* Use multipath devices before components */
268 "/dev/disk/by-partlabel", /* Single unique entry set by user */
269 "/dev/disk/by-partuuid", /* Generated partition uuid */
270 "/dev/disk/by-label", /* Custom persistent labels */
271 "/dev/disk/by-uuid", /* Single unique entry and persistent */
272 "/dev/disk/by-id", /* May be multiple entries and persistent */
273 "/dev/disk/by-path", /* Encodes physical location and persistent */
274 "/dev" /* UNSAFE device names will change */
275 };
276
277 const char * const *
zpool_default_search_paths(size_t * count)278 zpool_default_search_paths(size_t *count)
279 {
280 *count = ARRAY_SIZE(zpool_default_import_path);
281 return (zpool_default_import_path);
282 }
283
284 /*
285 * Given a full path to a device determine if that device appears in the
286 * import search path. If it does return the first match and store the
287 * index in the passed 'order' variable, otherwise return an error.
288 */
289 static int
zfs_path_order(const char * name,int * order)290 zfs_path_order(const char *name, int *order)
291 {
292 const char *env = getenv("ZPOOL_IMPORT_PATH");
293
294 if (env) {
295 for (int i = 0; ; ++i) {
296 env += strspn(env, ":");
297 size_t dirlen = strcspn(env, ":");
298 if (dirlen) {
299 if (strncmp(name, env, dirlen) == 0) {
300 *order = i;
301 return (0);
302 }
303
304 env += dirlen;
305 } else
306 break;
307 }
308 } else {
309 for (int i = 0; i < ARRAY_SIZE(zpool_default_import_path);
310 ++i) {
311 if (strncmp(name, zpool_default_import_path[i],
312 strlen(zpool_default_import_path[i])) == 0) {
313 *order = i;
314 return (0);
315 }
316 }
317 }
318
319 return (ENOENT);
320 }
321
322 /*
323 * Use libblkid to quickly enumerate all known zfs devices.
324 */
325 int
zpool_find_import_blkid(libpc_handle_t * hdl,pthread_mutex_t * lock,avl_tree_t ** slice_cache)326 zpool_find_import_blkid(libpc_handle_t *hdl, pthread_mutex_t *lock,
327 avl_tree_t **slice_cache)
328 {
329 rdsk_node_t *slice;
330 blkid_cache cache;
331 blkid_dev_iterate iter;
332 blkid_dev dev;
333 avl_index_t where;
334 int error;
335
336 *slice_cache = NULL;
337
338 error = blkid_get_cache(&cache, NULL);
339 if (error != 0)
340 return (error);
341
342 error = blkid_probe_all_new(cache);
343 if (error != 0) {
344 blkid_put_cache(cache);
345 return (error);
346 }
347
348 iter = blkid_dev_iterate_begin(cache);
349 if (iter == NULL) {
350 blkid_put_cache(cache);
351 return (EINVAL);
352 }
353
354 /* Only const char *s since 2.32 */
355 error = blkid_dev_set_search(iter,
356 (char *)"TYPE", (char *)"zfs_member");
357 if (error != 0) {
358 blkid_dev_iterate_end(iter);
359 blkid_put_cache(cache);
360 return (error);
361 }
362
363 *slice_cache = zutil_alloc(hdl, sizeof (avl_tree_t));
364 avl_create(*slice_cache, slice_cache_compare, sizeof (rdsk_node_t),
365 offsetof(rdsk_node_t, rn_node));
366
367 while (blkid_dev_next(iter, &dev) == 0) {
368 slice = zutil_alloc(hdl, sizeof (rdsk_node_t));
369 slice->rn_name = zutil_strdup(hdl, blkid_dev_devname(dev));
370 slice->rn_vdev_guid = 0;
371 slice->rn_lock = lock;
372 slice->rn_avl = *slice_cache;
373 slice->rn_hdl = hdl;
374 slice->rn_labelpaths = B_TRUE;
375
376 error = zfs_path_order(slice->rn_name, &slice->rn_order);
377 if (error == 0)
378 slice->rn_order += IMPORT_ORDER_SCAN_OFFSET;
379 else
380 slice->rn_order = IMPORT_ORDER_DEFAULT;
381
382 pthread_mutex_lock(lock);
383 if (avl_find(*slice_cache, slice, &where)) {
384 free(slice->rn_name);
385 free(slice);
386 } else {
387 avl_insert(*slice_cache, slice, where);
388 }
389 pthread_mutex_unlock(lock);
390 }
391
392 blkid_dev_iterate_end(iter);
393 blkid_put_cache(cache);
394
395 return (0);
396 }
397
398 /*
399 * Linux persistent device strings for vdev labels
400 *
401 * based on libudev for consistency with libudev disk add/remove events
402 */
403
404 typedef struct vdev_dev_strs {
405 char vds_devid[128];
406 char vds_devphys[128];
407 } vdev_dev_strs_t;
408
409 #ifdef HAVE_LIBUDEV
410
411 /*
412 * Obtain the persistent device id string (describes what)
413 *
414 * used by ZED vdev matching for auto-{online,expand,replace}
415 */
416 int
zfs_device_get_devid(struct udev_device * dev,char * bufptr,size_t buflen)417 zfs_device_get_devid(struct udev_device *dev, char *bufptr, size_t buflen)
418 {
419 struct udev_list_entry *entry;
420 const char *bus;
421 char devbyid[MAXPATHLEN];
422
423 /* The bus based by-id path is preferred */
424 bus = udev_device_get_property_value(dev, "ID_BUS");
425
426 if (bus == NULL) {
427 const char *dm_uuid;
428
429 /*
430 * For multipath nodes use the persistent uuid based identifier
431 *
432 * Example: /dev/disk/by-id/dm-uuid-mpath-35000c5006304de3f
433 */
434 dm_uuid = udev_device_get_property_value(dev, "DM_UUID");
435 if (dm_uuid != NULL) {
436 (void) snprintf(bufptr, buflen, "dm-uuid-%s", dm_uuid);
437 return (0);
438 }
439
440 /*
441 * For volumes use the persistent /dev/zvol/dataset identifier
442 */
443 entry = udev_device_get_devlinks_list_entry(dev);
444 while (entry != NULL) {
445 const char *name;
446
447 name = udev_list_entry_get_name(entry);
448 if (strncmp(name, ZVOL_ROOT, strlen(ZVOL_ROOT)) == 0) {
449 (void) strlcpy(bufptr, name, buflen);
450 return (0);
451 }
452 entry = udev_list_entry_get_next(entry);
453 }
454
455 /*
456 * NVME 'by-id' symlinks are similar to bus case
457 */
458 struct udev_device *parent;
459
460 parent = udev_device_get_parent_with_subsystem_devtype(dev,
461 "nvme", NULL);
462 if (parent != NULL)
463 bus = "nvme"; /* continue with bus symlink search */
464 else
465 return (ENODATA);
466 }
467
468 /*
469 * locate the bus specific by-id link
470 */
471 (void) snprintf(devbyid, sizeof (devbyid), "%s%s-", DEV_BYID_PATH, bus);
472 entry = udev_device_get_devlinks_list_entry(dev);
473 while (entry != NULL) {
474 const char *name;
475
476 name = udev_list_entry_get_name(entry);
477 if (strncmp(name, devbyid, strlen(devbyid)) == 0) {
478 name += strlen(DEV_BYID_PATH);
479 (void) strlcpy(bufptr, name, buflen);
480 return (0);
481 }
482 entry = udev_list_entry_get_next(entry);
483 }
484
485 return (ENODATA);
486 }
487
488 /*
489 * Obtain the persistent physical location string (describes where)
490 *
491 * used by ZED vdev matching for auto-{online,expand,replace}
492 */
493 int
zfs_device_get_physical(struct udev_device * dev,char * bufptr,size_t buflen)494 zfs_device_get_physical(struct udev_device *dev, char *bufptr, size_t buflen)
495 {
496 const char *physpath = NULL;
497 struct udev_list_entry *entry;
498
499 /*
500 * Normal disks use ID_PATH for their physical path.
501 */
502 physpath = udev_device_get_property_value(dev, "ID_PATH");
503 if (physpath != NULL && strlen(physpath) > 0) {
504 (void) strlcpy(bufptr, physpath, buflen);
505 return (0);
506 }
507
508 /*
509 * Device mapper devices are virtual and don't have a physical
510 * path. For them we use ID_VDEV instead, which is setup via the
511 * /etc/vdev_id.conf file. ID_VDEV provides a persistent path
512 * to a virtual device. If you don't have vdev_id.conf setup,
513 * you cannot use multipath autoreplace with device mapper.
514 */
515 physpath = udev_device_get_property_value(dev, "ID_VDEV");
516 if (physpath != NULL && strlen(physpath) > 0) {
517 (void) strlcpy(bufptr, physpath, buflen);
518 return (0);
519 }
520
521 /*
522 * For ZFS volumes use the persistent /dev/zvol/dataset identifier
523 */
524 entry = udev_device_get_devlinks_list_entry(dev);
525 while (entry != NULL) {
526 physpath = udev_list_entry_get_name(entry);
527 if (strncmp(physpath, ZVOL_ROOT, strlen(ZVOL_ROOT)) == 0) {
528 (void) strlcpy(bufptr, physpath, buflen);
529 return (0);
530 }
531 entry = udev_list_entry_get_next(entry);
532 }
533
534 /*
535 * For all other devices fallback to using the by-uuid name.
536 */
537 entry = udev_device_get_devlinks_list_entry(dev);
538 while (entry != NULL) {
539 physpath = udev_list_entry_get_name(entry);
540 if (strncmp(physpath, "/dev/disk/by-uuid", 17) == 0) {
541 (void) strlcpy(bufptr, physpath, buflen);
542 return (0);
543 }
544 entry = udev_list_entry_get_next(entry);
545 }
546
547 return (ENODATA);
548 }
549
550 /*
551 * A disk is considered a multipath whole disk when:
552 * DEVNAME key value has "dm-"
553 * DM_NAME key value has "mpath" prefix
554 * DM_UUID key exists
555 * ID_PART_TABLE_TYPE key does not exist or is not gpt
556 */
557 static boolean_t
udev_mpath_whole_disk(struct udev_device * dev)558 udev_mpath_whole_disk(struct udev_device *dev)
559 {
560 const char *devname, *type, *uuid;
561
562 devname = udev_device_get_property_value(dev, "DEVNAME");
563 type = udev_device_get_property_value(dev, "ID_PART_TABLE_TYPE");
564 uuid = udev_device_get_property_value(dev, "DM_UUID");
565
566 if ((devname != NULL && strncmp(devname, "/dev/dm-", 8) == 0) &&
567 ((type == NULL) || (strcmp(type, "gpt") != 0)) &&
568 (uuid != NULL)) {
569 return (B_TRUE);
570 }
571
572 return (B_FALSE);
573 }
574
575 static int
udev_device_is_ready(struct udev_device * dev)576 udev_device_is_ready(struct udev_device *dev)
577 {
578 #ifdef HAVE_LIBUDEV_UDEV_DEVICE_GET_IS_INITIALIZED
579 return (udev_device_get_is_initialized(dev));
580 #else
581 /* wait for DEVLINKS property to be initialized */
582 return (udev_device_get_property_value(dev, "DEVLINKS") != NULL);
583 #endif
584 }
585
586 #else
587
588 int
zfs_device_get_devid(struct udev_device * dev,char * bufptr,size_t buflen)589 zfs_device_get_devid(struct udev_device *dev, char *bufptr, size_t buflen)
590 {
591 (void) dev, (void) bufptr, (void) buflen;
592 return (ENODATA);
593 }
594
595 int
zfs_device_get_physical(struct udev_device * dev,char * bufptr,size_t buflen)596 zfs_device_get_physical(struct udev_device *dev, char *bufptr, size_t buflen)
597 {
598 (void) dev, (void) bufptr, (void) buflen;
599 return (ENODATA);
600 }
601
602 #endif /* HAVE_LIBUDEV */
603
604 /*
605 * Wait up to timeout_ms for udev to set up the device node. The device is
606 * considered ready when libudev determines it has been initialized, all of
607 * the device links have been verified to exist, and it has been allowed to
608 * settle. At this point the device can be accessed reliably. Depending on
609 * the complexity of the udev rules this process could take several seconds.
610 */
611 int
zpool_label_disk_wait(const char * path,int timeout_ms)612 zpool_label_disk_wait(const char *path, int timeout_ms)
613 {
614 #ifdef HAVE_LIBUDEV
615 struct udev *udev;
616 struct udev_device *dev = NULL;
617 char nodepath[MAXPATHLEN];
618 char *sysname = NULL;
619 int ret = ENODEV;
620 int settle_ms = 50;
621 long sleep_ms = 10;
622 hrtime_t start, settle;
623
624 if ((udev = udev_new()) == NULL)
625 return (ENXIO);
626
627 start = gethrtime();
628 settle = 0;
629
630 do {
631 if (sysname == NULL) {
632 if (realpath(path, nodepath) != NULL) {
633 sysname = strrchr(nodepath, '/') + 1;
634 } else {
635 (void) usleep(sleep_ms * MILLISEC);
636 continue;
637 }
638 }
639
640 dev = udev_device_new_from_subsystem_sysname(udev,
641 "block", sysname);
642 if ((dev != NULL) && udev_device_is_ready(dev)) {
643 struct udev_list_entry *links, *link = NULL;
644
645 ret = 0;
646 links = udev_device_get_devlinks_list_entry(dev);
647
648 udev_list_entry_foreach(link, links) {
649 struct stat64 statbuf;
650 const char *name;
651
652 name = udev_list_entry_get_name(link);
653 errno = 0;
654 if (stat64(name, &statbuf) == 0 && errno == 0)
655 continue;
656
657 settle = 0;
658 ret = ENODEV;
659 break;
660 }
661
662 if (ret == 0) {
663 if (settle == 0) {
664 settle = gethrtime();
665 } else if (NSEC2MSEC(gethrtime() - settle) >=
666 settle_ms) {
667 udev_device_unref(dev);
668 break;
669 }
670 }
671 }
672
673 udev_device_unref(dev);
674 (void) usleep(sleep_ms * MILLISEC);
675
676 } while (NSEC2MSEC(gethrtime() - start) < timeout_ms);
677
678 udev_unref(udev);
679
680 return (ret);
681 #else
682 int settle_ms = 50;
683 long sleep_ms = 10;
684 hrtime_t start, settle;
685 struct stat64 statbuf;
686
687 start = gethrtime();
688 settle = 0;
689
690 do {
691 errno = 0;
692 if ((stat64(path, &statbuf) == 0) && (errno == 0)) {
693 if (settle == 0)
694 settle = gethrtime();
695 else if (NSEC2MSEC(gethrtime() - settle) >= settle_ms)
696 return (0);
697 } else if (errno != ENOENT) {
698 return (errno);
699 }
700
701 usleep(sleep_ms * MILLISEC);
702 } while (NSEC2MSEC(gethrtime() - start) < timeout_ms);
703
704 return (ENODEV);
705 #endif /* HAVE_LIBUDEV */
706 }
707
708 /*
709 * Simplified version of zpool_label_disk_wait() where we wait for a device
710 * to appear using the default timeouts.
711 */
712 int
zpool_disk_wait(const char * path)713 zpool_disk_wait(const char *path)
714 {
715 int timeout;
716 timeout = zpool_getenv_int("ZPOOL_IMPORT_UDEV_TIMEOUT_MS",
717 DISK_LABEL_WAIT);
718
719 return (zpool_label_disk_wait(path, timeout));
720 }
721
722 /*
723 * Encode the persistent devices strings
724 * used for the vdev disk label
725 */
726 static int
encode_device_strings(const char * path,vdev_dev_strs_t * ds,boolean_t wholedisk)727 encode_device_strings(const char *path, vdev_dev_strs_t *ds,
728 boolean_t wholedisk)
729 {
730 #ifdef HAVE_LIBUDEV
731 struct udev *udev;
732 struct udev_device *dev = NULL;
733 char nodepath[MAXPATHLEN];
734 char *sysname;
735 int ret = ENODEV;
736 hrtime_t start;
737
738 if ((udev = udev_new()) == NULL)
739 return (ENXIO);
740
741 /* resolve path to a runtime device node instance */
742 if (realpath(path, nodepath) == NULL)
743 goto no_dev;
744
745 sysname = strrchr(nodepath, '/') + 1;
746
747 /*
748 * Wait up to 3 seconds for udev to set up the device node context
749 */
750 start = gethrtime();
751 do {
752 dev = udev_device_new_from_subsystem_sysname(udev, "block",
753 sysname);
754 if (dev == NULL)
755 goto no_dev;
756 if (udev_device_is_ready(dev))
757 break; /* udev ready */
758
759 udev_device_unref(dev);
760 dev = NULL;
761
762 if (NSEC2MSEC(gethrtime() - start) < 10)
763 (void) sched_yield(); /* yield/busy wait up to 10ms */
764 else
765 (void) usleep(10 * MILLISEC);
766
767 } while (NSEC2MSEC(gethrtime() - start) < (3 * MILLISEC));
768
769 if (dev == NULL)
770 goto no_dev;
771
772 /*
773 * Only whole disks require extra device strings
774 */
775 if (!wholedisk && !udev_mpath_whole_disk(dev))
776 goto no_dev;
777
778 ret = zfs_device_get_devid(dev, ds->vds_devid, sizeof (ds->vds_devid));
779 if (ret != 0)
780 goto no_dev_ref;
781
782 /* physical location string (optional) */
783 if (zfs_device_get_physical(dev, ds->vds_devphys,
784 sizeof (ds->vds_devphys)) != 0) {
785 ds->vds_devphys[0] = '\0'; /* empty string --> not available */
786 }
787
788 no_dev_ref:
789 udev_device_unref(dev);
790 no_dev:
791 udev_unref(udev);
792
793 return (ret);
794 #else
795 (void) path;
796 (void) ds;
797 (void) wholedisk;
798 return (ENOENT);
799 #endif
800 }
801
802 /*
803 * Rescan the enclosure sysfs path for turning on enclosure LEDs and store it
804 * in the nvlist * (if applicable). Like:
805 * vdev_enc_sysfs_path: '/sys/class/enclosure/11:0:1:0/SLOT 4'
806 *
807 * If an old path was in the nvlist, and the rescan can not find a new path,
808 * then keep the old path, since the disk may have been removed.
809 *
810 * path: The vdev path (value from ZPOOL_CONFIG_PATH)
811 * key: The nvlist_t name (like ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH)
812 */
813 void
update_vdev_config_dev_sysfs_path(nvlist_t * nv,const char * path,const char * key)814 update_vdev_config_dev_sysfs_path(nvlist_t *nv, const char *path,
815 const char *key)
816 {
817 char *upath, *spath;
818 const char *oldpath = NULL;
819
820 (void) nvlist_lookup_string(nv, key, &oldpath);
821
822 /* Add enclosure sysfs path (if disk is in an enclosure). */
823 upath = zfs_get_underlying_path(path);
824 spath = zfs_get_enclosure_sysfs_path(upath);
825
826 if (spath) {
827 (void) nvlist_add_string(nv, key, spath);
828 } else {
829 /*
830 * We couldn't dynamically scan the disk's enclosure sysfs path.
831 * This could be because the disk went away. If there's an old
832 * enclosure sysfs path in the nvlist, then keep using it.
833 */
834 if (!oldpath) {
835 (void) nvlist_remove_all(nv, key);
836 }
837 }
838
839 free(upath);
840 free(spath);
841 }
842
843 /*
844 * This will get called for each leaf vdev.
845 */
846 static int
sysfs_path_pool_vdev_iter_f(void * hdl_data,nvlist_t * nv,void * data)847 sysfs_path_pool_vdev_iter_f(void *hdl_data, nvlist_t *nv, void *data)
848 {
849 (void) hdl_data, (void) data;
850
851 const char *path = NULL;
852 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0)
853 return (1);
854
855 /* Rescan our enclosure sysfs path for this vdev */
856 update_vdev_config_dev_sysfs_path(nv, path,
857 ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
858 return (0);
859 }
860
861 /*
862 * Given an nvlist for our pool (with vdev tree), iterate over all the
863 * leaf vdevs and update their ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH.
864 */
865 void
update_vdevs_config_dev_sysfs_path(nvlist_t * config)866 update_vdevs_config_dev_sysfs_path(nvlist_t *config)
867 {
868 nvlist_t *nvroot = NULL;
869 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
870 &nvroot) == 0);
871 for_each_vdev_in_nvlist(nvroot, sysfs_path_pool_vdev_iter_f, NULL);
872 }
873
874 /*
875 * Update a leaf vdev's persistent device strings
876 *
877 * - only applies for a dedicated leaf vdev (aka whole disk)
878 * - updated during pool create|add|attach|import
879 * - used for matching device matching during auto-{online,expand,replace}
880 * - stored in a leaf disk config label (i.e. alongside 'path' NVP)
881 * - these strings are currently not used in kernel (i.e. for vdev_disk_open)
882 *
883 * single device node example:
884 * devid: 'scsi-MG03SCA300_350000494a8cb3d67-part1'
885 * phys_path: 'pci-0000:04:00.0-sas-0x50000394a8cb3d67-lun-0'
886 *
887 * multipath device node example:
888 * devid: 'dm-uuid-mpath-35000c5006304de3f'
889 *
890 * We also store the enclosure sysfs path for turning on enclosure LEDs
891 * (if applicable):
892 * vdev_enc_sysfs_path: '/sys/class/enclosure/11:0:1:0/SLOT 4'
893 */
894 void
update_vdev_config_dev_strs(nvlist_t * nv)895 update_vdev_config_dev_strs(nvlist_t *nv)
896 {
897 vdev_dev_strs_t vds;
898 const char *env, *type, *path;
899 uint64_t wholedisk = 0;
900
901 /*
902 * For the benefit of legacy ZFS implementations, allow
903 * for opting out of devid strings in the vdev label.
904 *
905 * example use:
906 * env ZFS_VDEV_DEVID_OPT_OUT=YES zpool import dozer
907 *
908 * explanation:
909 * Older OpenZFS implementations had issues when attempting to
910 * display pool config VDEV names if a "devid" NVP value is
911 * present in the pool's config.
912 *
913 * For example, a pool that originated on illumos platform would
914 * have a devid value in the config and "zpool status" would fail
915 * when listing the config.
916 *
917 * A pool can be stripped of any "devid" values on import or
918 * prevented from adding them on zpool create|add by setting
919 * ZFS_VDEV_DEVID_OPT_OUT.
920 */
921 env = getenv("ZFS_VDEV_DEVID_OPT_OUT");
922 if (env && (strtoul(env, NULL, 0) > 0 ||
923 !strncasecmp(env, "YES", 3) || !strncasecmp(env, "ON", 2))) {
924 (void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID);
925 (void) nvlist_remove_all(nv, ZPOOL_CONFIG_PHYS_PATH);
926 return;
927 }
928
929 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0 ||
930 strcmp(type, VDEV_TYPE_DISK) != 0) {
931 return;
932 }
933 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0)
934 return;
935 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
936
937 /*
938 * Update device string values in the config nvlist.
939 */
940 if (encode_device_strings(path, &vds, (boolean_t)wholedisk) == 0) {
941 (void) nvlist_add_string(nv, ZPOOL_CONFIG_DEVID, vds.vds_devid);
942 if (vds.vds_devphys[0] != '\0') {
943 (void) nvlist_add_string(nv, ZPOOL_CONFIG_PHYS_PATH,
944 vds.vds_devphys);
945 }
946 update_vdev_config_dev_sysfs_path(nv, path,
947 ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
948 } else {
949 /* Clear out any stale entries. */
950 (void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID);
951 (void) nvlist_remove_all(nv, ZPOOL_CONFIG_PHYS_PATH);
952 (void) nvlist_remove_all(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
953 }
954 }
955