summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorKeith M Wesolowski <[email protected]>2013-07-27 10:51:50 -0700
committerBrian Behlendorf <[email protected]>2013-11-04 11:18:14 -0800
commit96c2e961938d4018ddb393fa60e004d8a91a58e9 (patch)
tree6f831e836b96ef81a5daac0ef712df6ac394c492 /module/zfs
parent1a077756e8ba946a55f999fa1cb5f0e7dcb9aa81 (diff)
Illumos #3894
3894 zfs should not allow snapshot of inconsistent dataset Reviewed by: Matthew Ahrens <[email protected]> Approved by: Gordon Ross <[email protected]> References: https://www.illumos.org/issues/3894 illumos/illumos-gate@ca48f36f20f6098ceb19d5b084b6b3d4b8eca9fa Ported-by: Richard Yao <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Issue #1775
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/dmu_send.c4
-rw-r--r--module/zfs/dsl_dataset.c19
2 files changed, 18 insertions, 5 deletions
diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c
index 87744cb72..e80631b48 100644
--- a/module/zfs/dmu_send.c
+++ b/module/zfs/dmu_send.c
@@ -1584,7 +1584,7 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx)
return (error);
}
error = dsl_dataset_snapshot_check_impl(origin_head,
- drc->drc_tosnap, tx);
+ drc->drc_tosnap, tx, B_TRUE);
dsl_dataset_rele(origin_head, FTAG);
if (error != 0)
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);
} else {
error = dsl_dataset_snapshot_check_impl(drc->drc_ds,
- drc->drc_tosnap, tx);
+ drc->drc_tosnap, tx, B_TRUE);
}
return (error);
}
diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c
index 5ed3e8e87..16d5dad49 100644
--- a/module/zfs/dsl_dataset.c
+++ b/module/zfs/dsl_dataset.c
@@ -929,7 +929,7 @@ typedef struct dsl_dataset_snapshot_arg {
int
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;
uint64_t value;
@@ -955,6 +955,18 @@ dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
if (error != ENOENT)
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);
if (error != 0)
return (error);
@@ -991,7 +1003,7 @@ dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx)
error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
if (error == 0) {
error = dsl_dataset_snapshot_check_impl(ds,
- atp + 1, tx);
+ atp + 1, tx, B_FALSE);
dsl_dataset_rele(ds, FTAG);
}
@@ -1243,7 +1255,8 @@ dsl_dataset_snapshot_tmp_check(void *arg, dmu_tx_t *tx)
if (error != 0)
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) {
dsl_dataset_rele(ds, FTAG);
return (error);