mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 03:08:51 +03:00
Rebase master to b121
This commit is contained in:
@@ -117,6 +117,8 @@ enum {
|
||||
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_REFTAG_RELE, /* snapshot release: tag not found */
|
||||
EZFS_REFTAG_HOLD, /* snapshot hold: tag already exists */
|
||||
EZFS_UNKNOWN
|
||||
};
|
||||
|
||||
@@ -286,6 +288,7 @@ typedef enum {
|
||||
ZPOOL_STATUS_VERSION_OLDER, /* older on-disk version */
|
||||
ZPOOL_STATUS_RESILVERING, /* device being resilvered */
|
||||
ZPOOL_STATUS_OFFLINE_DEV, /* device online */
|
||||
ZPOOL_STATUS_REMOVED_DEV, /* removed device */
|
||||
|
||||
/*
|
||||
* Finally, the following indicates a healthy pool.
|
||||
@@ -454,8 +457,8 @@ extern int zfs_iter_snapshots(zfs_handle_t *, zfs_iter_f, void *);
|
||||
extern int zfs_create(libzfs_handle_t *, const char *, zfs_type_t,
|
||||
nvlist_t *);
|
||||
extern int zfs_create_ancestors(libzfs_handle_t *, const char *);
|
||||
extern int zfs_destroy(zfs_handle_t *);
|
||||
extern int zfs_destroy_snaps(zfs_handle_t *, char *);
|
||||
extern int zfs_destroy(zfs_handle_t *, boolean_t);
|
||||
extern int zfs_destroy_snaps(zfs_handle_t *, char *, boolean_t);
|
||||
extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *);
|
||||
extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *);
|
||||
extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t);
|
||||
@@ -463,6 +466,8 @@ extern int zfs_rename(zfs_handle_t *, const char *, boolean_t);
|
||||
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 *);
|
||||
extern int zfs_hold(zfs_handle_t *, const char *, const char *, boolean_t);
|
||||
extern int zfs_release(zfs_handle_t *, const char *, const char *, boolean_t);
|
||||
|
||||
typedef int (*zfs_userspace_cb_t)(void *arg, const char *domain,
|
||||
uid_t rid, uint64_t space);
|
||||
|
||||
@@ -508,6 +508,14 @@ change_one(zfs_handle_t *zhp, void *data)
|
||||
&idx);
|
||||
uu_list_insert(clp->cl_list, cn, idx);
|
||||
} else {
|
||||
/*
|
||||
* Add this child to beginning of the list. Children
|
||||
* below this one in the hierarchy will get added above
|
||||
* this one in the list. This produces a list in
|
||||
* reverse dataset name order.
|
||||
* This is necessary when the original mountpoint
|
||||
* is legacy or none.
|
||||
*/
|
||||
ASSERT(!clp->cl_alldependents);
|
||||
verify(uu_list_insert_before(clp->cl_list,
|
||||
uu_list_first(clp->cl_list), cn) == 0);
|
||||
@@ -574,6 +582,7 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
zfs_handle_t *temp;
|
||||
char property[ZFS_MAXPROPLEN];
|
||||
uu_compare_fn_t *compare = NULL;
|
||||
boolean_t legacy = B_FALSE;
|
||||
|
||||
if ((clp = zfs_alloc(zhp->zfs_hdl, sizeof (prop_changelist_t))) == NULL)
|
||||
return (NULL);
|
||||
@@ -586,8 +595,19 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
if (prop == ZFS_PROP_NAME || prop == ZFS_PROP_ZONED ||
|
||||
prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS ||
|
||||
prop == ZFS_PROP_SHARESMB) {
|
||||
compare = compare_mountpoints;
|
||||
clp->cl_sorted = B_TRUE;
|
||||
|
||||
if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT,
|
||||
property, sizeof (property),
|
||||
NULL, NULL, 0, B_FALSE) == 0 &&
|
||||
(strcmp(property, "legacy") == 0 ||
|
||||
strcmp(property, "none") == 0)) {
|
||||
|
||||
legacy = B_TRUE;
|
||||
}
|
||||
if (!legacy) {
|
||||
compare = compare_mountpoints;
|
||||
clp->cl_sorted = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
clp->cl_pool = uu_list_pool_create("changelist_pool",
|
||||
@@ -695,6 +715,12 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
(void) uu_list_find(clp->cl_list, cn, NULL, &idx);
|
||||
uu_list_insert(clp->cl_list, cn, idx);
|
||||
} else {
|
||||
/*
|
||||
* Add the target dataset to the end of the list.
|
||||
* The list is not really unsorted. The list will be
|
||||
* in reverse dataset name order. This is necessary
|
||||
* when the original mountpoint is legacy or none.
|
||||
*/
|
||||
verify(uu_list_insert_after(clp->cl_list,
|
||||
uu_list_last(clp->cl_list), cn) == 0);
|
||||
}
|
||||
@@ -703,11 +729,7 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
* If the mountpoint property was previously 'legacy', or 'none',
|
||||
* record it as the behavior of changelist_postfix() will be different.
|
||||
*/
|
||||
if ((clp->cl_prop == ZFS_PROP_MOUNTPOINT) &&
|
||||
(zfs_prop_get(zhp, prop, property, sizeof (property),
|
||||
NULL, NULL, 0, B_FALSE) == 0 &&
|
||||
(strcmp(property, "legacy") == 0 ||
|
||||
strcmp(property, "none") == 0))) {
|
||||
if ((clp->cl_prop == ZFS_PROP_MOUNTPOINT) && legacy) {
|
||||
/*
|
||||
* do not automatically mount ex-legacy datasets if
|
||||
* we specifically set canmount to noauto
|
||||
|
||||
+111
-30
@@ -47,6 +47,7 @@
|
||||
#include <ucred.h>
|
||||
#include <idmap.h>
|
||||
#include <aclutils.h>
|
||||
#include <directory.h>
|
||||
|
||||
#include <sys/spa.h>
|
||||
#include <sys/zap.h>
|
||||
@@ -1674,21 +1675,13 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
|
||||
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
|
||||
if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
|
||||
"unable to get %s property"),
|
||||
zfs_prop_to_name(prop));
|
||||
return (zfs_error(zhp->zfs_hdl, EZFS_BADVERSION,
|
||||
dgettext(TEXT_DOMAIN, "internal error")));
|
||||
return (-1);
|
||||
}
|
||||
if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &zplprops) != 0 ||
|
||||
nvlist_lookup_uint64(zplprops, zfs_prop_to_name(prop),
|
||||
val) != 0) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
|
||||
"unable to get %s property"),
|
||||
zfs_prop_to_name(prop));
|
||||
return (zfs_error(zhp->zfs_hdl, EZFS_NOMEM,
|
||||
dgettext(TEXT_DOMAIN, "internal error")));
|
||||
return (-1);
|
||||
}
|
||||
if (zplprops)
|
||||
nvlist_free(zplprops);
|
||||
@@ -2074,6 +2067,7 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
|
||||
{
|
||||
zfs_userquota_prop_t type;
|
||||
char *cp, *end;
|
||||
char *numericsid = NULL;
|
||||
boolean_t isuser;
|
||||
|
||||
domain[0] = '\0';
|
||||
@@ -2096,33 +2090,41 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
|
||||
if (strchr(cp, '@')) {
|
||||
/*
|
||||
* It's a SID name (eg "user@domain") that needs to be
|
||||
* turned into S-1-domainID-RID. There should be a
|
||||
* better way to do this, but for now just translate it
|
||||
* to the (possibly ephemeral) uid and then back to the
|
||||
* SID. This is like getsidname(noresolve=TRUE).
|
||||
* turned into S-1-domainID-RID.
|
||||
*/
|
||||
uid_t id;
|
||||
idmap_rid_t rid;
|
||||
char *mapdomain;
|
||||
|
||||
directory_error_t e;
|
||||
if (zoned && getzoneid() == GLOBAL_ZONEID)
|
||||
return (ENOENT);
|
||||
if (sid_to_id(cp, isuser, &id) != 0)
|
||||
if (isuser) {
|
||||
e = directory_sid_from_user_name(NULL,
|
||||
cp, &numericsid);
|
||||
} else {
|
||||
e = directory_sid_from_group_name(NULL,
|
||||
cp, &numericsid);
|
||||
}
|
||||
if (e != NULL) {
|
||||
directory_error_free(e);
|
||||
return (ENOENT);
|
||||
if (idmap_id_to_numeric_domain_rid(id, isuser,
|
||||
&mapdomain, &rid) != 0)
|
||||
}
|
||||
if (numericsid == NULL)
|
||||
return (ENOENT);
|
||||
(void) strlcpy(domain, mapdomain, domainlen);
|
||||
*ridp = rid;
|
||||
} else if (strncmp(cp, "S-1-", 4) == 0) {
|
||||
cp = numericsid;
|
||||
/* will be further decoded below */
|
||||
}
|
||||
|
||||
if (strncmp(cp, "S-1-", 4) == 0) {
|
||||
/* It's a numeric SID (eg "S-1-234-567-89") */
|
||||
(void) strcpy(domain, cp);
|
||||
(void) strlcpy(domain, cp, domainlen);
|
||||
cp = strrchr(domain, '-');
|
||||
*cp = '\0';
|
||||
cp++;
|
||||
|
||||
errno = 0;
|
||||
*ridp = strtoull(cp, &end, 10);
|
||||
if (numericsid) {
|
||||
free(numericsid);
|
||||
numericsid = NULL;
|
||||
}
|
||||
if (errno != 0 || *end != '\0')
|
||||
return (EINVAL);
|
||||
} else if (!isdigit(*cp)) {
|
||||
@@ -2158,13 +2160,14 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
|
||||
if (idmap_id_to_numeric_domain_rid(id, isuser,
|
||||
&mapdomain, &rid) != 0)
|
||||
return (ENOENT);
|
||||
(void) strcpy(domain, mapdomain);
|
||||
(void) strlcpy(domain, mapdomain, domainlen);
|
||||
*ridp = rid;
|
||||
} else {
|
||||
*ridp = id;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT3P(numericsid, ==, NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -2763,7 +2766,7 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
|
||||
* isn't mounted, and that there are no active dependents.
|
||||
*/
|
||||
int
|
||||
zfs_destroy(zfs_handle_t *zhp)
|
||||
zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
|
||||
{
|
||||
zfs_cmd_t zc = { 0 };
|
||||
|
||||
@@ -2787,6 +2790,7 @@ zfs_destroy(zfs_handle_t *zhp)
|
||||
zc.zc_objset_type = DMU_OST_ZFS;
|
||||
}
|
||||
|
||||
zc.zc_defer_destroy = defer;
|
||||
if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0) {
|
||||
return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
|
||||
dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
|
||||
@@ -2843,7 +2847,7 @@ zfs_remove_link_cb(zfs_handle_t *zhp, void *arg)
|
||||
* Destroys all snapshots with the given name in zhp & descendants.
|
||||
*/
|
||||
int
|
||||
zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname)
|
||||
zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
|
||||
{
|
||||
zfs_cmd_t zc = { 0 };
|
||||
int ret;
|
||||
@@ -2860,6 +2864,7 @@ zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname)
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
|
||||
(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
|
||||
zc.zc_defer_destroy = defer;
|
||||
|
||||
ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS, &zc);
|
||||
if (ret != 0) {
|
||||
@@ -3275,7 +3280,7 @@ rollback_destroy(zfs_handle_t *zhp, void *data)
|
||||
|
||||
logstr = zhp->zfs_hdl->libzfs_log_str;
|
||||
zhp->zfs_hdl->libzfs_log_str = NULL;
|
||||
cbp->cb_error |= zfs_destroy(zhp);
|
||||
cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
|
||||
zhp->zfs_hdl->libzfs_log_str = logstr;
|
||||
}
|
||||
} else {
|
||||
@@ -3289,7 +3294,7 @@ rollback_destroy(zfs_handle_t *zhp, void *data)
|
||||
zfs_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
if (zfs_destroy(zhp) != 0)
|
||||
if (zfs_destroy(zhp, B_FALSE) != 0)
|
||||
cbp->cb_error = B_TRUE;
|
||||
else
|
||||
changelist_remove(clp, zhp->zfs_name);
|
||||
@@ -4089,3 +4094,79 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
|
||||
boolean_t recursive)
|
||||
{
|
||||
zfs_cmd_t zc = { 0 };
|
||||
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
|
||||
(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
|
||||
(void) strlcpy(zc.zc_string, tag, sizeof (zc.zc_string));
|
||||
zc.zc_cookie = recursive;
|
||||
|
||||
if (zfs_ioctl(hdl, ZFS_IOC_HOLD, &zc) != 0) {
|
||||
char errbuf[ZFS_MAXNAMELEN+32];
|
||||
|
||||
/*
|
||||
* if it was recursive, the one that actually failed will be in
|
||||
* zc.zc_name.
|
||||
*/
|
||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||
"cannot hold '%s@%s'"), zc.zc_name, snapname);
|
||||
switch (errno) {
|
||||
case ENOTSUP:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"pool must be upgraded"));
|
||||
return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
|
||||
case EINVAL:
|
||||
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
|
||||
case EEXIST:
|
||||
return (zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf));
|
||||
default:
|
||||
return (zfs_standard_error_fmt(hdl, errno, errbuf));
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
|
||||
boolean_t recursive)
|
||||
{
|
||||
zfs_cmd_t zc = { 0 };
|
||||
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
|
||||
(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
|
||||
(void) strlcpy(zc.zc_string, tag, sizeof (zc.zc_string));
|
||||
zc.zc_cookie = recursive;
|
||||
|
||||
if (zfs_ioctl(hdl, ZFS_IOC_RELEASE, &zc) != 0) {
|
||||
char errbuf[ZFS_MAXNAMELEN+32];
|
||||
|
||||
/*
|
||||
* if it was recursive, the one that actually failed will be in
|
||||
* zc.zc_name.
|
||||
*/
|
||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||
"cannot release '%s@%s'"), zc.zc_name, snapname);
|
||||
switch (errno) {
|
||||
case ESRCH:
|
||||
return (zfs_error(hdl, EZFS_REFTAG_RELE, errbuf));
|
||||
case ENOTSUP:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"pool must be upgraded"));
|
||||
return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
|
||||
case EINVAL:
|
||||
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
|
||||
default:
|
||||
return (zfs_standard_error_fmt(hdl, errno, errbuf));
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,9 @@ fsavl_destroy(avl_tree_t *avl)
|
||||
free(avl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an nvlist, produce an avl tree of snapshots, ordered by guid
|
||||
*/
|
||||
static avl_tree_t *
|
||||
fsavl_create(nvlist_t *fss)
|
||||
{
|
||||
@@ -243,7 +246,9 @@ send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv)
|
||||
continue;
|
||||
|
||||
verify(nvpair_value_nvlist(elem, &propnv) == 0);
|
||||
if (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_RESERVATION) {
|
||||
if (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_RESERVATION ||
|
||||
prop == ZFS_PROP_REFQUOTA ||
|
||||
prop == ZFS_PROP_REFRESERVATION) {
|
||||
/* these guys are modifyable, but have no source */
|
||||
uint64_t value;
|
||||
verify(nvlist_lookup_uint64(propnv,
|
||||
@@ -274,6 +279,11 @@ send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* recursively generate nvlists describing datasets. See comment
|
||||
* for the data structure send_data_t above for description of contents
|
||||
* of the nvlist.
|
||||
*/
|
||||
static int
|
||||
send_iterate_fs(zfs_handle_t *zhp, void *arg)
|
||||
{
|
||||
@@ -689,9 +699,20 @@ again:
|
||||
}
|
||||
|
||||
/*
|
||||
* Dumps a backup of tosnap, incremental from fromsnap if it isn't NULL.
|
||||
* If 'doall', dump all intermediate snaps.
|
||||
* If 'replicate', dump special header and do recursively.
|
||||
* Generate a send stream for the dataset identified by the argument zhp.
|
||||
*
|
||||
* The content of the send stream is the snapshot identified by
|
||||
* 'tosnap'. Incremental streams are requested in two ways:
|
||||
* - from the snapshot identified by "fromsnap" (if non-null) or
|
||||
* - from the origin of the dataset identified by zhp, which must
|
||||
* be a clone. In this case, "fromsnap" is null and "fromorigin"
|
||||
* is TRUE.
|
||||
*
|
||||
* The send stream is recursive (i.e. dumps a hierarchy of snapshots) and
|
||||
* uses a special header (with a version field of DMU_BACKUP_HEADER_VERSION)
|
||||
* if "replicate" is set. If "doall" is set, dump all the intermediate
|
||||
* snapshots. The DMU_BACKUP_HEADER_VERSION header is used in the "doall"
|
||||
* case too.
|
||||
*/
|
||||
int
|
||||
zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||
@@ -900,11 +921,12 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
zc.zc_objset_type = DMU_OST_ZFS;
|
||||
(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
|
||||
|
||||
if (tryname) {
|
||||
(void) strcpy(newname, tryname);
|
||||
|
||||
zc.zc_objset_type = DMU_OST_ZFS;
|
||||
(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
|
||||
(void) strlcpy(zc.zc_value, tryname, sizeof (zc.zc_value));
|
||||
|
||||
if (flags.verbose) {
|
||||
@@ -959,12 +981,18 @@ recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
|
||||
int err = 0;
|
||||
prop_changelist_t *clp;
|
||||
zfs_handle_t *zhp;
|
||||
boolean_t defer = B_FALSE;
|
||||
int spa_version;
|
||||
|
||||
zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
|
||||
if (zhp == NULL)
|
||||
return (-1);
|
||||
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
|
||||
flags.force ? MS_FORCE : 0);
|
||||
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
|
||||
zfs_spa_version(zhp, &spa_version) == 0 &&
|
||||
spa_version >= SPA_VERSION_USERREFS)
|
||||
defer = B_TRUE;
|
||||
zfs_close(zhp);
|
||||
if (clp == NULL)
|
||||
return (-1);
|
||||
@@ -973,12 +1001,12 @@ recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
|
||||
return (err);
|
||||
|
||||
zc.zc_objset_type = DMU_OST_ZFS;
|
||||
zc.zc_defer_destroy = defer;
|
||||
(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
|
||||
|
||||
if (flags.verbose)
|
||||
(void) printf("attempting destroy %s\n", zc.zc_name);
|
||||
err = ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc);
|
||||
|
||||
if (err == 0) {
|
||||
if (flags.verbose)
|
||||
(void) printf("success\n");
|
||||
@@ -988,7 +1016,12 @@ recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
|
||||
(void) changelist_postfix(clp);
|
||||
changelist_free(clp);
|
||||
|
||||
if (err != 0)
|
||||
/*
|
||||
* Deferred destroy should always succeed. Since we can't tell
|
||||
* if it destroyed the dataset or just marked it for deferred
|
||||
* destroy, always do the rename just in case.
|
||||
*/
|
||||
if (err != 0 || defer)
|
||||
err = recv_rename(hdl, name, NULL, baselen, newname, flags);
|
||||
|
||||
return (err);
|
||||
@@ -1775,11 +1808,13 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
/* We can't do online recv in this case */
|
||||
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0);
|
||||
if (clp == NULL) {
|
||||
zfs_close(zhp);
|
||||
zcmd_free_nvlists(&zc);
|
||||
return (-1);
|
||||
}
|
||||
if (changelist_prefix(clp) != 0) {
|
||||
changelist_free(clp);
|
||||
zfs_close(zhp);
|
||||
zcmd_free_nvlists(&zc);
|
||||
return (-1);
|
||||
}
|
||||
@@ -1936,7 +1971,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
* (if created, or if we tore them down to do an incremental
|
||||
* restore), and the /dev links for the new snapshot (if
|
||||
* created). Also mount any children of the target filesystem
|
||||
* if we did an incremental receive.
|
||||
* if we did a replication receive (indicated by stream_avl
|
||||
* being non-NULL).
|
||||
*/
|
||||
cp = strchr(zc.zc_value, '@');
|
||||
if (cp && (ioctl_err == 0 || !newfs)) {
|
||||
@@ -1952,7 +1988,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
if (err == 0 && ioctl_err == 0)
|
||||
err = zvol_create_link(hdl,
|
||||
zc.zc_value);
|
||||
} else if (newfs) {
|
||||
} else if (newfs || stream_avl) {
|
||||
/*
|
||||
* Track the first/top of hierarchy fs,
|
||||
* for mounting and sharing later.
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -104,6 +104,13 @@ vdev_offlined(uint64_t state, uint64_t aux, uint64_t errs)
|
||||
return (state == VDEV_STATE_OFFLINE);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
vdev_removed(uint64_t state, uint64_t aux, uint64_t errs)
|
||||
{
|
||||
return (state == VDEV_STATE_REMOVED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect if any leaf devices that have seen errors or could not be opened.
|
||||
*/
|
||||
@@ -275,6 +282,12 @@ check_status(nvlist_t *config, boolean_t isimport)
|
||||
if (find_vdev_problem(nvroot, vdev_offlined))
|
||||
return (ZPOOL_STATUS_OFFLINE_DEV);
|
||||
|
||||
/*
|
||||
* Removed device
|
||||
*/
|
||||
if (find_vdev_problem(nvroot, vdev_removed))
|
||||
return (ZPOOL_STATUS_REMOVED_DEV);
|
||||
|
||||
/*
|
||||
* Currently resilvering
|
||||
*/
|
||||
|
||||
@@ -213,6 +213,11 @@ libzfs_error_description(libzfs_handle_t *hdl)
|
||||
case EZFS_UNPLAYED_LOGS:
|
||||
return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
|
||||
"logs"));
|
||||
case EZFS_REFTAG_RELE:
|
||||
return (dgettext(TEXT_DOMAIN, "no such tag on this dataset"));
|
||||
case EZFS_REFTAG_HOLD:
|
||||
return (dgettext(TEXT_DOMAIN, "tag already exists on this "
|
||||
"dataset"));
|
||||
case EZFS_UNKNOWN:
|
||||
return (dgettext(TEXT_DOMAIN, "unknown error"));
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user