mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Rebase master to b117
This commit is contained in:
+27
-13
@@ -116,6 +116,7 @@ enum {
|
||||
EZFS_VDEVNOTSUP, /* unsupported vdev type */
|
||||
EZFS_NOTSUP, /* ops not supported on this dataset */
|
||||
EZFS_ACTIVE_SPARE, /* pool has active shared spare devices */
|
||||
EZFS_UNPLAYED_LOGS, /* log device has unplayed logs */
|
||||
EZFS_UNKNOWN
|
||||
};
|
||||
|
||||
@@ -178,6 +179,7 @@ extern const char *libzfs_error_action(libzfs_handle_t *);
|
||||
extern const char *libzfs_error_description(libzfs_handle_t *);
|
||||
extern void libzfs_mnttab_init(libzfs_handle_t *);
|
||||
extern void libzfs_mnttab_fini(libzfs_handle_t *);
|
||||
extern void libzfs_mnttab_cache(libzfs_handle_t *, boolean_t);
|
||||
extern int libzfs_mnttab_find(libzfs_handle_t *, const char *,
|
||||
struct mnttab *);
|
||||
extern void libzfs_mnttab_add(libzfs_handle_t *, const char *,
|
||||
@@ -229,6 +231,8 @@ extern int zpool_vdev_clear(zpool_handle_t *, uint64_t);
|
||||
|
||||
extern nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *,
|
||||
boolean_t *, boolean_t *);
|
||||
extern nvlist_t *zpool_find_vdev_by_physpath(zpool_handle_t *, const char *,
|
||||
boolean_t *, boolean_t *, boolean_t *);
|
||||
extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, char *);
|
||||
|
||||
/*
|
||||
@@ -335,7 +339,8 @@ extern int zpool_stage_history(libzfs_handle_t *, const char *);
|
||||
extern void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *,
|
||||
size_t len);
|
||||
extern int zfs_ioctl(libzfs_handle_t *, int, struct zfs_cmd *);
|
||||
extern int zpool_get_physpath(zpool_handle_t *, char *);
|
||||
extern int zpool_get_physpath(zpool_handle_t *, char *, size_t);
|
||||
|
||||
/*
|
||||
* Basic handle manipulations. These functions do not create or destroy the
|
||||
* underlying datasets, only the references to them.
|
||||
@@ -368,6 +373,10 @@ extern int zfs_prop_get(zfs_handle_t *, zfs_prop_t, char *, size_t,
|
||||
zprop_source_t *, char *, size_t, boolean_t);
|
||||
extern int zfs_prop_get_numeric(zfs_handle_t *, zfs_prop_t, uint64_t *,
|
||||
zprop_source_t *, char *, size_t);
|
||||
extern int zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
|
||||
uint64_t *propvalue);
|
||||
extern int zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
|
||||
char *propbuf, int proplen, boolean_t literal);
|
||||
extern uint64_t zfs_prop_get_int(zfs_handle_t *, zfs_prop_t);
|
||||
extern int zfs_prop_inherit(zfs_handle_t *, const char *);
|
||||
extern const char *zfs_prop_values(zfs_prop_t);
|
||||
@@ -384,6 +393,7 @@ typedef struct zprop_list {
|
||||
} zprop_list_t;
|
||||
|
||||
extern int zfs_expand_proplist(zfs_handle_t *, zprop_list_t **);
|
||||
extern void zfs_prune_proplist(zfs_handle_t *, uint8_t *);
|
||||
|
||||
#define ZFS_MOUNTPOINT_NONE "none"
|
||||
#define ZFS_MOUNTPOINT_LEGACY "legacy"
|
||||
@@ -454,6 +464,12 @@ extern int zfs_send(zfs_handle_t *, const char *, const char *,
|
||||
boolean_t, boolean_t, boolean_t, boolean_t, int);
|
||||
extern int zfs_promote(zfs_handle_t *);
|
||||
|
||||
typedef int (*zfs_userspace_cb_t)(void *arg, const char *domain,
|
||||
uid_t rid, uint64_t space);
|
||||
|
||||
extern int zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
|
||||
zfs_userspace_cb_t func, void *arg);
|
||||
|
||||
typedef struct recvflags {
|
||||
/* print informational messages (ie, -v was specified) */
|
||||
int verbose : 1;
|
||||
@@ -491,17 +507,6 @@ extern boolean_t zfs_dataset_exists(libzfs_handle_t *, const char *,
|
||||
zfs_type_t);
|
||||
extern int zfs_spa_version(zfs_handle_t *, int *);
|
||||
|
||||
/*
|
||||
* dataset permission functions.
|
||||
*/
|
||||
extern int zfs_perm_set(zfs_handle_t *, nvlist_t *);
|
||||
extern int zfs_perm_remove(zfs_handle_t *, nvlist_t *);
|
||||
extern int zfs_build_perms(zfs_handle_t *, char *, char *,
|
||||
zfs_deleg_who_type_t, zfs_deleg_inherit_t, nvlist_t **nvlist_t);
|
||||
extern int zfs_perm_get(zfs_handle_t *, zfs_allow_t **);
|
||||
extern void zfs_free_allows(zfs_allow_t *);
|
||||
extern void zfs_deleg_permissions(void);
|
||||
|
||||
/*
|
||||
* Mount support functions.
|
||||
*/
|
||||
@@ -536,7 +541,7 @@ extern boolean_t zfs_is_shared_iscsi(zfs_handle_t *);
|
||||
extern int zfs_share_iscsi(zfs_handle_t *);
|
||||
extern int zfs_unshare_iscsi(zfs_handle_t *);
|
||||
extern int zfs_iscsi_perm_check(libzfs_handle_t *, char *, ucred_t *);
|
||||
extern int zfs_deleg_share_nfs(libzfs_handle_t *, char *, char *,
|
||||
extern int zfs_deleg_share_nfs(libzfs_handle_t *, char *, char *, char *,
|
||||
void *, void *, int, zfs_share_op_t);
|
||||
|
||||
/*
|
||||
@@ -574,6 +579,15 @@ extern int zpool_remove_zvol_links(zpool_handle_t *);
|
||||
/* is this zvol valid for use as a dump device? */
|
||||
extern int zvol_check_dump_config(char *);
|
||||
|
||||
/*
|
||||
* Management interfaces for SMB ACL files
|
||||
*/
|
||||
|
||||
int zfs_smb_acl_add(libzfs_handle_t *, char *, char *, char *);
|
||||
int zfs_smb_acl_remove(libzfs_handle_t *, char *, char *, char *);
|
||||
int zfs_smb_acl_purge(libzfs_handle_t *, char *, char *);
|
||||
int zfs_smb_acl_rename(libzfs_handle_t *, char *, char *, char *, char *);
|
||||
|
||||
/*
|
||||
* Enable and disable datasets within a pool by mounting/unmounting and
|
||||
* sharing/unsharing them.
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -63,6 +63,7 @@ struct libzfs_handle {
|
||||
int libzfs_printerr;
|
||||
void *libzfs_sharehdl; /* libshare handle */
|
||||
uint_t libzfs_shareflags;
|
||||
boolean_t libzfs_mnttab_enable;
|
||||
avl_tree_t libzfs_mnttab_cache;
|
||||
};
|
||||
#define ZFSSHARE_MISS 0x01 /* Didn't find entry in cache */
|
||||
@@ -78,6 +79,7 @@ struct zfs_handle {
|
||||
nvlist_t *zfs_user_props;
|
||||
boolean_t zfs_mntcheck;
|
||||
char *zfs_mntopts;
|
||||
uint8_t *zfs_props_table;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -185,7 +187,7 @@ extern int zfs_init_libshare(libzfs_handle_t *, int);
|
||||
extern void zfs_uninit_libshare(libzfs_handle_t *);
|
||||
extern int zfs_parse_options(char *, zfs_share_proto_t);
|
||||
|
||||
extern int zfs_unshare_proto(zfs_handle_t *zhp,
|
||||
extern int zfs_unshare_proto(zfs_handle_t *,
|
||||
const char *, zfs_share_proto_t *);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* Portions Copyright 2007 Ramprakash Jelari
|
||||
@@ -218,6 +218,7 @@ changelist_postfix(prop_changelist_t *clp)
|
||||
|
||||
boolean_t sharenfs;
|
||||
boolean_t sharesmb;
|
||||
boolean_t mounted;
|
||||
|
||||
/*
|
||||
* If we are in the global zone, but this dataset is exported
|
||||
@@ -272,20 +273,29 @@ changelist_postfix(prop_changelist_t *clp)
|
||||
shareopts, sizeof (shareopts), NULL, NULL, 0,
|
||||
B_FALSE) == 0) && (strcmp(shareopts, "off") != 0));
|
||||
|
||||
if ((cn->cn_mounted || clp->cl_waslegacy || sharenfs ||
|
||||
sharesmb) && !zfs_is_mounted(cn->cn_handle, NULL) &&
|
||||
zfs_mount(cn->cn_handle, NULL, 0) != 0)
|
||||
errors++;
|
||||
mounted = zfs_is_mounted(cn->cn_handle, NULL);
|
||||
|
||||
if (!mounted && (cn->cn_mounted ||
|
||||
((sharenfs || sharesmb || clp->cl_waslegacy) &&
|
||||
(zfs_prop_get_int(cn->cn_handle,
|
||||
ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_ON)))) {
|
||||
|
||||
if (zfs_mount(cn->cn_handle, NULL, 0) != 0)
|
||||
errors++;
|
||||
else
|
||||
mounted = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* We always re-share even if the filesystem is currently
|
||||
* shared, so that we can adopt any new options.
|
||||
* If the file system is mounted we always re-share even
|
||||
* if the filesystem is currently shared, so that we can
|
||||
* adopt any new options.
|
||||
*/
|
||||
if (sharenfs)
|
||||
if (sharenfs && mounted)
|
||||
errors += zfs_share_nfs(cn->cn_handle);
|
||||
else if (cn->cn_shared || clp->cl_waslegacy)
|
||||
errors += zfs_unshare_nfs(cn->cn_handle, NULL);
|
||||
if (sharesmb)
|
||||
if (sharesmb && mounted)
|
||||
errors += zfs_share_smb(cn->cn_handle);
|
||||
else if (cn->cn_shared || clp->cl_waslegacy)
|
||||
errors += zfs_unshare_smb(cn->cn_handle, NULL);
|
||||
@@ -621,8 +631,6 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
clp->cl_prop = ZFS_PROP_MOUNTPOINT;
|
||||
} else if (prop == ZFS_PROP_VOLSIZE) {
|
||||
clp->cl_prop = ZFS_PROP_MOUNTPOINT;
|
||||
} else if (prop == ZFS_PROP_VERSION) {
|
||||
clp->cl_prop = ZFS_PROP_MOUNTPOINT;
|
||||
} else {
|
||||
clp->cl_prop = prop;
|
||||
}
|
||||
|
||||
+481
-831
File diff suppressed because it is too large
Load Diff
@@ -19,12 +19,10 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Iterate over all children of the current object. This includes the normal
|
||||
* dataset hierarchy, but also arbitrary hierarchies due to clones. We want to
|
||||
@@ -399,13 +397,6 @@ iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
|
||||
for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
|
||||
ioctl(hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0;
|
||||
(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) {
|
||||
|
||||
/*
|
||||
* Ignore private dataset names.
|
||||
*/
|
||||
if (dataset_name_hidden(zc.zc_name))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Get statistics for this dataset, to determine the type of the
|
||||
* dataset and clone statistics. If this fails, the dataset has
|
||||
|
||||
+324
-107
@@ -42,6 +42,7 @@
|
||||
#include <sys/zfs_ioctl.h>
|
||||
#include <sys/zio.h>
|
||||
#include <strings.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "zfs_namecheck.h"
|
||||
#include "zfs_prop.h"
|
||||
@@ -55,6 +56,10 @@ static int read_efi_label(nvlist_t *config, diskaddr_t *sb);
|
||||
#define BOOTCMD "installboot(1M)"
|
||||
#endif
|
||||
|
||||
#define DISK_ROOT "/dev/dsk"
|
||||
#define RDISK_ROOT "/dev/rdsk"
|
||||
#define BACKUP_SLICE "s2"
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* zpool property functions
|
||||
@@ -627,6 +632,12 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Don't start the slice at the default block of 34; many storage
|
||||
* devices will use a stripe width of 128k, so start there instead.
|
||||
*/
|
||||
#define NEW_START_BLOCK 256
|
||||
|
||||
/*
|
||||
* Validate the given pool name, optionally putting an extended error message in
|
||||
* 'buf'.
|
||||
@@ -1369,46 +1380,90 @@ zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type)
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a vdev that matches the search criteria specified. We use the
|
||||
* the nvpair name to determine how we should look for the device.
|
||||
* 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
|
||||
* spare; but FALSE if its an INUSE spare.
|
||||
*/
|
||||
static nvlist_t *
|
||||
vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid,
|
||||
boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
|
||||
vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
|
||||
boolean_t *l2cache, boolean_t *log)
|
||||
{
|
||||
uint_t c, children;
|
||||
nvlist_t **child;
|
||||
uint64_t theguid, present;
|
||||
char *path;
|
||||
uint64_t wholedisk = 0;
|
||||
nvlist_t *ret;
|
||||
uint64_t is_log;
|
||||
char *srchkey;
|
||||
nvpair_t *pair = nvlist_next_nvpair(search, NULL);
|
||||
|
||||
verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0);
|
||||
/* Nothing to look for */
|
||||
if (search == NULL || pair == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (search == NULL &&
|
||||
nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) {
|
||||
/*
|
||||
* If the device has never been present since import, the only
|
||||
* reliable way to match the vdev is by GUID.
|
||||
*/
|
||||
if (theguid == guid)
|
||||
return (nv);
|
||||
} else if (search != NULL &&
|
||||
nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
|
||||
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
&wholedisk);
|
||||
if (wholedisk) {
|
||||
/*
|
||||
* For whole disks, the internal path has 's0', but the
|
||||
* path passed in by the user doesn't.
|
||||
*/
|
||||
if (strlen(search) == strlen(path) - 2 &&
|
||||
strncmp(search, path, strlen(search)) == 0)
|
||||
return (nv);
|
||||
} else if (strcmp(search, path) == 0) {
|
||||
return (nv);
|
||||
/* Obtain the key we will use to search */
|
||||
srchkey = nvpair_name(pair);
|
||||
|
||||
switch (nvpair_type(pair)) {
|
||||
case DATA_TYPE_UINT64: {
|
||||
uint64_t srchval, theguid, present;
|
||||
|
||||
verify(nvpair_value_uint64(pair, &srchval) == 0);
|
||||
if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
|
||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
|
||||
&present) == 0) {
|
||||
/*
|
||||
* If the device has never been present since
|
||||
* import, the only reliable way to match the
|
||||
* vdev is by GUID.
|
||||
*/
|
||||
verify(nvlist_lookup_uint64(nv,
|
||||
ZPOOL_CONFIG_GUID, &theguid) == 0);
|
||||
if (theguid == srchval)
|
||||
return (nv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DATA_TYPE_STRING: {
|
||||
char *srchval, *val;
|
||||
|
||||
verify(nvpair_value_string(pair, &srchval) == 0);
|
||||
if (nvlist_lookup_string(nv, srchkey, &val) != 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Search for the requested value. We special case the search
|
||||
* for ZPOOL_CONFIG_PATH when it's a wholedisk. Otherwise,
|
||||
* all other searches are simple string compares.
|
||||
*/
|
||||
if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0 && val) {
|
||||
uint64_t wholedisk = 0;
|
||||
|
||||
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
&wholedisk);
|
||||
if (wholedisk) {
|
||||
/*
|
||||
* For whole disks, the internal path has 's0',
|
||||
* but the path passed in by the user doesn't.
|
||||
*/
|
||||
if (strlen(srchval) == strlen(val) - 2 &&
|
||||
strncmp(srchval, val, strlen(srchval)) == 0)
|
||||
return (nv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Common case
|
||||
*/
|
||||
if (strcmp(srchval, val) == 0)
|
||||
return (nv);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
@@ -1416,7 +1471,7 @@ vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid,
|
||||
return (NULL);
|
||||
|
||||
for (c = 0; c < children; c++) {
|
||||
if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
|
||||
if ((ret = vdev_to_nvlist_iter(child[c], search,
|
||||
avail_spare, l2cache, NULL)) != NULL) {
|
||||
/*
|
||||
* The 'is_log' value is only set for the toplevel
|
||||
@@ -1437,7 +1492,7 @@ vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid,
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++) {
|
||||
if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
|
||||
if ((ret = vdev_to_nvlist_iter(child[c], search,
|
||||
avail_spare, l2cache, NULL)) != NULL) {
|
||||
*avail_spare = B_TRUE;
|
||||
return (ret);
|
||||
@@ -1448,7 +1503,7 @@ vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid,
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++) {
|
||||
if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
|
||||
if ((ret = vdev_to_nvlist_iter(child[c], search,
|
||||
avail_spare, l2cache, NULL)) != NULL) {
|
||||
*l2cache = B_TRUE;
|
||||
return (ret);
|
||||
@@ -1459,24 +1514,48 @@ vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a physical path (minus the "/devices" prefix), find the
|
||||
* associated vdev.
|
||||
*/
|
||||
nvlist_t *
|
||||
zpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath,
|
||||
boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
|
||||
{
|
||||
nvlist_t *search, *nvroot, *ret;
|
||||
|
||||
verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
|
||||
verify(nvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath) == 0);
|
||||
|
||||
verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&nvroot) == 0);
|
||||
|
||||
*avail_spare = B_FALSE;
|
||||
ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
|
||||
nvlist_free(search);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
nvlist_t *
|
||||
zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
|
||||
boolean_t *l2cache, boolean_t *log)
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
const char *search;
|
||||
char *end;
|
||||
nvlist_t *nvroot;
|
||||
nvlist_t *nvroot, *search, *ret;
|
||||
uint64_t guid;
|
||||
|
||||
verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
|
||||
|
||||
guid = strtoull(path, &end, 10);
|
||||
if (guid != 0 && *end == '\0') {
|
||||
search = NULL;
|
||||
verify(nvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid) == 0);
|
||||
} else if (path[0] != '/') {
|
||||
(void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path);
|
||||
search = buf;
|
||||
verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, buf) == 0);
|
||||
} else {
|
||||
search = path;
|
||||
verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, path) == 0);
|
||||
}
|
||||
|
||||
verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
@@ -1486,8 +1565,10 @@ zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
|
||||
*l2cache = B_FALSE;
|
||||
if (log != NULL)
|
||||
*log = B_FALSE;
|
||||
return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare,
|
||||
l2cache, log));
|
||||
ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
|
||||
nvlist_free(search);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1504,80 +1585,141 @@ vdev_online(nvlist_t *nv)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get phys_path for a root pool
|
||||
* Return 0 on success; non-zeron on failure.
|
||||
* Helper function for zpool_get_physpaths().
|
||||
*/
|
||||
int
|
||||
zpool_get_physpath(zpool_handle_t *zhp, char *physpath)
|
||||
static int
|
||||
vdev_get_one_physpath(nvlist_t *config, char *physpath, size_t physpath_size,
|
||||
size_t *bytes_written)
|
||||
{
|
||||
nvlist_t *vdev_root;
|
||||
nvlist_t **child;
|
||||
uint_t count;
|
||||
int i;
|
||||
size_t bytes_left, pos, rsz;
|
||||
char *tmppath;
|
||||
const char *format;
|
||||
|
||||
/*
|
||||
* Make sure this is a root pool, as phys_path doesn't mean
|
||||
* anything to a non-root pool.
|
||||
*/
|
||||
if (!pool_is_bootable(zhp))
|
||||
return (-1);
|
||||
if (nvlist_lookup_string(config, ZPOOL_CONFIG_PHYS_PATH,
|
||||
&tmppath) != 0)
|
||||
return (EZFS_NODEVICE);
|
||||
|
||||
verify(nvlist_lookup_nvlist(zhp->zpool_config,
|
||||
ZPOOL_CONFIG_VDEV_TREE, &vdev_root) == 0);
|
||||
pos = *bytes_written;
|
||||
bytes_left = physpath_size - pos;
|
||||
format = (pos == 0) ? "%s" : " %s";
|
||||
|
||||
if (nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &count) != 0)
|
||||
return (-2);
|
||||
rsz = snprintf(physpath + pos, bytes_left, format, tmppath);
|
||||
*bytes_written += rsz;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
nvlist_t **child2;
|
||||
uint_t count2;
|
||||
char *type;
|
||||
char *tmppath;
|
||||
int j;
|
||||
if (rsz >= bytes_left) {
|
||||
/* if physpath was not copied properly, clear it */
|
||||
if (bytes_left != 0) {
|
||||
physpath[pos] = 0;
|
||||
}
|
||||
return (EZFS_NOSPC);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (nvlist_lookup_string(child[i], ZPOOL_CONFIG_TYPE, &type)
|
||||
!= 0)
|
||||
return (-3);
|
||||
static int
|
||||
vdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size,
|
||||
size_t *rsz, boolean_t is_spare)
|
||||
{
|
||||
char *type;
|
||||
int ret;
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_DISK) == 0) {
|
||||
if (!vdev_online(child[i]))
|
||||
return (-8);
|
||||
verify(nvlist_lookup_string(child[i],
|
||||
ZPOOL_CONFIG_PHYS_PATH, &tmppath) == 0);
|
||||
(void) strncpy(physpath, tmppath, strlen(tmppath));
|
||||
} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) {
|
||||
if (nvlist_lookup_nvlist_array(child[i],
|
||||
ZPOOL_CONFIG_CHILDREN, &child2, &count2) != 0)
|
||||
return (-4);
|
||||
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
|
||||
return (EZFS_INVALCONFIG);
|
||||
|
||||
for (j = 0; j < count2; j++) {
|
||||
if (!vdev_online(child2[j]))
|
||||
return (-8);
|
||||
if (nvlist_lookup_string(child2[j],
|
||||
ZPOOL_CONFIG_PHYS_PATH, &tmppath) != 0)
|
||||
return (-5);
|
||||
if (strcmp(type, VDEV_TYPE_DISK) == 0) {
|
||||
/*
|
||||
* An active spare device has ZPOOL_CONFIG_IS_SPARE set.
|
||||
* For a spare vdev, we only want to boot from the active
|
||||
* spare device.
|
||||
*/
|
||||
if (is_spare) {
|
||||
uint64_t spare = 0;
|
||||
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_SPARE,
|
||||
&spare);
|
||||
if (!spare)
|
||||
return (EZFS_INVALCONFIG);
|
||||
}
|
||||
|
||||
if ((strlen(physpath) + strlen(tmppath)) >
|
||||
MAXNAMELEN)
|
||||
return (-6);
|
||||
if (vdev_online(nv)) {
|
||||
if ((ret = vdev_get_one_physpath(nv, physpath,
|
||||
phypath_size, rsz)) != 0)
|
||||
return (ret);
|
||||
}
|
||||
} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
|
||||
strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
|
||||
(is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
|
||||
nvlist_t **child;
|
||||
uint_t count;
|
||||
int i, ret;
|
||||
|
||||
if (strlen(physpath) == 0) {
|
||||
(void) strncpy(physpath, tmppath,
|
||||
strlen(tmppath));
|
||||
} else {
|
||||
(void) strcat(physpath, " ");
|
||||
(void) strcat(physpath, tmppath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return (-7);
|
||||
if (nvlist_lookup_nvlist_array(nv,
|
||||
ZPOOL_CONFIG_CHILDREN, &child, &count) != 0)
|
||||
return (EZFS_INVALCONFIG);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ret = vdev_get_physpaths(child[i], physpath,
|
||||
phypath_size, rsz, is_spare);
|
||||
if (ret == EZFS_NOSPC)
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
|
||||
return (EZFS_POOL_INVALARG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get phys_path for a root pool config.
|
||||
* Return 0 on success; non-zero on failure.
|
||||
*/
|
||||
static int
|
||||
zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
|
||||
{
|
||||
size_t rsz;
|
||||
nvlist_t *vdev_root;
|
||||
nvlist_t **child;
|
||||
uint_t count;
|
||||
char *type;
|
||||
|
||||
rsz = 0;
|
||||
|
||||
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&vdev_root) != 0)
|
||||
return (EZFS_INVALCONFIG);
|
||||
|
||||
if (nvlist_lookup_string(vdev_root, ZPOOL_CONFIG_TYPE, &type) != 0 ||
|
||||
nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &count) != 0)
|
||||
return (EZFS_INVALCONFIG);
|
||||
|
||||
/*
|
||||
* root pool can not have EFI labeled disks and can only have
|
||||
* a single top-level vdev.
|
||||
*/
|
||||
if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1 ||
|
||||
pool_uses_efi(vdev_root))
|
||||
return (EZFS_POOL_INVALARG);
|
||||
|
||||
(void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
|
||||
B_FALSE);
|
||||
|
||||
/* No online devices */
|
||||
if (rsz == 0)
|
||||
return (EZFS_NODEVICE);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get phys_path for a root pool
|
||||
* Return 0 on success; non-zero on failure.
|
||||
*/
|
||||
int
|
||||
zpool_get_physpath(zpool_handle_t *zhp, char *physpath, size_t phypath_size)
|
||||
{
|
||||
return (zpool_get_config_physpath(zhp->zpool_config, physpath,
|
||||
phypath_size));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns TRUE if the given guid corresponds to the given type.
|
||||
* This is used to check for hot spares (INUSE or not), and level 2 cache
|
||||
@@ -1606,6 +1748,45 @@ is_guid_type(zpool_handle_t *zhp, uint64_t guid, const char *type)
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device has being dynamically expanded then we need to relabel
|
||||
* the disk to use the new unallocated space.
|
||||
*/
|
||||
static int
|
||||
zpool_relabel_disk(libzfs_handle_t *hdl, const char *name)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
char errbuf[1024];
|
||||
int fd, error;
|
||||
int (*_efi_use_whole_disk)(int);
|
||||
|
||||
if ((_efi_use_whole_disk = (int (*)(int))dlsym(RTLD_DEFAULT,
|
||||
"efi_use_whole_disk")) == NULL)
|
||||
return (-1);
|
||||
|
||||
(void) snprintf(path, sizeof (path), "%s/%s", RDISK_ROOT, name);
|
||||
|
||||
if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
|
||||
"relabel '%s': unable to open device"), name);
|
||||
return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
|
||||
}
|
||||
|
||||
/*
|
||||
* It's possible that we might encounter an error if the device
|
||||
* does not have any unallocated space left. If so, we simply
|
||||
* ignore that error and continue on.
|
||||
*/
|
||||
error = _efi_use_whole_disk(fd);
|
||||
(void) close(fd);
|
||||
if (error && error != VT_ENOSPC) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
|
||||
"relabel '%s': unable to read disk capacity"), name);
|
||||
return (zfs_error(hdl, EZFS_NOCAP, errbuf));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bring the specified vdev online. The 'flags' parameter is a set of the
|
||||
* ZFS_ONLINE_* flags.
|
||||
@@ -1617,15 +1798,20 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
|
||||
zfs_cmd_t zc = { 0 };
|
||||
char msg[1024];
|
||||
nvlist_t *tgt;
|
||||
boolean_t avail_spare, l2cache;
|
||||
boolean_t avail_spare, l2cache, islog;
|
||||
libzfs_handle_t *hdl = zhp->zpool_hdl;
|
||||
|
||||
(void) snprintf(msg, sizeof (msg),
|
||||
dgettext(TEXT_DOMAIN, "cannot online %s"), path);
|
||||
if (flags & ZFS_ONLINE_EXPAND) {
|
||||
(void) snprintf(msg, sizeof (msg),
|
||||
dgettext(TEXT_DOMAIN, "cannot expand %s"), path);
|
||||
} else {
|
||||
(void) snprintf(msg, sizeof (msg),
|
||||
dgettext(TEXT_DOMAIN, "cannot online %s"), path);
|
||||
}
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
|
||||
if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
|
||||
NULL)) == NULL)
|
||||
&islog)) == NULL)
|
||||
return (zfs_error(hdl, EZFS_NODEVICE, msg));
|
||||
|
||||
verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
|
||||
@@ -1634,6 +1820,31 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
|
||||
is_guid_type(zhp, zc.zc_guid, ZPOOL_CONFIG_SPARES) == B_TRUE)
|
||||
return (zfs_error(hdl, EZFS_ISSPARE, msg));
|
||||
|
||||
if (flags & ZFS_ONLINE_EXPAND ||
|
||||
zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) {
|
||||
char *pathname = NULL;
|
||||
uint64_t wholedisk = 0;
|
||||
|
||||
(void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
&wholedisk);
|
||||
verify(nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH,
|
||||
&pathname) == 0);
|
||||
|
||||
/*
|
||||
* XXX - L2ARC 1.0 devices can't support expansion.
|
||||
*/
|
||||
if (l2cache) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"cannot expand cache devices"));
|
||||
return (zfs_error(hdl, EZFS_VDEVNOTSUP, msg));
|
||||
}
|
||||
|
||||
if (wholedisk) {
|
||||
pathname += strlen(DISK_ROOT) + 1;
|
||||
(void) zpool_relabel_disk(zhp->zpool_hdl, pathname);
|
||||
}
|
||||
}
|
||||
|
||||
zc.zc_cookie = VDEV_STATE_ONLINE;
|
||||
zc.zc_obj = flags;
|
||||
|
||||
@@ -1684,6 +1895,12 @@ zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
|
||||
*/
|
||||
return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
|
||||
|
||||
case EEXIST:
|
||||
/*
|
||||
* The log device has unplayed logs
|
||||
*/
|
||||
return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, msg));
|
||||
|
||||
default:
|
||||
return (zpool_standard_error(hdl, errno, msg));
|
||||
}
|
||||
@@ -1888,6 +2105,14 @@ zpool_vdev_attach(zpool_handle_t *zhp,
|
||||
(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Please "
|
||||
"be sure to invoke %s to make '%s' bootable.\n"),
|
||||
BOOTCMD, new_disk);
|
||||
|
||||
/*
|
||||
* XXX need a better way to prevent user from
|
||||
* booting up a half-baked vdev.
|
||||
*/
|
||||
(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Make "
|
||||
"sure to wait until resilver is done "
|
||||
"before rebooting.\n"));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -2803,14 +3028,6 @@ zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
|
||||
free(mntpnt);
|
||||
}
|
||||
|
||||
#define RDISK_ROOT "/dev/rdsk"
|
||||
#define BACKUP_SLICE "s2"
|
||||
/*
|
||||
* Don't start the slice at the default block of 34; many storage
|
||||
* devices will use a stripe width of 128k, so start there instead.
|
||||
*/
|
||||
#define NEW_START_BLOCK 256
|
||||
|
||||
/*
|
||||
* Read the EFI label from the config, if a label does not exist then
|
||||
* pass back the error to the caller. If the caller has passed a non-NULL
|
||||
|
||||
@@ -237,6 +237,8 @@ send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv)
|
||||
zfs_prop_t prop = zfs_name_to_prop(propname);
|
||||
nvlist_t *propnv;
|
||||
|
||||
assert(zfs_prop_user(propname) || prop != ZPROP_INVAL);
|
||||
|
||||
if (!zfs_prop_user(propname) && zfs_prop_readonly(prop))
|
||||
continue;
|
||||
|
||||
@@ -594,12 +596,18 @@ dump_filesystem(zfs_handle_t *zhp, void *arg)
|
||||
zhp->zfs_name, sdd->fromsnap);
|
||||
sdd->err = B_TRUE;
|
||||
} else if (!sdd->seento) {
|
||||
(void) fprintf(stderr,
|
||||
"WARNING: could not send %s@%s:\n"
|
||||
"incremental source (%s@%s) "
|
||||
"is not earlier than it\n",
|
||||
zhp->zfs_name, sdd->tosnap,
|
||||
zhp->zfs_name, sdd->fromsnap);
|
||||
if (sdd->fromsnap) {
|
||||
(void) fprintf(stderr,
|
||||
"WARNING: could not send %s@%s:\n"
|
||||
"incremental source (%s@%s) "
|
||||
"is not earlier than it\n",
|
||||
zhp->zfs_name, sdd->tosnap,
|
||||
zhp->zfs_name, sdd->fromsnap);
|
||||
} else {
|
||||
(void) fprintf(stderr, "WARNING: "
|
||||
"could not send %s@%s: does not exist\n",
|
||||
zhp->zfs_name, sdd->tosnap);
|
||||
}
|
||||
sdd->err = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -210,6 +210,9 @@ libzfs_error_description(libzfs_handle_t *hdl)
|
||||
case EZFS_ACTIVE_SPARE:
|
||||
return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
|
||||
"device"));
|
||||
case EZFS_UNPLAYED_LOGS:
|
||||
return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
|
||||
"logs"));
|
||||
case EZFS_UNKNOWN:
|
||||
return (dgettext(TEXT_DOMAIN, "unknown error"));
|
||||
default:
|
||||
@@ -364,6 +367,11 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
|
||||
case ENOTSUP:
|
||||
zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
|
||||
break;
|
||||
case EAGAIN:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"pool I/O is currently suspended"));
|
||||
zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
|
||||
break;
|
||||
default:
|
||||
zfs_error_aux(hdl, strerror(errno));
|
||||
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
|
||||
@@ -437,6 +445,11 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
|
||||
case EDQUOT:
|
||||
zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
|
||||
return (-1);
|
||||
case EAGAIN:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"pool I/O is currently suspended"));
|
||||
zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
|
||||
break;
|
||||
|
||||
default:
|
||||
zfs_error_aux(hdl, strerror(error));
|
||||
@@ -575,6 +588,7 @@ libzfs_init(void)
|
||||
|
||||
zfs_prop_init();
|
||||
zpool_prop_init();
|
||||
libzfs_mnttab_init(hdl);
|
||||
|
||||
return (hdl);
|
||||
}
|
||||
@@ -592,6 +606,7 @@ libzfs_fini(libzfs_handle_t *hdl)
|
||||
(void) free(hdl->libzfs_log_str);
|
||||
zpool_free_handles(hdl);
|
||||
namespace_clear(hdl);
|
||||
libzfs_mnttab_fini(hdl);
|
||||
free(hdl);
|
||||
}
|
||||
|
||||
@@ -1209,7 +1224,7 @@ addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
|
||||
* dataset property,
|
||||
*/
|
||||
if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL ||
|
||||
!zfs_prop_user(propname))) {
|
||||
(!zfs_prop_user(propname) && !zfs_prop_userquota(propname)))) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"invalid property '%s'"), propname);
|
||||
return (zfs_error(hdl, EZFS_BADPROP,
|
||||
|
||||
@@ -59,6 +59,7 @@ extern "C" {
|
||||
#include <atomic.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <libsysevent.h>
|
||||
#include <sys/note.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/cred.h>
|
||||
@@ -73,6 +74,7 @@ extern "C" {
|
||||
#include <sys/kstat.h>
|
||||
#include <sys/u8_textprep.h>
|
||||
#include <sys/sysevent/eventdefs.h>
|
||||
#include <sys/sysevent/dev.h>
|
||||
|
||||
/*
|
||||
* Debugging
|
||||
@@ -316,6 +318,7 @@ typedef void (task_func_t)(void *);
|
||||
#define TASKQ_PREPOPULATE 0x0001
|
||||
#define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */
|
||||
#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
|
||||
#define TASKQ_THREADS_CPU_PCT 0x0008 /* Use dynamic thread scheduling */
|
||||
|
||||
#define TQ_SLEEP KM_SLEEP /* Can block for memory */
|
||||
#define TQ_NOSLEEP KM_NOSLEEP /* cannot block for memory; may fail */
|
||||
@@ -540,6 +543,10 @@ typedef struct ksiddomain {
|
||||
ksiddomain_t *ksid_lookupdomain(const char *);
|
||||
void ksiddomain_rele(ksiddomain_t *);
|
||||
|
||||
#define DDI_SLEEP KM_SLEEP
|
||||
#define ddi_log_sysevent(_a, _b, _c, _d, _e, _f, _g) \
|
||||
sysevent_post_event(_c, _d, _b, "libzpool", _e, _f)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+14
-1
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -174,6 +174,19 @@ taskq_create(const char *name, int nthreads, pri_t pri,
|
||||
taskq_t *tq = kmem_zalloc(sizeof (taskq_t), KM_SLEEP);
|
||||
int t;
|
||||
|
||||
if (flags & TASKQ_THREADS_CPU_PCT) {
|
||||
int pct;
|
||||
ASSERT3S(nthreads, >=, 0);
|
||||
ASSERT3S(nthreads, <=, 100);
|
||||
pct = MIN(nthreads, 100);
|
||||
pct = MAX(pct, 0);
|
||||
|
||||
nthreads = (sysconf(_SC_NPROCESSORS_ONLN) * pct) / 100;
|
||||
nthreads = MAX(nthreads, 1); /* need at least 1 thread */
|
||||
} else {
|
||||
ASSERT3S(nthreads, >=, 1);
|
||||
}
|
||||
|
||||
rw_init(&tq->tq_threadlock, NULL, RW_DEFAULT, NULL);
|
||||
mutex_init(&tq->tq_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL);
|
||||
|
||||
Reference in New Issue
Block a user