mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	Add zfs_prepare_disk script for disk firmware install
Have libzfs call a special `zfs_prepare_disk` script before a disk is included into the pool. The user can edit this script to add things like a disk firmware update or a disk health check. Use of the script is totally optional. See the zfs_prepare_disk manpage for full details. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Tony Hutter <hutter2@llnl.gov> Closes #15243
This commit is contained in:
		
							parent
							
								
									35252ae0fd
								
							
						
					
					
						commit
						11574a7934
					
				@ -141,6 +141,17 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
 | 
				
			|||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Write an array of strings to the zed log
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void lines_to_zed_log_msg(char **lines, int lines_cnt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < lines_cnt; i++) {
 | 
				
			||||||
 | 
							zed_log_msg(LOG_INFO, "%s", lines[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Two stage replace on Linux
 | 
					 * Two stage replace on Linux
 | 
				
			||||||
 * since we get disk notifications
 | 
					 * since we get disk notifications
 | 
				
			||||||
@ -195,6 +206,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
 | 
				
			|||||||
	boolean_t is_mpath_wholedisk = B_FALSE;
 | 
						boolean_t is_mpath_wholedisk = B_FALSE;
 | 
				
			||||||
	uint_t c;
 | 
						uint_t c;
 | 
				
			||||||
	vdev_stat_t *vs;
 | 
						vdev_stat_t *vs;
 | 
				
			||||||
 | 
						char **lines = NULL;
 | 
				
			||||||
 | 
						int lines_cnt = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path) != 0)
 | 
						if (nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path) != 0)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
@ -377,6 +390,22 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (is_mpath_wholedisk) {
 | 
						if (is_mpath_wholedisk) {
 | 
				
			||||||
		/* Don't label device mapper or multipath disks. */
 | 
							/* Don't label device mapper or multipath disks. */
 | 
				
			||||||
 | 
							zed_log_msg(LOG_INFO,
 | 
				
			||||||
 | 
							    "  it's a multipath wholedisk, don't label");
 | 
				
			||||||
 | 
							if (zpool_prepare_disk(zhp, vdev, "autoreplace", &lines,
 | 
				
			||||||
 | 
							    &lines_cnt) != 0) {
 | 
				
			||||||
 | 
								zed_log_msg(LOG_INFO,
 | 
				
			||||||
 | 
								    "  zpool_prepare_disk: could not "
 | 
				
			||||||
 | 
								    "prepare '%s' (%s)", fullpath,
 | 
				
			||||||
 | 
								    libzfs_error_description(g_zfshdl));
 | 
				
			||||||
 | 
								if (lines_cnt > 0) {
 | 
				
			||||||
 | 
									zed_log_msg(LOG_INFO,
 | 
				
			||||||
 | 
									    "  zfs_prepare_disk output:");
 | 
				
			||||||
 | 
									lines_to_zed_log_msg(lines, lines_cnt);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								libzfs_free_str_array(lines, lines_cnt);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	} else if (!labeled) {
 | 
						} else if (!labeled) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * we're auto-replacing a raw disk, so label it first
 | 
							 * we're auto-replacing a raw disk, so label it first
 | 
				
			||||||
@ -399,10 +428,18 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
 | 
				
			|||||||
		 * If this is a request to label a whole disk, then attempt to
 | 
							 * If this is a request to label a whole disk, then attempt to
 | 
				
			||||||
		 * write out the label.
 | 
							 * write out the label.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (zpool_label_disk(g_zfshdl, zhp, leafname) != 0) {
 | 
							if (zpool_prepare_and_label_disk(g_zfshdl, zhp, leafname,
 | 
				
			||||||
			zed_log_msg(LOG_INFO, "  zpool_label_disk: could not "
 | 
							    vdev, "autoreplace", &lines, &lines_cnt) != 0) {
 | 
				
			||||||
 | 
								zed_log_msg(LOG_INFO,
 | 
				
			||||||
 | 
								    "  zpool_prepare_and_label_disk: could not "
 | 
				
			||||||
			    "label '%s' (%s)", leafname,
 | 
								    "label '%s' (%s)", leafname,
 | 
				
			||||||
			    libzfs_error_description(g_zfshdl));
 | 
								    libzfs_error_description(g_zfshdl));
 | 
				
			||||||
 | 
								if (lines_cnt > 0) {
 | 
				
			||||||
 | 
									zed_log_msg(LOG_INFO,
 | 
				
			||||||
 | 
									"  zfs_prepare_disk output:");
 | 
				
			||||||
 | 
									lines_to_zed_log_msg(lines, lines_cnt);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								libzfs_free_str_array(lines, lines_cnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			(void) zpool_vdev_online(zhp, fullpath,
 | 
								(void) zpool_vdev_online(zhp, fullpath,
 | 
				
			||||||
			    ZFS_ONLINE_FORCEFAULT, &newstate);
 | 
								    ZFS_ONLINE_FORCEFAULT, &newstate);
 | 
				
			||||||
@ -457,6 +494,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
 | 
				
			|||||||
		    DEV_BYID_PATH, new_devid);
 | 
							    DEV_BYID_PATH, new_devid);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						libzfs_free_str_array(lines, lines_cnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Construct the root vdev to pass to zpool_vdev_attach().  While adding
 | 
						 * Construct the root vdev to pass to zpool_vdev_attach().  While adding
 | 
				
			||||||
	 * the entire vdev structure is harmless, we construct a reduced set of
 | 
						 * the entire vdev structure is harmless, we construct a reduced set of
 | 
				
			||||||
 | 
				
			|||||||
@ -439,39 +439,23 @@ static void
 | 
				
			|||||||
vdev_run_cmd(vdev_cmd_data_t *data, char *cmd)
 | 
					vdev_run_cmd(vdev_cmd_data_t *data, char *cmd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
	char *argv[2] = {cmd, 0};
 | 
						char *argv[2] = {cmd};
 | 
				
			||||||
	char *env[5] = {"PATH=/bin:/sbin:/usr/bin:/usr/sbin", NULL, NULL, NULL,
 | 
						char **env;
 | 
				
			||||||
	    NULL};
 | 
					 | 
				
			||||||
	char **lines = NULL;
 | 
						char **lines = NULL;
 | 
				
			||||||
	int lines_cnt = 0;
 | 
						int lines_cnt = 0;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Setup our custom environment variables */
 | 
						env = zpool_vdev_script_alloc_env(data->pool, data->path, data->upath,
 | 
				
			||||||
	rc = asprintf(&env[1], "VDEV_PATH=%s",
 | 
						    data->vdev_enc_sysfs_path, NULL, NULL);
 | 
				
			||||||
	    data->path ? data->path : "");
 | 
						if (env == NULL)
 | 
				
			||||||
	if (rc == -1) {
 | 
					 | 
				
			||||||
		env[1] = NULL;
 | 
					 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rc = asprintf(&env[2], "VDEV_UPATH=%s",
 | 
					 | 
				
			||||||
	    data->upath ? data->upath : "");
 | 
					 | 
				
			||||||
	if (rc == -1) {
 | 
					 | 
				
			||||||
		env[2] = NULL;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rc = asprintf(&env[3], "VDEV_ENC_SYSFS_PATH=%s",
 | 
					 | 
				
			||||||
	    data->vdev_enc_sysfs_path ?
 | 
					 | 
				
			||||||
	    data->vdev_enc_sysfs_path : "");
 | 
					 | 
				
			||||||
	if (rc == -1) {
 | 
					 | 
				
			||||||
		env[3] = NULL;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Run the command */
 | 
						/* Run the command */
 | 
				
			||||||
	rc = libzfs_run_process_get_stdout_nopath(cmd, argv, env, &lines,
 | 
						rc = libzfs_run_process_get_stdout_nopath(cmd, argv, env, &lines,
 | 
				
			||||||
	    &lines_cnt);
 | 
						    &lines_cnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						zpool_vdev_script_free_env(env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rc != 0)
 | 
						if (rc != 0)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -483,10 +467,6 @@ vdev_run_cmd(vdev_cmd_data_t *data, char *cmd)
 | 
				
			|||||||
out:
 | 
					out:
 | 
				
			||||||
	if (lines != NULL)
 | 
						if (lines != NULL)
 | 
				
			||||||
		libzfs_free_str_array(lines, lines_cnt);
 | 
							libzfs_free_str_array(lines, lines_cnt);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Start with i = 1 since env[0] was statically allocated */
 | 
					 | 
				
			||||||
	for (i = 1; i < ARRAY_SIZE(env); i++)
 | 
					 | 
				
			||||||
		free(env[i]);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 | 
				
			|||||||
@ -124,6 +124,10 @@ vdev_cmd_data_list_t *all_pools_for_each_vdev_run(int argc, char **argv,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void free_vdev_cmd_data_list(vdev_cmd_data_list_t *vcdl);
 | 
					void free_vdev_cmd_data_list(vdev_cmd_data_list_t *vcdl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void free_vdev_cmd_data(vdev_cmd_data_t *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int vdev_run_cmd_simple(char *path, char *cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int check_device(const char *path, boolean_t force,
 | 
					int check_device(const char *path, boolean_t force,
 | 
				
			||||||
    boolean_t isspare, boolean_t iswholedisk);
 | 
					    boolean_t isspare, boolean_t iswholedisk);
 | 
				
			||||||
boolean_t check_sector_size_database(char *path, int *sector_size);
 | 
					boolean_t check_sector_size_database(char *path, int *sector_size);
 | 
				
			||||||
 | 
				
			|||||||
@ -921,6 +921,15 @@ zero_label(char *path)
 | 
				
			|||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					lines_to_stderr(char *lines[], int lines_cnt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < lines_cnt; i++) {
 | 
				
			||||||
 | 
							fprintf(stderr, "%s\n", lines[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Go through and find any whole disks in the vdev specification, labelling them
 | 
					 * Go through and find any whole disks in the vdev specification, labelling them
 | 
				
			||||||
 * as appropriate.  When constructing the vdev spec, we were unable to open this
 | 
					 * as appropriate.  When constructing the vdev spec, we were unable to open this
 | 
				
			||||||
@ -932,7 +941,7 @@ zero_label(char *path)
 | 
				
			|||||||
 * need to get the devid after we label the disk.
 | 
					 * need to get the devid after we label the disk.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
make_disks(zpool_handle_t *zhp, nvlist_t *nv)
 | 
					make_disks(zpool_handle_t *zhp, nvlist_t *nv, boolean_t replacing)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nvlist_t **child;
 | 
						nvlist_t **child;
 | 
				
			||||||
	uint_t c, children;
 | 
						uint_t c, children;
 | 
				
			||||||
@ -1017,6 +1026,8 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
 | 
				
			|||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (!is_exclusive && !is_spare(NULL, udevpath)) {
 | 
							if (!is_exclusive && !is_spare(NULL, udevpath)) {
 | 
				
			||||||
			char *devnode = strrchr(devpath, '/') + 1;
 | 
								char *devnode = strrchr(devpath, '/') + 1;
 | 
				
			||||||
 | 
								char **lines = NULL;
 | 
				
			||||||
 | 
								int lines_cnt = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ret = strncmp(udevpath, UDISK_ROOT, strlen(UDISK_ROOT));
 | 
								ret = strncmp(udevpath, UDISK_ROOT, strlen(UDISK_ROOT));
 | 
				
			||||||
			if (ret == 0) {
 | 
								if (ret == 0) {
 | 
				
			||||||
@ -1028,9 +1039,27 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
 | 
				
			|||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * When labeling a pool the raw device node name
 | 
								 * When labeling a pool the raw device node name
 | 
				
			||||||
			 * is provided as it appears under /dev/.
 | 
								 * is provided as it appears under /dev/.
 | 
				
			||||||
 | 
								 *
 | 
				
			||||||
 | 
								 * Note that 'zhp' will be NULL when we're creating a
 | 
				
			||||||
 | 
								 * pool.
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			if (zpool_label_disk(g_zfs, zhp, devnode) == -1)
 | 
								if (zpool_prepare_and_label_disk(g_zfs, zhp, devnode,
 | 
				
			||||||
 | 
								    nv, zhp == NULL ? "create" :
 | 
				
			||||||
 | 
								    replacing ? "replace" : "add", &lines,
 | 
				
			||||||
 | 
								    &lines_cnt) != 0) {
 | 
				
			||||||
 | 
									(void) fprintf(stderr,
 | 
				
			||||||
 | 
									    gettext(
 | 
				
			||||||
 | 
									    "Error preparing/labeling disk.\n"));
 | 
				
			||||||
 | 
									if (lines_cnt > 0) {
 | 
				
			||||||
 | 
										(void) fprintf(stderr,
 | 
				
			||||||
 | 
										gettext("zfs_prepare_disk output:\n"));
 | 
				
			||||||
 | 
										lines_to_stderr(lines, lines_cnt);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									libzfs_free_str_array(lines, lines_cnt);
 | 
				
			||||||
				return (-1);
 | 
									return (-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								libzfs_free_str_array(lines, lines_cnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * Wait for udev to signal the device is available
 | 
								 * Wait for udev to signal the device is available
 | 
				
			||||||
@ -1067,19 +1096,19 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (c = 0; c < children; c++)
 | 
						for (c = 0; c < children; c++)
 | 
				
			||||||
		if ((ret = make_disks(zhp, child[c])) != 0)
 | 
							if ((ret = make_disks(zhp, child[c], replacing)) != 0)
 | 
				
			||||||
			return (ret);
 | 
								return (ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
 | 
						if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
 | 
				
			||||||
	    &child, &children) == 0)
 | 
						    &child, &children) == 0)
 | 
				
			||||||
		for (c = 0; c < children; c++)
 | 
							for (c = 0; c < children; c++)
 | 
				
			||||||
			if ((ret = make_disks(zhp, child[c])) != 0)
 | 
								if ((ret = make_disks(zhp, child[c], replacing)) != 0)
 | 
				
			||||||
				return (ret);
 | 
									return (ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
 | 
						if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
 | 
				
			||||||
	    &child, &children) == 0)
 | 
						    &child, &children) == 0)
 | 
				
			||||||
		for (c = 0; c < children; c++)
 | 
							for (c = 0; c < children; c++)
 | 
				
			||||||
			if ((ret = make_disks(zhp, child[c])) != 0)
 | 
								if ((ret = make_disks(zhp, child[c], replacing)) != 0)
 | 
				
			||||||
				return (ret);
 | 
									return (ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
@ -1740,7 +1769,7 @@ split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props,
 | 
				
			|||||||
			return (NULL);
 | 
								return (NULL);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!flags.dryrun && make_disks(zhp, newroot) != 0) {
 | 
							if (!flags.dryrun && make_disks(zhp, newroot, B_FALSE) != 0) {
 | 
				
			||||||
			nvlist_free(newroot);
 | 
								nvlist_free(newroot);
 | 
				
			||||||
			return (NULL);
 | 
								return (NULL);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -1861,7 +1890,7 @@ make_root_vdev(zpool_handle_t *zhp, nvlist_t *props, int force, int check_rep,
 | 
				
			|||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Run through the vdev specification and label any whole disks found.
 | 
						 * Run through the vdev specification and label any whole disks found.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!dryrun && make_disks(zhp, newroot) != 0) {
 | 
						if (!dryrun && make_disks(zhp, newroot, replacing) != 0) {
 | 
				
			||||||
		nvlist_free(newroot);
 | 
							nvlist_free(newroot);
 | 
				
			||||||
		return (NULL);
 | 
							return (NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -41,6 +41,7 @@ AM_CPPFLAGS += -D_REENTRANT
 | 
				
			|||||||
AM_CPPFLAGS += -D_FILE_OFFSET_BITS=64
 | 
					AM_CPPFLAGS += -D_FILE_OFFSET_BITS=64
 | 
				
			||||||
AM_CPPFLAGS += -D_LARGEFILE64_SOURCE
 | 
					AM_CPPFLAGS += -D_LARGEFILE64_SOURCE
 | 
				
			||||||
AM_CPPFLAGS += -DLIBEXECDIR=\"$(libexecdir)\"
 | 
					AM_CPPFLAGS += -DLIBEXECDIR=\"$(libexecdir)\"
 | 
				
			||||||
 | 
					AM_CPPFLAGS += -DZFSEXECDIR=\"$(zfsexecdir)\"
 | 
				
			||||||
AM_CPPFLAGS += -DRUNSTATEDIR=\"$(runstatedir)\"
 | 
					AM_CPPFLAGS += -DRUNSTATEDIR=\"$(runstatedir)\"
 | 
				
			||||||
AM_CPPFLAGS += -DSBINDIR=\"$(sbindir)\"
 | 
					AM_CPPFLAGS += -DSBINDIR=\"$(sbindir)\"
 | 
				
			||||||
AM_CPPFLAGS += -DSYSCONFDIR=\"$(sysconfdir)\"
 | 
					AM_CPPFLAGS += -DSYSCONFDIR=\"$(sysconfdir)\"
 | 
				
			||||||
 | 
				
			|||||||
@ -318,6 +318,15 @@ extern nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *,
 | 
				
			|||||||
extern nvlist_t *zpool_find_vdev_by_physpath(zpool_handle_t *, const char *,
 | 
					extern nvlist_t *zpool_find_vdev_by_physpath(zpool_handle_t *, const char *,
 | 
				
			||||||
    boolean_t *, boolean_t *, boolean_t *);
 | 
					    boolean_t *, boolean_t *, boolean_t *);
 | 
				
			||||||
extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, const char *);
 | 
					extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, const char *);
 | 
				
			||||||
 | 
					extern int zpool_prepare_disk(zpool_handle_t *zhp, nvlist_t *vdev_nv,
 | 
				
			||||||
 | 
					    const char *prepare_str, char **lines[], int *lines_cnt);
 | 
				
			||||||
 | 
					extern int zpool_prepare_and_label_disk(libzfs_handle_t *hdl,
 | 
				
			||||||
 | 
					    zpool_handle_t *, const char *, nvlist_t *vdev_nv, const char *prepare_str,
 | 
				
			||||||
 | 
					    char **lines[], int *lines_cnt);
 | 
				
			||||||
 | 
					extern char ** zpool_vdev_script_alloc_env(const char *pool_name,
 | 
				
			||||||
 | 
					    const char *vdev_path, const char *vdev_upath,
 | 
				
			||||||
 | 
					    const char *vdev_enc_sysfs_path, const char *opt_key, const char *opt_val);
 | 
				
			||||||
 | 
					extern void zpool_vdev_script_free_env(char **env);
 | 
				
			||||||
extern uint64_t zpool_vdev_path_to_guid(zpool_handle_t *zhp, const char *path);
 | 
					extern uint64_t zpool_vdev_path_to_guid(zpool_handle_t *zhp, const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *zpool_get_state_str(zpool_handle_t *);
 | 
					const char *zpool_get_state_str(zpool_handle_t *);
 | 
				
			||||||
 | 
				
			|||||||
@ -333,6 +333,8 @@
 | 
				
			|||||||
    <elf-symbol name='zpool_open_canfail' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_open_canfail' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_open_silent' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_open_silent' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_pool_state_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_pool_state_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
 | 
					    <elf-symbol name='zpool_prepare_and_label_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
 | 
					    <elf-symbol name='zpool_prepare_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_print_unsup_feat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_print_unsup_feat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_prop_align_right' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_prop_align_right' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_prop_column_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_prop_column_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
@ -380,6 +382,8 @@
 | 
				
			|||||||
    <elf-symbol name='zpool_vdev_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_vdev_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_vdev_remove_cancel' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_vdev_remove_cancel' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_vdev_remove_wanted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_vdev_remove_wanted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
 | 
					    <elf-symbol name='zpool_vdev_script_alloc_env' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
 | 
					    <elf-symbol name='zpool_vdev_script_free_env' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_vdev_split' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_vdev_split' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
    <elf-symbol name='zpool_wait_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
					    <elf-symbol name='zpool_wait_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 | 
				
			||||||
 | 
				
			|||||||
@ -2121,3 +2121,196 @@ printf_color(const char *color, char *format, ...)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return (rc);
 | 
						return (rc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* PATH + 5 env vars + a NULL entry = 7 */
 | 
				
			||||||
 | 
					#define	ZPOOL_VDEV_SCRIPT_ENV_COUNT 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * There's a few places where ZFS will call external scripts (like the script
 | 
				
			||||||
 | 
					 * in zpool.d/ and `zfs_prepare_disk`).  These scripts are called with a
 | 
				
			||||||
 | 
					 * reduced $PATH, and some vdev specific environment vars set.  This function
 | 
				
			||||||
 | 
					 * will allocate an populate the environment variable array that is passed to
 | 
				
			||||||
 | 
					 * these scripts.  The user must free the arrays with zpool_vdev_free_env() when
 | 
				
			||||||
 | 
					 * they are done.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The following env vars will be set (but value could be blank):
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * POOL_NAME
 | 
				
			||||||
 | 
					 * VDEV_PATH
 | 
				
			||||||
 | 
					 * VDEV_UPATH
 | 
				
			||||||
 | 
					 * VDEV_ENC_SYSFS_PATH
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * In addition, you can set an optional environment variable named 'opt_key'
 | 
				
			||||||
 | 
					 * to 'opt_val' if you want.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns allocated env[] array on success, NULL otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					char **
 | 
				
			||||||
 | 
					zpool_vdev_script_alloc_env(const char *pool_name,
 | 
				
			||||||
 | 
					    const char *vdev_path, const char *vdev_upath,
 | 
				
			||||||
 | 
					    const char *vdev_enc_sysfs_path, const char *opt_key, const char *opt_val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char **env = NULL;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						env = calloc(ZPOOL_VDEV_SCRIPT_ENV_COUNT, sizeof (*env));
 | 
				
			||||||
 | 
						if (!env)
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						env[0] = strdup("PATH=/bin:/sbin:/usr/bin:/usr/sbin");
 | 
				
			||||||
 | 
						if (!env[0])
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Setup our custom environment variables */
 | 
				
			||||||
 | 
						rc = asprintf(&env[1], "POOL_NAME=%s", pool_name ? pool_name : "");
 | 
				
			||||||
 | 
						if (rc == -1) {
 | 
				
			||||||
 | 
							env[1] = NULL;
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = asprintf(&env[2], "VDEV_PATH=%s", vdev_path ? vdev_path : "");
 | 
				
			||||||
 | 
						if (rc == -1) {
 | 
				
			||||||
 | 
							env[2] = NULL;
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = asprintf(&env[3], "VDEV_UPATH=%s", vdev_upath ? vdev_upath : "");
 | 
				
			||||||
 | 
						if (rc == -1) {
 | 
				
			||||||
 | 
							env[3] = NULL;
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = asprintf(&env[4], "VDEV_ENC_SYSFS_PATH=%s",
 | 
				
			||||||
 | 
						    vdev_enc_sysfs_path ?  vdev_enc_sysfs_path : "");
 | 
				
			||||||
 | 
						if (rc == -1) {
 | 
				
			||||||
 | 
							env[4] = NULL;
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (opt_key != NULL) {
 | 
				
			||||||
 | 
							rc = asprintf(&env[5], "%s=%s", opt_key,
 | 
				
			||||||
 | 
							    opt_val ? opt_val : "");
 | 
				
			||||||
 | 
							if (rc == -1) {
 | 
				
			||||||
 | 
								env[5] = NULL;
 | 
				
			||||||
 | 
								goto error;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error:
 | 
				
			||||||
 | 
						for (int i = 0; i < ZPOOL_VDEV_SCRIPT_ENV_COUNT; i++)
 | 
				
			||||||
 | 
							free(env[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Free the env[] array that was allocated by zpool_vdev_script_alloc_env().
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					zpool_vdev_script_free_env(char **env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						for (int i = 0; i < ZPOOL_VDEV_SCRIPT_ENV_COUNT; i++)
 | 
				
			||||||
 | 
							free(env[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(env);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Prepare a disk by (optionally) running a program before labeling the disk.
 | 
				
			||||||
 | 
					 * This can be useful for installing disk firmware or doing some pre-flight
 | 
				
			||||||
 | 
					 * checks on the disk before it becomes part of the pool.  The program run is
 | 
				
			||||||
 | 
					 * located at ZFSEXECDIR/zfs_prepare_disk
 | 
				
			||||||
 | 
					 * (E.x: /usr/local/libexec/zfs/zfs_prepare_disk).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return 0 on success, non-zero on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					zpool_prepare_disk(zpool_handle_t *zhp, nvlist_t *vdev_nv,
 | 
				
			||||||
 | 
					    const char *prepare_str, char **lines[], int *lines_cnt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *script_path = ZFSEXECDIR "/zfs_prepare_disk";
 | 
				
			||||||
 | 
						const char *pool_name;
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Path to script and a NULL entry */
 | 
				
			||||||
 | 
						char *argv[2] = {(char *)script_path};
 | 
				
			||||||
 | 
						char **env = NULL;
 | 
				
			||||||
 | 
						char *path = NULL, *enc_sysfs_path = NULL;
 | 
				
			||||||
 | 
						char *upath;
 | 
				
			||||||
 | 
						*lines_cnt = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (access(script_path, X_OK) != 0) {
 | 
				
			||||||
 | 
							/* No script, nothing to do */
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void) nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_PATH, &path);
 | 
				
			||||||
 | 
						(void) nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
 | 
				
			||||||
 | 
						    &enc_sysfs_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						upath = zfs_get_underlying_path(path);
 | 
				
			||||||
 | 
						pool_name = zhp ? zpool_get_name(zhp) : NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						env = zpool_vdev_script_alloc_env(pool_name, path, upath,
 | 
				
			||||||
 | 
						    enc_sysfs_path, "VDEV_PREPARE", prepare_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(upath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (env == NULL) {
 | 
				
			||||||
 | 
							return (ENOMEM);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = libzfs_run_process_get_stdout(script_path, argv, env, lines,
 | 
				
			||||||
 | 
						    lines_cnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						zpool_vdev_script_free_env(env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (rc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Optionally run a script and then label a disk.  The script can be used to
 | 
				
			||||||
 | 
					 * prepare a disk for inclusion into the pool.  For example, it might update
 | 
				
			||||||
 | 
					 * the disk's firmware or check its health.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The 'name' provided is the short name, stripped of any leading
 | 
				
			||||||
 | 
					 * /dev path, and is passed to zpool_label_disk. vdev_nv is the nvlist for
 | 
				
			||||||
 | 
					 * the vdev.  prepare_str is a string that gets passed as the VDEV_PREPARE
 | 
				
			||||||
 | 
					 * env variable to the script.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The following env vars are passed to the script:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * POOL_NAME:		The pool name (blank during zpool create)
 | 
				
			||||||
 | 
					 * VDEV_PREPARE:	Reason why the disk is being prepared for inclusion:
 | 
				
			||||||
 | 
					 *			"create", "add", "replace", or "autoreplace"
 | 
				
			||||||
 | 
					 * VDEV_PATH:		Path to the disk
 | 
				
			||||||
 | 
					 * VDEV_UPATH:		One of the 'underlying paths' to the disk.  This is
 | 
				
			||||||
 | 
					 * 			useful for DM devices.
 | 
				
			||||||
 | 
					 * VDEV_ENC_SYSFS_PATH:	Path to the disk's enclosure sysfs path, if available.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Note, some of these values can be blank.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return 0 on success, non-zero otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					zpool_prepare_and_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp,
 | 
				
			||||||
 | 
					    const char *name, nvlist_t *vdev_nv, const char *prepare_str,
 | 
				
			||||||
 | 
					    char **lines[], int *lines_cnt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						char vdev_path[MAXPATHLEN];
 | 
				
			||||||
 | 
						(void) snprintf(vdev_path, sizeof (vdev_path), "%s/%s", DISK_ROOT,
 | 
				
			||||||
 | 
						    name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* zhp will be NULL when creating a pool */
 | 
				
			||||||
 | 
						rc = zpool_prepare_disk(zhp, vdev_nv, prepare_str, lines, lines_cnt);
 | 
				
			||||||
 | 
						if (rc != 0)
 | 
				
			||||||
 | 
							return (rc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = zpool_label_disk(hdl, zhp, name);
 | 
				
			||||||
 | 
						return (rc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -104,7 +104,8 @@ dist_man_MANS = \
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
nodist_man_MANS = \
 | 
					nodist_man_MANS = \
 | 
				
			||||||
	man8/zed.8 \
 | 
						man8/zed.8 \
 | 
				
			||||||
	man8/zfs-mount-generator.8
 | 
						man8/zfs-mount-generator.8 \
 | 
				
			||||||
 | 
						man8/zfs_prepare_disk.8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SUBSTFILES += $(nodist_man_MANS)
 | 
					SUBSTFILES += $(nodist_man_MANS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								man/man8/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								man/man8/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,2 +1,3 @@
 | 
				
			|||||||
/zed.8
 | 
					/zed.8
 | 
				
			||||||
/zfs-mount-generator.8
 | 
					/zfs-mount-generator.8
 | 
				
			||||||
 | 
					/zfs_prepare_disk.8
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										70
									
								
								man/man8/zfs_prepare_disk.8.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								man/man8/zfs_prepare_disk.8.in
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					.\"
 | 
				
			||||||
 | 
					.\" Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
 | 
				
			||||||
 | 
					.\" Copyright (C) 2023 Lawrence Livermore National Security, LLC.
 | 
				
			||||||
 | 
					.\" Refer to the OpenZFS git commit log for authoritative copyright attribution.
 | 
				
			||||||
 | 
					.\"
 | 
				
			||||||
 | 
					.\" The contents of this file are subject to the terms of the
 | 
				
			||||||
 | 
					.\" Common Development and Distribution License Version 1.0 (CDDL-1.0).
 | 
				
			||||||
 | 
					.\" You can obtain a copy of the license from the top-level file
 | 
				
			||||||
 | 
					.\" "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
 | 
				
			||||||
 | 
					.\" You may not use this file except in compliance with the license.
 | 
				
			||||||
 | 
					.\"
 | 
				
			||||||
 | 
					.\" Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049)
 | 
				
			||||||
 | 
					.\"
 | 
				
			||||||
 | 
					.Dd August 30, 2023
 | 
				
			||||||
 | 
					.Dt ZFS_PREPARE_DISK 8
 | 
				
			||||||
 | 
					.Os
 | 
				
			||||||
 | 
					.
 | 
				
			||||||
 | 
					.Sh NAME
 | 
				
			||||||
 | 
					.Nm zfs_prepare_disk
 | 
				
			||||||
 | 
					.Nd special script that gets run before bringing a disk into a pool
 | 
				
			||||||
 | 
					.Sh DESCRIPTION
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
 | 
					is an optional script that gets called by libzfs before bringing a disk into a
 | 
				
			||||||
 | 
					pool.
 | 
				
			||||||
 | 
					It can be modified by the user to run whatever commands are necessary to prepare
 | 
				
			||||||
 | 
					a disk for inclusion into the pool.
 | 
				
			||||||
 | 
					For example, users can add lines to
 | 
				
			||||||
 | 
					.Nm zfs_prepare_disk
 | 
				
			||||||
 | 
					to do things like update the drive's firmware or check the drive's health.
 | 
				
			||||||
 | 
					.Nm zfs_prepare_disk
 | 
				
			||||||
 | 
					is optional and can be removed if not needed.
 | 
				
			||||||
 | 
					libzfs will look for the script at @zfsexecdir@/zfs_prepare_disk.
 | 
				
			||||||
 | 
					.
 | 
				
			||||||
 | 
					.Ss Properties
 | 
				
			||||||
 | 
					.Nm zfs_prepare_disk
 | 
				
			||||||
 | 
					will be passed the following environment variables:
 | 
				
			||||||
 | 
					.sp
 | 
				
			||||||
 | 
					.Bl -tag -compact -width "VDEV_ENC_SYSFS_PATH"
 | 
				
			||||||
 | 
					.
 | 
				
			||||||
 | 
					.It Nm POOL_NAME
 | 
				
			||||||
 | 
					.No Name of the pool
 | 
				
			||||||
 | 
					.It Nm VDEV_PATH
 | 
				
			||||||
 | 
					.No Path to the disk (like /dev/sda)
 | 
				
			||||||
 | 
					.It Nm VDEV_PREPARE
 | 
				
			||||||
 | 
					.No Reason why the disk is being prepared for inclusion
 | 
				
			||||||
 | 
					('create', 'add', 'replace', or 'autoreplace').
 | 
				
			||||||
 | 
					This can be useful if you only want the script to be run under certain actions.
 | 
				
			||||||
 | 
					.It Nm VDEV_UPATH
 | 
				
			||||||
 | 
					.No Path to one of the underlying devices for the
 | 
				
			||||||
 | 
					disk.
 | 
				
			||||||
 | 
					For multipath this would return one of the /dev/sd* paths to the disk.
 | 
				
			||||||
 | 
					If the device is not a device mapper device, then
 | 
				
			||||||
 | 
					.Nm VDEV_UPATH
 | 
				
			||||||
 | 
					just returns the same value as
 | 
				
			||||||
 | 
					.Nm VDEV_PATH
 | 
				
			||||||
 | 
					.It Nm VDEV_ENC_SYSFS_PATH
 | 
				
			||||||
 | 
					.No Path to the disk's enclosure sysfs path, if available
 | 
				
			||||||
 | 
					.El
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
 | 
					Note that some of these variables may have a blank value.
 | 
				
			||||||
 | 
					.Nm POOL_NAME
 | 
				
			||||||
 | 
					is blank at pool creation time, for example.
 | 
				
			||||||
 | 
					.Sh ENVIRONMENT
 | 
				
			||||||
 | 
					.Nm zfs_prepare_disk
 | 
				
			||||||
 | 
					runs with a limited $PATH.
 | 
				
			||||||
 | 
					.Sh EXIT STATUS
 | 
				
			||||||
 | 
					.Nm zfs_prepare_disk
 | 
				
			||||||
 | 
					should return 0 on success, non-zero otherwise.
 | 
				
			||||||
 | 
					If non-zero is returned, the disk will not be included in the pool.
 | 
				
			||||||
 | 
					.
 | 
				
			||||||
@ -9,6 +9,9 @@ dist_pkgdata_SCRIPTS = \
 | 
				
			|||||||
	zloop.sh \
 | 
						zloop.sh \
 | 
				
			||||||
	zfs-helpers.sh
 | 
						zfs-helpers.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dist_zfsexec_SCRIPTS = \
 | 
				
			||||||
 | 
						zfs_prepare_disk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXTRA_SCRIPTS = \
 | 
					EXTRA_SCRIPTS = \
 | 
				
			||||||
	commitcheck.sh \
 | 
						commitcheck.sh \
 | 
				
			||||||
	common.sh.in \
 | 
						common.sh.in \
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								scripts/zfs_prepare_disk
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								scripts/zfs_prepare_disk
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This is an optional helper script that is automatically called by libzfs
 | 
				
			||||||
 | 
					# before a disk is about to be added into the pool.  It can be modified by
 | 
				
			||||||
 | 
					# the user to run whatever commands are necessary to prepare a disk for
 | 
				
			||||||
 | 
					# inclusion into the pool.  For example, users can add lines to this
 | 
				
			||||||
 | 
					# script to do things like update the drive's firmware or check the drive's
 | 
				
			||||||
 | 
					# health.  The script is optional and can be removed if it is not needed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# See the zfs_prepare_disk(8) man page for details.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Example:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# echo "Prepare disk $VDEV_PATH ($VDEV_UPATH) for $VDEV_PREPARE in $POOL_NAME"
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit 0
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user