xref: /freebsd/sys/contrib/openzfs/cmd/zpool/os/linux/zpool_vdev_os.c (revision 22649d4dba730d46244fd2dff4fd174903c8379f)
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 /*
14  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
15  * Copyright (c) 2013, 2018 by Delphix. All rights reserved.
16  * Copyright (c) 2016, 2017 Intel Corporation.
17  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
18  */
19 
20 /*
21  * Functions to convert between a list of vdevs and an nvlist representing the
22  * configuration.  Each entry in the list can be one of:
23  *
24  * 	Device vdevs
25  * 		disk=(path=..., devid=...)
26  * 		file=(path=...)
27  *
28  * 	Group vdevs
29  * 		raidz[1|2]=(...)
30  * 		mirror=(...)
31  *
32  * 	Hot spares
33  *
34  * While the underlying implementation supports it, group vdevs cannot contain
35  * other group vdevs.  All userland verification of devices is contained within
36  * this file.  If successful, the nvlist returned can be passed directly to the
37  * kernel; we've done as much verification as possible in userland.
38  *
39  * Hot spares are a special case, and passed down as an array of disk vdevs, at
40  * the same level as the root of the vdev tree.
41  *
42  * The only function exported by this file is 'make_root_vdev'.  The
43  * function performs several passes:
44  *
45  * 	1. Construct the vdev specification.  Performs syntax validation and
46  *         makes sure each device is valid.
47  * 	2. Check for devices in use.  Using libblkid to make sure that no
48  *         devices are also in use.  Some can be overridden using the 'force'
49  *         flag, others cannot.
50  * 	3. Check for replication errors if the 'force' flag is not specified.
51  *         validates that the replication level is consistent across the
52  *         entire pool.
53  * 	4. Call libzfs to label any whole disks with an EFI label.
54  */
55 
56 #include <assert.h>
57 #include <ctype.h>
58 #include <errno.h>
59 #include <fcntl.h>
60 #include <libintl.h>
61 #include <libnvpair.h>
62 #include <libzutil.h>
63 #include <limits.h>
64 #include <sys/spa.h>
65 #include <stdio.h>
66 #include <string.h>
67 #include <unistd.h>
68 #include "zpool_util.h"
69 #include <sys/zfs_context.h>
70 
71 #include <scsi/scsi.h>
72 #include <scsi/sg.h>
73 #include <sys/efi_partition.h>
74 #include <sys/stat.h>
75 #include <sys/mntent.h>
76 #include <uuid/uuid.h>
77 #include <blkid/blkid.h>
78 
79 typedef struct vdev_disk_db_entry
80 {
81 	/* 24 byte name + 1 byte NULL terminator to make GCC happy */
82 	char id[25];
83 	int sector_size;
84 } vdev_disk_db_entry_t;
85 
86 /*
87  * Database of block devices that lie about physical sector sizes.  The
88  * identification string must be precisely 24 characters to avoid false
89  * negatives
90  */
91 static vdev_disk_db_entry_t vdev_disk_database[] = {
92 	{"ATA     ADATA SSD S396 3", 8192},
93 	{"ATA     APPLE SSD SM128E", 8192},
94 	{"ATA     APPLE SSD SM256E", 8192},
95 	{"ATA     APPLE SSD SM512E", 8192},
96 	{"ATA     APPLE SSD SM768E", 8192},
97 	{"ATA     C400-MTFDDAC064M", 8192},
98 	{"ATA     C400-MTFDDAC128M", 8192},
99 	{"ATA     C400-MTFDDAC256M", 8192},
100 	{"ATA     C400-MTFDDAC512M", 8192},
101 	{"ATA     Corsair Force 3 ", 8192},
102 	{"ATA     Corsair Force GS", 8192},
103 	{"ATA     INTEL SSDSA2CT04", 8192},
104 	{"ATA     INTEL SSDSA2BZ10", 8192},
105 	{"ATA     INTEL SSDSA2BZ20", 8192},
106 	{"ATA     INTEL SSDSA2BZ30", 8192},
107 	{"ATA     INTEL SSDSA2CW04", 8192},
108 	{"ATA     INTEL SSDSA2CW08", 8192},
109 	{"ATA     INTEL SSDSA2CW12", 8192},
110 	{"ATA     INTEL SSDSA2CW16", 8192},
111 	{"ATA     INTEL SSDSA2CW30", 8192},
112 	{"ATA     INTEL SSDSA2CW60", 8192},
113 	{"ATA     INTEL SSDSC2CT06", 8192},
114 	{"ATA     INTEL SSDSC2CT12", 8192},
115 	{"ATA     INTEL SSDSC2CT18", 8192},
116 	{"ATA     INTEL SSDSC2CT24", 8192},
117 	{"ATA     INTEL SSDSC2CW06", 8192},
118 	{"ATA     INTEL SSDSC2CW12", 8192},
119 	{"ATA     INTEL SSDSC2CW18", 8192},
120 	{"ATA     INTEL SSDSC2CW24", 8192},
121 	{"ATA     INTEL SSDSC2CW48", 8192},
122 	{"ATA     KINGSTON SH100S3", 8192},
123 	{"ATA     KINGSTON SH103S3", 8192},
124 	{"ATA     M4-CT064M4SSD2  ", 8192},
125 	{"ATA     M4-CT128M4SSD2  ", 8192},
126 	{"ATA     M4-CT256M4SSD2  ", 8192},
127 	{"ATA     M4-CT512M4SSD2  ", 8192},
128 	{"ATA     OCZ-AGILITY2    ", 8192},
129 	{"ATA     OCZ-AGILITY3    ", 8192},
130 	{"ATA     OCZ-VERTEX2 3.5 ", 8192},
131 	{"ATA     OCZ-VERTEX3     ", 8192},
132 	{"ATA     OCZ-VERTEX3 LT  ", 8192},
133 	{"ATA     OCZ-VERTEX3 MI  ", 8192},
134 	{"ATA     OCZ-VERTEX4     ", 8192},
135 	{"ATA     SAMSUNG MZ7WD120", 8192},
136 	{"ATA     SAMSUNG MZ7WD240", 8192},
137 	{"ATA     SAMSUNG MZ7WD480", 8192},
138 	{"ATA     SAMSUNG MZ7WD960", 8192},
139 	{"ATA     SAMSUNG SSD 830 ", 8192},
140 	{"ATA     Samsung SSD 840 ", 8192},
141 	{"ATA     SanDisk SSD U100", 8192},
142 	{"ATA     TOSHIBA THNSNH06", 8192},
143 	{"ATA     TOSHIBA THNSNH12", 8192},
144 	{"ATA     TOSHIBA THNSNH25", 8192},
145 	{"ATA     TOSHIBA THNSNH51", 8192},
146 	{"ATA     APPLE SSD TS064C", 4096},
147 	{"ATA     APPLE SSD TS128C", 4096},
148 	{"ATA     APPLE SSD TS256C", 4096},
149 	{"ATA     APPLE SSD TS512C", 4096},
150 	{"ATA     INTEL SSDSA2M040", 4096},
151 	{"ATA     INTEL SSDSA2M080", 4096},
152 	{"ATA     INTEL SSDSA2M160", 4096},
153 	{"ATA     INTEL SSDSC2MH12", 4096},
154 	{"ATA     INTEL SSDSC2MH25", 4096},
155 	{"ATA     OCZ CORE_SSD    ", 4096},
156 	{"ATA     OCZ-VERTEX      ", 4096},
157 	{"ATA     SAMSUNG MCCOE32G", 4096},
158 	{"ATA     SAMSUNG MCCOE64G", 4096},
159 	{"ATA     SAMSUNG SSD PM80", 4096},
160 	/* Flash drives optimized for 4KB IOs on larger pages */
161 	{"ATA     INTEL SSDSC2BA10", 4096},
162 	{"ATA     INTEL SSDSC2BA20", 4096},
163 	{"ATA     INTEL SSDSC2BA40", 4096},
164 	{"ATA     INTEL SSDSC2BA80", 4096},
165 	{"ATA     INTEL SSDSC2BB08", 4096},
166 	{"ATA     INTEL SSDSC2BB12", 4096},
167 	{"ATA     INTEL SSDSC2BB16", 4096},
168 	{"ATA     INTEL SSDSC2BB24", 4096},
169 	{"ATA     INTEL SSDSC2BB30", 4096},
170 	{"ATA     INTEL SSDSC2BB40", 4096},
171 	{"ATA     INTEL SSDSC2BB48", 4096},
172 	{"ATA     INTEL SSDSC2BB60", 4096},
173 	{"ATA     INTEL SSDSC2BB80", 4096},
174 	{"ATA     INTEL SSDSC2BW24", 4096},
175 	{"ATA     INTEL SSDSC2BW48", 4096},
176 	{"ATA     INTEL SSDSC2BP24", 4096},
177 	{"ATA     INTEL SSDSC2BP48", 4096},
178 	{"NA      SmrtStorSDLKAE9W", 4096},
179 	{"NVMe    Amazon EC2 NVMe ", 4096},
180 	/* Imported from Open Solaris */
181 	{"ATA     MARVELL SD88SA02", 4096},
182 	/* Advanced format Hard drives */
183 	{"ATA     Hitachi HDS5C303", 4096},
184 	{"ATA     SAMSUNG HD204UI ", 4096},
185 	{"ATA     ST2000DL004 HD20", 4096},
186 	{"ATA     WDC WD10EARS-00M", 4096},
187 	{"ATA     WDC WD10EARS-00S", 4096},
188 	{"ATA     WDC WD10EARS-00Z", 4096},
189 	{"ATA     WDC WD15EARS-00M", 4096},
190 	{"ATA     WDC WD15EARS-00S", 4096},
191 	{"ATA     WDC WD15EARS-00Z", 4096},
192 	{"ATA     WDC WD20EARS-00M", 4096},
193 	{"ATA     WDC WD20EARS-00S", 4096},
194 	{"ATA     WDC WD20EARS-00Z", 4096},
195 	{"ATA     WDC WD1600BEVT-0", 4096},
196 	{"ATA     WDC WD2500BEVT-0", 4096},
197 	{"ATA     WDC WD3200BEVT-0", 4096},
198 	{"ATA     WDC WD5000BEVT-0", 4096},
199 };
200 
201 
202 #define	INQ_REPLY_LEN	96
203 #define	INQ_CMD_LEN	6
204 
205 static const int vdev_disk_database_size =
206 	sizeof (vdev_disk_database) / sizeof (vdev_disk_database[0]);
207 
208 boolean_t
check_sector_size_database(char * path,int * sector_size)209 check_sector_size_database(char *path, int *sector_size)
210 {
211 	unsigned char inq_buff[INQ_REPLY_LEN];
212 	unsigned char sense_buffer[32];
213 	unsigned char inq_cmd_blk[INQ_CMD_LEN] =
214 	    {INQUIRY, 0, 0, 0, INQ_REPLY_LEN, 0};
215 	sg_io_hdr_t io_hdr;
216 	int error;
217 	int fd;
218 	int i;
219 
220 	/* Prepare INQUIRY command */
221 	memset(&io_hdr, 0, sizeof (sg_io_hdr_t));
222 	io_hdr.interface_id = 'S';
223 	io_hdr.cmd_len = sizeof (inq_cmd_blk);
224 	io_hdr.mx_sb_len = sizeof (sense_buffer);
225 	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
226 	io_hdr.dxfer_len = INQ_REPLY_LEN;
227 	io_hdr.dxferp = inq_buff;
228 	io_hdr.cmdp = inq_cmd_blk;
229 	io_hdr.sbp = sense_buffer;
230 	io_hdr.timeout = 10;		/* 10 milliseconds is ample time */
231 
232 	if ((fd = open(path, O_RDONLY|O_DIRECT)) < 0)
233 		return (B_FALSE);
234 
235 	error = ioctl(fd, SG_IO, (unsigned long) &io_hdr);
236 
237 	(void) close(fd);
238 
239 	if (error < 0)
240 		return (B_FALSE);
241 
242 	if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
243 		return (B_FALSE);
244 
245 	for (i = 0; i < vdev_disk_database_size; i++) {
246 		if (memcmp(inq_buff + 8, vdev_disk_database[i].id, 24))
247 			continue;
248 
249 		*sector_size = vdev_disk_database[i].sector_size;
250 		return (B_TRUE);
251 	}
252 
253 	return (B_FALSE);
254 }
255 
256 static int
check_slice(const char * path,blkid_cache cache,int force,boolean_t isspare)257 check_slice(const char *path, blkid_cache cache, int force, boolean_t isspare)
258 {
259 	int err;
260 	char *value;
261 
262 	/* No valid type detected device is safe to use */
263 	value = blkid_get_tag_value(cache, "TYPE", path);
264 	if (value == NULL)
265 		return (0);
266 
267 	/*
268 	 * If libblkid detects a ZFS device, we check the device
269 	 * using check_file() to see if it's safe.  The one safe
270 	 * case is a spare device shared between multiple pools.
271 	 */
272 	if (strcmp(value, "zfs_member") == 0) {
273 		err = check_file(path, force, isspare);
274 	} else {
275 		if (force) {
276 			err = 0;
277 		} else {
278 			err = -1;
279 			vdev_error(gettext("%s contains a filesystem of "
280 			    "type '%s'\n"), path, value);
281 		}
282 	}
283 
284 	free(value);
285 
286 	return (err);
287 }
288 
289 /*
290  * Validate that a disk including all partitions are safe to use.
291  *
292  * For EFI labeled disks this can done relatively easily with the libefi
293  * library.  The partition numbers are extracted from the label and used
294  * to generate the expected /dev/ paths.  Each partition can then be
295  * checked for conflicts.
296  *
297  * For non-EFI labeled disks (MBR/EBR/etc) the same process is possible
298  * but due to the lack of a readily available libraries this scanning is
299  * not implemented.  Instead only the device path as given is checked.
300  */
301 static int
check_disk(const char * path,blkid_cache cache,int force,boolean_t isspare,boolean_t iswholedisk)302 check_disk(const char *path, blkid_cache cache, int force,
303     boolean_t isspare, boolean_t iswholedisk)
304 {
305 	struct dk_gpt *vtoc;
306 	char slice_path[MAXPATHLEN];
307 	int err = 0;
308 	int fd, i;
309 	int flags = O_RDONLY|O_DIRECT;
310 
311 	if (!iswholedisk)
312 		return (check_slice(path, cache, force, isspare));
313 
314 	/* only spares can be shared, other devices require exclusive access */
315 	if (!isspare)
316 		flags |= O_EXCL;
317 
318 	if ((fd = open(path, flags)) < 0) {
319 		char *value = blkid_get_tag_value(cache, "TYPE", path);
320 		(void) fprintf(stderr, gettext("%s is in use and contains "
321 		    "a %s filesystem.\n"), path, value ? value : "unknown");
322 		free(value);
323 		return (-1);
324 	}
325 
326 	/*
327 	 * Expected to fail for non-EFI labeled disks.  Just check the device
328 	 * as given and do not attempt to detect and scan partitions.
329 	 */
330 	err = efi_alloc_and_read(fd, &vtoc);
331 	if (err) {
332 		(void) close(fd);
333 		return (check_slice(path, cache, force, isspare));
334 	}
335 
336 	/*
337 	 * The primary efi partition label is damaged however the secondary
338 	 * label at the end of the device is intact.  Rather than use this
339 	 * label we should play it safe and treat this as a non efi device.
340 	 */
341 	if (vtoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) {
342 		efi_free(vtoc);
343 		(void) close(fd);
344 
345 		if (force) {
346 			/* Partitions will now be created using the backup */
347 			return (0);
348 		} else {
349 			vdev_error(gettext("%s contains a corrupt primary "
350 			    "EFI label.\n"), path);
351 			return (-1);
352 		}
353 	}
354 
355 	for (i = 0; i < vtoc->efi_nparts; i++) {
356 
357 		if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED ||
358 		    uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_guid))
359 			continue;
360 
361 		if (strncmp(path, UDISK_ROOT, strlen(UDISK_ROOT)) == 0)
362 			(void) snprintf(slice_path, sizeof (slice_path),
363 			    "%s%s%d", path, "-part", i+1);
364 		else
365 			(void) snprintf(slice_path, sizeof (slice_path),
366 			    "%s%s%d", path, isdigit(path[strlen(path)-1]) ?
367 			    "p" : "", i+1);
368 
369 		err = check_slice(slice_path, cache, force, isspare);
370 		if (err)
371 			break;
372 	}
373 
374 	efi_free(vtoc);
375 	(void) close(fd);
376 
377 	return (err);
378 }
379 
380 int
check_device(const char * path,boolean_t force,boolean_t isspare,boolean_t iswholedisk)381 check_device(const char *path, boolean_t force,
382     boolean_t isspare, boolean_t iswholedisk)
383 {
384 	blkid_cache cache;
385 	int error;
386 
387 	error = blkid_get_cache(&cache, NULL);
388 	if (error != 0) {
389 		(void) fprintf(stderr, gettext("unable to access the blkid "
390 		    "cache.\n"));
391 		return (-1);
392 	}
393 
394 	error = check_disk(path, cache, force, isspare, iswholedisk);
395 	blkid_put_cache(cache);
396 
397 	return (error);
398 }
399 
400 void
after_zpool_upgrade(zpool_handle_t * zhp)401 after_zpool_upgrade(zpool_handle_t *zhp)
402 {
403 	(void) zhp;
404 }
405 
406 int
check_file(const char * file,boolean_t force,boolean_t isspare)407 check_file(const char *file, boolean_t force, boolean_t isspare)
408 {
409 	return (check_file_generic(file, force, isspare));
410 }
411 
412 /*
413  * Read from a sysfs file and return an allocated string.  Removes
414  * the newline from the end of the string if there is one.
415  *
416  * Returns a string on success (which must be freed), or NULL on error.
417  */
zpool_sysfs_gets(char * path)418 static char *zpool_sysfs_gets(char *path)
419 {
420 	int fd;
421 	struct stat statbuf;
422 	char *buf = NULL;
423 	ssize_t count = 0;
424 	fd = open(path, O_RDONLY);
425 	if (fd < 0)
426 		return (NULL);
427 
428 	if (fstat(fd, &statbuf) != 0) {
429 		close(fd);
430 		return (NULL);
431 	}
432 
433 	buf = calloc(statbuf.st_size + 1, sizeof (*buf));
434 	if (buf == NULL) {
435 		close(fd);
436 		return (NULL);
437 	}
438 
439 	/*
440 	 * Note, we can read less bytes than st_size, and that's ok.  Sysfs
441 	 * files will report their size is 4k even if they only return a small
442 	 * string.
443 	 */
444 	count = read(fd, buf, statbuf.st_size);
445 	if (count < 0) {
446 		/* Error doing read() or we overran the buffer */
447 		close(fd);
448 		free(buf);
449 		return (NULL);
450 	}
451 
452 	/* Remove trailing newline */
453 	if (count > 0 && buf[count - 1] == '\n')
454 		buf[count - 1] = 0;
455 
456 	close(fd);
457 
458 	return (buf);
459 }
460 
461 /*
462  * Write a string to a sysfs file.
463  *
464  * Returns 0 on success, non-zero otherwise.
465  */
zpool_sysfs_puts(char * path,char * str)466 static int zpool_sysfs_puts(char *path, char *str)
467 {
468 	FILE *file;
469 
470 	file = fopen(path, "w");
471 	if (!file) {
472 		return (-1);
473 	}
474 
475 	if (fputs(str, file) < 0) {
476 		fclose(file);
477 		return (-2);
478 	}
479 	fclose(file);
480 	return (0);
481 }
482 
483 /* Given a vdev nvlist_t, rescan its enclosure sysfs path */
484 static void
rescan_vdev_config_dev_sysfs_path(nvlist_t * vdev_nv)485 rescan_vdev_config_dev_sysfs_path(nvlist_t *vdev_nv)
486 {
487 	update_vdev_config_dev_sysfs_path(vdev_nv,
488 	    fnvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_PATH),
489 	    ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
490 }
491 
492 /*
493  * Given a power string: "on", "off", "1", or "0", return 0 if it's an
494  * off value, 1 if it's an on value, and -1 if the value is unrecognized.
495  */
zpool_power_parse_value(char * str)496 static int zpool_power_parse_value(char *str)
497 {
498 	if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0))
499 		return (0);
500 
501 	if ((strcmp(str, "on") == 0) || (strcmp(str, "1") == 0))
502 		return (1);
503 
504 	return (-1);
505 }
506 
507 /*
508  * Given a vdev string return an allocated string containing the sysfs path to
509  * its power control file.  Also do a check if the power control file really
510  * exists and has correct permissions.
511  *
512  * Example returned strings:
513  *
514  * /sys/class/enclosure/0:0:122:0/10/power_status
515  * /sys/bus/pci/slots/10/power
516  *
517  * Returns allocated string on success (which must be freed), NULL on failure.
518  */
519 static char *
zpool_power_sysfs_path(zpool_handle_t * zhp,char * vdev)520 zpool_power_sysfs_path(zpool_handle_t *zhp, char *vdev)
521 {
522 	const char *enc_sysfs_dir = NULL;
523 	char *path = NULL;
524 	nvlist_t *vdev_nv = zpool_find_vdev(zhp, vdev, NULL, NULL, NULL);
525 
526 	if (vdev_nv == NULL) {
527 		return (NULL);
528 	}
529 
530 	/* Make sure we're getting the updated enclosure sysfs path */
531 	rescan_vdev_config_dev_sysfs_path(vdev_nv);
532 
533 	if (nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
534 	    &enc_sysfs_dir) != 0) {
535 		return (NULL);
536 	}
537 
538 	if (asprintf(&path, "%s/power_status", enc_sysfs_dir) == -1)
539 		return (NULL);
540 
541 	if (access(path, W_OK) != 0) {
542 		free(path);
543 		path = NULL;
544 		/* No HDD 'power_control' file, maybe it's NVMe? */
545 		if (asprintf(&path, "%s/power", enc_sysfs_dir) == -1) {
546 			return (NULL);
547 		}
548 
549 		if (access(path, R_OK | W_OK) != 0) {
550 			/* Not NVMe either */
551 			free(path);
552 			return (NULL);
553 		}
554 	}
555 
556 	return (path);
557 }
558 
559 /*
560  * Given a path to a sysfs power control file, return B_TRUE if you should use
561  * "on/off" words to control it, or B_FALSE otherwise ("0/1" to control).
562  */
563 static boolean_t
zpool_power_use_word(char * sysfs_path)564 zpool_power_use_word(char *sysfs_path)
565 {
566 	if (strcmp(&sysfs_path[strlen(sysfs_path) - strlen("power_status")],
567 	    "power_status") == 0) {
568 		return (B_TRUE);
569 	}
570 	return (B_FALSE);
571 }
572 
573 /*
574  * Check the sysfs power control value for a vdev.
575  *
576  * Returns:
577  *  0 - Power is off
578  *  1 - Power is on
579  * -1 - Error or unsupported
580  */
581 int
zpool_power_current_state(zpool_handle_t * zhp,char * vdev)582 zpool_power_current_state(zpool_handle_t *zhp, char *vdev)
583 {
584 	char *val;
585 	int rc;
586 
587 	char *path = zpool_power_sysfs_path(zhp, vdev);
588 	if (path == NULL)
589 		return (-1);
590 
591 	val = zpool_sysfs_gets(path);
592 	if (val == NULL) {
593 		free(path);
594 		return (-1);
595 	}
596 
597 	rc = zpool_power_parse_value(val);
598 	free(val);
599 	free(path);
600 	return (rc);
601 }
602 
603 /*
604  * Turn on or off the slot to a device
605  *
606  * Device path is the full path to the device (like /dev/sda or /dev/sda1).
607  *
608  * Return code:
609  * 0:		Success
610  * ENOTSUP:	Power control not supported for OS
611  * EBADSLT:	Couldn't read current power state
612  * ENOENT:	No sysfs path to power control
613  * EIO:	Couldn't write sysfs power value
614  * EBADE:	Sysfs power value didn't change
615  */
616 int
zpool_power(zpool_handle_t * zhp,char * vdev,boolean_t turn_on)617 zpool_power(zpool_handle_t *zhp, char *vdev, boolean_t turn_on)
618 {
619 	char *sysfs_path;
620 	const char *val;
621 	int rc;
622 	int timeout_ms;
623 
624 	rc = zpool_power_current_state(zhp, vdev);
625 	if (rc == -1) {
626 		return (EBADSLT);
627 	}
628 
629 	/* Already correct value? */
630 	if (rc == (int)turn_on)
631 		return (0);
632 
633 	sysfs_path = zpool_power_sysfs_path(zhp, vdev);
634 	if (sysfs_path == NULL)
635 		return (ENOENT);
636 
637 	if (zpool_power_use_word(sysfs_path)) {
638 		val = turn_on ? "on" : "off";
639 	} else {
640 		val = turn_on ? "1" : "0";
641 	}
642 
643 	rc = zpool_sysfs_puts(sysfs_path, (char *)val);
644 
645 	free(sysfs_path);
646 	if (rc != 0) {
647 		return (EIO);
648 	}
649 
650 	/*
651 	 * Wait up to 30 seconds for sysfs power value to change after
652 	 * writing it.
653 	 */
654 	timeout_ms = zpool_getenv_int("ZPOOL_POWER_ON_SLOT_TIMEOUT_MS", 30000);
655 	for (int i = 0; i < MAX(1, timeout_ms / 200); i++) {
656 		rc = zpool_power_current_state(zhp, vdev);
657 		if (rc == (int)turn_on)
658 			return (0);	/* success */
659 
660 		fsleep(0.200);	/* 200ms */
661 	}
662 
663 	/* sysfs value never changed */
664 	return (EBADE);
665 }
666