4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
26 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
27 * Copyright (c) 2018 Datto Inc.
28 * Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
29 * Copyright (c) 2017, Intel Corporation.
30 * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
42 #include <sys/efi_partition.h>
43 #include <sys/systeminfo.h>
44 #include <sys/zfs_ioctl.h>
45 #include <sys/vdev_disk.h>
49 #include "zfs_namecheck.h"
51 #include "../../libzfs_impl.h"
52 #include "zfs_comutil.h"
53 #include "zfeature_common.h"
56 * If the device has being dynamically expanded then we need to relabel
57 * the disk to use the new unallocated space.
60 zpool_relabel_disk(libzfs_handle_t
*hdl
, const char *path
, const char *msg
)
64 if ((fd
= open(path
, O_RDWR
|O_DIRECT
|O_CLOEXEC
)) < 0) {
65 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "cannot "
66 "relabel '%s': unable to open device: %d"), path
, errno
);
67 return (zfs_error(hdl
, EZFS_OPENFAILED
, msg
));
71 * It's possible that we might encounter an error if the device
72 * does not have any unallocated space left. If so, we simply
73 * ignore that error and continue on.
75 error
= efi_use_whole_disk(fd
);
77 /* Flush the buffers to disk and invalidate the page cache. */
79 (void) ioctl(fd
, BLKFLSBUF
);
82 if (error
&& error
!= VT_ENOSPC
) {
83 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "cannot "
84 "relabel '%s': unable to read disk capacity"), path
);
85 return (zfs_error(hdl
, EZFS_NOCAP
, msg
));
91 * Read the EFI label from the config, if a label does not exist then
92 * pass back the error to the caller. If the caller has passed a non-NULL
93 * diskaddr argument then we set it to the starting address of the EFI
97 read_efi_label(nvlist_t
*config
, diskaddr_t
*sb
)
101 char diskname
[MAXPATHLEN
];
104 if (nvlist_lookup_string(config
, ZPOOL_CONFIG_PATH
, &path
) != 0)
107 (void) snprintf(diskname
, sizeof (diskname
), "%s%s", DISK_ROOT
,
109 if ((fd
= open(diskname
, O_RDONLY
|O_DIRECT
|O_CLOEXEC
)) >= 0) {
112 if ((err
= efi_alloc_and_read(fd
, &vtoc
)) >= 0) {
114 *sb
= vtoc
->efi_parts
[0].p_start
;
123 * determine where a partition starts on a disk in the current
127 find_start_block(nvlist_t
*config
)
131 diskaddr_t sb
= MAXOFFSET_T
;
134 if (nvlist_lookup_nvlist_array(config
,
135 ZPOOL_CONFIG_CHILDREN
, &child
, &children
) != 0) {
136 if (nvlist_lookup_uint64(config
,
137 ZPOOL_CONFIG_WHOLE_DISK
,
138 &wholedisk
) != 0 || !wholedisk
) {
139 return (MAXOFFSET_T
);
141 if (read_efi_label(config
, &sb
) < 0)
146 for (c
= 0; c
< children
; c
++) {
147 sb
= find_start_block(child
[c
]);
148 if (sb
!= MAXOFFSET_T
) {
152 return (MAXOFFSET_T
);
156 zpool_label_disk_check(char *path
)
161 if ((fd
= open(path
, O_RDONLY
|O_DIRECT
|O_CLOEXEC
)) < 0)
164 if ((err
= efi_alloc_and_read(fd
, &vtoc
)) != 0) {
169 if (vtoc
->efi_flags
& EFI_GPT_PRIMARY_CORRUPT
) {
181 * Generate a unique partition name for the ZFS member. Partitions must
182 * have unique names to ensure udev will be able to create symlinks under
183 * /dev/disk/by-partlabel/ for all pool members. The partition names are
184 * of the form <pool>-<unique-id>.
187 zpool_label_name(char *label_name
, int label_size
)
192 fd
= open("/dev/urandom", O_RDONLY
|O_CLOEXEC
);
194 if (read(fd
, &id
, sizeof (id
)) != sizeof (id
))
201 id
= (((uint64_t)rand()) << 32) | (uint64_t)rand();
203 snprintf(label_name
, label_size
, "zfs-%016llx", (u_longlong_t
)id
);
207 * Label an individual disk. The name provided is the short name,
208 * stripped of any leading /dev path.
211 zpool_label_disk(libzfs_handle_t
*hdl
, zpool_handle_t
*zhp
, const char *name
)
213 char path
[MAXPATHLEN
];
216 size_t resv
= EFI_MIN_RESV_SIZE
;
218 diskaddr_t start_block
;
219 char errbuf
[ERRBUFLEN
];
221 /* prepare an error message just in case */
222 (void) snprintf(errbuf
, sizeof (errbuf
),
223 dgettext(TEXT_DOMAIN
, "cannot label '%s'"), name
);
226 nvlist_t
*nvroot
= fnvlist_lookup_nvlist(zhp
->zpool_config
,
227 ZPOOL_CONFIG_VDEV_TREE
);
229 if (zhp
->zpool_start_block
== 0)
230 start_block
= find_start_block(nvroot
);
232 start_block
= zhp
->zpool_start_block
;
233 zhp
->zpool_start_block
= start_block
;
236 start_block
= NEW_START_BLOCK
;
239 (void) snprintf(path
, sizeof (path
), "%s/%s", DISK_ROOT
, name
);
241 if ((fd
= open(path
, O_RDWR
|O_DIRECT
|O_EXCL
|O_CLOEXEC
)) < 0) {
243 * This shouldn't happen. We've long since verified that this
246 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "cannot "
247 "label '%s': unable to open device: %d"), path
, errno
);
248 return (zfs_error(hdl
, EZFS_OPENFAILED
, errbuf
));
251 if (efi_alloc_and_init(fd
, EFI_NUMPAR
, &vtoc
) != 0) {
253 * The only way this can fail is if we run out of memory, or we
254 * were unable to read the disk's capacity
257 (void) no_memory(hdl
);
260 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "cannot "
261 "label '%s': unable to read disk capacity"), path
);
263 return (zfs_error(hdl
, EZFS_NOCAP
, errbuf
));
266 slice_size
= vtoc
->efi_last_u_lba
+ 1;
267 slice_size
-= EFI_MIN_RESV_SIZE
;
268 if (start_block
== MAXOFFSET_T
)
269 start_block
= NEW_START_BLOCK
;
270 slice_size
-= start_block
;
271 slice_size
= P2ALIGN_TYPED(slice_size
, PARTITION_END_ALIGNMENT
,
274 vtoc
->efi_parts
[0].p_start
= start_block
;
275 vtoc
->efi_parts
[0].p_size
= slice_size
;
277 if (vtoc
->efi_parts
[0].p_size
* vtoc
->efi_lbasize
< SPA_MINDEVSIZE
) {
281 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "cannot "
282 "label '%s': partition would be less than the minimum "
283 "device size (64M)"), path
);
284 return (zfs_error(hdl
, EZFS_LABELFAILED
, errbuf
));
288 * Why we use V_USR: V_BACKUP confuses users, and is considered
289 * disposable by some EFI utilities (since EFI doesn't have a backup
290 * slice). V_UNASSIGNED is supposed to be used only for zero size
291 * partitions, and efi_write() will fail if we use it.
292 * Other available types were all pretty specific.
293 * V_USR is as close to reality as we
294 * can get, in the absence of V_OTHER.
296 vtoc
->efi_parts
[0].p_tag
= V_USR
;
297 zpool_label_name(vtoc
->efi_parts
[0].p_name
, EFI_PART_NAME_LEN
);
299 vtoc
->efi_parts
[8].p_start
= slice_size
+ start_block
;
300 vtoc
->efi_parts
[8].p_size
= resv
;
301 vtoc
->efi_parts
[8].p_tag
= V_RESERVED
;
303 rval
= efi_write(fd
, vtoc
);
305 /* Flush the buffers to disk and invalidate the page cache. */
307 (void) ioctl(fd
, BLKFLSBUF
);
310 rval
= efi_rescan(fd
);
313 * Some block drivers (like pcata) may not support EFI GPT labels.
314 * Print out a helpful error message directing the user to manually
315 * label the disk and give a specific slice.
321 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "try using "
322 "parted(8) and then provide a specific slice: %d"), rval
);
323 return (zfs_error(hdl
, EZFS_LABELFAILED
, errbuf
));
329 (void) snprintf(path
, sizeof (path
), "%s/%s", DISK_ROOT
, name
);
330 (void) zfs_append_partition(path
, MAXPATHLEN
);
332 /* Wait to udev to signal use the device has settled. */
333 rval
= zpool_label_disk_wait(path
, DISK_LABEL_WAIT
);
335 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "failed to "
336 "detect device partitions on '%s': %d"), path
, rval
);
337 return (zfs_error(hdl
, EZFS_LABELFAILED
, errbuf
));
340 /* We can't be to paranoid. Read the label back and verify it. */
341 (void) snprintf(path
, sizeof (path
), "%s/%s", DISK_ROOT
, name
);
342 rval
= zpool_label_disk_check(path
);
344 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "freshly written "
345 "EFI label on '%s' is damaged. Ensure\nthis device "
346 "is not in use, and is functioning properly: %d"),
348 return (zfs_error(hdl
, EZFS_LABELFAILED
, errbuf
));