Print this page
8520 lzc_rollback_to should support rolling back to origin
7198 libzfs should gracefully handle EINVAL from lzc_rollback
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Dan McDonald <danmcd@joyent.com>
NEX-9673 Add capability to replicate cloned datasets relative to origin
Reviewed by: Alex Deiter <alex.deiter@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-13340 Continuous replication service may fail if a user removes nested datasets
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-3562 filename normalization doesn't work for removes (sync with upstream)
NEX-9406 Add a property to show that a dataset has been modified since a snapshot
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Revert "NEX-7251 Resume_token is not cleared right after finishing receive"
This reverts commit 9e97a45e8cf6ca59307a39e2d3c11c6e845e4187.
NEX-7251 Resume_token is not cleared right after finishing receive
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
NEX-6815 KRRP: 'sess-send-stop' hangs forever if the sources pool does not have free space
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-5366 Race between unique_insert() and unique_remove() causes ZFS fsid change
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Dan Vatca <dan.vatca@gmail.com>
NEX-5795 Rename 'wrc' as 'wbc' in the source and in the tech docs
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5272 KRRP: replicate snapshot properties
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
6328 Fix cstyle errors in zfs codebase (fix studio)
6328 Fix cstyle errors in zfs codebase
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Jorgen Lundman <lundman@lundman.net>
Approved by: Robert Mustacchi <rm@joyent.com>
2605 want to resume interrupted zfs send
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Xin Li <delphij@freebsd.org>
Reviewed by: Arne Jansen <sensille@gmx.net>
Approved by: Dan McDonald <danmcd@omniti.com>
6160 /usr/lib/fs/zfs/bootinstall should use bootadm
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Reviewed by: Adam Števko <adam.stevko@gmail.com>
Reviewed by: Josef Sipek <jeffpc@josefsipek.net>
Approved by: Richard Lowe <richlowe@richlowe.net>
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R (NULL is not an int)
6171 dsl_prop_unregister() slows down dataset eviction.
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R (fix studio build)
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Garrett D'Amore <garrett@damore.org>
6047 SPARC boot should support feature@embedded_data
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Approved by: Dan McDonald <danmcd@omniti.com>
5959 clean up per-dataset feature count code
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
NEX-4582 update wrc test cases for allow to use write back cache per tree of datasets
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
5960 zfs recv should prefetch indirect blocks
5925 zfs receive -o origin=
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
5909 ensure that shared snap names don't become too long after promotion
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
5393 spurious failures from dsl_dataset_hold_obj()
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Will Andrews <willa@spectralogic.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Revert "NEX-4476 WRC: Allow to use write back cache per tree of datasets"
This reverts commit fe97b74444278a6f36fec93179133641296312da.
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-3964 It should not be allowed to rename a snapshot that its new name is matched to the prefix of in-kernel autosnapshots
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3669 Faults for fans that don't exist
Reviewed by: Jeffry Molanus <jeffry.molanus@nexenta.com>
NEX-3891 Hide the snapshots that belong to in-kernel autosnap-service
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-3329 libnsl: set_up_connection() over TCP does not adhere the specified timeout
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-3521 CLONE - Port NEX-3209 normalization=formD and casesensitivity=mixed behaves improperly, squashing case
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-3558 KRRP Integration
4370 avoid transmitting holes during zfs send
4371 DMU code clean up
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Approved by: Garrett D'Amore <garrett@damore.org>
re #13318 rb4428 kernel panic during failover with autosync running on the active node
re #12619 rb4429 More dp->dp_config_rwlock holds
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (fix lint -courtesy of Yuri Pankov)
re #12584 rb4049 zfsxx latest code merge (fix lint - courtesy of Yuri Pankov)
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
re 12063 rb 3793 Panic on zpool destroy
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/zfs/dsl_dataset.c
+++ new/usr/src/uts/common/fs/zfs/dsl_dataset.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
25 25 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
26 26 * Copyright (c) 2014 RackTop Systems.
27 27 * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
28 28 * Copyright (c) 2014 Integros [integros.com]
29 29 * Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
30 30 * Copyright 2017 Nexenta Systems, Inc.
31 31 */
32 32
33 33 #include <sys/dmu_objset.h>
34 34 #include <sys/dsl_dataset.h>
35 35 #include <sys/dsl_dir.h>
36 36 #include <sys/dsl_prop.h>
37 37 #include <sys/dsl_synctask.h>
38 38 #include <sys/dmu_traverse.h>
|
↓ open down ↓ |
38 lines elided |
↑ open up ↑ |
39 39 #include <sys/dmu_impl.h>
40 40 #include <sys/dmu_tx.h>
41 41 #include <sys/arc.h>
42 42 #include <sys/zio.h>
43 43 #include <sys/zap.h>
44 44 #include <sys/zfeature.h>
45 45 #include <sys/unique.h>
46 46 #include <sys/zfs_context.h>
47 47 #include <sys/zfs_ioctl.h>
48 48 #include <sys/spa.h>
49 -#include <sys/vdev.h>
49 +#include <sys/spa_impl.h>
50 50 #include <sys/zfs_znode.h>
51 51 #include <sys/zfs_onexit.h>
52 52 #include <sys/zvol.h>
53 53 #include <sys/dsl_scan.h>
54 54 #include <sys/dsl_deadlist.h>
55 55 #include <sys/dsl_destroy.h>
56 56 #include <sys/dsl_userhold.h>
57 57 #include <sys/dsl_bookmark.h>
58 +#include <sys/autosnap.h>
58 59 #include <sys/dmu_send.h>
59 60 #include <sys/zio_checksum.h>
60 61 #include <sys/zio_compress.h>
61 62 #include <zfs_fletcher.h>
62 63
63 64 /*
64 65 * The SPA supports block sizes up to 16MB. However, very large blocks
65 66 * can have an impact on i/o latency (e.g. tying up a spinning disk for
66 67 * ~300ms), and also potentially on the memory allocator. Therefore,
67 68 * we do not allow the recordsize to be set larger than zfs_max_recordsize
68 69 * (default 1MB). Larger blocks can be created by changing this tunable,
69 70 * and pools with larger blocks can always be imported and used, regardless
70 71 * of this setting.
71 72 */
72 73 int zfs_max_recordsize = 1 * 1024 * 1024;
73 74
74 75 #define SWITCH64(x, y) \
|
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
75 76 { \
76 77 uint64_t __tmp = (x); \
77 78 (x) = (y); \
78 79 (y) = __tmp; \
79 80 }
80 81
81 82 #define DS_REF_MAX (1ULL << 62)
82 83
83 84 extern inline dsl_dataset_phys_t *dsl_dataset_phys(dsl_dataset_t *ds);
84 85
85 -static void dsl_dataset_set_remap_deadlist_object(dsl_dataset_t *ds,
86 - uint64_t obj, dmu_tx_t *tx);
87 -static void dsl_dataset_unset_remap_deadlist_object(dsl_dataset_t *ds,
88 - dmu_tx_t *tx);
89 -
90 86 extern int spa_asize_inflation;
91 87
92 88 static zil_header_t zero_zil;
93 89
90 +kmem_cache_t *zfs_ds_collector_cache = NULL;
91 +
92 +zfs_ds_collector_entry_t *
93 +dsl_dataset_collector_cache_alloc()
94 +{
95 + return (kmem_cache_alloc(zfs_ds_collector_cache, KM_SLEEP));
96 +}
97 +
98 +void
99 +dsl_dataset_collector_cache_free(zfs_ds_collector_entry_t *entry)
100 +{
101 + kmem_cache_free(zfs_ds_collector_cache, entry);
102 +}
103 +
94 104 /*
95 105 * Figure out how much of this delta should be propogated to the dsl_dir
96 106 * layer. If there's a refreservation, that space has already been
97 107 * partially accounted for in our ancestors.
98 108 */
99 109 static int64_t
100 110 parent_delta(dsl_dataset_t *ds, int64_t delta)
101 111 {
102 112 dsl_dataset_phys_t *ds_phys;
103 113 uint64_t old_bytes, new_bytes;
104 114
105 115 if (ds->ds_reserved == 0)
106 116 return (delta);
107 117
108 118 ds_phys = dsl_dataset_phys(ds);
109 119 old_bytes = MAX(ds_phys->ds_unique_bytes, ds->ds_reserved);
110 120 new_bytes = MAX(ds_phys->ds_unique_bytes + delta, ds->ds_reserved);
111 121
112 122 ASSERT3U(ABS((int64_t)(new_bytes - old_bytes)), <=, ABS(delta));
113 123 return (new_bytes - old_bytes);
114 124 }
115 125
116 126 void
117 127 dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
118 128 {
119 129 int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
120 130 int compressed = BP_GET_PSIZE(bp);
121 131 int uncompressed = BP_GET_UCSIZE(bp);
122 132 int64_t delta;
123 133
124 134 dprintf_bp(bp, "ds=%p", ds);
125 135
126 136 ASSERT(dmu_tx_is_syncing(tx));
127 137 /* It could have been compressed away to nothing */
128 138 if (BP_IS_HOLE(bp))
129 139 return;
130 140 ASSERT(BP_GET_TYPE(bp) != DMU_OT_NONE);
131 141 ASSERT(DMU_OT_IS_VALID(BP_GET_TYPE(bp)));
132 142 if (ds == NULL) {
133 143 dsl_pool_mos_diduse_space(tx->tx_pool,
134 144 used, compressed, uncompressed);
135 145 return;
136 146 }
137 147
138 148 ASSERT3U(bp->blk_birth, >, dsl_dataset_phys(ds)->ds_prev_snap_txg);
139 149 dmu_buf_will_dirty(ds->ds_dbuf, tx);
140 150 mutex_enter(&ds->ds_lock);
141 151 delta = parent_delta(ds, used);
142 152 dsl_dataset_phys(ds)->ds_referenced_bytes += used;
143 153 dsl_dataset_phys(ds)->ds_compressed_bytes += compressed;
144 154 dsl_dataset_phys(ds)->ds_uncompressed_bytes += uncompressed;
145 155 dsl_dataset_phys(ds)->ds_unique_bytes += used;
146 156
147 157 if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE) {
148 158 ds->ds_feature_activation_needed[SPA_FEATURE_LARGE_BLOCKS] =
149 159 B_TRUE;
150 160 }
151 161
152 162 spa_feature_t f = zio_checksum_to_feature(BP_GET_CHECKSUM(bp));
|
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
153 163 if (f != SPA_FEATURE_NONE)
154 164 ds->ds_feature_activation_needed[f] = B_TRUE;
155 165
156 166 mutex_exit(&ds->ds_lock);
157 167 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
158 168 compressed, uncompressed, tx);
159 169 dsl_dir_transfer_space(ds->ds_dir, used - delta,
160 170 DD_USED_REFRSRV, DD_USED_HEAD, tx);
161 171 }
162 172
163 -/*
164 - * Called when the specified segment has been remapped, and is thus no
165 - * longer referenced in the head dataset. The vdev must be indirect.
166 - *
167 - * If the segment is referenced by a snapshot, put it on the remap deadlist.
168 - * Otherwise, add this segment to the obsolete spacemap.
169 - */
170 -void
171 -dsl_dataset_block_remapped(dsl_dataset_t *ds, uint64_t vdev, uint64_t offset,
172 - uint64_t size, uint64_t birth, dmu_tx_t *tx)
173 -{
174 - spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
175 -
176 - ASSERT(dmu_tx_is_syncing(tx));
177 - ASSERT(birth <= tx->tx_txg);
178 - ASSERT(!ds->ds_is_snapshot);
179 -
180 - if (birth > dsl_dataset_phys(ds)->ds_prev_snap_txg) {
181 - spa_vdev_indirect_mark_obsolete(spa, vdev, offset, size, tx);
182 - } else {
183 - blkptr_t fakebp;
184 - dva_t *dva = &fakebp.blk_dva[0];
185 -
186 - ASSERT(ds != NULL);
187 -
188 - mutex_enter(&ds->ds_remap_deadlist_lock);
189 - if (!dsl_dataset_remap_deadlist_exists(ds)) {
190 - dsl_dataset_create_remap_deadlist(ds, tx);
191 - }
192 - mutex_exit(&ds->ds_remap_deadlist_lock);
193 -
194 - BP_ZERO(&fakebp);
195 - fakebp.blk_birth = birth;
196 - DVA_SET_VDEV(dva, vdev);
197 - DVA_SET_OFFSET(dva, offset);
198 - DVA_SET_ASIZE(dva, size);
199 -
200 - dsl_deadlist_insert(&ds->ds_remap_deadlist, &fakebp, tx);
201 - }
202 -}
203 -
204 173 int
205 174 dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
206 175 boolean_t async)
207 176 {
208 177 int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
209 178 int compressed = BP_GET_PSIZE(bp);
210 179 int uncompressed = BP_GET_UCSIZE(bp);
180 + wbc_data_t *wbc_data = spa_get_wbc_data(tx->tx_pool->dp_spa);
211 181
212 182 if (BP_IS_HOLE(bp))
213 183 return (0);
214 184
215 185 ASSERT(dmu_tx_is_syncing(tx));
216 186 ASSERT(bp->blk_birth <= tx->tx_txg);
217 187
218 188 if (ds == NULL) {
219 189 dsl_free(tx->tx_pool, tx->tx_txg, bp);
220 190 dsl_pool_mos_diduse_space(tx->tx_pool,
221 191 -used, -compressed, -uncompressed);
222 192 return (used);
223 193 }
224 194 ASSERT3P(tx->tx_pool, ==, ds->ds_dir->dd_pool);
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
225 195
226 196 ASSERT(!ds->ds_is_snapshot);
227 197 dmu_buf_will_dirty(ds->ds_dbuf, tx);
228 198
229 199 if (bp->blk_birth > dsl_dataset_phys(ds)->ds_prev_snap_txg) {
230 200 int64_t delta;
231 201
232 202 dprintf_bp(bp, "freeing ds=%llu", ds->ds_object);
233 203 dsl_free(tx->tx_pool, tx->tx_txg, bp);
234 204
205 + /* update amount of data which is changed in the window */
206 + mutex_enter(&wbc_data->wbc_lock);
207 + if (wbc_data->wbc_isvalid &&
208 + bp->blk_birth && wbc_data->wbc_finish_txg &&
209 + bp->blk_birth <= wbc_data->wbc_finish_txg &&
210 + bp->blk_birth >= wbc_data->wbc_start_txg &&
211 + !wbc_data->wbc_purge) {
212 +
213 + wbc_data->wbc_altered_bytes += used;
214 + if (wbc_data->wbc_altered_limit &&
215 + wbc_data->wbc_altered_bytes >
216 + wbc_data->wbc_altered_limit) {
217 + wbc_purge_window(tx->tx_pool->dp_spa, tx);
218 + }
219 + }
220 + mutex_exit(&wbc_data->wbc_lock);
221 +
235 222 mutex_enter(&ds->ds_lock);
236 223 ASSERT(dsl_dataset_phys(ds)->ds_unique_bytes >= used ||
237 224 !DS_UNIQUE_IS_ACCURATE(ds));
238 225 delta = parent_delta(ds, -used);
239 226 dsl_dataset_phys(ds)->ds_unique_bytes -= used;
240 227 mutex_exit(&ds->ds_lock);
241 228 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
242 229 delta, -compressed, -uncompressed, tx);
243 230 dsl_dir_transfer_space(ds->ds_dir, -used - delta,
244 231 DD_USED_REFRSRV, DD_USED_HEAD, tx);
245 232 } else {
246 233 dprintf_bp(bp, "putting on dead list: %s", "");
247 234 if (async) {
248 235 /*
249 236 * We are here as part of zio's write done callback,
250 237 * which means we're a zio interrupt thread. We can't
251 238 * call dsl_deadlist_insert() now because it may block
252 239 * waiting for I/O. Instead, put bp on the deferred
253 240 * queue and let dsl_pool_sync() finish the job.
254 241 */
255 242 bplist_append(&ds->ds_pending_deadlist, bp);
256 243 } else {
257 244 dsl_deadlist_insert(&ds->ds_deadlist, bp, tx);
258 245 }
259 246 ASSERT3U(ds->ds_prev->ds_object, ==,
260 247 dsl_dataset_phys(ds)->ds_prev_snap_obj);
261 248 ASSERT(dsl_dataset_phys(ds->ds_prev)->ds_num_children > 0);
262 249 /* if (bp->blk_birth > prev prev snap txg) prev unique += bs */
263 250 if (dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj ==
264 251 ds->ds_object && bp->blk_birth >
265 252 dsl_dataset_phys(ds->ds_prev)->ds_prev_snap_txg) {
266 253 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
267 254 mutex_enter(&ds->ds_prev->ds_lock);
268 255 dsl_dataset_phys(ds->ds_prev)->ds_unique_bytes += used;
269 256 mutex_exit(&ds->ds_prev->ds_lock);
270 257 }
271 258 if (bp->blk_birth > ds->ds_dir->dd_origin_txg) {
272 259 dsl_dir_transfer_space(ds->ds_dir, used,
273 260 DD_USED_HEAD, DD_USED_SNAP, tx);
274 261 }
275 262 }
276 263 mutex_enter(&ds->ds_lock);
277 264 ASSERT3U(dsl_dataset_phys(ds)->ds_referenced_bytes, >=, used);
278 265 dsl_dataset_phys(ds)->ds_referenced_bytes -= used;
279 266 ASSERT3U(dsl_dataset_phys(ds)->ds_compressed_bytes, >=, compressed);
280 267 dsl_dataset_phys(ds)->ds_compressed_bytes -= compressed;
281 268 ASSERT3U(dsl_dataset_phys(ds)->ds_uncompressed_bytes, >=, uncompressed);
282 269 dsl_dataset_phys(ds)->ds_uncompressed_bytes -= uncompressed;
283 270 mutex_exit(&ds->ds_lock);
284 271
285 272 return (used);
286 273 }
287 274
288 275 /*
289 276 * We have to release the fsid syncronously or we risk that a subsequent
290 277 * mount of the same dataset will fail to unique_insert the fsid. This
291 278 * failure would manifest itself as the fsid of this dataset changing
292 279 * between mounts which makes NFS clients quite unhappy.
293 280 */
294 281 static void
295 282 dsl_dataset_evict_sync(void *dbu)
296 283 {
297 284 dsl_dataset_t *ds = dbu;
298 285
299 286 ASSERT(ds->ds_owner == NULL);
300 287
301 288 unique_remove(ds->ds_fsid_guid);
302 289 }
303 290
304 291 static void
305 292 dsl_dataset_evict_async(void *dbu)
306 293 {
307 294 dsl_dataset_t *ds = dbu;
308 295
309 296 ASSERT(ds->ds_owner == NULL);
310 297
311 298 ds->ds_dbuf = NULL;
|
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
312 299
313 300 if (ds->ds_objset != NULL)
314 301 dmu_objset_evict(ds->ds_objset);
315 302
316 303 if (ds->ds_prev) {
317 304 dsl_dataset_rele(ds->ds_prev, ds);
318 305 ds->ds_prev = NULL;
319 306 }
320 307
321 308 bplist_destroy(&ds->ds_pending_deadlist);
322 - if (dsl_deadlist_is_open(&ds->ds_deadlist))
309 + if (ds->ds_deadlist.dl_os != NULL)
323 310 dsl_deadlist_close(&ds->ds_deadlist);
324 - if (dsl_deadlist_is_open(&ds->ds_remap_deadlist))
325 - dsl_deadlist_close(&ds->ds_remap_deadlist);
326 311 if (ds->ds_dir)
327 312 dsl_dir_async_rele(ds->ds_dir, ds);
328 313
329 314 ASSERT(!list_link_active(&ds->ds_synced_link));
330 315
331 316 list_destroy(&ds->ds_prop_cbs);
332 317 mutex_destroy(&ds->ds_lock);
333 318 mutex_destroy(&ds->ds_opening_lock);
334 319 mutex_destroy(&ds->ds_sendstream_lock);
335 - mutex_destroy(&ds->ds_remap_deadlist_lock);
336 320 refcount_destroy(&ds->ds_longholds);
337 321 rrw_destroy(&ds->ds_bp_rwlock);
338 322
339 323 kmem_free(ds, sizeof (dsl_dataset_t));
340 324 }
341 325
342 326 int
343 327 dsl_dataset_get_snapname(dsl_dataset_t *ds)
344 328 {
345 329 dsl_dataset_phys_t *headphys;
346 330 int err;
347 331 dmu_buf_t *headdbuf;
348 332 dsl_pool_t *dp = ds->ds_dir->dd_pool;
349 333 objset_t *mos = dp->dp_meta_objset;
350 334
351 335 if (ds->ds_snapname[0])
352 336 return (0);
353 337 if (dsl_dataset_phys(ds)->ds_next_snap_obj == 0)
354 338 return (0);
355 339
356 340 err = dmu_bonus_hold(mos, dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj,
357 341 FTAG, &headdbuf);
358 342 if (err != 0)
359 343 return (err);
360 344 headphys = headdbuf->db_data;
361 345 err = zap_value_search(dp->dp_meta_objset,
362 346 headphys->ds_snapnames_zapobj, ds->ds_object, 0, ds->ds_snapname);
363 347 dmu_buf_rele(headdbuf, FTAG);
364 348 return (err);
365 349 }
366 350
367 351 int
368 352 dsl_dataset_snap_lookup(dsl_dataset_t *ds, const char *name, uint64_t *value)
369 353 {
370 354 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
371 355 uint64_t snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj;
372 356 matchtype_t mt = 0;
373 357 int err;
374 358
375 359 if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
376 360 mt = MT_NORMALIZE;
377 361
378 362 err = zap_lookup_norm(mos, snapobj, name, 8, 1,
379 363 value, mt, NULL, 0, NULL);
380 364 if (err == ENOTSUP && (mt & MT_NORMALIZE))
381 365 err = zap_lookup(mos, snapobj, name, 8, 1, value);
382 366 return (err);
383 367 }
384 368
385 369 int
386 370 dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx,
387 371 boolean_t adj_cnt)
388 372 {
389 373 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
390 374 uint64_t snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj;
391 375 matchtype_t mt = 0;
392 376 int err;
393 377
394 378 dsl_dir_snap_cmtime_update(ds->ds_dir);
395 379
396 380 if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
397 381 mt = MT_NORMALIZE;
398 382
399 383 err = zap_remove_norm(mos, snapobj, name, mt, tx);
400 384 if (err == ENOTSUP && (mt & MT_NORMALIZE))
401 385 err = zap_remove(mos, snapobj, name, tx);
402 386
403 387 if (err == 0 && adj_cnt)
404 388 dsl_fs_ss_count_adjust(ds->ds_dir, -1,
405 389 DD_FIELD_SNAPSHOT_COUNT, tx);
406 390
407 391 return (err);
408 392 }
409 393
410 394 boolean_t
411 395 dsl_dataset_try_add_ref(dsl_pool_t *dp, dsl_dataset_t *ds, void *tag)
412 396 {
413 397 dmu_buf_t *dbuf = ds->ds_dbuf;
414 398 boolean_t result = B_FALSE;
415 399
416 400 if (dbuf != NULL && dmu_buf_try_add_ref(dbuf, dp->dp_meta_objset,
417 401 ds->ds_object, DMU_BONUS_BLKID, tag)) {
418 402
419 403 if (ds == dmu_buf_get_user(dbuf))
420 404 result = B_TRUE;
421 405 else
422 406 dmu_buf_rele(dbuf, tag);
423 407 }
424 408
425 409 return (result);
426 410 }
427 411
428 412 int
429 413 dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
430 414 dsl_dataset_t **dsp)
431 415 {
432 416 objset_t *mos = dp->dp_meta_objset;
433 417 dmu_buf_t *dbuf;
434 418 dsl_dataset_t *ds;
435 419 int err;
436 420 dmu_object_info_t doi;
437 421
438 422 ASSERT(dsl_pool_config_held(dp));
439 423
440 424 err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
441 425 if (err != 0)
442 426 return (err);
443 427
444 428 /* Make sure dsobj has the correct object type. */
445 429 dmu_object_info_from_db(dbuf, &doi);
446 430 if (doi.doi_bonus_type != DMU_OT_DSL_DATASET) {
447 431 dmu_buf_rele(dbuf, tag);
448 432 return (SET_ERROR(EINVAL));
449 433 }
|
↓ open down ↓ |
104 lines elided |
↑ open up ↑ |
450 434
451 435 ds = dmu_buf_get_user(dbuf);
452 436 if (ds == NULL) {
453 437 dsl_dataset_t *winner = NULL;
454 438
455 439 ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
456 440 ds->ds_dbuf = dbuf;
457 441 ds->ds_object = dsobj;
458 442 ds->ds_is_snapshot = dsl_dataset_phys(ds)->ds_num_children != 0;
459 443
460 - err = dsl_dir_hold_obj(dp, dsl_dataset_phys(ds)->ds_dir_obj,
461 - NULL, ds, &ds->ds_dir);
462 - if (err != 0) {
463 - kmem_free(ds, sizeof (dsl_dataset_t));
464 - dmu_buf_rele(dbuf, tag);
465 - return (err);
466 - }
467 -
468 444 mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
469 445 mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
470 446 mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
471 - mutex_init(&ds->ds_remap_deadlist_lock,
472 - NULL, MUTEX_DEFAULT, NULL);
473 447 rrw_init(&ds->ds_bp_rwlock, B_FALSE);
474 448 refcount_create(&ds->ds_longholds);
475 449
476 450 bplist_create(&ds->ds_pending_deadlist);
451 + dsl_deadlist_open(&ds->ds_deadlist,
452 + mos, dsl_dataset_phys(ds)->ds_deadlist_obj);
477 453
478 454 list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t),
479 455 offsetof(dmu_sendarg_t, dsa_link));
480 456
481 457 list_create(&ds->ds_prop_cbs, sizeof (dsl_prop_cb_record_t),
482 458 offsetof(dsl_prop_cb_record_t, cbr_ds_node));
483 459
484 460 if (doi.doi_type == DMU_OTN_ZAP_METADATA) {
485 461 for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
486 462 if (!(spa_feature_table[f].fi_flags &
487 463 ZFEATURE_FLAG_PER_DATASET))
488 464 continue;
489 465 err = zap_contains(mos, dsobj,
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
490 466 spa_feature_table[f].fi_guid);
491 467 if (err == 0) {
492 468 ds->ds_feature_inuse[f] = B_TRUE;
493 469 } else {
494 470 ASSERT3U(err, ==, ENOENT);
495 471 err = 0;
496 472 }
497 473 }
498 474 }
499 475
476 + err = dsl_dir_hold_obj(dp,
477 + dsl_dataset_phys(ds)->ds_dir_obj, NULL, ds, &ds->ds_dir);
478 + if (err != 0) {
479 + mutex_destroy(&ds->ds_lock);
480 + mutex_destroy(&ds->ds_opening_lock);
481 + mutex_destroy(&ds->ds_sendstream_lock);
482 + refcount_destroy(&ds->ds_longholds);
483 + bplist_destroy(&ds->ds_pending_deadlist);
484 + dsl_deadlist_close(&ds->ds_deadlist);
485 + kmem_free(ds, sizeof (dsl_dataset_t));
486 + dmu_buf_rele(dbuf, tag);
487 + return (err);
488 + }
489 +
500 490 if (!ds->ds_is_snapshot) {
501 491 ds->ds_snapname[0] = '\0';
502 492 if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
503 493 err = dsl_dataset_hold_obj(dp,
504 494 dsl_dataset_phys(ds)->ds_prev_snap_obj,
505 495 ds, &ds->ds_prev);
506 496 }
507 497 if (doi.doi_type == DMU_OTN_ZAP_METADATA) {
508 498 int zaperr = zap_lookup(mos, ds->ds_object,
509 499 DS_FIELD_BOOKMARK_NAMES,
510 500 sizeof (ds->ds_bookmarks), 1,
511 501 &ds->ds_bookmarks);
512 502 if (zaperr != ENOENT)
513 503 VERIFY0(zaperr);
514 504 }
515 505 } else {
516 506 if (zfs_flags & ZFS_DEBUG_SNAPNAMES)
517 507 err = dsl_dataset_get_snapname(ds);
518 508 if (err == 0 &&
519 509 dsl_dataset_phys(ds)->ds_userrefs_obj != 0) {
520 510 err = zap_count(
521 511 ds->ds_dir->dd_pool->dp_meta_objset,
522 512 dsl_dataset_phys(ds)->ds_userrefs_obj,
523 513 &ds->ds_userrefs);
524 514 }
525 515 }
526 516
527 517 if (err == 0 && !ds->ds_is_snapshot) {
528 518 err = dsl_prop_get_int_ds(ds,
529 519 zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
530 520 &ds->ds_reserved);
531 521 if (err == 0) {
532 522 err = dsl_prop_get_int_ds(ds,
533 523 zfs_prop_to_name(ZFS_PROP_REFQUOTA),
534 524 &ds->ds_quota);
535 525 }
536 526 } else {
537 527 ds->ds_reserved = ds->ds_quota = 0;
538 528 }
539 529
540 - dsl_deadlist_open(&ds->ds_deadlist,
541 - mos, dsl_dataset_phys(ds)->ds_deadlist_obj);
542 - uint64_t remap_deadlist_obj =
543 - dsl_dataset_get_remap_deadlist_object(ds);
544 - if (remap_deadlist_obj != 0) {
545 - dsl_deadlist_open(&ds->ds_remap_deadlist, mos,
546 - remap_deadlist_obj);
547 - }
548 -
549 530 dmu_buf_init_user(&ds->ds_dbu, dsl_dataset_evict_sync,
550 531 dsl_dataset_evict_async, &ds->ds_dbuf);
551 532 if (err == 0)
552 533 winner = dmu_buf_set_user_ie(dbuf, &ds->ds_dbu);
553 534
554 535 if (err != 0 || winner != NULL) {
555 536 bplist_destroy(&ds->ds_pending_deadlist);
556 537 dsl_deadlist_close(&ds->ds_deadlist);
557 - if (dsl_deadlist_is_open(&ds->ds_remap_deadlist))
558 - dsl_deadlist_close(&ds->ds_remap_deadlist);
559 538 if (ds->ds_prev)
560 539 dsl_dataset_rele(ds->ds_prev, ds);
561 540 dsl_dir_rele(ds->ds_dir, ds);
562 541 mutex_destroy(&ds->ds_lock);
563 542 mutex_destroy(&ds->ds_opening_lock);
564 543 mutex_destroy(&ds->ds_sendstream_lock);
565 544 refcount_destroy(&ds->ds_longholds);
566 545 kmem_free(ds, sizeof (dsl_dataset_t));
567 546 if (err != 0) {
568 547 dmu_buf_rele(dbuf, tag);
569 548 return (err);
570 549 }
571 550 ds = winner;
572 551 } else {
573 552 ds->ds_fsid_guid =
574 553 unique_insert(dsl_dataset_phys(ds)->ds_fsid_guid);
575 554 if (ds->ds_fsid_guid !=
576 555 dsl_dataset_phys(ds)->ds_fsid_guid) {
577 556 zfs_dbgmsg("ds_fsid_guid changed from "
578 557 "%llx to %llx for pool %s dataset id %llu",
579 558 (long long)
580 559 dsl_dataset_phys(ds)->ds_fsid_guid,
581 560 (long long)ds->ds_fsid_guid,
582 561 spa_name(dp->dp_spa),
583 562 dsobj);
584 563 }
585 564 }
586 565 }
587 566 ASSERT3P(ds->ds_dbuf, ==, dbuf);
588 567 ASSERT3P(dsl_dataset_phys(ds), ==, dbuf->db_data);
589 568 ASSERT(dsl_dataset_phys(ds)->ds_prev_snap_obj != 0 ||
590 569 spa_version(dp->dp_spa) < SPA_VERSION_ORIGIN ||
591 570 dp->dp_origin_snap == NULL || ds == dp->dp_origin_snap);
592 571 *dsp = ds;
593 572 return (0);
594 573 }
595 574
596 575 int
597 576 dsl_dataset_hold(dsl_pool_t *dp, const char *name,
598 577 void *tag, dsl_dataset_t **dsp)
599 578 {
600 579 dsl_dir_t *dd;
601 580 const char *snapname;
602 581 uint64_t obj;
603 582 int err = 0;
604 583 dsl_dataset_t *ds;
605 584
606 585 err = dsl_dir_hold(dp, name, FTAG, &dd, &snapname);
607 586 if (err != 0)
608 587 return (err);
609 588
610 589 ASSERT(dsl_pool_config_held(dp));
611 590 obj = dsl_dir_phys(dd)->dd_head_dataset_obj;
612 591 if (obj != 0)
613 592 err = dsl_dataset_hold_obj(dp, obj, tag, &ds);
614 593 else
615 594 err = SET_ERROR(ENOENT);
616 595
617 596 /* we may be looking for a snapshot */
618 597 if (err == 0 && snapname != NULL) {
619 598 dsl_dataset_t *snap_ds;
620 599
621 600 if (*snapname++ != '@') {
622 601 dsl_dataset_rele(ds, tag);
623 602 dsl_dir_rele(dd, FTAG);
624 603 return (SET_ERROR(ENOENT));
625 604 }
626 605
627 606 dprintf("looking for snapshot '%s'\n", snapname);
628 607 err = dsl_dataset_snap_lookup(ds, snapname, &obj);
629 608 if (err == 0)
630 609 err = dsl_dataset_hold_obj(dp, obj, tag, &snap_ds);
631 610 dsl_dataset_rele(ds, tag);
632 611
633 612 if (err == 0) {
634 613 mutex_enter(&snap_ds->ds_lock);
635 614 if (snap_ds->ds_snapname[0] == 0)
636 615 (void) strlcpy(snap_ds->ds_snapname, snapname,
637 616 sizeof (snap_ds->ds_snapname));
638 617 mutex_exit(&snap_ds->ds_lock);
639 618 ds = snap_ds;
640 619 }
641 620 }
642 621 if (err == 0)
643 622 *dsp = ds;
644 623 dsl_dir_rele(dd, FTAG);
645 624 return (err);
646 625 }
647 626
648 627 int
649 628 dsl_dataset_own_obj(dsl_pool_t *dp, uint64_t dsobj,
650 629 void *tag, dsl_dataset_t **dsp)
651 630 {
652 631 int err = dsl_dataset_hold_obj(dp, dsobj, tag, dsp);
653 632 if (err != 0)
654 633 return (err);
655 634 if (!dsl_dataset_tryown(*dsp, tag)) {
656 635 dsl_dataset_rele(*dsp, tag);
657 636 *dsp = NULL;
658 637 return (SET_ERROR(EBUSY));
659 638 }
660 639 return (0);
661 640 }
662 641
663 642 int
664 643 dsl_dataset_own(dsl_pool_t *dp, const char *name,
665 644 void *tag, dsl_dataset_t **dsp)
666 645 {
667 646 int err = dsl_dataset_hold(dp, name, tag, dsp);
668 647 if (err != 0)
669 648 return (err);
670 649 if (!dsl_dataset_tryown(*dsp, tag)) {
671 650 dsl_dataset_rele(*dsp, tag);
672 651 return (SET_ERROR(EBUSY));
673 652 }
674 653 return (0);
675 654 }
676 655
677 656 /*
678 657 * See the comment above dsl_pool_hold() for details. In summary, a long
679 658 * hold is used to prevent destruction of a dataset while the pool hold
680 659 * is dropped, allowing other concurrent operations (e.g. spa_sync()).
681 660 *
682 661 * The dataset and pool must be held when this function is called. After it
683 662 * is called, the pool hold may be released while the dataset is still held
684 663 * and accessed.
685 664 */
686 665 void
687 666 dsl_dataset_long_hold(dsl_dataset_t *ds, void *tag)
688 667 {
689 668 ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
690 669 (void) refcount_add(&ds->ds_longholds, tag);
691 670 }
692 671
693 672 void
694 673 dsl_dataset_long_rele(dsl_dataset_t *ds, void *tag)
695 674 {
696 675 (void) refcount_remove(&ds->ds_longholds, tag);
697 676 }
698 677
699 678 /* Return B_TRUE if there are any long holds on this dataset. */
700 679 boolean_t
701 680 dsl_dataset_long_held(dsl_dataset_t *ds)
702 681 {
703 682 return (!refcount_is_zero(&ds->ds_longholds));
704 683 }
705 684
706 685 void
707 686 dsl_dataset_name(dsl_dataset_t *ds, char *name)
708 687 {
709 688 if (ds == NULL) {
710 689 (void) strcpy(name, "mos");
711 690 } else {
712 691 dsl_dir_name(ds->ds_dir, name);
713 692 VERIFY0(dsl_dataset_get_snapname(ds));
714 693 if (ds->ds_snapname[0]) {
715 694 VERIFY3U(strlcat(name, "@", ZFS_MAX_DATASET_NAME_LEN),
716 695 <, ZFS_MAX_DATASET_NAME_LEN);
717 696 /*
718 697 * We use a "recursive" mutex so that we
719 698 * can call dprintf_ds() with ds_lock held.
720 699 */
721 700 if (!MUTEX_HELD(&ds->ds_lock)) {
722 701 mutex_enter(&ds->ds_lock);
723 702 VERIFY3U(strlcat(name, ds->ds_snapname,
724 703 ZFS_MAX_DATASET_NAME_LEN), <,
725 704 ZFS_MAX_DATASET_NAME_LEN);
726 705 mutex_exit(&ds->ds_lock);
727 706 } else {
728 707 VERIFY3U(strlcat(name, ds->ds_snapname,
729 708 ZFS_MAX_DATASET_NAME_LEN), <,
730 709 ZFS_MAX_DATASET_NAME_LEN);
731 710 }
732 711 }
733 712 }
734 713 }
735 714
736 715 int
737 716 dsl_dataset_namelen(dsl_dataset_t *ds)
738 717 {
739 718 VERIFY0(dsl_dataset_get_snapname(ds));
740 719 mutex_enter(&ds->ds_lock);
741 720 int len = dsl_dir_namelen(ds->ds_dir) + 1 + strlen(ds->ds_snapname);
742 721 mutex_exit(&ds->ds_lock);
743 722 return (len);
744 723 }
745 724
746 725 void
747 726 dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
748 727 {
749 728 dmu_buf_rele(ds->ds_dbuf, tag);
750 729 }
751 730
752 731 void
753 732 dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
754 733 {
755 734 ASSERT3P(ds->ds_owner, ==, tag);
756 735 ASSERT(ds->ds_dbuf != NULL);
757 736
758 737 mutex_enter(&ds->ds_lock);
759 738 ds->ds_owner = NULL;
760 739 mutex_exit(&ds->ds_lock);
761 740 dsl_dataset_long_rele(ds, tag);
762 741 dsl_dataset_rele(ds, tag);
763 742 }
764 743
765 744 boolean_t
766 745 dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
767 746 {
768 747 boolean_t gotit = FALSE;
769 748
770 749 ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
771 750 mutex_enter(&ds->ds_lock);
772 751 if (ds->ds_owner == NULL && !DS_IS_INCONSISTENT(ds)) {
773 752 ds->ds_owner = tag;
774 753 dsl_dataset_long_hold(ds, tag);
775 754 gotit = TRUE;
776 755 }
777 756 mutex_exit(&ds->ds_lock);
778 757 return (gotit);
779 758 }
780 759
781 760 boolean_t
782 761 dsl_dataset_has_owner(dsl_dataset_t *ds)
783 762 {
784 763 boolean_t rv;
785 764 mutex_enter(&ds->ds_lock);
786 765 rv = (ds->ds_owner != NULL);
787 766 mutex_exit(&ds->ds_lock);
788 767 return (rv);
789 768 }
790 769
791 770 static void
792 771 dsl_dataset_activate_feature(uint64_t dsobj, spa_feature_t f, dmu_tx_t *tx)
793 772 {
794 773 spa_t *spa = dmu_tx_pool(tx)->dp_spa;
795 774 objset_t *mos = dmu_tx_pool(tx)->dp_meta_objset;
796 775 uint64_t zero = 0;
797 776
798 777 VERIFY(spa_feature_table[f].fi_flags & ZFEATURE_FLAG_PER_DATASET);
799 778
800 779 spa_feature_incr(spa, f, tx);
801 780 dmu_object_zapify(mos, dsobj, DMU_OT_DSL_DATASET, tx);
802 781
803 782 VERIFY0(zap_add(mos, dsobj, spa_feature_table[f].fi_guid,
804 783 sizeof (zero), 1, &zero, tx));
805 784 }
806 785
807 786 void
808 787 dsl_dataset_deactivate_feature(uint64_t dsobj, spa_feature_t f, dmu_tx_t *tx)
809 788 {
810 789 spa_t *spa = dmu_tx_pool(tx)->dp_spa;
811 790 objset_t *mos = dmu_tx_pool(tx)->dp_meta_objset;
812 791
813 792 VERIFY(spa_feature_table[f].fi_flags & ZFEATURE_FLAG_PER_DATASET);
814 793
815 794 VERIFY0(zap_remove(mos, dsobj, spa_feature_table[f].fi_guid, tx));
816 795 spa_feature_decr(spa, f, tx);
817 796 }
818 797
819 798 uint64_t
820 799 dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
821 800 uint64_t flags, dmu_tx_t *tx)
822 801 {
823 802 dsl_pool_t *dp = dd->dd_pool;
824 803 dmu_buf_t *dbuf;
825 804 dsl_dataset_phys_t *dsphys;
826 805 uint64_t dsobj;
827 806 objset_t *mos = dp->dp_meta_objset;
828 807
829 808 if (origin == NULL)
830 809 origin = dp->dp_origin_snap;
831 810
832 811 ASSERT(origin == NULL || origin->ds_dir->dd_pool == dp);
833 812 ASSERT(origin == NULL || dsl_dataset_phys(origin)->ds_num_children > 0);
834 813 ASSERT(dmu_tx_is_syncing(tx));
835 814 ASSERT(dsl_dir_phys(dd)->dd_head_dataset_obj == 0);
836 815
837 816 dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0,
838 817 DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx);
839 818 VERIFY0(dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
840 819 dmu_buf_will_dirty(dbuf, tx);
841 820 dsphys = dbuf->db_data;
842 821 bzero(dsphys, sizeof (dsl_dataset_phys_t));
843 822 dsphys->ds_dir_obj = dd->dd_object;
844 823 dsphys->ds_flags = flags;
845 824 dsphys->ds_fsid_guid = unique_create();
846 825 (void) random_get_pseudo_bytes((void*)&dsphys->ds_guid,
847 826 sizeof (dsphys->ds_guid));
848 827 dsphys->ds_snapnames_zapobj =
849 828 zap_create_norm(mos, U8_TEXTPREP_TOUPPER, DMU_OT_DSL_DS_SNAP_MAP,
850 829 DMU_OT_NONE, 0, tx);
851 830 dsphys->ds_creation_time = gethrestime_sec();
852 831 dsphys->ds_creation_txg = tx->tx_txg == TXG_INITIAL ? 1 : tx->tx_txg;
853 832
854 833 if (origin == NULL) {
855 834 dsphys->ds_deadlist_obj = dsl_deadlist_alloc(mos, tx);
856 835 } else {
857 836 dsl_dataset_t *ohds; /* head of the origin snapshot */
858 837
859 838 dsphys->ds_prev_snap_obj = origin->ds_object;
860 839 dsphys->ds_prev_snap_txg =
861 840 dsl_dataset_phys(origin)->ds_creation_txg;
862 841 dsphys->ds_referenced_bytes =
863 842 dsl_dataset_phys(origin)->ds_referenced_bytes;
864 843 dsphys->ds_compressed_bytes =
865 844 dsl_dataset_phys(origin)->ds_compressed_bytes;
866 845 dsphys->ds_uncompressed_bytes =
867 846 dsl_dataset_phys(origin)->ds_uncompressed_bytes;
868 847 rrw_enter(&origin->ds_bp_rwlock, RW_READER, FTAG);
869 848 dsphys->ds_bp = dsl_dataset_phys(origin)->ds_bp;
870 849 rrw_exit(&origin->ds_bp_rwlock, FTAG);
871 850
872 851 /*
873 852 * Inherit flags that describe the dataset's contents
874 853 * (INCONSISTENT) or properties (Case Insensitive).
875 854 */
876 855 dsphys->ds_flags |= dsl_dataset_phys(origin)->ds_flags &
877 856 (DS_FLAG_INCONSISTENT | DS_FLAG_CI_DATASET);
878 857
879 858 for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
880 859 if (origin->ds_feature_inuse[f])
881 860 dsl_dataset_activate_feature(dsobj, f, tx);
882 861 }
883 862
884 863 dmu_buf_will_dirty(origin->ds_dbuf, tx);
885 864 dsl_dataset_phys(origin)->ds_num_children++;
886 865
887 866 VERIFY0(dsl_dataset_hold_obj(dp,
888 867 dsl_dir_phys(origin->ds_dir)->dd_head_dataset_obj,
889 868 FTAG, &ohds));
890 869 dsphys->ds_deadlist_obj = dsl_deadlist_clone(&ohds->ds_deadlist,
891 870 dsphys->ds_prev_snap_txg, dsphys->ds_prev_snap_obj, tx);
892 871 dsl_dataset_rele(ohds, FTAG);
893 872
894 873 if (spa_version(dp->dp_spa) >= SPA_VERSION_NEXT_CLONES) {
895 874 if (dsl_dataset_phys(origin)->ds_next_clones_obj == 0) {
896 875 dsl_dataset_phys(origin)->ds_next_clones_obj =
897 876 zap_create(mos,
898 877 DMU_OT_NEXT_CLONES, DMU_OT_NONE, 0, tx);
899 878 }
900 879 VERIFY0(zap_add_int(mos,
901 880 dsl_dataset_phys(origin)->ds_next_clones_obj,
902 881 dsobj, tx));
903 882 }
904 883
905 884 dmu_buf_will_dirty(dd->dd_dbuf, tx);
906 885 dsl_dir_phys(dd)->dd_origin_obj = origin->ds_object;
907 886 if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
908 887 if (dsl_dir_phys(origin->ds_dir)->dd_clones == 0) {
909 888 dmu_buf_will_dirty(origin->ds_dir->dd_dbuf, tx);
910 889 dsl_dir_phys(origin->ds_dir)->dd_clones =
911 890 zap_create(mos,
912 891 DMU_OT_DSL_CLONES, DMU_OT_NONE, 0, tx);
913 892 }
914 893 VERIFY0(zap_add_int(mos,
915 894 dsl_dir_phys(origin->ds_dir)->dd_clones,
916 895 dsobj, tx));
917 896 }
918 897 }
919 898
920 899 if (spa_version(dp->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE)
921 900 dsphys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
922 901
923 902 dmu_buf_rele(dbuf, FTAG);
924 903
925 904 dmu_buf_will_dirty(dd->dd_dbuf, tx);
926 905 dsl_dir_phys(dd)->dd_head_dataset_obj = dsobj;
927 906
928 907 return (dsobj);
929 908 }
930 909
931 910 static void
932 911 dsl_dataset_zero_zil(dsl_dataset_t *ds, dmu_tx_t *tx)
933 912 {
934 913 objset_t *os;
935 914
936 915 VERIFY0(dmu_objset_from_ds(ds, &os));
937 916 if (bcmp(&os->os_zil_header, &zero_zil, sizeof (zero_zil)) != 0) {
938 917 dsl_pool_t *dp = ds->ds_dir->dd_pool;
939 918 zio_t *zio;
940 919
941 920 bzero(&os->os_zil_header, sizeof (os->os_zil_header));
942 921
943 922 zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
944 923 dsl_dataset_sync(ds, zio, tx);
945 924 VERIFY0(zio_wait(zio));
946 925
947 926 /* dsl_dataset_sync_done will drop this reference. */
948 927 dmu_buf_add_ref(ds->ds_dbuf, ds);
949 928 dsl_dataset_sync_done(ds, tx);
950 929 }
951 930 }
952 931
953 932 uint64_t
954 933 dsl_dataset_create_sync(dsl_dir_t *pdd, const char *lastname,
955 934 dsl_dataset_t *origin, uint64_t flags, cred_t *cr, dmu_tx_t *tx)
956 935 {
957 936 dsl_pool_t *dp = pdd->dd_pool;
958 937 uint64_t dsobj, ddobj;
959 938 dsl_dir_t *dd;
960 939
961 940 ASSERT(dmu_tx_is_syncing(tx));
962 941 ASSERT(lastname[0] != '@');
963 942
964 943 ddobj = dsl_dir_create_sync(dp, pdd, lastname, tx);
965 944 VERIFY0(dsl_dir_hold_obj(dp, ddobj, lastname, FTAG, &dd));
966 945
967 946 dsobj = dsl_dataset_create_sync_dd(dd, origin,
968 947 flags & ~DS_CREATE_FLAG_NODIRTY, tx);
969 948
970 949 dsl_deleg_set_create_perms(dd, tx, cr);
971 950
972 951 /*
973 952 * Since we're creating a new node we know it's a leaf, so we can
974 953 * initialize the counts if the limit feature is active.
975 954 */
976 955 if (spa_feature_is_active(dp->dp_spa, SPA_FEATURE_FS_SS_LIMIT)) {
977 956 uint64_t cnt = 0;
978 957 objset_t *os = dd->dd_pool->dp_meta_objset;
979 958
980 959 dsl_dir_zapify(dd, tx);
981 960 VERIFY0(zap_add(os, dd->dd_object, DD_FIELD_FILESYSTEM_COUNT,
982 961 sizeof (cnt), 1, &cnt, tx));
983 962 VERIFY0(zap_add(os, dd->dd_object, DD_FIELD_SNAPSHOT_COUNT,
984 963 sizeof (cnt), 1, &cnt, tx));
985 964 }
986 965
987 966 dsl_dir_rele(dd, FTAG);
988 967
989 968 /*
990 969 * If we are creating a clone, make sure we zero out any stale
991 970 * data from the origin snapshots zil header.
992 971 */
993 972 if (origin != NULL && !(flags & DS_CREATE_FLAG_NODIRTY)) {
994 973 dsl_dataset_t *ds;
995 974
996 975 VERIFY0(dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
997 976 dsl_dataset_zero_zil(ds, tx);
998 977 dsl_dataset_rele(ds, FTAG);
999 978 }
1000 979
1001 980 return (dsobj);
1002 981 }
1003 982
1004 983 /*
1005 984 * The unique space in the head dataset can be calculated by subtracting
1006 985 * the space used in the most recent snapshot, that is still being used
1007 986 * in this file system, from the space currently in use. To figure out
1008 987 * the space in the most recent snapshot still in use, we need to take
1009 988 * the total space used in the snapshot and subtract out the space that
1010 989 * has been freed up since the snapshot was taken.
1011 990 */
1012 991 void
1013 992 dsl_dataset_recalc_head_uniq(dsl_dataset_t *ds)
1014 993 {
1015 994 uint64_t mrs_used;
1016 995 uint64_t dlused, dlcomp, dluncomp;
1017 996
1018 997 ASSERT(!ds->ds_is_snapshot);
1019 998
1020 999 if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0)
1021 1000 mrs_used = dsl_dataset_phys(ds->ds_prev)->ds_referenced_bytes;
1022 1001 else
1023 1002 mrs_used = 0;
1024 1003
1025 1004 dsl_deadlist_space(&ds->ds_deadlist, &dlused, &dlcomp, &dluncomp);
1026 1005
1027 1006 ASSERT3U(dlused, <=, mrs_used);
1028 1007 dsl_dataset_phys(ds)->ds_unique_bytes =
1029 1008 dsl_dataset_phys(ds)->ds_referenced_bytes - (mrs_used - dlused);
1030 1009
1031 1010 if (spa_version(ds->ds_dir->dd_pool->dp_spa) >=
1032 1011 SPA_VERSION_UNIQUE_ACCURATE)
1033 1012 dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
1034 1013 }
1035 1014
1036 1015 void
1037 1016 dsl_dataset_remove_from_next_clones(dsl_dataset_t *ds, uint64_t obj,
1038 1017 dmu_tx_t *tx)
1039 1018 {
1040 1019 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
1041 1020 uint64_t count;
1042 1021 int err;
1043 1022
1044 1023 ASSERT(dsl_dataset_phys(ds)->ds_num_children >= 2);
1045 1024 err = zap_remove_int(mos, dsl_dataset_phys(ds)->ds_next_clones_obj,
1046 1025 obj, tx);
1047 1026 /*
1048 1027 * The err should not be ENOENT, but a bug in a previous version
1049 1028 * of the code could cause upgrade_clones_cb() to not set
1050 1029 * ds_next_snap_obj when it should, leading to a missing entry.
1051 1030 * If we knew that the pool was created after
1052 1031 * SPA_VERSION_NEXT_CLONES, we could assert that it isn't
1053 1032 * ENOENT. However, at least we can check that we don't have
1054 1033 * too many entries in the next_clones_obj even after failing to
1055 1034 * remove this one.
1056 1035 */
1057 1036 if (err != ENOENT)
1058 1037 VERIFY0(err);
1059 1038 ASSERT0(zap_count(mos, dsl_dataset_phys(ds)->ds_next_clones_obj,
1060 1039 &count));
1061 1040 ASSERT3U(count, <=, dsl_dataset_phys(ds)->ds_num_children - 2);
1062 1041 }
1063 1042
1064 1043
1065 1044 blkptr_t *
1066 1045 dsl_dataset_get_blkptr(dsl_dataset_t *ds)
1067 1046 {
1068 1047 return (&dsl_dataset_phys(ds)->ds_bp);
1069 1048 }
1070 1049
1071 1050 spa_t *
1072 1051 dsl_dataset_get_spa(dsl_dataset_t *ds)
1073 1052 {
1074 1053 return (ds->ds_dir->dd_pool->dp_spa);
1075 1054 }
1076 1055
1077 1056 void
1078 1057 dsl_dataset_dirty(dsl_dataset_t *ds, dmu_tx_t *tx)
1079 1058 {
1080 1059 dsl_pool_t *dp;
1081 1060
1082 1061 if (ds == NULL) /* this is the meta-objset */
1083 1062 return;
1084 1063
1085 1064 ASSERT(ds->ds_objset != NULL);
1086 1065
1087 1066 if (dsl_dataset_phys(ds)->ds_next_snap_obj != 0)
1088 1067 panic("dirtying snapshot!");
1089 1068
1090 1069 /* Must not dirty a dataset in the same txg where it got snapshotted. */
1091 1070 ASSERT3U(tx->tx_txg, >, dsl_dataset_phys(ds)->ds_prev_snap_txg);
1092 1071
1093 1072 dp = ds->ds_dir->dd_pool;
1094 1073 if (txg_list_add(&dp->dp_dirty_datasets, ds, tx->tx_txg)) {
1095 1074 /* up the hold count until we can be written out */
1096 1075 dmu_buf_add_ref(ds->ds_dbuf, ds);
1097 1076 }
1098 1077 }
1099 1078
1100 1079 boolean_t
1101 1080 dsl_dataset_is_dirty(dsl_dataset_t *ds)
1102 1081 {
1103 1082 for (int t = 0; t < TXG_SIZE; t++) {
1104 1083 if (txg_list_member(&ds->ds_dir->dd_pool->dp_dirty_datasets,
1105 1084 ds, t))
1106 1085 return (B_TRUE);
1107 1086 }
1108 1087 return (B_FALSE);
1109 1088 }
1110 1089
1111 1090 static int
1112 1091 dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx)
1113 1092 {
1114 1093 uint64_t asize;
1115 1094
1116 1095 if (!dmu_tx_is_syncing(tx))
1117 1096 return (0);
1118 1097
1119 1098 /*
1120 1099 * If there's an fs-only reservation, any blocks that might become
1121 1100 * owned by the snapshot dataset must be accommodated by space
1122 1101 * outside of the reservation.
1123 1102 */
1124 1103 ASSERT(ds->ds_reserved == 0 || DS_UNIQUE_IS_ACCURATE(ds));
1125 1104 asize = MIN(dsl_dataset_phys(ds)->ds_unique_bytes, ds->ds_reserved);
1126 1105 if (asize > dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE))
1127 1106 return (SET_ERROR(ENOSPC));
1128 1107
1129 1108 /*
1130 1109 * Propagate any reserved space for this snapshot to other
1131 1110 * snapshot checks in this sync group.
1132 1111 */
1133 1112 if (asize > 0)
1134 1113 dsl_dir_willuse_space(ds->ds_dir, asize, tx);
1135 1114
1136 1115 return (0);
1137 1116 }
1138 1117
1139 1118 int
1140 1119 dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
1141 1120 dmu_tx_t *tx, boolean_t recv, uint64_t cnt, cred_t *cr)
1142 1121 {
1143 1122 int error;
1144 1123 uint64_t value;
1145 1124
1146 1125 ds->ds_trysnap_txg = tx->tx_txg;
1147 1126
1148 1127 if (!dmu_tx_is_syncing(tx))
1149 1128 return (0);
1150 1129
1151 1130 /*
1152 1131 * We don't allow multiple snapshots of the same txg. If there
1153 1132 * is already one, try again.
1154 1133 */
1155 1134 if (dsl_dataset_phys(ds)->ds_prev_snap_txg >= tx->tx_txg)
1156 1135 return (SET_ERROR(EAGAIN));
1157 1136
1158 1137 /*
1159 1138 * Check for conflicting snapshot name.
1160 1139 */
1161 1140 error = dsl_dataset_snap_lookup(ds, snapname, &value);
1162 1141 if (error == 0)
1163 1142 return (SET_ERROR(EEXIST));
1164 1143 if (error != ENOENT)
1165 1144 return (error);
1166 1145
1167 1146 /*
1168 1147 * We don't allow taking snapshots of inconsistent datasets, such as
1169 1148 * those into which we are currently receiving. However, if we are
1170 1149 * creating this snapshot as part of a receive, this check will be
1171 1150 * executed atomically with respect to the completion of the receive
1172 1151 * itself but prior to the clearing of DS_FLAG_INCONSISTENT; in this
1173 1152 * case we ignore this, knowing it will be fixed up for us shortly in
1174 1153 * dmu_recv_end_sync().
1175 1154 */
1176 1155 if (!recv && DS_IS_INCONSISTENT(ds))
1177 1156 return (SET_ERROR(EBUSY));
1178 1157
1179 1158 /*
1180 1159 * Skip the check for temporary snapshots or if we have already checked
1181 1160 * the counts in dsl_dataset_snapshot_check. This means we really only
1182 1161 * check the count here when we're receiving a stream.
1183 1162 */
1184 1163 if (cnt != 0 && cr != NULL) {
1185 1164 error = dsl_fs_ss_limit_check(ds->ds_dir, cnt,
1186 1165 ZFS_PROP_SNAPSHOT_LIMIT, NULL, cr);
1187 1166 if (error != 0)
1188 1167 return (error);
1189 1168 }
1190 1169
1191 1170 error = dsl_dataset_snapshot_reserve_space(ds, tx);
1192 1171 if (error != 0)
1193 1172 return (error);
1194 1173
1195 1174 return (0);
|
↓ open down ↓ |
627 lines elided |
↑ open up ↑ |
1196 1175 }
1197 1176
1198 1177 int
1199 1178 dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx)
1200 1179 {
1201 1180 dsl_dataset_snapshot_arg_t *ddsa = arg;
1202 1181 dsl_pool_t *dp = dmu_tx_pool(tx);
1203 1182 nvpair_t *pair;
1204 1183 int rv = 0;
1205 1184
1185 + if (ddsa->ddsa_autosnap && dmu_tx_is_syncing(tx))
1186 + autosnap_invalidate_list(dp, ddsa->ddsa_snaps);
1187 +
1206 1188 /*
1207 1189 * Pre-compute how many total new snapshots will be created for each
1208 1190 * level in the tree and below. This is needed for validating the
1209 1191 * snapshot limit when either taking a recursive snapshot or when
1210 1192 * taking multiple snapshots.
1211 1193 *
1212 1194 * The problem is that the counts are not actually adjusted when
1213 1195 * we are checking, only when we finally sync. For a single snapshot,
1214 1196 * this is easy, the count will increase by 1 at each node up the tree,
1215 1197 * but its more complicated for the recursive/multiple snapshot case.
1216 1198 *
1217 1199 * The dsl_fs_ss_limit_check function does recursively check the count
1218 1200 * at each level up the tree but since it is validating each snapshot
1219 1201 * independently we need to be sure that we are validating the complete
1220 1202 * count for the entire set of snapshots. We do this by rolling up the
1221 1203 * counts for each component of the name into an nvlist and then
1222 1204 * checking each of those cases with the aggregated count.
1223 1205 *
1224 1206 * This approach properly handles not only the recursive snapshot
1225 1207 * case (where we get all of those on the ddsa_snaps list) but also
1226 1208 * the sibling case (e.g. snapshot a/b and a/c so that we will also
1227 1209 * validate the limit on 'a' using a count of 2).
1228 1210 *
1229 1211 * We validate the snapshot names in the third loop and only report
1230 1212 * name errors once.
1231 1213 */
1232 1214 if (dmu_tx_is_syncing(tx)) {
1233 1215 nvlist_t *cnt_track = NULL;
1234 1216 cnt_track = fnvlist_alloc();
1235 1217
1236 1218 /* Rollup aggregated counts into the cnt_track list */
1237 1219 for (pair = nvlist_next_nvpair(ddsa->ddsa_snaps, NULL);
1238 1220 pair != NULL;
1239 1221 pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
1240 1222 char *pdelim;
1241 1223 uint64_t val;
1242 1224 char nm[MAXPATHLEN];
1243 1225
1244 1226 (void) strlcpy(nm, nvpair_name(pair), sizeof (nm));
1245 1227 pdelim = strchr(nm, '@');
1246 1228 if (pdelim == NULL)
1247 1229 continue;
1248 1230 *pdelim = '\0';
1249 1231
1250 1232 do {
1251 1233 if (nvlist_lookup_uint64(cnt_track, nm,
1252 1234 &val) == 0) {
1253 1235 /* update existing entry */
1254 1236 fnvlist_add_uint64(cnt_track, nm,
1255 1237 val + 1);
1256 1238 } else {
1257 1239 /* add to list */
1258 1240 fnvlist_add_uint64(cnt_track, nm, 1);
1259 1241 }
1260 1242
1261 1243 pdelim = strrchr(nm, '/');
1262 1244 if (pdelim != NULL)
1263 1245 *pdelim = '\0';
1264 1246 } while (pdelim != NULL);
1265 1247 }
1266 1248
1267 1249 /* Check aggregated counts at each level */
1268 1250 for (pair = nvlist_next_nvpair(cnt_track, NULL);
1269 1251 pair != NULL; pair = nvlist_next_nvpair(cnt_track, pair)) {
1270 1252 int error = 0;
1271 1253 char *name;
1272 1254 uint64_t cnt = 0;
1273 1255 dsl_dataset_t *ds;
1274 1256
1275 1257 name = nvpair_name(pair);
1276 1258 cnt = fnvpair_value_uint64(pair);
1277 1259 ASSERT(cnt > 0);
1278 1260
1279 1261 error = dsl_dataset_hold(dp, name, FTAG, &ds);
1280 1262 if (error == 0) {
1281 1263 error = dsl_fs_ss_limit_check(ds->ds_dir, cnt,
1282 1264 ZFS_PROP_SNAPSHOT_LIMIT, NULL,
1283 1265 ddsa->ddsa_cr);
1284 1266 dsl_dataset_rele(ds, FTAG);
1285 1267 }
1286 1268
1287 1269 if (error != 0) {
1288 1270 if (ddsa->ddsa_errors != NULL)
1289 1271 fnvlist_add_int32(ddsa->ddsa_errors,
1290 1272 name, error);
1291 1273 rv = error;
1292 1274 /* only report one error for this check */
1293 1275 break;
1294 1276 }
1295 1277 }
1296 1278 nvlist_free(cnt_track);
1297 1279 }
1298 1280
1299 1281 for (pair = nvlist_next_nvpair(ddsa->ddsa_snaps, NULL);
1300 1282 pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
1301 1283 int error = 0;
1302 1284 dsl_dataset_t *ds;
1303 1285 char *name, *atp;
1304 1286 char dsname[ZFS_MAX_DATASET_NAME_LEN];
1305 1287
1306 1288 name = nvpair_name(pair);
1307 1289 if (strlen(name) >= ZFS_MAX_DATASET_NAME_LEN)
1308 1290 error = SET_ERROR(ENAMETOOLONG);
1309 1291 if (error == 0) {
1310 1292 atp = strchr(name, '@');
1311 1293 if (atp == NULL)
1312 1294 error = SET_ERROR(EINVAL);
1313 1295 if (error == 0)
1314 1296 (void) strlcpy(dsname, name, atp - name + 1);
1315 1297 }
1316 1298 if (error == 0)
1317 1299 error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
1318 1300 if (error == 0) {
1319 1301 /* passing 0/NULL skips dsl_fs_ss_limit_check */
1320 1302 error = dsl_dataset_snapshot_check_impl(ds,
1321 1303 atp + 1, tx, B_FALSE, 0, NULL);
1322 1304 dsl_dataset_rele(ds, FTAG);
1323 1305 }
1324 1306
1325 1307 if (error != 0) {
1326 1308 if (ddsa->ddsa_errors != NULL) {
1327 1309 fnvlist_add_int32(ddsa->ddsa_errors,
1328 1310 name, error);
1329 1311 }
1330 1312 rv = error;
1331 1313 }
1332 1314 }
1333 1315
1334 1316 return (rv);
1335 1317 }
|
↓ open down ↓ |
120 lines elided |
↑ open up ↑ |
1336 1318
1337 1319 void
1338 1320 dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
1339 1321 dmu_tx_t *tx)
1340 1322 {
1341 1323 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1342 1324 dmu_buf_t *dbuf;
1343 1325 dsl_dataset_phys_t *dsphys;
1344 1326 uint64_t dsobj, crtxg;
1345 1327 objset_t *mos = dp->dp_meta_objset;
1346 - objset_t *os;
1328 + objset_t *os = NULL;
1329 + uint64_t unique_bytes = 0;
1347 1330
1348 1331 ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
1349 1332
1350 1333 /*
1351 1334 * If we are on an old pool, the zil must not be active, in which
1352 1335 * case it will be zeroed. Usually zil_suspend() accomplishes this.
1353 1336 */
1354 1337 ASSERT(spa_version(dmu_tx_pool(tx)->dp_spa) >= SPA_VERSION_FAST_SNAP ||
1355 1338 dmu_objset_from_ds(ds, &os) != 0 ||
1356 1339 bcmp(&os->os_phys->os_zil_header, &zero_zil,
1357 1340 sizeof (zero_zil)) == 0);
1358 1341
1359 1342 /* Should not snapshot a dirty dataset. */
1360 1343 ASSERT(!txg_list_member(&ds->ds_dir->dd_pool->dp_dirty_datasets,
1361 1344 ds, tx->tx_txg));
1362 1345
1363 1346 dsl_fs_ss_count_adjust(ds->ds_dir, 1, DD_FIELD_SNAPSHOT_COUNT, tx);
1364 1347
1365 1348 /*
1366 1349 * The origin's ds_creation_txg has to be < TXG_INITIAL
1367 1350 */
1368 1351 if (strcmp(snapname, ORIGIN_DIR_NAME) == 0)
1369 1352 crtxg = 1;
1370 1353 else
1371 1354 crtxg = tx->tx_txg;
1372 1355
1373 1356 dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0,
1374 1357 DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx);
1375 1358 VERIFY0(dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
1376 1359 dmu_buf_will_dirty(dbuf, tx);
1377 1360 dsphys = dbuf->db_data;
1378 1361 bzero(dsphys, sizeof (dsl_dataset_phys_t));
1379 1362 dsphys->ds_dir_obj = ds->ds_dir->dd_object;
1380 1363 dsphys->ds_fsid_guid = unique_create();
1381 1364 (void) random_get_pseudo_bytes((void*)&dsphys->ds_guid,
1382 1365 sizeof (dsphys->ds_guid));
1383 1366 dsphys->ds_prev_snap_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
1384 1367 dsphys->ds_prev_snap_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
1385 1368 dsphys->ds_next_snap_obj = ds->ds_object;
1386 1369 dsphys->ds_num_children = 1;
1387 1370 dsphys->ds_creation_time = gethrestime_sec();
1388 1371 dsphys->ds_creation_txg = crtxg;
1389 1372 dsphys->ds_deadlist_obj = dsl_dataset_phys(ds)->ds_deadlist_obj;
1390 1373 dsphys->ds_referenced_bytes = dsl_dataset_phys(ds)->ds_referenced_bytes;
1391 1374 dsphys->ds_compressed_bytes = dsl_dataset_phys(ds)->ds_compressed_bytes;
1392 1375 dsphys->ds_uncompressed_bytes =
1393 1376 dsl_dataset_phys(ds)->ds_uncompressed_bytes;
1394 1377 dsphys->ds_flags = dsl_dataset_phys(ds)->ds_flags;
1395 1378 rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
1396 1379 dsphys->ds_bp = dsl_dataset_phys(ds)->ds_bp;
1397 1380 rrw_exit(&ds->ds_bp_rwlock, FTAG);
1398 1381 dmu_buf_rele(dbuf, FTAG);
1399 1382
1400 1383 for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
1401 1384 if (ds->ds_feature_inuse[f])
1402 1385 dsl_dataset_activate_feature(dsobj, f, tx);
1403 1386 }
1404 1387
1405 1388 ASSERT3U(ds->ds_prev != 0, ==,
1406 1389 dsl_dataset_phys(ds)->ds_prev_snap_obj != 0);
1407 1390 if (ds->ds_prev) {
1408 1391 uint64_t next_clones_obj =
1409 1392 dsl_dataset_phys(ds->ds_prev)->ds_next_clones_obj;
1410 1393 ASSERT(dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj ==
1411 1394 ds->ds_object ||
1412 1395 dsl_dataset_phys(ds->ds_prev)->ds_num_children > 1);
1413 1396 if (dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj ==
1414 1397 ds->ds_object) {
1415 1398 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
1416 1399 ASSERT3U(dsl_dataset_phys(ds)->ds_prev_snap_txg, ==,
1417 1400 dsl_dataset_phys(ds->ds_prev)->ds_creation_txg);
1418 1401 dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj = dsobj;
1419 1402 } else if (next_clones_obj != 0) {
1420 1403 dsl_dataset_remove_from_next_clones(ds->ds_prev,
1421 1404 dsphys->ds_next_snap_obj, tx);
1422 1405 VERIFY0(zap_add_int(mos,
1423 1406 next_clones_obj, dsobj, tx));
1424 1407 }
1425 1408 }
1426 1409
1427 1410 /*
1428 1411 * If we have a reference-reservation on this dataset, we will
1429 1412 * need to increase the amount of refreservation being charged
1430 1413 * since our unique space is going to zero.
1431 1414 */
1432 1415 if (ds->ds_reserved) {
1433 1416 int64_t delta;
1434 1417 ASSERT(DS_UNIQUE_IS_ACCURATE(ds));
1435 1418 delta = MIN(dsl_dataset_phys(ds)->ds_unique_bytes,
1436 1419 ds->ds_reserved);
1437 1420 dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV,
1438 1421 delta, 0, 0, tx);
1439 1422 }
1440 1423
|
↓ open down ↓ |
84 lines elided |
↑ open up ↑ |
1441 1424 dmu_buf_will_dirty(ds->ds_dbuf, tx);
1442 1425 dsl_dataset_phys(ds)->ds_deadlist_obj =
1443 1426 dsl_deadlist_clone(&ds->ds_deadlist, UINT64_MAX,
1444 1427 dsl_dataset_phys(ds)->ds_prev_snap_obj, tx);
1445 1428 dsl_deadlist_close(&ds->ds_deadlist);
1446 1429 dsl_deadlist_open(&ds->ds_deadlist, mos,
1447 1430 dsl_dataset_phys(ds)->ds_deadlist_obj);
1448 1431 dsl_deadlist_add_key(&ds->ds_deadlist,
1449 1432 dsl_dataset_phys(ds)->ds_prev_snap_txg, tx);
1450 1433
1451 - if (dsl_dataset_remap_deadlist_exists(ds)) {
1452 - uint64_t remap_deadlist_obj =
1453 - dsl_dataset_get_remap_deadlist_object(ds);
1454 - /*
1455 - * Move the remap_deadlist to the snapshot. The head
1456 - * will create a new remap deadlist on demand, from
1457 - * dsl_dataset_block_remapped().
1458 - */
1459 - dsl_dataset_unset_remap_deadlist_object(ds, tx);
1460 - dsl_deadlist_close(&ds->ds_remap_deadlist);
1461 -
1462 - dmu_object_zapify(mos, dsobj, DMU_OT_DSL_DATASET, tx);
1463 - VERIFY0(zap_add(mos, dsobj, DS_FIELD_REMAP_DEADLIST,
1464 - sizeof (remap_deadlist_obj), 1, &remap_deadlist_obj, tx));
1465 - }
1466 -
1467 1434 ASSERT3U(dsl_dataset_phys(ds)->ds_prev_snap_txg, <, tx->tx_txg);
1468 1435 dsl_dataset_phys(ds)->ds_prev_snap_obj = dsobj;
1469 1436 dsl_dataset_phys(ds)->ds_prev_snap_txg = crtxg;
1437 + unique_bytes = dsl_dataset_phys(ds)->ds_unique_bytes;
1470 1438 dsl_dataset_phys(ds)->ds_unique_bytes = 0;
1471 -
1472 1439 if (spa_version(dp->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE)
1473 1440 dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
1474 1441
1475 1442 VERIFY0(zap_add(mos, dsl_dataset_phys(ds)->ds_snapnames_zapobj,
1476 1443 snapname, 8, 1, &dsobj, tx));
1477 1444
1478 1445 if (ds->ds_prev)
1479 1446 dsl_dataset_rele(ds->ds_prev, ds);
1480 1447 VERIFY0(dsl_dataset_hold_obj(dp,
1481 1448 dsl_dataset_phys(ds)->ds_prev_snap_obj, ds, &ds->ds_prev));
1482 1449
1483 1450 dsl_scan_ds_snapshotted(ds, tx);
1484 1451
1485 1452 dsl_dir_snap_cmtime_update(ds->ds_dir);
1486 1453
1487 1454 spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, "");
1455 +
1456 + if (autosnap_check_name(snapname)) {
1457 + autosnap_create_cb(spa_get_autosnap(dp->dp_spa),
1458 + ds, snapname, tx->tx_txg);
1459 + }
1460 +
1461 + if (os == NULL)
1462 + VERIFY0(dmu_objset_from_ds(ds, &os));
1463 +
1464 + if (os->os_wbc_mode != ZFS_WBC_MODE_OFF)
1465 + wbc_add_bytes(dp->dp_spa, tx->tx_txg, unique_bytes);
1488 1466 }
1489 1467
1490 1468 void
1491 1469 dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx)
1492 1470 {
1493 1471 dsl_dataset_snapshot_arg_t *ddsa = arg;
1494 1472 dsl_pool_t *dp = dmu_tx_pool(tx);
1495 1473 nvpair_t *pair;
1496 1474
1497 1475 for (pair = nvlist_next_nvpair(ddsa->ddsa_snaps, NULL);
1498 1476 pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
1499 1477 dsl_dataset_t *ds;
1500 1478 char *name, *atp;
1501 1479 char dsname[ZFS_MAX_DATASET_NAME_LEN];
1502 1480
1503 1481 name = nvpair_name(pair);
1482 +
1504 1483 atp = strchr(name, '@');
1505 1484 (void) strlcpy(dsname, name, atp - name + 1);
1506 1485 VERIFY0(dsl_dataset_hold(dp, dsname, FTAG, &ds));
1507 1486
1508 1487 dsl_dataset_snapshot_sync_impl(ds, atp + 1, tx);
1509 1488 if (ddsa->ddsa_props != NULL) {
1510 1489 dsl_props_set_sync_impl(ds->ds_prev,
1511 1490 ZPROP_SRC_LOCAL, ddsa->ddsa_props, tx);
1512 1491 }
1513 1492 dsl_dataset_rele(ds, FTAG);
1514 1493 }
1515 1494 }
1516 1495
1517 1496 /*
1518 1497 * The snapshots must all be in the same pool.
1519 1498 * All-or-nothing: if there are any failures, nothing will be modified.
1520 1499 */
1521 1500 int
1522 1501 dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
1523 1502 {
1524 1503 dsl_dataset_snapshot_arg_t ddsa;
1525 1504 nvpair_t *pair;
1526 1505 boolean_t needsuspend;
1527 1506 int error;
1528 1507 spa_t *spa;
1529 1508 char *firstname;
1530 1509 nvlist_t *suspended = NULL;
1531 1510
1532 1511 pair = nvlist_next_nvpair(snaps, NULL);
1533 1512 if (pair == NULL)
1534 1513 return (0);
1535 1514 firstname = nvpair_name(pair);
1536 1515
1537 1516 error = spa_open(firstname, &spa, FTAG);
1538 1517 if (error != 0)
1539 1518 return (error);
1540 1519 needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
1541 1520 spa_close(spa, FTAG);
1542 1521
1543 1522 if (needsuspend) {
1544 1523 suspended = fnvlist_alloc();
1545 1524 for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
1546 1525 pair = nvlist_next_nvpair(snaps, pair)) {
1547 1526 char fsname[ZFS_MAX_DATASET_NAME_LEN];
1548 1527 char *snapname = nvpair_name(pair);
1549 1528 char *atp;
1550 1529 void *cookie;
1551 1530
1552 1531 atp = strchr(snapname, '@');
1553 1532 if (atp == NULL) {
1554 1533 error = SET_ERROR(EINVAL);
1555 1534 break;
1556 1535 }
1557 1536 (void) strlcpy(fsname, snapname, atp - snapname + 1);
1558 1537
1559 1538 error = zil_suspend(fsname, &cookie);
1560 1539 if (error != 0)
|
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
1561 1540 break;
1562 1541 fnvlist_add_uint64(suspended, fsname,
1563 1542 (uintptr_t)cookie);
1564 1543 }
1565 1544 }
1566 1545
1567 1546 ddsa.ddsa_snaps = snaps;
1568 1547 ddsa.ddsa_props = props;
1569 1548 ddsa.ddsa_errors = errors;
1570 1549 ddsa.ddsa_cr = CRED();
1550 + ddsa.ddsa_autosnap = B_FALSE;
1571 1551
1572 1552 if (error == 0) {
1573 1553 error = dsl_sync_task(firstname, dsl_dataset_snapshot_check,
1574 1554 dsl_dataset_snapshot_sync, &ddsa,
1575 1555 fnvlist_num_pairs(snaps) * 3, ZFS_SPACE_CHECK_NORMAL);
1576 1556 }
1577 1557
1578 1558 if (suspended != NULL) {
1579 1559 for (pair = nvlist_next_nvpair(suspended, NULL); pair != NULL;
1580 1560 pair = nvlist_next_nvpair(suspended, pair)) {
1581 1561 zil_resume((void *)(uintptr_t)
1582 1562 fnvpair_value_uint64(pair));
1583 1563 }
1584 1564 fnvlist_free(suspended);
1585 1565 }
1586 1566
1587 1567 return (error);
1588 1568 }
1589 1569
1590 1570 typedef struct dsl_dataset_snapshot_tmp_arg {
1591 1571 const char *ddsta_fsname;
1592 1572 const char *ddsta_snapname;
1593 1573 minor_t ddsta_cleanup_minor;
1594 1574 const char *ddsta_htag;
1595 1575 } dsl_dataset_snapshot_tmp_arg_t;
1596 1576
1597 1577 static int
1598 1578 dsl_dataset_snapshot_tmp_check(void *arg, dmu_tx_t *tx)
1599 1579 {
1600 1580 dsl_dataset_snapshot_tmp_arg_t *ddsta = arg;
1601 1581 dsl_pool_t *dp = dmu_tx_pool(tx);
1602 1582 dsl_dataset_t *ds;
1603 1583 int error;
1604 1584
1605 1585 error = dsl_dataset_hold(dp, ddsta->ddsta_fsname, FTAG, &ds);
1606 1586 if (error != 0)
1607 1587 return (error);
1608 1588
1609 1589 /* NULL cred means no limit check for tmp snapshot */
1610 1590 error = dsl_dataset_snapshot_check_impl(ds, ddsta->ddsta_snapname,
1611 1591 tx, B_FALSE, 0, NULL);
1612 1592 if (error != 0) {
1613 1593 dsl_dataset_rele(ds, FTAG);
1614 1594 return (error);
1615 1595 }
1616 1596
1617 1597 if (spa_version(dp->dp_spa) < SPA_VERSION_USERREFS) {
1618 1598 dsl_dataset_rele(ds, FTAG);
1619 1599 return (SET_ERROR(ENOTSUP));
1620 1600 }
1621 1601 error = dsl_dataset_user_hold_check_one(NULL, ddsta->ddsta_htag,
1622 1602 B_TRUE, tx);
1623 1603 if (error != 0) {
1624 1604 dsl_dataset_rele(ds, FTAG);
1625 1605 return (error);
1626 1606 }
1627 1607
1628 1608 dsl_dataset_rele(ds, FTAG);
1629 1609 return (0);
1630 1610 }
1631 1611
1632 1612 static void
1633 1613 dsl_dataset_snapshot_tmp_sync(void *arg, dmu_tx_t *tx)
1634 1614 {
1635 1615 dsl_dataset_snapshot_tmp_arg_t *ddsta = arg;
1636 1616 dsl_pool_t *dp = dmu_tx_pool(tx);
1637 1617 dsl_dataset_t *ds;
1638 1618
1639 1619 VERIFY0(dsl_dataset_hold(dp, ddsta->ddsta_fsname, FTAG, &ds));
1640 1620
1641 1621 dsl_dataset_snapshot_sync_impl(ds, ddsta->ddsta_snapname, tx);
1642 1622 dsl_dataset_user_hold_sync_one(ds->ds_prev, ddsta->ddsta_htag,
1643 1623 ddsta->ddsta_cleanup_minor, gethrestime_sec(), tx);
1644 1624 dsl_destroy_snapshot_sync_impl(ds->ds_prev, B_TRUE, tx);
1645 1625
1646 1626 dsl_dataset_rele(ds, FTAG);
1647 1627 }
1648 1628
1649 1629 int
1650 1630 dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
1651 1631 minor_t cleanup_minor, const char *htag)
1652 1632 {
1653 1633 dsl_dataset_snapshot_tmp_arg_t ddsta;
1654 1634 int error;
1655 1635 spa_t *spa;
1656 1636 boolean_t needsuspend;
1657 1637 void *cookie;
1658 1638
1659 1639 ddsta.ddsta_fsname = fsname;
1660 1640 ddsta.ddsta_snapname = snapname;
1661 1641 ddsta.ddsta_cleanup_minor = cleanup_minor;
1662 1642 ddsta.ddsta_htag = htag;
1663 1643
1664 1644 error = spa_open(fsname, &spa, FTAG);
1665 1645 if (error != 0)
1666 1646 return (error);
1667 1647 needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
1668 1648 spa_close(spa, FTAG);
1669 1649
1670 1650 if (needsuspend) {
1671 1651 error = zil_suspend(fsname, &cookie);
1672 1652 if (error != 0)
1673 1653 return (error);
1674 1654 }
1675 1655
1676 1656 error = dsl_sync_task(fsname, dsl_dataset_snapshot_tmp_check,
1677 1657 dsl_dataset_snapshot_tmp_sync, &ddsta, 3, ZFS_SPACE_CHECK_RESERVED);
1678 1658
1679 1659 if (needsuspend)
1680 1660 zil_resume(cookie);
1681 1661 return (error);
1682 1662 }
1683 1663
1684 1664 void
1685 1665 dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
1686 1666 {
1687 1667 ASSERT(dmu_tx_is_syncing(tx));
1688 1668 ASSERT(ds->ds_objset != NULL);
1689 1669 ASSERT(dsl_dataset_phys(ds)->ds_next_snap_obj == 0);
1690 1670
1691 1671 /*
1692 1672 * in case we had to change ds_fsid_guid when we opened it,
1693 1673 * sync it out now.
1694 1674 */
1695 1675 dmu_buf_will_dirty(ds->ds_dbuf, tx);
1696 1676 dsl_dataset_phys(ds)->ds_fsid_guid = ds->ds_fsid_guid;
1697 1677
1698 1678 if (ds->ds_resume_bytes[tx->tx_txg & TXG_MASK] != 0) {
1699 1679 VERIFY0(zap_update(tx->tx_pool->dp_meta_objset,
1700 1680 ds->ds_object, DS_FIELD_RESUME_OBJECT, 8, 1,
1701 1681 &ds->ds_resume_object[tx->tx_txg & TXG_MASK], tx));
1702 1682 VERIFY0(zap_update(tx->tx_pool->dp_meta_objset,
1703 1683 ds->ds_object, DS_FIELD_RESUME_OFFSET, 8, 1,
1704 1684 &ds->ds_resume_offset[tx->tx_txg & TXG_MASK], tx));
1705 1685 VERIFY0(zap_update(tx->tx_pool->dp_meta_objset,
1706 1686 ds->ds_object, DS_FIELD_RESUME_BYTES, 8, 1,
1707 1687 &ds->ds_resume_bytes[tx->tx_txg & TXG_MASK], tx));
1708 1688 ds->ds_resume_object[tx->tx_txg & TXG_MASK] = 0;
1709 1689 ds->ds_resume_offset[tx->tx_txg & TXG_MASK] = 0;
1710 1690 ds->ds_resume_bytes[tx->tx_txg & TXG_MASK] = 0;
1711 1691 }
1712 1692
1713 1693 dmu_objset_sync(ds->ds_objset, zio, tx);
1714 1694
1715 1695 for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
1716 1696 if (ds->ds_feature_activation_needed[f]) {
1717 1697 if (ds->ds_feature_inuse[f])
1718 1698 continue;
1719 1699 dsl_dataset_activate_feature(ds->ds_object, f, tx);
1720 1700 ds->ds_feature_inuse[f] = B_TRUE;
1721 1701 }
1722 1702 }
1723 1703 }
1724 1704
1725 1705 static int
1726 1706 deadlist_enqueue_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
1727 1707 {
1728 1708 dsl_deadlist_t *dl = arg;
1729 1709 dsl_deadlist_insert(dl, bp, tx);
1730 1710 return (0);
1731 1711 }
1732 1712
1733 1713 void
1734 1714 dsl_dataset_sync_done(dsl_dataset_t *ds, dmu_tx_t *tx)
1735 1715 {
1736 1716 objset_t *os = ds->ds_objset;
1737 1717
1738 1718 bplist_iterate(&ds->ds_pending_deadlist,
1739 1719 deadlist_enqueue_cb, &ds->ds_deadlist, tx);
1740 1720
1741 1721 if (os->os_synced_dnodes != NULL) {
1742 1722 multilist_destroy(os->os_synced_dnodes);
1743 1723 os->os_synced_dnodes = NULL;
1744 1724 }
1745 1725
1746 1726 ASSERT(!dmu_objset_is_dirty(os, dmu_tx_get_txg(tx)));
1747 1727
1748 1728 dmu_buf_rele(ds->ds_dbuf, ds);
1749 1729 }
1750 1730
1751 1731 int
1752 1732 get_clones_stat_impl(dsl_dataset_t *ds, nvlist_t *val)
1753 1733 {
1754 1734 uint64_t count = 0;
1755 1735 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
1756 1736 zap_cursor_t zc;
1757 1737 zap_attribute_t za;
1758 1738
1759 1739 ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
1760 1740
1761 1741 /*
1762 1742 * There may be missing entries in ds_next_clones_obj
1763 1743 * due to a bug in a previous version of the code.
1764 1744 * Only trust it if it has the right number of entries.
1765 1745 */
1766 1746 if (dsl_dataset_phys(ds)->ds_next_clones_obj != 0) {
1767 1747 VERIFY0(zap_count(mos, dsl_dataset_phys(ds)->ds_next_clones_obj,
1768 1748 &count));
1769 1749 }
1770 1750 if (count != dsl_dataset_phys(ds)->ds_num_children - 1) {
1771 1751 return (ENOENT);
1772 1752 }
1773 1753 for (zap_cursor_init(&zc, mos,
1774 1754 dsl_dataset_phys(ds)->ds_next_clones_obj);
1775 1755 zap_cursor_retrieve(&zc, &za) == 0;
1776 1756 zap_cursor_advance(&zc)) {
1777 1757 dsl_dataset_t *clone;
1778 1758 char buf[ZFS_MAX_DATASET_NAME_LEN];
1779 1759 VERIFY0(dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
1780 1760 za.za_first_integer, FTAG, &clone));
1781 1761 dsl_dir_name(clone->ds_dir, buf);
1782 1762 fnvlist_add_boolean(val, buf);
1783 1763 dsl_dataset_rele(clone, FTAG);
1784 1764 }
1785 1765 zap_cursor_fini(&zc);
1786 1766 return (0);
1787 1767 }
1788 1768
1789 1769 void
1790 1770 get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv)
1791 1771 {
1792 1772 nvlist_t *propval = fnvlist_alloc();
1793 1773 nvlist_t *val;
1794 1774
1795 1775 /*
1796 1776 * We use nvlist_alloc() instead of fnvlist_alloc() because the
1797 1777 * latter would allocate the list with NV_UNIQUE_NAME flag.
1798 1778 * As a result, every time a clone name is appended to the list
1799 1779 * it would be (linearly) searched for for a duplicate name.
1800 1780 * We already know that all clone names must be unique and we
1801 1781 * want avoid the quadratic complexity of double-checking that
1802 1782 * because we can have a large number of clones.
1803 1783 */
1804 1784 VERIFY0(nvlist_alloc(&val, 0, KM_SLEEP));
1805 1785
1806 1786 if (get_clones_stat_impl(ds, val) == 0) {
1807 1787 fnvlist_add_nvlist(propval, ZPROP_VALUE, val);
1808 1788 fnvlist_add_nvlist(nv, zfs_prop_to_name(ZFS_PROP_CLONES),
1809 1789 propval);
1810 1790 }
1811 1791
1812 1792 nvlist_free(val);
1813 1793 nvlist_free(propval);
1814 1794 }
1815 1795
1816 1796 /*
1817 1797 * Returns a string that represents the receive resume stats token. It should
1818 1798 * be freed with strfree().
1819 1799 */
1820 1800 char *
1821 1801 get_receive_resume_stats_impl(dsl_dataset_t *ds)
1822 1802 {
1823 1803 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1824 1804
1825 1805 if (dsl_dataset_has_resume_receive_state(ds)) {
1826 1806 char *str;
1827 1807 void *packed;
1828 1808 uint8_t *compressed;
1829 1809 uint64_t val;
1830 1810 nvlist_t *token_nv = fnvlist_alloc();
1831 1811 size_t packed_size, compressed_size;
1832 1812
1833 1813 if (zap_lookup(dp->dp_meta_objset, ds->ds_object,
1834 1814 DS_FIELD_RESUME_FROMGUID, sizeof (val), 1, &val) == 0) {
1835 1815 fnvlist_add_uint64(token_nv, "fromguid", val);
1836 1816 }
1837 1817 if (zap_lookup(dp->dp_meta_objset, ds->ds_object,
1838 1818 DS_FIELD_RESUME_OBJECT, sizeof (val), 1, &val) == 0) {
1839 1819 fnvlist_add_uint64(token_nv, "object", val);
1840 1820 }
1841 1821 if (zap_lookup(dp->dp_meta_objset, ds->ds_object,
1842 1822 DS_FIELD_RESUME_OFFSET, sizeof (val), 1, &val) == 0) {
1843 1823 fnvlist_add_uint64(token_nv, "offset", val);
1844 1824 }
1845 1825 if (zap_lookup(dp->dp_meta_objset, ds->ds_object,
1846 1826 DS_FIELD_RESUME_BYTES, sizeof (val), 1, &val) == 0) {
1847 1827 fnvlist_add_uint64(token_nv, "bytes", val);
1848 1828 }
1849 1829 if (zap_lookup(dp->dp_meta_objset, ds->ds_object,
1850 1830 DS_FIELD_RESUME_TOGUID, sizeof (val), 1, &val) == 0) {
1851 1831 fnvlist_add_uint64(token_nv, "toguid", val);
1852 1832 }
1853 1833 char buf[256];
1854 1834 if (zap_lookup(dp->dp_meta_objset, ds->ds_object,
1855 1835 DS_FIELD_RESUME_TONAME, 1, sizeof (buf), buf) == 0) {
1856 1836 fnvlist_add_string(token_nv, "toname", buf);
1857 1837 }
1858 1838 if (zap_contains(dp->dp_meta_objset, ds->ds_object,
1859 1839 DS_FIELD_RESUME_LARGEBLOCK) == 0) {
1860 1840 fnvlist_add_boolean(token_nv, "largeblockok");
1861 1841 }
1862 1842 if (zap_contains(dp->dp_meta_objset, ds->ds_object,
1863 1843 DS_FIELD_RESUME_EMBEDOK) == 0) {
1864 1844 fnvlist_add_boolean(token_nv, "embedok");
1865 1845 }
1866 1846 if (zap_contains(dp->dp_meta_objset, ds->ds_object,
1867 1847 DS_FIELD_RESUME_COMPRESSOK) == 0) {
1868 1848 fnvlist_add_boolean(token_nv, "compressok");
1869 1849 }
1870 1850 packed = fnvlist_pack(token_nv, &packed_size);
1871 1851 fnvlist_free(token_nv);
1872 1852 compressed = kmem_alloc(packed_size, KM_SLEEP);
1873 1853
1874 1854 compressed_size = gzip_compress(packed, compressed,
1875 1855 packed_size, packed_size, 6);
1876 1856
1877 1857 zio_cksum_t cksum;
1878 1858 fletcher_4_native(compressed, compressed_size, NULL, &cksum);
1879 1859
1880 1860 str = kmem_alloc(compressed_size * 2 + 1, KM_SLEEP);
1881 1861 for (int i = 0; i < compressed_size; i++) {
1882 1862 (void) sprintf(str + i * 2, "%02x", compressed[i]);
1883 1863 }
1884 1864 str[compressed_size * 2] = '\0';
1885 1865 char *propval = kmem_asprintf("%u-%llx-%llx-%s",
1886 1866 ZFS_SEND_RESUME_TOKEN_VERSION,
1887 1867 (longlong_t)cksum.zc_word[0],
1888 1868 (longlong_t)packed_size, str);
1889 1869 kmem_free(packed, packed_size);
1890 1870 kmem_free(str, compressed_size * 2 + 1);
1891 1871 kmem_free(compressed, packed_size);
1892 1872 return (propval);
1893 1873 }
1894 1874 return (strdup(""));
1895 1875 }
1896 1876
1897 1877 /*
1898 1878 * Returns a string that represents the receive resume stats token of the
1899 1879 * dataset's child. It should be freed with strfree().
1900 1880 */
1901 1881 char *
1902 1882 get_child_receive_stats(dsl_dataset_t *ds)
1903 1883 {
1904 1884 char recvname[ZFS_MAX_DATASET_NAME_LEN + 6];
1905 1885 dsl_dataset_t *recv_ds;
1906 1886 dsl_dataset_name(ds, recvname);
1907 1887 if (strlcat(recvname, "/", sizeof (recvname)) <
1908 1888 sizeof (recvname) &&
1909 1889 strlcat(recvname, recv_clone_name, sizeof (recvname)) <
1910 1890 sizeof (recvname) &&
1911 1891 dsl_dataset_hold(ds->ds_dir->dd_pool, recvname, FTAG,
1912 1892 &recv_ds) == 0) {
1913 1893 char *propval = get_receive_resume_stats_impl(recv_ds);
1914 1894 dsl_dataset_rele(recv_ds, FTAG);
1915 1895 return (propval);
1916 1896 }
1917 1897 return (strdup(""));
1918 1898 }
1919 1899
1920 1900 static void
1921 1901 get_receive_resume_stats(dsl_dataset_t *ds, nvlist_t *nv)
1922 1902 {
1923 1903 char *propval = get_receive_resume_stats_impl(ds);
1924 1904 if (strcmp(propval, "") != 0) {
1925 1905 dsl_prop_nvlist_add_string(nv,
1926 1906 ZFS_PROP_RECEIVE_RESUME_TOKEN, propval);
1927 1907 } else {
1928 1908 char *childval = get_child_receive_stats(ds);
1929 1909 if (strcmp(childval, "") != 0) {
1930 1910 dsl_prop_nvlist_add_string(nv,
1931 1911 ZFS_PROP_RECEIVE_RESUME_TOKEN, childval);
1932 1912 }
1933 1913 strfree(childval);
1934 1914 }
1935 1915 strfree(propval);
1936 1916 }
1937 1917
1938 1918 uint64_t
1939 1919 dsl_get_refratio(dsl_dataset_t *ds)
1940 1920 {
1941 1921 uint64_t ratio = dsl_dataset_phys(ds)->ds_compressed_bytes == 0 ? 100 :
1942 1922 (dsl_dataset_phys(ds)->ds_uncompressed_bytes * 100 /
1943 1923 dsl_dataset_phys(ds)->ds_compressed_bytes);
1944 1924 return (ratio);
1945 1925 }
1946 1926
1947 1927 uint64_t
1948 1928 dsl_get_logicalreferenced(dsl_dataset_t *ds)
1949 1929 {
1950 1930 return (dsl_dataset_phys(ds)->ds_uncompressed_bytes);
1951 1931 }
1952 1932
1953 1933 uint64_t
1954 1934 dsl_get_compressratio(dsl_dataset_t *ds)
1955 1935 {
1956 1936 if (ds->ds_is_snapshot) {
1957 1937 return (dsl_get_refratio(ds));
1958 1938 } else {
1959 1939 dsl_dir_t *dd = ds->ds_dir;
1960 1940 mutex_enter(&dd->dd_lock);
1961 1941 uint64_t val = dsl_dir_get_compressratio(dd);
1962 1942 mutex_exit(&dd->dd_lock);
1963 1943 return (val);
1964 1944 }
1965 1945 }
1966 1946
1967 1947 uint64_t
1968 1948 dsl_get_used(dsl_dataset_t *ds)
1969 1949 {
1970 1950 if (ds->ds_is_snapshot) {
1971 1951 return (dsl_dataset_phys(ds)->ds_unique_bytes);
1972 1952 } else {
1973 1953 dsl_dir_t *dd = ds->ds_dir;
1974 1954 mutex_enter(&dd->dd_lock);
1975 1955 uint64_t val = dsl_dir_get_used(dd);
1976 1956 mutex_exit(&dd->dd_lock);
1977 1957 return (val);
1978 1958 }
1979 1959 }
1980 1960
1981 1961 uint64_t
1982 1962 dsl_get_creation(dsl_dataset_t *ds)
1983 1963 {
1984 1964 return (dsl_dataset_phys(ds)->ds_creation_time);
1985 1965 }
1986 1966
1987 1967 uint64_t
1988 1968 dsl_get_creationtxg(dsl_dataset_t *ds)
1989 1969 {
1990 1970 return (dsl_dataset_phys(ds)->ds_creation_txg);
1991 1971 }
1992 1972
1993 1973 uint64_t
1994 1974 dsl_get_refquota(dsl_dataset_t *ds)
1995 1975 {
1996 1976 return (ds->ds_quota);
1997 1977 }
1998 1978
1999 1979 uint64_t
2000 1980 dsl_get_refreservation(dsl_dataset_t *ds)
2001 1981 {
2002 1982 return (ds->ds_reserved);
2003 1983 }
2004 1984
2005 1985 uint64_t
2006 1986 dsl_get_guid(dsl_dataset_t *ds)
2007 1987 {
2008 1988 return (dsl_dataset_phys(ds)->ds_guid);
2009 1989 }
2010 1990
2011 1991 uint64_t
2012 1992 dsl_get_unique(dsl_dataset_t *ds)
2013 1993 {
2014 1994 return (dsl_dataset_phys(ds)->ds_unique_bytes);
2015 1995 }
2016 1996
2017 1997 uint64_t
2018 1998 dsl_get_objsetid(dsl_dataset_t *ds)
2019 1999 {
2020 2000 return (ds->ds_object);
2021 2001 }
2022 2002
2023 2003 uint64_t
2024 2004 dsl_get_userrefs(dsl_dataset_t *ds)
2025 2005 {
2026 2006 return (ds->ds_userrefs);
2027 2007 }
2028 2008
2029 2009 uint64_t
2030 2010 dsl_get_defer_destroy(dsl_dataset_t *ds)
2031 2011 {
2032 2012 return (DS_IS_DEFER_DESTROY(ds) ? 1 : 0);
2033 2013 }
2034 2014
2035 2015 uint64_t
2036 2016 dsl_get_referenced(dsl_dataset_t *ds)
2037 2017 {
2038 2018 return (dsl_dataset_phys(ds)->ds_referenced_bytes);
2039 2019 }
2040 2020
2041 2021 uint64_t
2042 2022 dsl_get_numclones(dsl_dataset_t *ds)
2043 2023 {
2044 2024 ASSERT(ds->ds_is_snapshot);
2045 2025 return (dsl_dataset_phys(ds)->ds_num_children - 1);
2046 2026 }
2047 2027
2048 2028 uint64_t
2049 2029 dsl_get_inconsistent(dsl_dataset_t *ds)
2050 2030 {
2051 2031 return ((dsl_dataset_phys(ds)->ds_flags & DS_FLAG_INCONSISTENT) ?
2052 2032 1 : 0);
2053 2033 }
2054 2034
2055 2035 uint64_t
2056 2036 dsl_get_available(dsl_dataset_t *ds)
2057 2037 {
2058 2038 uint64_t refdbytes = dsl_get_referenced(ds);
2059 2039 uint64_t availbytes = dsl_dir_space_available(ds->ds_dir,
2060 2040 NULL, 0, TRUE);
2061 2041 if (ds->ds_reserved > dsl_dataset_phys(ds)->ds_unique_bytes) {
2062 2042 availbytes +=
2063 2043 ds->ds_reserved - dsl_dataset_phys(ds)->ds_unique_bytes;
2064 2044 }
2065 2045 if (ds->ds_quota != 0) {
2066 2046 /*
2067 2047 * Adjust available bytes according to refquota
2068 2048 */
2069 2049 if (refdbytes < ds->ds_quota) {
2070 2050 availbytes = MIN(availbytes,
2071 2051 ds->ds_quota - refdbytes);
2072 2052 } else {
2073 2053 availbytes = 0;
2074 2054 }
2075 2055 }
2076 2056 return (availbytes);
2077 2057 }
2078 2058
2079 2059 int
2080 2060 dsl_get_written(dsl_dataset_t *ds, uint64_t *written)
2081 2061 {
2082 2062 dsl_pool_t *dp = ds->ds_dir->dd_pool;
2083 2063 dsl_dataset_t *prev;
2084 2064 int err = dsl_dataset_hold_obj(dp,
2085 2065 dsl_dataset_phys(ds)->ds_prev_snap_obj, FTAG, &prev);
2086 2066 if (err == 0) {
2087 2067 uint64_t comp, uncomp;
2088 2068 err = dsl_dataset_space_written(prev, ds, written,
2089 2069 &comp, &uncomp);
2090 2070 dsl_dataset_rele(prev, FTAG);
2091 2071 }
2092 2072 return (err);
2093 2073 }
2094 2074
2095 2075 /*
2096 2076 * 'snap' should be a buffer of size ZFS_MAX_DATASET_NAME_LEN.
2097 2077 */
2098 2078 int
2099 2079 dsl_get_prev_snap(dsl_dataset_t *ds, char *snap)
2100 2080 {
2101 2081 dsl_pool_t *dp = ds->ds_dir->dd_pool;
2102 2082 if (ds->ds_prev != NULL && ds->ds_prev != dp->dp_origin_snap) {
2103 2083 dsl_dataset_name(ds->ds_prev, snap);
2104 2084 return (0);
2105 2085 } else {
2106 2086 return (ENOENT);
2107 2087 }
2108 2088 }
2109 2089
2110 2090 /*
2111 2091 * Returns the mountpoint property and source for the given dataset in the value
2112 2092 * and source buffers. The value buffer must be at least as large as MAXPATHLEN
2113 2093 * and the source buffer as least as large a ZFS_MAX_DATASET_NAME_LEN.
2114 2094 * Returns 0 on success and an error on failure.
2115 2095 */
2116 2096 int
2117 2097 dsl_get_mountpoint(dsl_dataset_t *ds, const char *dsname, char *value,
2118 2098 char *source)
2119 2099 {
2120 2100 int error;
2121 2101 dsl_pool_t *dp = ds->ds_dir->dd_pool;
2122 2102
2123 2103 /* Retrieve the mountpoint value stored in the zap opbject */
2124 2104 error = dsl_prop_get_ds(ds, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 1,
2125 2105 ZAP_MAXVALUELEN, value, source);
2126 2106 if (error != 0) {
2127 2107 return (error);
2128 2108 }
2129 2109
2130 2110 /* Process the dsname and source to find the full mountpoint string */
2131 2111 if (value[0] == '/') {
2132 2112 char *buf = kmem_alloc(ZAP_MAXVALUELEN, KM_SLEEP);
2133 2113 char *root = buf;
2134 2114 const char *relpath;
2135 2115
2136 2116 /*
2137 2117 * If we inherit the mountpoint, even from a dataset
2138 2118 * with a received value, the source will be the path of
2139 2119 * the dataset we inherit from. If source is
2140 2120 * ZPROP_SOURCE_VAL_RECVD, the received value is not
2141 2121 * inherited.
2142 2122 */
2143 2123 if (strcmp(source, ZPROP_SOURCE_VAL_RECVD) == 0) {
2144 2124 relpath = "";
2145 2125 } else {
2146 2126 ASSERT0(strncmp(dsname, source, strlen(source)));
2147 2127 relpath = dsname + strlen(source);
2148 2128 if (relpath[0] == '/')
2149 2129 relpath++;
2150 2130 }
2151 2131
2152 2132 spa_altroot(dp->dp_spa, root, ZAP_MAXVALUELEN);
2153 2133
2154 2134 /*
2155 2135 * Special case an alternate root of '/'. This will
2156 2136 * avoid having multiple leading slashes in the
2157 2137 * mountpoint path.
2158 2138 */
2159 2139 if (strcmp(root, "/") == 0)
2160 2140 root++;
2161 2141
2162 2142 /*
2163 2143 * If the mountpoint is '/' then skip over this
2164 2144 * if we are obtaining either an alternate root or
2165 2145 * an inherited mountpoint.
2166 2146 */
2167 2147 char *mnt = value;
2168 2148 if (value[1] == '\0' && (root[0] != '\0' ||
2169 2149 relpath[0] != '\0'))
2170 2150 mnt = value + 1;
2171 2151
2172 2152 if (relpath[0] == '\0') {
2173 2153 (void) snprintf(value, ZAP_MAXVALUELEN, "%s%s",
2174 2154 root, mnt);
2175 2155 } else {
2176 2156 (void) snprintf(value, ZAP_MAXVALUELEN, "%s%s%s%s",
2177 2157 root, mnt, relpath[0] == '@' ? "" : "/",
2178 2158 relpath);
2179 2159 }
2180 2160 kmem_free(buf, ZAP_MAXVALUELEN);
2181 2161 } else {
2182 2162 /* 'legacy' or 'none' */
2183 2163 (void) snprintf(value, ZAP_MAXVALUELEN, "%s", value);
2184 2164 }
2185 2165 return (0);
2186 2166 }
2187 2167
2188 2168 void
2189 2169 dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
2190 2170 {
2191 2171 dsl_pool_t *dp = ds->ds_dir->dd_pool;
2192 2172
2193 2173 ASSERT(dsl_pool_config_held(dp));
2194 2174
|
↓ open down ↓ |
614 lines elided |
↑ open up ↑ |
2195 2175 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO,
2196 2176 dsl_get_refratio(ds));
2197 2177 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALREFERENCED,
2198 2178 dsl_get_logicalreferenced(ds));
2199 2179 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO,
2200 2180 dsl_get_compressratio(ds));
2201 2181 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
2202 2182 dsl_get_used(ds));
2203 2183
2204 2184 if (ds->ds_is_snapshot) {
2185 + dsl_dataset_t *hds = NULL;
2186 + boolean_t modified = B_FALSE;
2187 +
2188 + if (dsl_dataset_hold_obj(dp,
2189 + dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj,
2190 + FTAG, &hds) == 0) {
2191 + modified = dsl_dataset_modified_since_snap(hds, ds);
2192 + dsl_dataset_rele(hds, FTAG);
2193 + }
2194 +
2195 + dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_MODIFIED,
2196 + modified ? 1 : 0);
2197 +
2205 2198 get_clones_stat(ds, nv);
2206 2199 } else {
2207 2200 char buf[ZFS_MAX_DATASET_NAME_LEN];
2208 2201 if (dsl_get_prev_snap(ds, buf) == 0)
2209 2202 dsl_prop_nvlist_add_string(nv, ZFS_PROP_PREV_SNAP,
2210 2203 buf);
2211 2204 dsl_dir_stats(ds->ds_dir, nv);
2212 2205 }
2213 2206
2214 2207 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_AVAILABLE,
2215 2208 dsl_get_available(ds));
2216 2209 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFERENCED,
2217 2210 dsl_get_referenced(ds));
2218 2211 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATION,
2219 2212 dsl_get_creation(ds));
2220 2213 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATETXG,
2221 2214 dsl_get_creationtxg(ds));
2222 2215 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFQUOTA,
2223 2216 dsl_get_refquota(ds));
2224 2217 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRESERVATION,
2225 2218 dsl_get_refreservation(ds));
2226 2219 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_GUID,
2227 2220 dsl_get_guid(ds));
2228 2221 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_UNIQUE,
2229 2222 dsl_get_unique(ds));
2230 2223 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_OBJSETID,
2231 2224 dsl_get_objsetid(ds));
2232 2225 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USERREFS,
2233 2226 dsl_get_userrefs(ds));
2234 2227 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY,
2235 2228 dsl_get_defer_destroy(ds));
2236 2229
2237 2230 if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
2238 2231 uint64_t written;
2239 2232 if (dsl_get_written(ds, &written) == 0) {
2240 2233 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_WRITTEN,
2241 2234 written);
2242 2235 }
2243 2236 }
2244 2237
2245 2238 if (!dsl_dataset_is_snapshot(ds)) {
2246 2239 /*
2247 2240 * A failed "newfs" (e.g. full) resumable receive leaves
2248 2241 * the stats set on this dataset. Check here for the prop.
2249 2242 */
2250 2243 get_receive_resume_stats(ds, nv);
2251 2244
2252 2245 /*
2253 2246 * A failed incremental resumable receive leaves the
2254 2247 * stats set on our child named "%recv". Check the child
2255 2248 * for the prop.
2256 2249 */
2257 2250 /* 6 extra bytes for /%recv */
2258 2251 char recvname[ZFS_MAX_DATASET_NAME_LEN + 6];
2259 2252 dsl_dataset_t *recv_ds;
2260 2253 dsl_dataset_name(ds, recvname);
2261 2254 if (strlcat(recvname, "/", sizeof (recvname)) <
2262 2255 sizeof (recvname) &&
2263 2256 strlcat(recvname, recv_clone_name, sizeof (recvname)) <
2264 2257 sizeof (recvname) &&
2265 2258 dsl_dataset_hold(dp, recvname, FTAG, &recv_ds) == 0) {
2266 2259 get_receive_resume_stats(recv_ds, nv);
2267 2260 dsl_dataset_rele(recv_ds, FTAG);
2268 2261 }
2269 2262 }
2270 2263 }
2271 2264
|
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
2272 2265 void
2273 2266 dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_stats_t *stat)
2274 2267 {
2275 2268 dsl_pool_t *dp = ds->ds_dir->dd_pool;
2276 2269 ASSERT(dsl_pool_config_held(dp));
2277 2270
2278 2271 stat->dds_creation_txg = dsl_get_creationtxg(ds);
2279 2272 stat->dds_inconsistent = dsl_get_inconsistent(ds);
2280 2273 stat->dds_guid = dsl_get_guid(ds);
2281 2274 stat->dds_origin[0] = '\0';
2275 + stat->dds_is_snapshot = B_FALSE;
2276 + stat->dds_is_autosnapshot = B_FALSE;
2282 2277 if (ds->ds_is_snapshot) {
2283 - stat->dds_is_snapshot = B_TRUE;
2278 + if (autosnap_is_autosnap(ds))
2279 + stat->dds_is_autosnapshot = B_TRUE;
2280 + else
2281 + stat->dds_is_snapshot = B_TRUE;
2282 +
2284 2283 stat->dds_num_clones = dsl_get_numclones(ds);
2285 2284 } else {
2286 - stat->dds_is_snapshot = B_FALSE;
2287 2285 stat->dds_num_clones = 0;
2288 2286
2289 2287 if (dsl_dir_is_clone(ds->ds_dir)) {
2290 2288 dsl_dir_get_origin(ds->ds_dir, stat->dds_origin);
2291 2289 }
2292 2290 }
2293 2291 }
2294 2292
2295 2293 uint64_t
2296 2294 dsl_dataset_fsid_guid(dsl_dataset_t *ds)
2297 2295 {
2298 2296 return (ds->ds_fsid_guid);
2299 2297 }
2300 2298
2301 2299 void
2302 2300 dsl_dataset_space(dsl_dataset_t *ds,
2303 2301 uint64_t *refdbytesp, uint64_t *availbytesp,
2304 2302 uint64_t *usedobjsp, uint64_t *availobjsp)
2305 2303 {
2306 2304 *refdbytesp = dsl_dataset_phys(ds)->ds_referenced_bytes;
2307 2305 *availbytesp = dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE);
2308 2306 if (ds->ds_reserved > dsl_dataset_phys(ds)->ds_unique_bytes)
2309 2307 *availbytesp +=
2310 2308 ds->ds_reserved - dsl_dataset_phys(ds)->ds_unique_bytes;
2311 2309 if (ds->ds_quota != 0) {
2312 2310 /*
2313 2311 * Adjust available bytes according to refquota
2314 2312 */
2315 2313 if (*refdbytesp < ds->ds_quota)
2316 2314 *availbytesp = MIN(*availbytesp,
2317 2315 ds->ds_quota - *refdbytesp);
2318 2316 else
2319 2317 *availbytesp = 0;
2320 2318 }
2321 2319 rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
2322 2320 *usedobjsp = BP_GET_FILL(&dsl_dataset_phys(ds)->ds_bp);
2323 2321 rrw_exit(&ds->ds_bp_rwlock, FTAG);
2324 2322 *availobjsp = DN_MAX_OBJECT - *usedobjsp;
2325 2323 }
2326 2324
2327 2325 boolean_t
2328 2326 dsl_dataset_modified_since_snap(dsl_dataset_t *ds, dsl_dataset_t *snap)
2329 2327 {
2330 2328 dsl_pool_t *dp = ds->ds_dir->dd_pool;
2331 2329 uint64_t birth;
2332 2330
2333 2331 ASSERT(dsl_pool_config_held(dp));
2334 2332 if (snap == NULL)
2335 2333 return (B_FALSE);
2336 2334 rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
2337 2335 birth = dsl_dataset_get_blkptr(ds)->blk_birth;
2338 2336 rrw_exit(&ds->ds_bp_rwlock, FTAG);
2339 2337 if (birth > dsl_dataset_phys(snap)->ds_creation_txg) {
2340 2338 objset_t *os, *os_snap;
2341 2339 /*
2342 2340 * It may be that only the ZIL differs, because it was
2343 2341 * reset in the head. Don't count that as being
2344 2342 * modified.
2345 2343 */
2346 2344 if (dmu_objset_from_ds(ds, &os) != 0)
2347 2345 return (B_TRUE);
2348 2346 if (dmu_objset_from_ds(snap, &os_snap) != 0)
2349 2347 return (B_TRUE);
2350 2348 return (bcmp(&os->os_phys->os_meta_dnode,
2351 2349 &os_snap->os_phys->os_meta_dnode,
2352 2350 sizeof (os->os_phys->os_meta_dnode)) != 0);
2353 2351 }
2354 2352 return (B_FALSE);
2355 2353 }
2356 2354
2357 2355 typedef struct dsl_dataset_rename_snapshot_arg {
2358 2356 const char *ddrsa_fsname;
2359 2357 const char *ddrsa_oldsnapname;
2360 2358 const char *ddrsa_newsnapname;
2361 2359 boolean_t ddrsa_recursive;
2362 2360 dmu_tx_t *ddrsa_tx;
2363 2361 } dsl_dataset_rename_snapshot_arg_t;
2364 2362
2365 2363 /* ARGSUSED */
2366 2364 static int
2367 2365 dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp,
2368 2366 dsl_dataset_t *hds, void *arg)
2369 2367 {
2370 2368 dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
2371 2369 int error;
2372 2370 uint64_t val;
2373 2371
2374 2372 error = dsl_dataset_snap_lookup(hds, ddrsa->ddrsa_oldsnapname, &val);
2375 2373 if (error != 0) {
2376 2374 /* ignore nonexistent snapshots */
2377 2375 return (error == ENOENT ? 0 : error);
2378 2376 }
2379 2377
2380 2378 /* new name should not exist */
2381 2379 error = dsl_dataset_snap_lookup(hds, ddrsa->ddrsa_newsnapname, &val);
2382 2380 if (error == 0)
2383 2381 error = SET_ERROR(EEXIST);
2384 2382 else if (error == ENOENT)
2385 2383 error = 0;
2386 2384
2387 2385 /* dataset name + 1 for the "@" + the new snapshot name must fit */
2388 2386 if (dsl_dir_namelen(hds->ds_dir) + 1 +
2389 2387 strlen(ddrsa->ddrsa_newsnapname) >= ZFS_MAX_DATASET_NAME_LEN)
2390 2388 error = SET_ERROR(ENAMETOOLONG);
2391 2389
2392 2390 return (error);
|
↓ open down ↓ |
96 lines elided |
↑ open up ↑ |
2393 2391 }
2394 2392
2395 2393 static int
2396 2394 dsl_dataset_rename_snapshot_check(void *arg, dmu_tx_t *tx)
2397 2395 {
2398 2396 dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
2399 2397 dsl_pool_t *dp = dmu_tx_pool(tx);
2400 2398 dsl_dataset_t *hds;
2401 2399 int error;
2402 2400
2401 + /* You cannot rename an autosnapshot */
2402 + if (autosnap_check_name(ddrsa->ddrsa_oldsnapname))
2403 + return (SET_ERROR(EPERM));
2404 +
2405 + /* New name cannot match the AUTOSNAP prefix */
2406 + if (autosnap_check_name(ddrsa->ddrsa_newsnapname))
2407 + return (SET_ERROR(EPERM));
2408 +
2403 2409 error = dsl_dataset_hold(dp, ddrsa->ddrsa_fsname, FTAG, &hds);
2404 2410 if (error != 0)
2405 2411 return (error);
2406 2412
2407 2413 if (ddrsa->ddrsa_recursive) {
2408 2414 error = dmu_objset_find_dp(dp, hds->ds_dir->dd_object,
2409 2415 dsl_dataset_rename_snapshot_check_impl, ddrsa,
2410 2416 DS_FIND_CHILDREN);
2411 2417 } else {
2412 2418 error = dsl_dataset_rename_snapshot_check_impl(dp, hds, ddrsa);
2413 2419 }
2414 2420 dsl_dataset_rele(hds, FTAG);
2415 2421 return (error);
2416 2422 }
2417 2423
2418 2424 static int
2419 2425 dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp,
2420 2426 dsl_dataset_t *hds, void *arg)
2421 2427 {
2422 2428 dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
2423 2429 dsl_dataset_t *ds;
2424 2430 uint64_t val;
2425 2431 dmu_tx_t *tx = ddrsa->ddrsa_tx;
2426 2432 int error;
2427 2433
2428 2434 error = dsl_dataset_snap_lookup(hds, ddrsa->ddrsa_oldsnapname, &val);
2429 2435 ASSERT(error == 0 || error == ENOENT);
2430 2436 if (error == ENOENT) {
2431 2437 /* ignore nonexistent snapshots */
2432 2438 return (0);
2433 2439 }
2434 2440
2435 2441 VERIFY0(dsl_dataset_hold_obj(dp, val, FTAG, &ds));
2436 2442
2437 2443 /* log before we change the name */
2438 2444 spa_history_log_internal_ds(ds, "rename", tx,
2439 2445 "-> @%s", ddrsa->ddrsa_newsnapname);
2440 2446
2441 2447 VERIFY0(dsl_dataset_snap_remove(hds, ddrsa->ddrsa_oldsnapname, tx,
2442 2448 B_FALSE));
2443 2449 mutex_enter(&ds->ds_lock);
2444 2450 (void) strcpy(ds->ds_snapname, ddrsa->ddrsa_newsnapname);
2445 2451 mutex_exit(&ds->ds_lock);
2446 2452 VERIFY0(zap_add(dp->dp_meta_objset,
2447 2453 dsl_dataset_phys(hds)->ds_snapnames_zapobj,
2448 2454 ds->ds_snapname, 8, 1, &ds->ds_object, tx));
2449 2455
2450 2456 dsl_dataset_rele(ds, FTAG);
2451 2457 return (0);
2452 2458 }
2453 2459
2454 2460 static void
2455 2461 dsl_dataset_rename_snapshot_sync(void *arg, dmu_tx_t *tx)
2456 2462 {
2457 2463 dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
2458 2464 dsl_pool_t *dp = dmu_tx_pool(tx);
2459 2465 dsl_dataset_t *hds;
2460 2466
2461 2467 VERIFY0(dsl_dataset_hold(dp, ddrsa->ddrsa_fsname, FTAG, &hds));
2462 2468 ddrsa->ddrsa_tx = tx;
2463 2469 if (ddrsa->ddrsa_recursive) {
2464 2470 VERIFY0(dmu_objset_find_dp(dp, hds->ds_dir->dd_object,
2465 2471 dsl_dataset_rename_snapshot_sync_impl, ddrsa,
2466 2472 DS_FIND_CHILDREN));
2467 2473 } else {
2468 2474 VERIFY0(dsl_dataset_rename_snapshot_sync_impl(dp, hds, ddrsa));
2469 2475 }
2470 2476 dsl_dataset_rele(hds, FTAG);
2471 2477 }
2472 2478
2473 2479 int
2474 2480 dsl_dataset_rename_snapshot(const char *fsname,
2475 2481 const char *oldsnapname, const char *newsnapname, boolean_t recursive)
2476 2482 {
2477 2483 dsl_dataset_rename_snapshot_arg_t ddrsa;
2478 2484
2479 2485 ddrsa.ddrsa_fsname = fsname;
2480 2486 ddrsa.ddrsa_oldsnapname = oldsnapname;
2481 2487 ddrsa.ddrsa_newsnapname = newsnapname;
2482 2488 ddrsa.ddrsa_recursive = recursive;
2483 2489
2484 2490 return (dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
2485 2491 dsl_dataset_rename_snapshot_sync, &ddrsa,
2486 2492 1, ZFS_SPACE_CHECK_RESERVED));
2487 2493 }
2488 2494
2489 2495 /*
2490 2496 * If we're doing an ownership handoff, we need to make sure that there is
2491 2497 * only one long hold on the dataset. We're not allowed to change anything here
2492 2498 * so we don't permanently release the long hold or regular hold here. We want
2493 2499 * to do this only when syncing to avoid the dataset unexpectedly going away
2494 2500 * when we release the long hold.
2495 2501 */
2496 2502 static int
2497 2503 dsl_dataset_handoff_check(dsl_dataset_t *ds, void *owner, dmu_tx_t *tx)
2498 2504 {
2499 2505 boolean_t held;
2500 2506
2501 2507 if (!dmu_tx_is_syncing(tx))
2502 2508 return (0);
2503 2509
2504 2510 if (owner != NULL) {
2505 2511 VERIFY3P(ds->ds_owner, ==, owner);
2506 2512 dsl_dataset_long_rele(ds, owner);
2507 2513 }
2508 2514
2509 2515 held = dsl_dataset_long_held(ds);
2510 2516
2511 2517 if (owner != NULL)
2512 2518 dsl_dataset_long_hold(ds, owner);
2513 2519
2514 2520 if (held)
2515 2521 return (SET_ERROR(EBUSY));
2516 2522
2517 2523 return (0);
2518 2524 }
2519 2525
2520 2526 int
2521 2527 dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx)
2522 2528 {
2523 2529 dsl_dataset_rollback_arg_t *ddra = arg;
2524 2530 dsl_pool_t *dp = dmu_tx_pool(tx);
2525 2531 dsl_dataset_t *ds;
2526 2532 int64_t unused_refres_delta;
2527 2533 int error;
2528 2534
2529 2535 error = dsl_dataset_hold(dp, ddra->ddra_fsname, FTAG, &ds);
2530 2536 if (error != 0)
2531 2537 return (error);
2532 2538
2533 2539 /* must not be a snapshot */
2534 2540 if (ds->ds_is_snapshot) {
2535 2541 dsl_dataset_rele(ds, FTAG);
2536 2542 return (SET_ERROR(EINVAL));
2537 2543 }
2538 2544
2539 2545 /* must have a most recent snapshot */
2540 2546 if (dsl_dataset_phys(ds)->ds_prev_snap_txg < TXG_INITIAL) {
2541 2547 dsl_dataset_rele(ds, FTAG);
2542 2548 return (SET_ERROR(ESRCH));
2543 2549 }
2544 2550
2545 2551 /*
2546 2552 * No rollback to a snapshot created in the current txg, because
2547 2553 * the rollback may dirty the dataset and create blocks that are
2548 2554 * not reachable from the rootbp while having a birth txg that
2549 2555 * falls into the snapshot's range.
2550 2556 */
2551 2557 if (dmu_tx_is_syncing(tx) &&
2552 2558 dsl_dataset_phys(ds)->ds_prev_snap_txg >= tx->tx_txg) {
2553 2559 dsl_dataset_rele(ds, FTAG);
2554 2560 return (SET_ERROR(EAGAIN));
2555 2561 }
2556 2562
2557 2563 /*
2558 2564 * If the expected target snapshot is specified, then check that
2559 2565 * the latest snapshot is it.
2560 2566 */
2561 2567 if (ddra->ddra_tosnap != NULL) {
2562 2568 dsl_dataset_t *snapds;
2563 2569
2564 2570 /* Check if the target snapshot exists at all. */
2565 2571 error = dsl_dataset_hold(dp, ddra->ddra_tosnap, FTAG, &snapds);
2566 2572 if (error != 0) {
2567 2573 /*
2568 2574 * ESRCH is used to signal that the target snapshot does
2569 2575 * not exist, while ENOENT is used to report that
2570 2576 * the rolled back dataset does not exist.
2571 2577 * ESRCH is also used to cover other cases where the
2572 2578 * target snapshot is not related to the dataset being
2573 2579 * rolled back such as being in a different pool.
2574 2580 */
2575 2581 if (error == ENOENT || error == EXDEV)
2576 2582 error = SET_ERROR(ESRCH);
2577 2583 dsl_dataset_rele(ds, FTAG);
2578 2584 return (error);
2579 2585 }
2580 2586 ASSERT(snapds->ds_is_snapshot);
2581 2587
2582 2588 /* Check if the snapshot is the latest snapshot indeed. */
2583 2589 if (snapds != ds->ds_prev) {
2584 2590 /*
2585 2591 * Distinguish between the case where the only problem
2586 2592 * is intervening snapshots (EEXIST) vs the snapshot
2587 2593 * not being a valid target for rollback (ESRCH).
2588 2594 */
2589 2595 if (snapds->ds_dir == ds->ds_dir ||
2590 2596 (dsl_dir_is_clone(ds->ds_dir) &&
2591 2597 dsl_dir_phys(ds->ds_dir)->dd_origin_obj ==
2592 2598 snapds->ds_object)) {
2593 2599 error = SET_ERROR(EEXIST);
2594 2600 } else {
2595 2601 error = SET_ERROR(ESRCH);
2596 2602 }
2597 2603 dsl_dataset_rele(snapds, FTAG);
2598 2604 dsl_dataset_rele(ds, FTAG);
2599 2605 return (error);
2600 2606 }
2601 2607 dsl_dataset_rele(snapds, FTAG);
2602 2608 }
2603 2609
2604 2610 /* must not have any bookmarks after the most recent snapshot */
2605 2611 nvlist_t *proprequest = fnvlist_alloc();
2606 2612 fnvlist_add_boolean(proprequest, zfs_prop_to_name(ZFS_PROP_CREATETXG));
2607 2613 nvlist_t *bookmarks = fnvlist_alloc();
2608 2614 error = dsl_get_bookmarks_impl(ds, proprequest, bookmarks);
2609 2615 fnvlist_free(proprequest);
2610 2616 if (error != 0) {
2611 2617 dsl_dataset_rele(ds, FTAG);
2612 2618 return (error);
2613 2619 }
2614 2620 for (nvpair_t *pair = nvlist_next_nvpair(bookmarks, NULL);
2615 2621 pair != NULL; pair = nvlist_next_nvpair(bookmarks, pair)) {
2616 2622 nvlist_t *valuenv =
2617 2623 fnvlist_lookup_nvlist(fnvpair_value_nvlist(pair),
2618 2624 zfs_prop_to_name(ZFS_PROP_CREATETXG));
2619 2625 uint64_t createtxg = fnvlist_lookup_uint64(valuenv, "value");
2620 2626 if (createtxg > dsl_dataset_phys(ds)->ds_prev_snap_txg) {
2621 2627 fnvlist_free(bookmarks);
2622 2628 dsl_dataset_rele(ds, FTAG);
2623 2629 return (SET_ERROR(EEXIST));
2624 2630 }
2625 2631 }
2626 2632 fnvlist_free(bookmarks);
2627 2633
2628 2634 error = dsl_dataset_handoff_check(ds, ddra->ddra_owner, tx);
2629 2635 if (error != 0) {
2630 2636 dsl_dataset_rele(ds, FTAG);
2631 2637 return (error);
2632 2638 }
2633 2639
2634 2640 /*
2635 2641 * Check if the snap we are rolling back to uses more than
2636 2642 * the refquota.
2637 2643 */
2638 2644 if (ds->ds_quota != 0 &&
2639 2645 dsl_dataset_phys(ds->ds_prev)->ds_referenced_bytes > ds->ds_quota) {
2640 2646 dsl_dataset_rele(ds, FTAG);
2641 2647 return (SET_ERROR(EDQUOT));
2642 2648 }
2643 2649
2644 2650 /*
2645 2651 * When we do the clone swap, we will temporarily use more space
2646 2652 * due to the refreservation (the head will no longer have any
2647 2653 * unique space, so the entire amount of the refreservation will need
2648 2654 * to be free). We will immediately destroy the clone, freeing
2649 2655 * this space, but the freeing happens over many txg's.
2650 2656 */
2651 2657 unused_refres_delta = (int64_t)MIN(ds->ds_reserved,
2652 2658 dsl_dataset_phys(ds)->ds_unique_bytes);
2653 2659
2654 2660 if (unused_refres_delta > 0 &&
2655 2661 unused_refres_delta >
2656 2662 dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE)) {
2657 2663 dsl_dataset_rele(ds, FTAG);
2658 2664 return (SET_ERROR(ENOSPC));
2659 2665 }
2660 2666
2661 2667 dsl_dataset_rele(ds, FTAG);
2662 2668 return (0);
2663 2669 }
2664 2670
2665 2671 void
2666 2672 dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx)
2667 2673 {
2668 2674 dsl_dataset_rollback_arg_t *ddra = arg;
2669 2675 dsl_pool_t *dp = dmu_tx_pool(tx);
2670 2676 dsl_dataset_t *ds, *clone;
2671 2677 uint64_t cloneobj;
2672 2678 char namebuf[ZFS_MAX_DATASET_NAME_LEN];
2673 2679
2674 2680 VERIFY0(dsl_dataset_hold(dp, ddra->ddra_fsname, FTAG, &ds));
2675 2681
2676 2682 dsl_dataset_name(ds->ds_prev, namebuf);
2677 2683 fnvlist_add_string(ddra->ddra_result, "target", namebuf);
2678 2684
2679 2685 cloneobj = dsl_dataset_create_sync(ds->ds_dir, "%rollback",
2680 2686 ds->ds_prev, DS_CREATE_FLAG_NODIRTY, kcred, tx);
2681 2687
2682 2688 VERIFY0(dsl_dataset_hold_obj(dp, cloneobj, FTAG, &clone));
2683 2689
2684 2690 dsl_dataset_clone_swap_sync_impl(clone, ds, tx);
2685 2691 dsl_dataset_zero_zil(ds, tx);
2686 2692
2687 2693 dsl_destroy_head_sync_impl(clone, tx);
2688 2694
2689 2695 dsl_dataset_rele(clone, FTAG);
2690 2696 dsl_dataset_rele(ds, FTAG);
2691 2697 }
2692 2698
2693 2699 /*
2694 2700 * Rolls back the given filesystem or volume to the most recent snapshot.
2695 2701 * The name of the most recent snapshot will be returned under key "target"
2696 2702 * in the result nvlist.
2697 2703 *
2698 2704 * If owner != NULL:
2699 2705 * - The existing dataset MUST be owned by the specified owner at entry
2700 2706 * - Upon return, dataset will still be held by the same owner, whether we
2701 2707 * succeed or not.
2702 2708 *
2703 2709 * This mode is required any time the existing filesystem is mounted. See
2704 2710 * notes above zfs_suspend_fs() for further details.
2705 2711 */
2706 2712 int
2707 2713 dsl_dataset_rollback(const char *fsname, const char *tosnap, void *owner,
2708 2714 nvlist_t *result)
2709 2715 {
2710 2716 dsl_dataset_rollback_arg_t ddra;
2711 2717
2712 2718 ddra.ddra_fsname = fsname;
2713 2719 ddra.ddra_tosnap = tosnap;
2714 2720 ddra.ddra_owner = owner;
2715 2721 ddra.ddra_result = result;
2716 2722
2717 2723 return (dsl_sync_task(fsname, dsl_dataset_rollback_check,
2718 2724 dsl_dataset_rollback_sync, &ddra,
2719 2725 1, ZFS_SPACE_CHECK_RESERVED));
2720 2726 }
2721 2727
2722 2728 struct promotenode {
2723 2729 list_node_t link;
2724 2730 dsl_dataset_t *ds;
2725 2731 };
2726 2732
2727 2733 static int snaplist_space(list_t *l, uint64_t mintxg, uint64_t *spacep);
2728 2734 static int promote_hold(dsl_dataset_promote_arg_t *ddpa, dsl_pool_t *dp,
2729 2735 void *tag);
2730 2736 static void promote_rele(dsl_dataset_promote_arg_t *ddpa, void *tag);
2731 2737
2732 2738 int
2733 2739 dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
2734 2740 {
2735 2741 dsl_dataset_promote_arg_t *ddpa = arg;
2736 2742 dsl_pool_t *dp = dmu_tx_pool(tx);
2737 2743 dsl_dataset_t *hds;
2738 2744 struct promotenode *snap;
2739 2745 dsl_dataset_t *origin_ds;
2740 2746 int err;
2741 2747 uint64_t unused;
2742 2748 uint64_t ss_mv_cnt;
2743 2749 size_t max_snap_len;
2744 2750 boolean_t conflicting_snaps;
2745 2751
2746 2752 err = promote_hold(ddpa, dp, FTAG);
2747 2753 if (err != 0)
2748 2754 return (err);
2749 2755
2750 2756 hds = ddpa->ddpa_clone;
2751 2757 snap = list_head(&ddpa->shared_snaps);
2752 2758 origin_ds = snap->ds;
2753 2759 max_snap_len = MAXNAMELEN - strlen(ddpa->ddpa_clonename) - 1;
2754 2760
2755 2761 snap = list_head(&ddpa->origin_snaps);
2756 2762
2757 2763 if (dsl_dataset_phys(hds)->ds_flags & DS_FLAG_NOPROMOTE) {
2758 2764 promote_rele(ddpa, FTAG);
2759 2765 return (SET_ERROR(EXDEV));
2760 2766 }
2761 2767
2762 2768 /*
2763 2769 * Compute and check the amount of space to transfer. Since this is
2764 2770 * so expensive, don't do the preliminary check.
2765 2771 */
2766 2772 if (!dmu_tx_is_syncing(tx)) {
2767 2773 promote_rele(ddpa, FTAG);
2768 2774 return (0);
2769 2775 }
2770 2776
2771 2777 /* compute origin's new unique space */
2772 2778 snap = list_tail(&ddpa->clone_snaps);
2773 2779 ASSERT3U(dsl_dataset_phys(snap->ds)->ds_prev_snap_obj, ==,
2774 2780 origin_ds->ds_object);
2775 2781 dsl_deadlist_space_range(&snap->ds->ds_deadlist,
2776 2782 dsl_dataset_phys(origin_ds)->ds_prev_snap_txg, UINT64_MAX,
2777 2783 &ddpa->unique, &unused, &unused);
2778 2784
2779 2785 /*
2780 2786 * Walk the snapshots that we are moving
2781 2787 *
2782 2788 * Compute space to transfer. Consider the incremental changes
2783 2789 * to used by each snapshot:
2784 2790 * (my used) = (prev's used) + (blocks born) - (blocks killed)
2785 2791 * So each snapshot gave birth to:
2786 2792 * (blocks born) = (my used) - (prev's used) + (blocks killed)
2787 2793 * So a sequence would look like:
2788 2794 * (uN - u(N-1) + kN) + ... + (u1 - u0 + k1) + (u0 - 0 + k0)
2789 2795 * Which simplifies to:
2790 2796 * uN + kN + kN-1 + ... + k1 + k0
2791 2797 * Note however, if we stop before we reach the ORIGIN we get:
2792 2798 * uN + kN + kN-1 + ... + kM - uM-1
2793 2799 */
2794 2800 conflicting_snaps = B_FALSE;
2795 2801 ss_mv_cnt = 0;
2796 2802 ddpa->used = dsl_dataset_phys(origin_ds)->ds_referenced_bytes;
2797 2803 ddpa->comp = dsl_dataset_phys(origin_ds)->ds_compressed_bytes;
2798 2804 ddpa->uncomp = dsl_dataset_phys(origin_ds)->ds_uncompressed_bytes;
2799 2805 for (snap = list_head(&ddpa->shared_snaps); snap;
2800 2806 snap = list_next(&ddpa->shared_snaps, snap)) {
2801 2807 uint64_t val, dlused, dlcomp, dluncomp;
2802 2808 dsl_dataset_t *ds = snap->ds;
2803 2809
2804 2810 ss_mv_cnt++;
2805 2811
2806 2812 /*
2807 2813 * If there are long holds, we won't be able to evict
2808 2814 * the objset.
2809 2815 */
2810 2816 if (dsl_dataset_long_held(ds)) {
2811 2817 err = SET_ERROR(EBUSY);
2812 2818 goto out;
2813 2819 }
2814 2820
2815 2821 /* Check that the snapshot name does not conflict */
2816 2822 VERIFY0(dsl_dataset_get_snapname(ds));
2817 2823 if (strlen(ds->ds_snapname) >= max_snap_len) {
2818 2824 err = SET_ERROR(ENAMETOOLONG);
2819 2825 goto out;
2820 2826 }
2821 2827 err = dsl_dataset_snap_lookup(hds, ds->ds_snapname, &val);
2822 2828 if (err == 0) {
2823 2829 fnvlist_add_boolean(ddpa->err_ds,
2824 2830 snap->ds->ds_snapname);
2825 2831 conflicting_snaps = B_TRUE;
2826 2832 } else if (err != ENOENT) {
2827 2833 goto out;
2828 2834 }
2829 2835
2830 2836 /* The very first snapshot does not have a deadlist */
2831 2837 if (dsl_dataset_phys(ds)->ds_prev_snap_obj == 0)
2832 2838 continue;
2833 2839
2834 2840 dsl_deadlist_space(&ds->ds_deadlist,
2835 2841 &dlused, &dlcomp, &dluncomp);
2836 2842 ddpa->used += dlused;
2837 2843 ddpa->comp += dlcomp;
2838 2844 ddpa->uncomp += dluncomp;
2839 2845 }
2840 2846
2841 2847 /*
2842 2848 * In order to return the full list of conflicting snapshots, we check
2843 2849 * whether there was a conflict after traversing all of them.
2844 2850 */
2845 2851 if (conflicting_snaps) {
2846 2852 err = SET_ERROR(EEXIST);
2847 2853 goto out;
2848 2854 }
2849 2855
2850 2856 /*
2851 2857 * If we are a clone of a clone then we never reached ORIGIN,
2852 2858 * so we need to subtract out the clone origin's used space.
2853 2859 */
2854 2860 if (ddpa->origin_origin) {
2855 2861 ddpa->used -=
2856 2862 dsl_dataset_phys(ddpa->origin_origin)->ds_referenced_bytes;
2857 2863 ddpa->comp -=
2858 2864 dsl_dataset_phys(ddpa->origin_origin)->ds_compressed_bytes;
2859 2865 ddpa->uncomp -=
2860 2866 dsl_dataset_phys(ddpa->origin_origin)->
2861 2867 ds_uncompressed_bytes;
2862 2868 }
2863 2869
2864 2870 /* Check that there is enough space and limit headroom here */
2865 2871 err = dsl_dir_transfer_possible(origin_ds->ds_dir, hds->ds_dir,
2866 2872 0, ss_mv_cnt, ddpa->used, ddpa->cr);
2867 2873 if (err != 0)
2868 2874 goto out;
2869 2875
2870 2876 /*
2871 2877 * Compute the amounts of space that will be used by snapshots
2872 2878 * after the promotion (for both origin and clone). For each,
2873 2879 * it is the amount of space that will be on all of their
2874 2880 * deadlists (that was not born before their new origin).
2875 2881 */
2876 2882 if (dsl_dir_phys(hds->ds_dir)->dd_flags & DD_FLAG_USED_BREAKDOWN) {
2877 2883 uint64_t space;
2878 2884
2879 2885 /*
2880 2886 * Note, typically this will not be a clone of a clone,
2881 2887 * so dd_origin_txg will be < TXG_INITIAL, so
2882 2888 * these snaplist_space() -> dsl_deadlist_space_range()
2883 2889 * calls will be fast because they do not have to
2884 2890 * iterate over all bps.
2885 2891 */
2886 2892 snap = list_head(&ddpa->origin_snaps);
2887 2893 err = snaplist_space(&ddpa->shared_snaps,
2888 2894 snap->ds->ds_dir->dd_origin_txg, &ddpa->cloneusedsnap);
2889 2895 if (err != 0)
2890 2896 goto out;
2891 2897
2892 2898 err = snaplist_space(&ddpa->clone_snaps,
2893 2899 snap->ds->ds_dir->dd_origin_txg, &space);
2894 2900 if (err != 0)
2895 2901 goto out;
2896 2902 ddpa->cloneusedsnap += space;
2897 2903 }
2898 2904 if (dsl_dir_phys(origin_ds->ds_dir)->dd_flags &
2899 2905 DD_FLAG_USED_BREAKDOWN) {
2900 2906 err = snaplist_space(&ddpa->origin_snaps,
2901 2907 dsl_dataset_phys(origin_ds)->ds_creation_txg,
2902 2908 &ddpa->originusedsnap);
2903 2909 if (err != 0)
2904 2910 goto out;
2905 2911 }
2906 2912
2907 2913 out:
2908 2914 promote_rele(ddpa, FTAG);
2909 2915 return (err);
2910 2916 }
2911 2917
2912 2918 void
2913 2919 dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx)
2914 2920 {
2915 2921 dsl_dataset_promote_arg_t *ddpa = arg;
2916 2922 dsl_pool_t *dp = dmu_tx_pool(tx);
2917 2923 dsl_dataset_t *hds;
2918 2924 struct promotenode *snap;
2919 2925 dsl_dataset_t *origin_ds;
2920 2926 dsl_dataset_t *origin_head;
2921 2927 dsl_dir_t *dd;
2922 2928 dsl_dir_t *odd = NULL;
2923 2929 uint64_t oldnext_obj;
2924 2930 int64_t delta;
2925 2931
2926 2932 VERIFY0(promote_hold(ddpa, dp, FTAG));
2927 2933 hds = ddpa->ddpa_clone;
2928 2934
2929 2935 ASSERT0(dsl_dataset_phys(hds)->ds_flags & DS_FLAG_NOPROMOTE);
2930 2936
2931 2937 snap = list_head(&ddpa->shared_snaps);
2932 2938 origin_ds = snap->ds;
2933 2939 dd = hds->ds_dir;
2934 2940
2935 2941 snap = list_head(&ddpa->origin_snaps);
2936 2942 origin_head = snap->ds;
2937 2943
2938 2944 /*
2939 2945 * We need to explicitly open odd, since origin_ds's dd will be
2940 2946 * changing.
2941 2947 */
2942 2948 VERIFY0(dsl_dir_hold_obj(dp, origin_ds->ds_dir->dd_object,
2943 2949 NULL, FTAG, &odd));
2944 2950
2945 2951 /* change origin's next snap */
2946 2952 dmu_buf_will_dirty(origin_ds->ds_dbuf, tx);
2947 2953 oldnext_obj = dsl_dataset_phys(origin_ds)->ds_next_snap_obj;
2948 2954 snap = list_tail(&ddpa->clone_snaps);
2949 2955 ASSERT3U(dsl_dataset_phys(snap->ds)->ds_prev_snap_obj, ==,
2950 2956 origin_ds->ds_object);
2951 2957 dsl_dataset_phys(origin_ds)->ds_next_snap_obj = snap->ds->ds_object;
2952 2958
2953 2959 /* change the origin's next clone */
2954 2960 if (dsl_dataset_phys(origin_ds)->ds_next_clones_obj) {
2955 2961 dsl_dataset_remove_from_next_clones(origin_ds,
2956 2962 snap->ds->ds_object, tx);
2957 2963 VERIFY0(zap_add_int(dp->dp_meta_objset,
2958 2964 dsl_dataset_phys(origin_ds)->ds_next_clones_obj,
2959 2965 oldnext_obj, tx));
2960 2966 }
2961 2967
2962 2968 /* change origin */
2963 2969 dmu_buf_will_dirty(dd->dd_dbuf, tx);
2964 2970 ASSERT3U(dsl_dir_phys(dd)->dd_origin_obj, ==, origin_ds->ds_object);
2965 2971 dsl_dir_phys(dd)->dd_origin_obj = dsl_dir_phys(odd)->dd_origin_obj;
2966 2972 dd->dd_origin_txg = origin_head->ds_dir->dd_origin_txg;
2967 2973 dmu_buf_will_dirty(odd->dd_dbuf, tx);
2968 2974 dsl_dir_phys(odd)->dd_origin_obj = origin_ds->ds_object;
2969 2975 origin_head->ds_dir->dd_origin_txg =
2970 2976 dsl_dataset_phys(origin_ds)->ds_creation_txg;
2971 2977
2972 2978 /* change dd_clone entries */
2973 2979 if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
2974 2980 VERIFY0(zap_remove_int(dp->dp_meta_objset,
2975 2981 dsl_dir_phys(odd)->dd_clones, hds->ds_object, tx));
2976 2982 VERIFY0(zap_add_int(dp->dp_meta_objset,
2977 2983 dsl_dir_phys(ddpa->origin_origin->ds_dir)->dd_clones,
2978 2984 hds->ds_object, tx));
2979 2985
2980 2986 VERIFY0(zap_remove_int(dp->dp_meta_objset,
2981 2987 dsl_dir_phys(ddpa->origin_origin->ds_dir)->dd_clones,
2982 2988 origin_head->ds_object, tx));
2983 2989 if (dsl_dir_phys(dd)->dd_clones == 0) {
2984 2990 dsl_dir_phys(dd)->dd_clones =
2985 2991 zap_create(dp->dp_meta_objset, DMU_OT_DSL_CLONES,
2986 2992 DMU_OT_NONE, 0, tx);
2987 2993 }
2988 2994 VERIFY0(zap_add_int(dp->dp_meta_objset,
2989 2995 dsl_dir_phys(dd)->dd_clones, origin_head->ds_object, tx));
2990 2996 }
2991 2997
2992 2998 /* move snapshots to this dir */
2993 2999 for (snap = list_head(&ddpa->shared_snaps); snap;
2994 3000 snap = list_next(&ddpa->shared_snaps, snap)) {
2995 3001 dsl_dataset_t *ds = snap->ds;
2996 3002
2997 3003 /*
2998 3004 * Property callbacks are registered to a particular
2999 3005 * dsl_dir. Since ours is changing, evict the objset
3000 3006 * so that they will be unregistered from the old dsl_dir.
3001 3007 */
3002 3008 if (ds->ds_objset) {
3003 3009 dmu_objset_evict(ds->ds_objset);
3004 3010 ds->ds_objset = NULL;
3005 3011 }
3006 3012
3007 3013 /* move snap name entry */
3008 3014 VERIFY0(dsl_dataset_get_snapname(ds));
3009 3015 VERIFY0(dsl_dataset_snap_remove(origin_head,
3010 3016 ds->ds_snapname, tx, B_TRUE));
3011 3017 VERIFY0(zap_add(dp->dp_meta_objset,
3012 3018 dsl_dataset_phys(hds)->ds_snapnames_zapobj, ds->ds_snapname,
3013 3019 8, 1, &ds->ds_object, tx));
3014 3020 dsl_fs_ss_count_adjust(hds->ds_dir, 1,
3015 3021 DD_FIELD_SNAPSHOT_COUNT, tx);
3016 3022
3017 3023 /* change containing dsl_dir */
3018 3024 dmu_buf_will_dirty(ds->ds_dbuf, tx);
3019 3025 ASSERT3U(dsl_dataset_phys(ds)->ds_dir_obj, ==, odd->dd_object);
3020 3026 dsl_dataset_phys(ds)->ds_dir_obj = dd->dd_object;
3021 3027 ASSERT3P(ds->ds_dir, ==, odd);
3022 3028 dsl_dir_rele(ds->ds_dir, ds);
3023 3029 VERIFY0(dsl_dir_hold_obj(dp, dd->dd_object,
3024 3030 NULL, ds, &ds->ds_dir));
3025 3031
3026 3032 /* move any clone references */
3027 3033 if (dsl_dataset_phys(ds)->ds_next_clones_obj &&
3028 3034 spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
3029 3035 zap_cursor_t zc;
3030 3036 zap_attribute_t za;
3031 3037
3032 3038 for (zap_cursor_init(&zc, dp->dp_meta_objset,
3033 3039 dsl_dataset_phys(ds)->ds_next_clones_obj);
3034 3040 zap_cursor_retrieve(&zc, &za) == 0;
3035 3041 zap_cursor_advance(&zc)) {
3036 3042 dsl_dataset_t *cnds;
3037 3043 uint64_t o;
3038 3044
3039 3045 if (za.za_first_integer == oldnext_obj) {
3040 3046 /*
3041 3047 * We've already moved the
3042 3048 * origin's reference.
3043 3049 */
3044 3050 continue;
3045 3051 }
3046 3052
3047 3053 VERIFY0(dsl_dataset_hold_obj(dp,
3048 3054 za.za_first_integer, FTAG, &cnds));
3049 3055 o = dsl_dir_phys(cnds->ds_dir)->
3050 3056 dd_head_dataset_obj;
3051 3057
3052 3058 VERIFY0(zap_remove_int(dp->dp_meta_objset,
3053 3059 dsl_dir_phys(odd)->dd_clones, o, tx));
3054 3060 VERIFY0(zap_add_int(dp->dp_meta_objset,
3055 3061 dsl_dir_phys(dd)->dd_clones, o, tx));
3056 3062 dsl_dataset_rele(cnds, FTAG);
3057 3063 }
3058 3064 zap_cursor_fini(&zc);
3059 3065 }
3060 3066
3061 3067 ASSERT(!dsl_prop_hascb(ds));
3062 3068 }
3063 3069
3064 3070 /*
3065 3071 * Change space accounting.
3066 3072 * Note, pa->*usedsnap and dd_used_breakdown[SNAP] will either
3067 3073 * both be valid, or both be 0 (resulting in delta == 0). This
3068 3074 * is true for each of {clone,origin} independently.
3069 3075 */
3070 3076
3071 3077 delta = ddpa->cloneusedsnap -
3072 3078 dsl_dir_phys(dd)->dd_used_breakdown[DD_USED_SNAP];
3073 3079 ASSERT3S(delta, >=, 0);
3074 3080 ASSERT3U(ddpa->used, >=, delta);
3075 3081 dsl_dir_diduse_space(dd, DD_USED_SNAP, delta, 0, 0, tx);
3076 3082 dsl_dir_diduse_space(dd, DD_USED_HEAD,
3077 3083 ddpa->used - delta, ddpa->comp, ddpa->uncomp, tx);
3078 3084
3079 3085 delta = ddpa->originusedsnap -
3080 3086 dsl_dir_phys(odd)->dd_used_breakdown[DD_USED_SNAP];
3081 3087 ASSERT3S(delta, <=, 0);
3082 3088 ASSERT3U(ddpa->used, >=, -delta);
3083 3089 dsl_dir_diduse_space(odd, DD_USED_SNAP, delta, 0, 0, tx);
3084 3090 dsl_dir_diduse_space(odd, DD_USED_HEAD,
3085 3091 -ddpa->used - delta, -ddpa->comp, -ddpa->uncomp, tx);
3086 3092
3087 3093 dsl_dataset_phys(origin_ds)->ds_unique_bytes = ddpa->unique;
3088 3094
3089 3095 /* log history record */
3090 3096 spa_history_log_internal_ds(hds, "promote", tx, "");
3091 3097
3092 3098 dsl_dir_rele(odd, FTAG);
3093 3099 promote_rele(ddpa, FTAG);
3094 3100 }
3095 3101
3096 3102 /*
3097 3103 * Make a list of dsl_dataset_t's for the snapshots between first_obj
3098 3104 * (exclusive) and last_obj (inclusive). The list will be in reverse
3099 3105 * order (last_obj will be the list_head()). If first_obj == 0, do all
3100 3106 * snapshots back to this dataset's origin.
3101 3107 */
3102 3108 static int
3103 3109 snaplist_make(dsl_pool_t *dp,
3104 3110 uint64_t first_obj, uint64_t last_obj, list_t *l, void *tag)
3105 3111 {
3106 3112 uint64_t obj = last_obj;
3107 3113
3108 3114 list_create(l, sizeof (struct promotenode),
3109 3115 offsetof(struct promotenode, link));
3110 3116
3111 3117 while (obj != first_obj) {
3112 3118 dsl_dataset_t *ds;
3113 3119 struct promotenode *snap;
3114 3120 int err;
3115 3121
3116 3122 err = dsl_dataset_hold_obj(dp, obj, tag, &ds);
3117 3123 ASSERT(err != ENOENT);
3118 3124 if (err != 0)
3119 3125 return (err);
3120 3126
3121 3127 if (first_obj == 0)
3122 3128 first_obj = dsl_dir_phys(ds->ds_dir)->dd_origin_obj;
3123 3129
3124 3130 snap = kmem_alloc(sizeof (*snap), KM_SLEEP);
3125 3131 snap->ds = ds;
3126 3132 list_insert_tail(l, snap);
3127 3133 obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
3128 3134 }
3129 3135
3130 3136 return (0);
3131 3137 }
3132 3138
3133 3139 static int
3134 3140 snaplist_space(list_t *l, uint64_t mintxg, uint64_t *spacep)
3135 3141 {
3136 3142 struct promotenode *snap;
3137 3143
3138 3144 *spacep = 0;
3139 3145 for (snap = list_head(l); snap; snap = list_next(l, snap)) {
3140 3146 uint64_t used, comp, uncomp;
3141 3147 dsl_deadlist_space_range(&snap->ds->ds_deadlist,
3142 3148 mintxg, UINT64_MAX, &used, &comp, &uncomp);
3143 3149 *spacep += used;
3144 3150 }
3145 3151 return (0);
3146 3152 }
3147 3153
3148 3154 static void
3149 3155 snaplist_destroy(list_t *l, void *tag)
3150 3156 {
3151 3157 struct promotenode *snap;
3152 3158
3153 3159 if (l == NULL || !list_link_active(&l->list_head))
3154 3160 return;
3155 3161
3156 3162 while ((snap = list_tail(l)) != NULL) {
3157 3163 list_remove(l, snap);
3158 3164 dsl_dataset_rele(snap->ds, tag);
3159 3165 kmem_free(snap, sizeof (*snap));
3160 3166 }
3161 3167 list_destroy(l);
3162 3168 }
3163 3169
3164 3170 static int
3165 3171 promote_hold(dsl_dataset_promote_arg_t *ddpa, dsl_pool_t *dp, void *tag)
3166 3172 {
3167 3173 int error;
3168 3174 dsl_dir_t *dd;
3169 3175 struct promotenode *snap;
3170 3176
3171 3177 error = dsl_dataset_hold(dp, ddpa->ddpa_clonename, tag,
3172 3178 &ddpa->ddpa_clone);
3173 3179 if (error != 0)
3174 3180 return (error);
3175 3181 dd = ddpa->ddpa_clone->ds_dir;
3176 3182
3177 3183 if (ddpa->ddpa_clone->ds_is_snapshot ||
3178 3184 !dsl_dir_is_clone(dd)) {
3179 3185 dsl_dataset_rele(ddpa->ddpa_clone, tag);
3180 3186 return (SET_ERROR(EINVAL));
3181 3187 }
3182 3188
3183 3189 error = snaplist_make(dp, 0, dsl_dir_phys(dd)->dd_origin_obj,
3184 3190 &ddpa->shared_snaps, tag);
3185 3191 if (error != 0)
3186 3192 goto out;
3187 3193
3188 3194 error = snaplist_make(dp, 0, ddpa->ddpa_clone->ds_object,
3189 3195 &ddpa->clone_snaps, tag);
3190 3196 if (error != 0)
3191 3197 goto out;
3192 3198
3193 3199 snap = list_head(&ddpa->shared_snaps);
3194 3200 ASSERT3U(snap->ds->ds_object, ==, dsl_dir_phys(dd)->dd_origin_obj);
3195 3201 error = snaplist_make(dp, dsl_dir_phys(dd)->dd_origin_obj,
3196 3202 dsl_dir_phys(snap->ds->ds_dir)->dd_head_dataset_obj,
3197 3203 &ddpa->origin_snaps, tag);
3198 3204 if (error != 0)
3199 3205 goto out;
3200 3206
3201 3207 if (dsl_dir_phys(snap->ds->ds_dir)->dd_origin_obj != 0) {
3202 3208 error = dsl_dataset_hold_obj(dp,
3203 3209 dsl_dir_phys(snap->ds->ds_dir)->dd_origin_obj,
3204 3210 tag, &ddpa->origin_origin);
3205 3211 if (error != 0)
3206 3212 goto out;
3207 3213 }
3208 3214 out:
3209 3215 if (error != 0)
3210 3216 promote_rele(ddpa, tag);
3211 3217 return (error);
3212 3218 }
3213 3219
3214 3220 static void
3215 3221 promote_rele(dsl_dataset_promote_arg_t *ddpa, void *tag)
3216 3222 {
3217 3223 snaplist_destroy(&ddpa->shared_snaps, tag);
3218 3224 snaplist_destroy(&ddpa->clone_snaps, tag);
3219 3225 snaplist_destroy(&ddpa->origin_snaps, tag);
3220 3226 if (ddpa->origin_origin != NULL)
3221 3227 dsl_dataset_rele(ddpa->origin_origin, tag);
3222 3228 dsl_dataset_rele(ddpa->ddpa_clone, tag);
3223 3229 }
3224 3230
3225 3231 /*
3226 3232 * Promote a clone.
3227 3233 *
3228 3234 * If it fails due to a conflicting snapshot name, "conflsnap" will be filled
3229 3235 * in with the name. (It must be at least ZFS_MAX_DATASET_NAME_LEN bytes long.)
3230 3236 */
3231 3237 int
3232 3238 dsl_dataset_promote(const char *name, char *conflsnap)
3233 3239 {
3234 3240 dsl_dataset_promote_arg_t ddpa = { 0 };
3235 3241 uint64_t numsnaps;
3236 3242 int error;
3237 3243 nvpair_t *snap_pair;
3238 3244 objset_t *os;
3239 3245
3240 3246 /*
3241 3247 * We will modify space proportional to the number of
3242 3248 * snapshots. Compute numsnaps.
3243 3249 */
3244 3250 error = dmu_objset_hold(name, FTAG, &os);
3245 3251 if (error != 0)
3246 3252 return (error);
3247 3253 error = zap_count(dmu_objset_pool(os)->dp_meta_objset,
3248 3254 dsl_dataset_phys(dmu_objset_ds(os))->ds_snapnames_zapobj,
3249 3255 &numsnaps);
3250 3256 dmu_objset_rele(os, FTAG);
3251 3257 if (error != 0)
3252 3258 return (error);
3253 3259
3254 3260 ddpa.ddpa_clonename = name;
3255 3261 ddpa.err_ds = fnvlist_alloc();
3256 3262 ddpa.cr = CRED();
3257 3263
3258 3264 error = dsl_sync_task(name, dsl_dataset_promote_check,
3259 3265 dsl_dataset_promote_sync, &ddpa,
3260 3266 2 + numsnaps, ZFS_SPACE_CHECK_RESERVED);
3261 3267
3262 3268 /*
3263 3269 * Return the first conflicting snapshot found.
3264 3270 */
3265 3271 snap_pair = nvlist_next_nvpair(ddpa.err_ds, NULL);
3266 3272 if (snap_pair != NULL && conflsnap != NULL)
3267 3273 (void) strcpy(conflsnap, nvpair_name(snap_pair));
3268 3274
3269 3275 fnvlist_free(ddpa.err_ds);
3270 3276 return (error);
3271 3277 }
3272 3278
3273 3279 int
3274 3280 dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
3275 3281 dsl_dataset_t *origin_head, boolean_t force, void *owner, dmu_tx_t *tx)
3276 3282 {
3277 3283 /*
3278 3284 * "slack" factor for received datasets with refquota set on them.
3279 3285 * See the bottom of this function for details on its use.
3280 3286 */
3281 3287 uint64_t refquota_slack = DMU_MAX_ACCESS * spa_asize_inflation;
3282 3288 int64_t unused_refres_delta;
3283 3289
3284 3290 /* they should both be heads */
3285 3291 if (clone->ds_is_snapshot ||
3286 3292 origin_head->ds_is_snapshot)
3287 3293 return (SET_ERROR(EINVAL));
3288 3294
3289 3295 /* if we are not forcing, the branch point should be just before them */
3290 3296 if (!force && clone->ds_prev != origin_head->ds_prev)
3291 3297 return (SET_ERROR(EINVAL));
3292 3298
3293 3299 /* clone should be the clone (unless they are unrelated) */
3294 3300 if (clone->ds_prev != NULL &&
3295 3301 clone->ds_prev != clone->ds_dir->dd_pool->dp_origin_snap &&
3296 3302 origin_head->ds_dir != clone->ds_prev->ds_dir)
3297 3303 return (SET_ERROR(EINVAL));
3298 3304
3299 3305 /* the clone should be a child of the origin */
3300 3306 if (clone->ds_dir->dd_parent != origin_head->ds_dir)
3301 3307 return (SET_ERROR(EINVAL));
3302 3308
3303 3309 /* origin_head shouldn't be modified unless 'force' */
3304 3310 if (!force &&
3305 3311 dsl_dataset_modified_since_snap(origin_head, origin_head->ds_prev))
3306 3312 return (SET_ERROR(ETXTBSY));
3307 3313
3308 3314 /* origin_head should have no long holds (e.g. is not mounted) */
3309 3315 if (dsl_dataset_handoff_check(origin_head, owner, tx))
3310 3316 return (SET_ERROR(EBUSY));
3311 3317
3312 3318 /* check amount of any unconsumed refreservation */
3313 3319 unused_refres_delta =
3314 3320 (int64_t)MIN(origin_head->ds_reserved,
3315 3321 dsl_dataset_phys(origin_head)->ds_unique_bytes) -
3316 3322 (int64_t)MIN(origin_head->ds_reserved,
3317 3323 dsl_dataset_phys(clone)->ds_unique_bytes);
3318 3324
3319 3325 if (unused_refres_delta > 0 &&
3320 3326 unused_refres_delta >
3321 3327 dsl_dir_space_available(origin_head->ds_dir, NULL, 0, TRUE))
3322 3328 return (SET_ERROR(ENOSPC));
3323 3329
3324 3330 /*
3325 3331 * The clone can't be too much over the head's refquota.
3326 3332 *
3327 3333 * To ensure that the entire refquota can be used, we allow one
3328 3334 * transaction to exceed the the refquota. Therefore, this check
3329 3335 * needs to also allow for the space referenced to be more than the
3330 3336 * refquota. The maximum amount of space that one transaction can use
3331 3337 * on disk is DMU_MAX_ACCESS * spa_asize_inflation. Allowing this
3332 3338 * overage ensures that we are able to receive a filesystem that
3333 3339 * exceeds the refquota on the source system.
3334 3340 *
|
↓ open down ↓ |
922 lines elided |
↑ open up ↑ |
3335 3341 * So that overage is the refquota_slack we use below.
3336 3342 */
3337 3343 if (origin_head->ds_quota != 0 &&
3338 3344 dsl_dataset_phys(clone)->ds_referenced_bytes >
3339 3345 origin_head->ds_quota + refquota_slack)
3340 3346 return (SET_ERROR(EDQUOT));
3341 3347
3342 3348 return (0);
3343 3349 }
3344 3350
3345 -static void
3346 -dsl_dataset_swap_remap_deadlists(dsl_dataset_t *clone,
3347 - dsl_dataset_t *origin, dmu_tx_t *tx)
3348 -{
3349 - uint64_t clone_remap_dl_obj, origin_remap_dl_obj;
3350 - dsl_pool_t *dp = dmu_tx_pool(tx);
3351 -
3352 - ASSERT(dsl_pool_sync_context(dp));
3353 -
3354 - clone_remap_dl_obj = dsl_dataset_get_remap_deadlist_object(clone);
3355 - origin_remap_dl_obj = dsl_dataset_get_remap_deadlist_object(origin);
3356 -
3357 - if (clone_remap_dl_obj != 0) {
3358 - dsl_deadlist_close(&clone->ds_remap_deadlist);
3359 - dsl_dataset_unset_remap_deadlist_object(clone, tx);
3360 - }
3361 - if (origin_remap_dl_obj != 0) {
3362 - dsl_deadlist_close(&origin->ds_remap_deadlist);
3363 - dsl_dataset_unset_remap_deadlist_object(origin, tx);
3364 - }
3365 -
3366 - if (clone_remap_dl_obj != 0) {
3367 - dsl_dataset_set_remap_deadlist_object(origin,
3368 - clone_remap_dl_obj, tx);
3369 - dsl_deadlist_open(&origin->ds_remap_deadlist,
3370 - dp->dp_meta_objset, clone_remap_dl_obj);
3371 - }
3372 - if (origin_remap_dl_obj != 0) {
3373 - dsl_dataset_set_remap_deadlist_object(clone,
3374 - origin_remap_dl_obj, tx);
3375 - dsl_deadlist_open(&clone->ds_remap_deadlist,
3376 - dp->dp_meta_objset, origin_remap_dl_obj);
3377 - }
3378 -}
3379 -
3380 3351 void
3381 3352 dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
3382 3353 dsl_dataset_t *origin_head, dmu_tx_t *tx)
3383 3354 {
3384 3355 dsl_pool_t *dp = dmu_tx_pool(tx);
3385 3356 int64_t unused_refres_delta;
3386 3357
3387 3358 ASSERT(clone->ds_reserved == 0);
3388 3359 /*
3389 3360 * NOTE: On DEBUG kernels there could be a race between this and
3390 3361 * the check function if spa_asize_inflation is adjusted...
3391 3362 */
3392 3363 ASSERT(origin_head->ds_quota == 0 ||
3393 3364 dsl_dataset_phys(clone)->ds_unique_bytes <= origin_head->ds_quota +
3394 3365 DMU_MAX_ACCESS * spa_asize_inflation);
3395 3366 ASSERT3P(clone->ds_prev, ==, origin_head->ds_prev);
3396 3367
3397 3368 /*
3398 3369 * Swap per-dataset feature flags.
3399 3370 */
3400 3371 for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
3401 3372 if (!(spa_feature_table[f].fi_flags &
3402 3373 ZFEATURE_FLAG_PER_DATASET)) {
3403 3374 ASSERT(!clone->ds_feature_inuse[f]);
3404 3375 ASSERT(!origin_head->ds_feature_inuse[f]);
3405 3376 continue;
3406 3377 }
3407 3378
3408 3379 boolean_t clone_inuse = clone->ds_feature_inuse[f];
3409 3380 boolean_t origin_head_inuse = origin_head->ds_feature_inuse[f];
3410 3381
3411 3382 if (clone_inuse) {
3412 3383 dsl_dataset_deactivate_feature(clone->ds_object, f, tx);
3413 3384 clone->ds_feature_inuse[f] = B_FALSE;
3414 3385 }
3415 3386 if (origin_head_inuse) {
3416 3387 dsl_dataset_deactivate_feature(origin_head->ds_object,
3417 3388 f, tx);
3418 3389 origin_head->ds_feature_inuse[f] = B_FALSE;
3419 3390 }
3420 3391 if (clone_inuse) {
3421 3392 dsl_dataset_activate_feature(origin_head->ds_object,
3422 3393 f, tx);
3423 3394 origin_head->ds_feature_inuse[f] = B_TRUE;
3424 3395 }
3425 3396 if (origin_head_inuse) {
3426 3397 dsl_dataset_activate_feature(clone->ds_object, f, tx);
3427 3398 clone->ds_feature_inuse[f] = B_TRUE;
3428 3399 }
3429 3400 }
3430 3401
3431 3402 dmu_buf_will_dirty(clone->ds_dbuf, tx);
3432 3403 dmu_buf_will_dirty(origin_head->ds_dbuf, tx);
3433 3404
3434 3405 if (clone->ds_objset != NULL) {
3435 3406 dmu_objset_evict(clone->ds_objset);
3436 3407 clone->ds_objset = NULL;
3437 3408 }
3438 3409
3439 3410 if (origin_head->ds_objset != NULL) {
3440 3411 dmu_objset_evict(origin_head->ds_objset);
3441 3412 origin_head->ds_objset = NULL;
3442 3413 }
3443 3414
3444 3415 unused_refres_delta =
3445 3416 (int64_t)MIN(origin_head->ds_reserved,
3446 3417 dsl_dataset_phys(origin_head)->ds_unique_bytes) -
3447 3418 (int64_t)MIN(origin_head->ds_reserved,
3448 3419 dsl_dataset_phys(clone)->ds_unique_bytes);
3449 3420
3450 3421 /*
3451 3422 * Reset origin's unique bytes, if it exists.
3452 3423 */
3453 3424 if (clone->ds_prev) {
3454 3425 dsl_dataset_t *origin = clone->ds_prev;
3455 3426 uint64_t comp, uncomp;
3456 3427
3457 3428 dmu_buf_will_dirty(origin->ds_dbuf, tx);
3458 3429 dsl_deadlist_space_range(&clone->ds_deadlist,
3459 3430 dsl_dataset_phys(origin)->ds_prev_snap_txg, UINT64_MAX,
3460 3431 &dsl_dataset_phys(origin)->ds_unique_bytes, &comp, &uncomp);
3461 3432 }
3462 3433
3463 3434 /* swap blkptrs */
3464 3435 {
3465 3436 rrw_enter(&clone->ds_bp_rwlock, RW_WRITER, FTAG);
3466 3437 rrw_enter(&origin_head->ds_bp_rwlock, RW_WRITER, FTAG);
3467 3438 blkptr_t tmp;
3468 3439 tmp = dsl_dataset_phys(origin_head)->ds_bp;
3469 3440 dsl_dataset_phys(origin_head)->ds_bp =
3470 3441 dsl_dataset_phys(clone)->ds_bp;
3471 3442 dsl_dataset_phys(clone)->ds_bp = tmp;
3472 3443 rrw_exit(&origin_head->ds_bp_rwlock, FTAG);
3473 3444 rrw_exit(&clone->ds_bp_rwlock, FTAG);
3474 3445 }
3475 3446
3476 3447 /* set dd_*_bytes */
3477 3448 {
3478 3449 int64_t dused, dcomp, duncomp;
3479 3450 uint64_t cdl_used, cdl_comp, cdl_uncomp;
3480 3451 uint64_t odl_used, odl_comp, odl_uncomp;
3481 3452
3482 3453 ASSERT3U(dsl_dir_phys(clone->ds_dir)->
3483 3454 dd_used_breakdown[DD_USED_SNAP], ==, 0);
3484 3455
3485 3456 dsl_deadlist_space(&clone->ds_deadlist,
3486 3457 &cdl_used, &cdl_comp, &cdl_uncomp);
3487 3458 dsl_deadlist_space(&origin_head->ds_deadlist,
3488 3459 &odl_used, &odl_comp, &odl_uncomp);
3489 3460
3490 3461 dused = dsl_dataset_phys(clone)->ds_referenced_bytes +
3491 3462 cdl_used -
3492 3463 (dsl_dataset_phys(origin_head)->ds_referenced_bytes +
3493 3464 odl_used);
3494 3465 dcomp = dsl_dataset_phys(clone)->ds_compressed_bytes +
3495 3466 cdl_comp -
3496 3467 (dsl_dataset_phys(origin_head)->ds_compressed_bytes +
3497 3468 odl_comp);
3498 3469 duncomp = dsl_dataset_phys(clone)->ds_uncompressed_bytes +
3499 3470 cdl_uncomp -
3500 3471 (dsl_dataset_phys(origin_head)->ds_uncompressed_bytes +
3501 3472 odl_uncomp);
3502 3473
3503 3474 dsl_dir_diduse_space(origin_head->ds_dir, DD_USED_HEAD,
3504 3475 dused, dcomp, duncomp, tx);
3505 3476 dsl_dir_diduse_space(clone->ds_dir, DD_USED_HEAD,
3506 3477 -dused, -dcomp, -duncomp, tx);
3507 3478
3508 3479 /*
3509 3480 * The difference in the space used by snapshots is the
3510 3481 * difference in snapshot space due to the head's
3511 3482 * deadlist (since that's the only thing that's
3512 3483 * changing that affects the snapused).
3513 3484 */
3514 3485 dsl_deadlist_space_range(&clone->ds_deadlist,
3515 3486 origin_head->ds_dir->dd_origin_txg, UINT64_MAX,
3516 3487 &cdl_used, &cdl_comp, &cdl_uncomp);
3517 3488 dsl_deadlist_space_range(&origin_head->ds_deadlist,
3518 3489 origin_head->ds_dir->dd_origin_txg, UINT64_MAX,
3519 3490 &odl_used, &odl_comp, &odl_uncomp);
3520 3491 dsl_dir_transfer_space(origin_head->ds_dir, cdl_used - odl_used,
3521 3492 DD_USED_HEAD, DD_USED_SNAP, tx);
3522 3493 }
3523 3494
3524 3495 /* swap ds_*_bytes */
3525 3496 SWITCH64(dsl_dataset_phys(origin_head)->ds_referenced_bytes,
3526 3497 dsl_dataset_phys(clone)->ds_referenced_bytes);
3527 3498 SWITCH64(dsl_dataset_phys(origin_head)->ds_compressed_bytes,
3528 3499 dsl_dataset_phys(clone)->ds_compressed_bytes);
3529 3500 SWITCH64(dsl_dataset_phys(origin_head)->ds_uncompressed_bytes,
3530 3501 dsl_dataset_phys(clone)->ds_uncompressed_bytes);
3531 3502 SWITCH64(dsl_dataset_phys(origin_head)->ds_unique_bytes,
3532 3503 dsl_dataset_phys(clone)->ds_unique_bytes);
3533 3504
3534 3505 /* apply any parent delta for change in unconsumed refreservation */
3535 3506 dsl_dir_diduse_space(origin_head->ds_dir, DD_USED_REFRSRV,
3536 3507 unused_refres_delta, 0, 0, tx);
3537 3508
3538 3509 /*
|
↓ open down ↓ |
149 lines elided |
↑ open up ↑ |
3539 3510 * Swap deadlists.
3540 3511 */
3541 3512 dsl_deadlist_close(&clone->ds_deadlist);
3542 3513 dsl_deadlist_close(&origin_head->ds_deadlist);
3543 3514 SWITCH64(dsl_dataset_phys(origin_head)->ds_deadlist_obj,
3544 3515 dsl_dataset_phys(clone)->ds_deadlist_obj);
3545 3516 dsl_deadlist_open(&clone->ds_deadlist, dp->dp_meta_objset,
3546 3517 dsl_dataset_phys(clone)->ds_deadlist_obj);
3547 3518 dsl_deadlist_open(&origin_head->ds_deadlist, dp->dp_meta_objset,
3548 3519 dsl_dataset_phys(origin_head)->ds_deadlist_obj);
3549 - dsl_dataset_swap_remap_deadlists(clone, origin_head, tx);
3550 3520
3551 3521 dsl_scan_ds_clone_swapped(origin_head, clone, tx);
3552 3522
3553 3523 spa_history_log_internal_ds(clone, "clone swap", tx,
3554 3524 "parent=%s", origin_head->ds_dir->dd_myname);
3555 3525 }
3556 3526
3557 3527 /*
3558 3528 * Given a pool name and a dataset object number in that pool,
3559 3529 * return the name of that dataset.
3560 3530 */
3561 3531 int
3562 3532 dsl_dsobj_to_dsname(char *pname, uint64_t obj, char *buf)
3563 3533 {
3564 3534 dsl_pool_t *dp;
3565 3535 dsl_dataset_t *ds;
3566 3536 int error;
3567 3537
3568 3538 error = dsl_pool_hold(pname, FTAG, &dp);
3569 3539 if (error != 0)
3570 3540 return (error);
3571 3541
3572 3542 error = dsl_dataset_hold_obj(dp, obj, FTAG, &ds);
3573 3543 if (error == 0) {
3574 3544 dsl_dataset_name(ds, buf);
3575 3545 dsl_dataset_rele(ds, FTAG);
3576 3546 }
3577 3547 dsl_pool_rele(dp, FTAG);
3578 3548
3579 3549 return (error);
3580 3550 }
3581 3551
3582 3552 int
3583 3553 dsl_dataset_check_quota(dsl_dataset_t *ds, boolean_t check_quota,
3584 3554 uint64_t asize, uint64_t inflight, uint64_t *used, uint64_t *ref_rsrv)
3585 3555 {
3586 3556 int error = 0;
3587 3557
3588 3558 ASSERT3S(asize, >, 0);
3589 3559
3590 3560 /*
3591 3561 * *ref_rsrv is the portion of asize that will come from any
3592 3562 * unconsumed refreservation space.
3593 3563 */
3594 3564 *ref_rsrv = 0;
3595 3565
3596 3566 mutex_enter(&ds->ds_lock);
3597 3567 /*
3598 3568 * Make a space adjustment for reserved bytes.
3599 3569 */
3600 3570 if (ds->ds_reserved > dsl_dataset_phys(ds)->ds_unique_bytes) {
3601 3571 ASSERT3U(*used, >=,
3602 3572 ds->ds_reserved - dsl_dataset_phys(ds)->ds_unique_bytes);
3603 3573 *used -=
3604 3574 (ds->ds_reserved - dsl_dataset_phys(ds)->ds_unique_bytes);
3605 3575 *ref_rsrv =
3606 3576 asize - MIN(asize, parent_delta(ds, asize + inflight));
3607 3577 }
3608 3578
3609 3579 if (!check_quota || ds->ds_quota == 0) {
3610 3580 mutex_exit(&ds->ds_lock);
3611 3581 return (0);
3612 3582 }
3613 3583 /*
3614 3584 * If they are requesting more space, and our current estimate
3615 3585 * is over quota, they get to try again unless the actual
3616 3586 * on-disk is over quota and there are no pending changes (which
3617 3587 * may free up space for us).
3618 3588 */
3619 3589 if (dsl_dataset_phys(ds)->ds_referenced_bytes + inflight >=
3620 3590 ds->ds_quota) {
3621 3591 if (inflight > 0 ||
3622 3592 dsl_dataset_phys(ds)->ds_referenced_bytes < ds->ds_quota)
3623 3593 error = SET_ERROR(ERESTART);
3624 3594 else
3625 3595 error = SET_ERROR(EDQUOT);
3626 3596 }
3627 3597 mutex_exit(&ds->ds_lock);
3628 3598
3629 3599 return (error);
3630 3600 }
3631 3601
3632 3602 typedef struct dsl_dataset_set_qr_arg {
3633 3603 const char *ddsqra_name;
3634 3604 zprop_source_t ddsqra_source;
3635 3605 uint64_t ddsqra_value;
3636 3606 } dsl_dataset_set_qr_arg_t;
3637 3607
3638 3608
3639 3609 /* ARGSUSED */
3640 3610 static int
3641 3611 dsl_dataset_set_refquota_check(void *arg, dmu_tx_t *tx)
3642 3612 {
3643 3613 dsl_dataset_set_qr_arg_t *ddsqra = arg;
3644 3614 dsl_pool_t *dp = dmu_tx_pool(tx);
3645 3615 dsl_dataset_t *ds;
3646 3616 int error;
3647 3617 uint64_t newval;
3648 3618
3649 3619 if (spa_version(dp->dp_spa) < SPA_VERSION_REFQUOTA)
3650 3620 return (SET_ERROR(ENOTSUP));
3651 3621
3652 3622 error = dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds);
3653 3623 if (error != 0)
3654 3624 return (error);
3655 3625
3656 3626 if (ds->ds_is_snapshot) {
3657 3627 dsl_dataset_rele(ds, FTAG);
3658 3628 return (SET_ERROR(EINVAL));
3659 3629 }
3660 3630
3661 3631 error = dsl_prop_predict(ds->ds_dir,
3662 3632 zfs_prop_to_name(ZFS_PROP_REFQUOTA),
3663 3633 ddsqra->ddsqra_source, ddsqra->ddsqra_value, &newval);
3664 3634 if (error != 0) {
3665 3635 dsl_dataset_rele(ds, FTAG);
3666 3636 return (error);
3667 3637 }
3668 3638
3669 3639 if (newval == 0) {
3670 3640 dsl_dataset_rele(ds, FTAG);
3671 3641 return (0);
3672 3642 }
3673 3643
3674 3644 if (newval < dsl_dataset_phys(ds)->ds_referenced_bytes ||
3675 3645 newval < ds->ds_reserved) {
3676 3646 dsl_dataset_rele(ds, FTAG);
3677 3647 return (SET_ERROR(ENOSPC));
3678 3648 }
3679 3649
3680 3650 dsl_dataset_rele(ds, FTAG);
3681 3651 return (0);
3682 3652 }
3683 3653
3684 3654 static void
3685 3655 dsl_dataset_set_refquota_sync(void *arg, dmu_tx_t *tx)
3686 3656 {
3687 3657 dsl_dataset_set_qr_arg_t *ddsqra = arg;
3688 3658 dsl_pool_t *dp = dmu_tx_pool(tx);
3689 3659 dsl_dataset_t *ds;
3690 3660 uint64_t newval;
3691 3661
3692 3662 VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
3693 3663
3694 3664 dsl_prop_set_sync_impl(ds,
3695 3665 zfs_prop_to_name(ZFS_PROP_REFQUOTA),
3696 3666 ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
3697 3667 &ddsqra->ddsqra_value, tx);
3698 3668
3699 3669 VERIFY0(dsl_prop_get_int_ds(ds,
3700 3670 zfs_prop_to_name(ZFS_PROP_REFQUOTA), &newval));
3701 3671
3702 3672 if (ds->ds_quota != newval) {
3703 3673 dmu_buf_will_dirty(ds->ds_dbuf, tx);
3704 3674 ds->ds_quota = newval;
3705 3675 }
3706 3676 dsl_dataset_rele(ds, FTAG);
3707 3677 }
3708 3678
3709 3679 int
3710 3680 dsl_dataset_set_refquota(const char *dsname, zprop_source_t source,
3711 3681 uint64_t refquota)
3712 3682 {
3713 3683 dsl_dataset_set_qr_arg_t ddsqra;
3714 3684
3715 3685 ddsqra.ddsqra_name = dsname;
3716 3686 ddsqra.ddsqra_source = source;
3717 3687 ddsqra.ddsqra_value = refquota;
3718 3688
3719 3689 return (dsl_sync_task(dsname, dsl_dataset_set_refquota_check,
3720 3690 dsl_dataset_set_refquota_sync, &ddsqra, 0, ZFS_SPACE_CHECK_NONE));
3721 3691 }
3722 3692
3723 3693 static int
3724 3694 dsl_dataset_set_refreservation_check(void *arg, dmu_tx_t *tx)
3725 3695 {
3726 3696 dsl_dataset_set_qr_arg_t *ddsqra = arg;
3727 3697 dsl_pool_t *dp = dmu_tx_pool(tx);
3728 3698 dsl_dataset_t *ds;
3729 3699 int error;
3730 3700 uint64_t newval, unique;
3731 3701
3732 3702 if (spa_version(dp->dp_spa) < SPA_VERSION_REFRESERVATION)
3733 3703 return (SET_ERROR(ENOTSUP));
3734 3704
3735 3705 error = dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds);
3736 3706 if (error != 0)
3737 3707 return (error);
3738 3708
3739 3709 if (ds->ds_is_snapshot) {
3740 3710 dsl_dataset_rele(ds, FTAG);
3741 3711 return (SET_ERROR(EINVAL));
3742 3712 }
3743 3713
3744 3714 error = dsl_prop_predict(ds->ds_dir,
3745 3715 zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
3746 3716 ddsqra->ddsqra_source, ddsqra->ddsqra_value, &newval);
3747 3717 if (error != 0) {
3748 3718 dsl_dataset_rele(ds, FTAG);
3749 3719 return (error);
3750 3720 }
3751 3721
3752 3722 /*
3753 3723 * If we are doing the preliminary check in open context, the
3754 3724 * space estimates may be inaccurate.
3755 3725 */
3756 3726 if (!dmu_tx_is_syncing(tx)) {
3757 3727 dsl_dataset_rele(ds, FTAG);
3758 3728 return (0);
3759 3729 }
3760 3730
3761 3731 mutex_enter(&ds->ds_lock);
3762 3732 if (!DS_UNIQUE_IS_ACCURATE(ds))
3763 3733 dsl_dataset_recalc_head_uniq(ds);
3764 3734 unique = dsl_dataset_phys(ds)->ds_unique_bytes;
3765 3735 mutex_exit(&ds->ds_lock);
3766 3736
3767 3737 if (MAX(unique, newval) > MAX(unique, ds->ds_reserved)) {
3768 3738 uint64_t delta = MAX(unique, newval) -
3769 3739 MAX(unique, ds->ds_reserved);
3770 3740
3771 3741 if (delta >
3772 3742 dsl_dir_space_available(ds->ds_dir, NULL, 0, B_TRUE) ||
3773 3743 (ds->ds_quota > 0 && newval > ds->ds_quota)) {
3774 3744 dsl_dataset_rele(ds, FTAG);
3775 3745 return (SET_ERROR(ENOSPC));
3776 3746 }
3777 3747 }
3778 3748
3779 3749 dsl_dataset_rele(ds, FTAG);
3780 3750 return (0);
3781 3751 }
3782 3752
3783 3753 void
3784 3754 dsl_dataset_set_refreservation_sync_impl(dsl_dataset_t *ds,
3785 3755 zprop_source_t source, uint64_t value, dmu_tx_t *tx)
3786 3756 {
3787 3757 uint64_t newval;
3788 3758 uint64_t unique;
3789 3759 int64_t delta;
3790 3760
3791 3761 dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
3792 3762 source, sizeof (value), 1, &value, tx);
3793 3763
3794 3764 VERIFY0(dsl_prop_get_int_ds(ds,
3795 3765 zfs_prop_to_name(ZFS_PROP_REFRESERVATION), &newval));
3796 3766
3797 3767 dmu_buf_will_dirty(ds->ds_dbuf, tx);
3798 3768 mutex_enter(&ds->ds_dir->dd_lock);
3799 3769 mutex_enter(&ds->ds_lock);
3800 3770 ASSERT(DS_UNIQUE_IS_ACCURATE(ds));
3801 3771 unique = dsl_dataset_phys(ds)->ds_unique_bytes;
3802 3772 delta = MAX(0, (int64_t)(newval - unique)) -
3803 3773 MAX(0, (int64_t)(ds->ds_reserved - unique));
3804 3774 ds->ds_reserved = newval;
3805 3775 mutex_exit(&ds->ds_lock);
3806 3776
3807 3777 dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV, delta, 0, 0, tx);
3808 3778 mutex_exit(&ds->ds_dir->dd_lock);
3809 3779 }
3810 3780
3811 3781 static void
3812 3782 dsl_dataset_set_refreservation_sync(void *arg, dmu_tx_t *tx)
3813 3783 {
3814 3784 dsl_dataset_set_qr_arg_t *ddsqra = arg;
3815 3785 dsl_pool_t *dp = dmu_tx_pool(tx);
3816 3786 dsl_dataset_t *ds;
3817 3787
3818 3788 VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
3819 3789 dsl_dataset_set_refreservation_sync_impl(ds,
3820 3790 ddsqra->ddsqra_source, ddsqra->ddsqra_value, tx);
3821 3791 dsl_dataset_rele(ds, FTAG);
3822 3792 }
3823 3793
3824 3794 int
3825 3795 dsl_dataset_set_refreservation(const char *dsname, zprop_source_t source,
3826 3796 uint64_t refreservation)
3827 3797 {
3828 3798 dsl_dataset_set_qr_arg_t ddsqra;
3829 3799
3830 3800 ddsqra.ddsqra_name = dsname;
3831 3801 ddsqra.ddsqra_source = source;
3832 3802 ddsqra.ddsqra_value = refreservation;
3833 3803
3834 3804 return (dsl_sync_task(dsname, dsl_dataset_set_refreservation_check,
3835 3805 dsl_dataset_set_refreservation_sync, &ddsqra,
3836 3806 0, ZFS_SPACE_CHECK_NONE));
3837 3807 }
3838 3808
3839 3809 /*
3840 3810 * Return (in *usedp) the amount of space written in new that is not
3841 3811 * present in oldsnap. New may be a snapshot or the head. Old must be
3842 3812 * a snapshot before new, in new's filesystem (or its origin). If not then
3843 3813 * fail and return EINVAL.
3844 3814 *
3845 3815 * The written space is calculated by considering two components: First, we
3846 3816 * ignore any freed space, and calculate the written as new's used space
3847 3817 * minus old's used space. Next, we add in the amount of space that was freed
3848 3818 * between the two snapshots, thus reducing new's used space relative to old's.
3849 3819 * Specifically, this is the space that was born before old->ds_creation_txg,
3850 3820 * and freed before new (ie. on new's deadlist or a previous deadlist).
3851 3821 *
3852 3822 * space freed [---------------------]
3853 3823 * snapshots ---O-------O--------O-------O------
3854 3824 * oldsnap new
3855 3825 */
3856 3826 int
3857 3827 dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new,
3858 3828 uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
3859 3829 {
3860 3830 int err = 0;
3861 3831 uint64_t snapobj;
3862 3832 dsl_pool_t *dp = new->ds_dir->dd_pool;
3863 3833
3864 3834 ASSERT(dsl_pool_config_held(dp));
3865 3835
3866 3836 *usedp = 0;
3867 3837 *usedp += dsl_dataset_phys(new)->ds_referenced_bytes;
3868 3838 *usedp -= dsl_dataset_phys(oldsnap)->ds_referenced_bytes;
3869 3839
3870 3840 *compp = 0;
3871 3841 *compp += dsl_dataset_phys(new)->ds_compressed_bytes;
3872 3842 *compp -= dsl_dataset_phys(oldsnap)->ds_compressed_bytes;
3873 3843
3874 3844 *uncompp = 0;
3875 3845 *uncompp += dsl_dataset_phys(new)->ds_uncompressed_bytes;
3876 3846 *uncompp -= dsl_dataset_phys(oldsnap)->ds_uncompressed_bytes;
3877 3847
3878 3848 snapobj = new->ds_object;
3879 3849 while (snapobj != oldsnap->ds_object) {
3880 3850 dsl_dataset_t *snap;
3881 3851 uint64_t used, comp, uncomp;
3882 3852
3883 3853 if (snapobj == new->ds_object) {
3884 3854 snap = new;
3885 3855 } else {
3886 3856 err = dsl_dataset_hold_obj(dp, snapobj, FTAG, &snap);
3887 3857 if (err != 0)
3888 3858 break;
3889 3859 }
3890 3860
3891 3861 if (dsl_dataset_phys(snap)->ds_prev_snap_txg ==
3892 3862 dsl_dataset_phys(oldsnap)->ds_creation_txg) {
3893 3863 /*
3894 3864 * The blocks in the deadlist can not be born after
3895 3865 * ds_prev_snap_txg, so get the whole deadlist space,
3896 3866 * which is more efficient (especially for old-format
3897 3867 * deadlists). Unfortunately the deadlist code
3898 3868 * doesn't have enough information to make this
3899 3869 * optimization itself.
3900 3870 */
3901 3871 dsl_deadlist_space(&snap->ds_deadlist,
3902 3872 &used, &comp, &uncomp);
3903 3873 } else {
3904 3874 dsl_deadlist_space_range(&snap->ds_deadlist,
3905 3875 0, dsl_dataset_phys(oldsnap)->ds_creation_txg,
3906 3876 &used, &comp, &uncomp);
3907 3877 }
3908 3878 *usedp += used;
3909 3879 *compp += comp;
3910 3880 *uncompp += uncomp;
3911 3881
3912 3882 /*
3913 3883 * If we get to the beginning of the chain of snapshots
3914 3884 * (ds_prev_snap_obj == 0) before oldsnap, then oldsnap
3915 3885 * was not a snapshot of/before new.
3916 3886 */
3917 3887 snapobj = dsl_dataset_phys(snap)->ds_prev_snap_obj;
3918 3888 if (snap != new)
3919 3889 dsl_dataset_rele(snap, FTAG);
3920 3890 if (snapobj == 0) {
3921 3891 err = SET_ERROR(EINVAL);
3922 3892 break;
3923 3893 }
3924 3894
3925 3895 }
3926 3896 return (err);
3927 3897 }
3928 3898
3929 3899 /*
3930 3900 * Return (in *usedp) the amount of space that will be reclaimed if firstsnap,
3931 3901 * lastsnap, and all snapshots in between are deleted.
3932 3902 *
3933 3903 * blocks that would be freed [---------------------------]
3934 3904 * snapshots ---O-------O--------O-------O--------O
3935 3905 * firstsnap lastsnap
3936 3906 *
3937 3907 * This is the set of blocks that were born after the snap before firstsnap,
3938 3908 * (birth > firstsnap->prev_snap_txg) and died before the snap after the
3939 3909 * last snap (ie, is on lastsnap->ds_next->ds_deadlist or an earlier deadlist).
3940 3910 * We calculate this by iterating over the relevant deadlists (from the snap
3941 3911 * after lastsnap, backward to the snap after firstsnap), summing up the
3942 3912 * space on the deadlist that was born after the snap before firstsnap.
3943 3913 */
3944 3914 int
3945 3915 dsl_dataset_space_wouldfree(dsl_dataset_t *firstsnap,
3946 3916 dsl_dataset_t *lastsnap,
3947 3917 uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
3948 3918 {
3949 3919 int err = 0;
3950 3920 uint64_t snapobj;
3951 3921 dsl_pool_t *dp = firstsnap->ds_dir->dd_pool;
3952 3922
3953 3923 ASSERT(firstsnap->ds_is_snapshot);
3954 3924 ASSERT(lastsnap->ds_is_snapshot);
3955 3925
3956 3926 /*
3957 3927 * Check that the snapshots are in the same dsl_dir, and firstsnap
3958 3928 * is before lastsnap.
3959 3929 */
3960 3930 if (firstsnap->ds_dir != lastsnap->ds_dir ||
3961 3931 dsl_dataset_phys(firstsnap)->ds_creation_txg >
3962 3932 dsl_dataset_phys(lastsnap)->ds_creation_txg)
3963 3933 return (SET_ERROR(EINVAL));
3964 3934
3965 3935 *usedp = *compp = *uncompp = 0;
3966 3936
3967 3937 snapobj = dsl_dataset_phys(lastsnap)->ds_next_snap_obj;
3968 3938 while (snapobj != firstsnap->ds_object) {
3969 3939 dsl_dataset_t *ds;
3970 3940 uint64_t used, comp, uncomp;
3971 3941
3972 3942 err = dsl_dataset_hold_obj(dp, snapobj, FTAG, &ds);
3973 3943 if (err != 0)
3974 3944 break;
3975 3945
3976 3946 dsl_deadlist_space_range(&ds->ds_deadlist,
3977 3947 dsl_dataset_phys(firstsnap)->ds_prev_snap_txg, UINT64_MAX,
3978 3948 &used, &comp, &uncomp);
3979 3949 *usedp += used;
3980 3950 *compp += comp;
3981 3951 *uncompp += uncomp;
3982 3952
3983 3953 snapobj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
3984 3954 ASSERT3U(snapobj, !=, 0);
3985 3955 dsl_dataset_rele(ds, FTAG);
3986 3956 }
3987 3957 return (err);
3988 3958 }
3989 3959
3990 3960 /*
3991 3961 * Return TRUE if 'earlier' is an earlier snapshot in 'later's timeline.
3992 3962 * For example, they could both be snapshots of the same filesystem, and
3993 3963 * 'earlier' is before 'later'. Or 'earlier' could be the origin of
3994 3964 * 'later's filesystem. Or 'earlier' could be an older snapshot in the origin's
3995 3965 * filesystem. Or 'earlier' could be the origin's origin.
3996 3966 *
3997 3967 * If non-zero, earlier_txg is used instead of earlier's ds_creation_txg.
3998 3968 */
3999 3969 boolean_t
4000 3970 dsl_dataset_is_before(dsl_dataset_t *later, dsl_dataset_t *earlier,
4001 3971 uint64_t earlier_txg)
4002 3972 {
4003 3973 dsl_pool_t *dp = later->ds_dir->dd_pool;
4004 3974 int error;
4005 3975 boolean_t ret;
4006 3976
4007 3977 ASSERT(dsl_pool_config_held(dp));
4008 3978 ASSERT(earlier->ds_is_snapshot || earlier_txg != 0);
4009 3979
4010 3980 if (earlier_txg == 0)
4011 3981 earlier_txg = dsl_dataset_phys(earlier)->ds_creation_txg;
4012 3982
4013 3983 if (later->ds_is_snapshot &&
4014 3984 earlier_txg >= dsl_dataset_phys(later)->ds_creation_txg)
4015 3985 return (B_FALSE);
4016 3986
4017 3987 if (later->ds_dir == earlier->ds_dir)
4018 3988 return (B_TRUE);
4019 3989 if (!dsl_dir_is_clone(later->ds_dir))
4020 3990 return (B_FALSE);
4021 3991
4022 3992 if (dsl_dir_phys(later->ds_dir)->dd_origin_obj == earlier->ds_object)
4023 3993 return (B_TRUE);
4024 3994 dsl_dataset_t *origin;
4025 3995 error = dsl_dataset_hold_obj(dp,
4026 3996 dsl_dir_phys(later->ds_dir)->dd_origin_obj, FTAG, &origin);
4027 3997 if (error != 0)
4028 3998 return (B_FALSE);
4029 3999 ret = dsl_dataset_is_before(origin, earlier, earlier_txg);
4030 4000 dsl_dataset_rele(origin, FTAG);
4031 4001 return (ret);
|
↓ open down ↓ |
472 lines elided |
↑ open up ↑ |
4032 4002 }
4033 4003
4034 4004 void
4035 4005 dsl_dataset_zapify(dsl_dataset_t *ds, dmu_tx_t *tx)
4036 4006 {
4037 4007 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
4038 4008 dmu_object_zapify(mos, ds->ds_object, DMU_OT_DSL_DATASET, tx);
4039 4009 }
4040 4010
4041 4011 boolean_t
4042 -dsl_dataset_is_zapified(dsl_dataset_t *ds)
4012 +dataset_name_hidden(const char *name)
4043 4013 {
4044 - dmu_object_info_t doi;
4045 -
4046 - dmu_object_info_from_db(ds->ds_dbuf, &doi);
4047 - return (doi.doi_type == DMU_OTN_ZAP_METADATA);
4014 + if (strchr(name, '$') != NULL)
4015 + return (B_TRUE);
4016 + if (strchr(name, '%') != NULL)
4017 + return (B_TRUE);
4018 + if (!INGLOBALZONE(curproc) && !zone_dataset_visible(name, NULL))
4019 + return (B_TRUE);
4020 + return (B_FALSE);
4048 4021 }
4049 4022
4050 -boolean_t
4051 -dsl_dataset_has_resume_receive_state(dsl_dataset_t *ds)
4052 -{
4053 - return (dsl_dataset_is_zapified(ds) &&
4054 - zap_contains(ds->ds_dir->dd_pool->dp_meta_objset,
4055 - ds->ds_object, DS_FIELD_RESUME_TOGUID) == 0);
4056 -}
4057 -
4058 4023 uint64_t
4059 -dsl_dataset_get_remap_deadlist_object(dsl_dataset_t *ds)
4024 +dsl_dataset_creation_txg(const char *name)
4060 4025 {
4061 - uint64_t remap_deadlist_obj;
4026 + dsl_pool_t *dp;
4027 + dsl_dataset_t *ds;
4062 4028 int err;
4029 + uint64_t ret = UINT64_MAX;
4063 4030
4064 - if (!dsl_dataset_is_zapified(ds))
4065 - return (0);
4031 + err = dsl_pool_hold(name, FTAG, &dp);
4066 4032
4067 - err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset, ds->ds_object,
4068 - DS_FIELD_REMAP_DEADLIST, sizeof (remap_deadlist_obj), 1,
4069 - &remap_deadlist_obj);
4033 + if (err)
4034 + return (ret);
4070 4035
4071 - if (err != 0) {
4072 - VERIFY3S(err, ==, ENOENT);
4073 - return (0);
4036 + err = dsl_dataset_hold(dp, name, FTAG, &ds);
4037 +
4038 + if (!err) {
4039 + ret = dsl_dataset_phys(ds)->ds_creation_txg;
4040 + dsl_dataset_rele(ds, FTAG);
4074 4041 }
4075 4042
4076 - ASSERT(remap_deadlist_obj != 0);
4077 - return (remap_deadlist_obj);
4043 + dsl_pool_rele(dp, FTAG);
4044 +
4045 + return (ret);
4078 4046 }
4079 4047
4080 4048 boolean_t
4081 -dsl_dataset_remap_deadlist_exists(dsl_dataset_t *ds)
4049 +dsl_dataset_is_zapified(dsl_dataset_t *ds)
4082 4050 {
4083 - EQUIV(dsl_deadlist_is_open(&ds->ds_remap_deadlist),
4084 - dsl_dataset_get_remap_deadlist_object(ds) != 0);
4085 - return (dsl_deadlist_is_open(&ds->ds_remap_deadlist));
4086 -}
4051 + dmu_object_info_t doi;
4087 4052
4088 -static void
4089 -dsl_dataset_set_remap_deadlist_object(dsl_dataset_t *ds, uint64_t obj,
4090 - dmu_tx_t *tx)
4091 -{
4092 - ASSERT(obj != 0);
4093 - dsl_dataset_zapify(ds, tx);
4094 - VERIFY0(zap_add(ds->ds_dir->dd_pool->dp_meta_objset, ds->ds_object,
4095 - DS_FIELD_REMAP_DEADLIST, sizeof (obj), 1, &obj, tx));
4053 + dmu_object_info_from_db(ds->ds_dbuf, &doi);
4054 + return (doi.doi_type == DMU_OTN_ZAP_METADATA);
4096 4055 }
4097 4056
4098 -static void
4099 -dsl_dataset_unset_remap_deadlist_object(dsl_dataset_t *ds, dmu_tx_t *tx)
4057 +boolean_t
4058 +dsl_dataset_has_resume_receive_state(dsl_dataset_t *ds)
4100 4059 {
4101 - VERIFY0(zap_remove(ds->ds_dir->dd_pool->dp_meta_objset,
4102 - ds->ds_object, DS_FIELD_REMAP_DEADLIST, tx));
4103 -}
4104 -
4105 -void
4106 -dsl_dataset_destroy_remap_deadlist(dsl_dataset_t *ds, dmu_tx_t *tx)
4107 -{
4108 - uint64_t remap_deadlist_object;
4109 - spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
4110 -
4111 - ASSERT(dmu_tx_is_syncing(tx));
4112 - ASSERT(dsl_dataset_remap_deadlist_exists(ds));
4113 -
4114 - remap_deadlist_object = ds->ds_remap_deadlist.dl_object;
4115 - dsl_deadlist_close(&ds->ds_remap_deadlist);
4116 - dsl_deadlist_free(spa_meta_objset(spa), remap_deadlist_object, tx);
4117 - dsl_dataset_unset_remap_deadlist_object(ds, tx);
4118 - spa_feature_decr(spa, SPA_FEATURE_OBSOLETE_COUNTS, tx);
4119 -}
4120 -
4121 -void
4122 -dsl_dataset_create_remap_deadlist(dsl_dataset_t *ds, dmu_tx_t *tx)
4123 -{
4124 - uint64_t remap_deadlist_obj;
4125 - spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
4126 -
4127 - ASSERT(dmu_tx_is_syncing(tx));
4128 - ASSERT(MUTEX_HELD(&ds->ds_remap_deadlist_lock));
4129 - /*
4130 - * Currently we only create remap deadlists when there are indirect
4131 - * vdevs with referenced mappings.
4132 - */
4133 - ASSERT(spa_feature_is_active(spa, SPA_FEATURE_DEVICE_REMOVAL));
4134 -
4135 - remap_deadlist_obj = dsl_deadlist_clone(
4136 - &ds->ds_deadlist, UINT64_MAX,
4137 - dsl_dataset_phys(ds)->ds_prev_snap_obj, tx);
4138 - dsl_dataset_set_remap_deadlist_object(ds,
4139 - remap_deadlist_obj, tx);
4140 - dsl_deadlist_open(&ds->ds_remap_deadlist, spa_meta_objset(spa),
4141 - remap_deadlist_obj);
4142 - spa_feature_incr(spa, SPA_FEATURE_OBSOLETE_COUNTS, tx);
4060 + return (dsl_dataset_is_zapified(ds) &&
4061 + zap_contains(ds->ds_dir->dd_pool->dp_meta_objset,
4062 + ds->ds_object, DS_FIELD_RESUME_TOGUID) == 0);
4143 4063 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX