mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-01-12 19:20:28 +03:00
Illumos #3894
3894 zfs should not allow snapshot of inconsistent dataset Reviewed by: Matthew Ahrens <mahrens@delphix.com> Approved by: Gordon Ross <gwr@nexenta.com> References: https://www.illumos.org/issues/3894 illumos/illumos-gate@ca48f36f20 Ported-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Issue #1775
This commit is contained in:
parent
1a077756e8
commit
96c2e96193
@ -3480,6 +3480,12 @@ zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
|
|||||||
int rv = 0;
|
int rv = 0;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
if (sd->sd_recursive &&
|
||||||
|
zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) != 0) {
|
||||||
|
zfs_close(zhp);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
error = asprintf(&name, "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
|
error = asprintf(&name, "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
|
||||||
if (error == -1)
|
if (error == -1)
|
||||||
nomem();
|
nomem();
|
||||||
|
@ -251,7 +251,7 @@ int dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
|
|||||||
void dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
|
void dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
|
||||||
dsl_dataset_t *origin_head, dmu_tx_t *tx);
|
dsl_dataset_t *origin_head, dmu_tx_t *tx);
|
||||||
int dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
|
int dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
|
||||||
dmu_tx_t *tx);
|
dmu_tx_t *tx, boolean_t recv);
|
||||||
void dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
|
void dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
|
||||||
dmu_tx_t *tx);
|
dmu_tx_t *tx);
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ typedef enum {
|
|||||||
ZFS_PROP_CLONES,
|
ZFS_PROP_CLONES,
|
||||||
ZFS_PROP_LOGICALUSED,
|
ZFS_PROP_LOGICALUSED,
|
||||||
ZFS_PROP_LOGICALREFERENCED,
|
ZFS_PROP_LOGICALREFERENCED,
|
||||||
|
ZFS_PROP_INCONSISTENT, /* not exposed to the user */
|
||||||
ZFS_PROP_SNAPDEV,
|
ZFS_PROP_SNAPDEV,
|
||||||
ZFS_PROP_ACLTYPE,
|
ZFS_PROP_ACLTYPE,
|
||||||
ZFS_NUM_PROPS
|
ZFS_NUM_PROPS
|
||||||
|
@ -1872,6 +1872,10 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
|
|||||||
zcmd_free_nvlists(&zc);
|
zcmd_free_nvlists(&zc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ZFS_PROP_INCONSISTENT:
|
||||||
|
*val = zhp->zfs_dmustats.dds_inconsistent;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
switch (zfs_prop_get_type(prop)) {
|
switch (zfs_prop_get_type(prop)) {
|
||||||
case PROP_TYPE_NUMBER:
|
case PROP_TYPE_NUMBER:
|
||||||
@ -3514,13 +3518,16 @@ zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
|
|||||||
char name[ZFS_MAXNAMELEN];
|
char name[ZFS_MAXNAMELEN];
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
(void) snprintf(name, sizeof (name),
|
if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) == 0) {
|
||||||
"%s@%s", zfs_get_name(zhp), sd->sd_snapname);
|
(void) snprintf(name, sizeof (name),
|
||||||
|
"%s@%s", zfs_get_name(zhp), sd->sd_snapname);
|
||||||
|
|
||||||
fnvlist_add_boolean(sd->sd_nvl, name);
|
fnvlist_add_boolean(sd->sd_nvl, name);
|
||||||
|
|
||||||
rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
|
rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
|
||||||
|
}
|
||||||
zfs_close(zhp);
|
zfs_close(zhp);
|
||||||
|
|
||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,6 +410,8 @@ zfs_prop_init(void)
|
|||||||
PROP_READONLY, ZFS_TYPE_DATASET, "UNIQUE");
|
PROP_READONLY, ZFS_TYPE_DATASET, "UNIQUE");
|
||||||
zprop_register_hidden(ZFS_PROP_OBJSETID, "objsetid", PROP_TYPE_NUMBER,
|
zprop_register_hidden(ZFS_PROP_OBJSETID, "objsetid", PROP_TYPE_NUMBER,
|
||||||
PROP_READONLY, ZFS_TYPE_DATASET, "OBJSETID");
|
PROP_READONLY, ZFS_TYPE_DATASET, "OBJSETID");
|
||||||
|
zprop_register_hidden(ZFS_PROP_INCONSISTENT, "inconsistent",
|
||||||
|
PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_DATASET, "INCONSISTENT");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Property to be removed once libbe is integrated
|
* Property to be removed once libbe is integrated
|
||||||
|
@ -1584,7 +1584,7 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
error = dsl_dataset_snapshot_check_impl(origin_head,
|
error = dsl_dataset_snapshot_check_impl(origin_head,
|
||||||
drc->drc_tosnap, tx);
|
drc->drc_tosnap, tx, B_TRUE);
|
||||||
dsl_dataset_rele(origin_head, FTAG);
|
dsl_dataset_rele(origin_head, FTAG);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
@ -1592,7 +1592,7 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx)
|
|||||||
error = dsl_destroy_head_check_impl(drc->drc_ds, 1);
|
error = dsl_destroy_head_check_impl(drc->drc_ds, 1);
|
||||||
} else {
|
} else {
|
||||||
error = dsl_dataset_snapshot_check_impl(drc->drc_ds,
|
error = dsl_dataset_snapshot_check_impl(drc->drc_ds,
|
||||||
drc->drc_tosnap, tx);
|
drc->drc_tosnap, tx, B_TRUE);
|
||||||
}
|
}
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
@ -929,7 +929,7 @@ typedef struct dsl_dataset_snapshot_arg {
|
|||||||
|
|
||||||
int
|
int
|
||||||
dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
|
dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
|
||||||
dmu_tx_t *tx)
|
dmu_tx_t *tx, boolean_t recv)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
@ -955,6 +955,18 @@ dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
|
|||||||
if (error != ENOENT)
|
if (error != ENOENT)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't allow taking snapshots of inconsistent datasets, such as
|
||||||
|
* those into which we are currently receiving. However, if we are
|
||||||
|
* creating this snapshot as part of a receive, this check will be
|
||||||
|
* executed atomically with respect to the completion of the receive
|
||||||
|
* itself but prior to the clearing of DS_FLAG_INCONSISTENT; in this
|
||||||
|
* case we ignore this, knowing it will be fixed up for us shortly in
|
||||||
|
* dmu_recv_end_sync().
|
||||||
|
*/
|
||||||
|
if (!recv && DS_IS_INCONSISTENT(ds))
|
||||||
|
return (SET_ERROR(EBUSY));
|
||||||
|
|
||||||
error = dsl_dataset_snapshot_reserve_space(ds, tx);
|
error = dsl_dataset_snapshot_reserve_space(ds, tx);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
@ -991,7 +1003,7 @@ dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx)
|
|||||||
error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
|
error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
error = dsl_dataset_snapshot_check_impl(ds,
|
error = dsl_dataset_snapshot_check_impl(ds,
|
||||||
atp + 1, tx);
|
atp + 1, tx, B_FALSE);
|
||||||
dsl_dataset_rele(ds, FTAG);
|
dsl_dataset_rele(ds, FTAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1243,7 +1255,8 @@ dsl_dataset_snapshot_tmp_check(void *arg, dmu_tx_t *tx)
|
|||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
error = dsl_dataset_snapshot_check_impl(ds, ddsta->ddsta_snapname, tx);
|
error = dsl_dataset_snapshot_check_impl(ds, ddsta->ddsta_snapname,
|
||||||
|
tx, B_FALSE);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
dsl_dataset_rele(ds, FTAG);
|
dsl_dataset_rele(ds, FTAG);
|
||||||
return (error);
|
return (error);
|
||||||
|
Loading…
Reference in New Issue
Block a user