Deleted Added
full compact
dmu_traverse.c (268649) dmu_traverse.c (268650)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 44 unchanged lines hidden (view full) ---

53typedef struct traverse_data {
54 spa_t *td_spa;
55 uint64_t td_objset;
56 blkptr_t *td_rootbp;
57 uint64_t td_min_txg;
58 zbookmark_t *td_resume;
59 int td_flags;
60 prefetch_data_t *td_pfd;
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 44 unchanged lines hidden (view full) ---

53typedef struct traverse_data {
54 spa_t *td_spa;
55 uint64_t td_objset;
56 blkptr_t *td_rootbp;
57 uint64_t td_min_txg;
58 zbookmark_t *td_resume;
59 int td_flags;
60 prefetch_data_t *td_pfd;
61 boolean_t td_paused;
61 blkptr_cb_t *td_func;
62 void *td_arg;
63} traverse_data_t;
64
65static int traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
66 uint64_t objset, uint64_t object);
67static void prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *,
68 uint64_t objset, uint64_t object);

--- 89 unchanged lines hidden (view full) ---

158 */
159 if (zbookmark_is_before(dnp, zb, td->td_resume))
160 return (RESUME_SKIP_ALL);
161
162 /*
163 * If we found the block we're trying to resume from, zero
164 * the bookmark out to indicate that we have resumed.
165 */
62 blkptr_cb_t *td_func;
63 void *td_arg;
64} traverse_data_t;
65
66static int traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
67 uint64_t objset, uint64_t object);
68static void prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *,
69 uint64_t objset, uint64_t object);

--- 89 unchanged lines hidden (view full) ---

159 */
160 if (zbookmark_is_before(dnp, zb, td->td_resume))
161 return (RESUME_SKIP_ALL);
162
163 /*
164 * If we found the block we're trying to resume from, zero
165 * the bookmark out to indicate that we have resumed.
166 */
166 ASSERT3U(zb->zb_object, <=, td->td_resume->zb_object);
167 if (bcmp(zb, td->td_resume, sizeof (*zb)) == 0) {
168 bzero(td->td_resume, sizeof (*zb));
169 if (td->td_flags & TRAVERSE_POST)
170 return (RESUME_SKIP_CHILDREN);
171 }
172 }
173 return (RESUME_SKIP_NONE);
174}
175
176static void
167 if (bcmp(zb, td->td_resume, sizeof (*zb)) == 0) {
168 bzero(td->td_resume, sizeof (*zb));
169 if (td->td_flags & TRAVERSE_POST)
170 return (RESUME_SKIP_CHILDREN);
171 }
172 }
173 return (RESUME_SKIP_NONE);
174}
175
176static void
177traverse_pause(traverse_data_t *td, const zbookmark_t *zb)
178{
179 ASSERT(td->td_resume != NULL);
180 ASSERT0(zb->zb_level);
181 bcopy(zb, td->td_resume, sizeof (*td->td_resume));
182}
183
184static void
185traverse_prefetch_metadata(traverse_data_t *td,
186 const blkptr_t *bp, const zbookmark_t *zb)
187{
188 uint32_t flags = ARC_NOWAIT | ARC_PREFETCH;
189
190 if (!(td->td_flags & TRAVERSE_PREFETCH_METADATA))
191 return;
192 /*

--- 12 unchanged lines hidden (view full) ---

205 ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
206}
207
208static int
209traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
210 const blkptr_t *bp, const zbookmark_t *zb)
211{
212 zbookmark_t czb;
177traverse_prefetch_metadata(traverse_data_t *td,
178 const blkptr_t *bp, const zbookmark_t *zb)
179{
180 uint32_t flags = ARC_NOWAIT | ARC_PREFETCH;
181
182 if (!(td->td_flags & TRAVERSE_PREFETCH_METADATA))
183 return;
184 /*

--- 12 unchanged lines hidden (view full) ---

197 ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
198}
199
200static int
201traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
202 const blkptr_t *bp, const zbookmark_t *zb)
203{
204 zbookmark_t czb;
213 int err = 0, lasterr = 0;
205 int err = 0;
214 arc_buf_t *buf = NULL;
215 prefetch_data_t *pd = td->td_pfd;
216 boolean_t hard = td->td_flags & TRAVERSE_HARD;
206 arc_buf_t *buf = NULL;
207 prefetch_data_t *pd = td->td_pfd;
208 boolean_t hard = td->td_flags & TRAVERSE_HARD;
217 boolean_t pause = B_FALSE;
218
219 switch (resume_skip_check(td, dnp, zb)) {
220 case RESUME_SKIP_ALL:
221 return (0);
222 case RESUME_SKIP_CHILDREN:
223 goto post;
224 case RESUME_SKIP_NONE:
225 break;

--- 22 unchanged lines hidden (view full) ---

248 return (0);
249 }
250 } else if (bp->blk_birth <= td->td_min_txg) {
251 return (0);
252 }
253
254 if (BP_IS_HOLE(bp)) {
255 err = td->td_func(td->td_spa, NULL, bp, zb, dnp, td->td_arg);
209
210 switch (resume_skip_check(td, dnp, zb)) {
211 case RESUME_SKIP_ALL:
212 return (0);
213 case RESUME_SKIP_CHILDREN:
214 goto post;
215 case RESUME_SKIP_NONE:
216 break;

--- 22 unchanged lines hidden (view full) ---

239 return (0);
240 }
241 } else if (bp->blk_birth <= td->td_min_txg) {
242 return (0);
243 }
244
245 if (BP_IS_HOLE(bp)) {
246 err = td->td_func(td->td_spa, NULL, bp, zb, dnp, td->td_arg);
256 return (err);
247 if (err != 0)
248 goto post;
249 return (0);
257 }
258
259 if (pd && !pd->pd_exited &&
260 ((pd->pd_flags & TRAVERSE_PREFETCH_DATA) ||
261 BP_GET_TYPE(bp) == DMU_OT_DNODE || BP_GET_LEVEL(bp) > 0)) {
262 mutex_enter(&pd->pd_mtx);
263 ASSERT(pd->pd_blks_fetched >= 0);
264 while (pd->pd_blks_fetched == 0 && !pd->pd_exited)
265 cv_wait(&pd->pd_cv, &pd->pd_mtx);
266 pd->pd_blks_fetched--;
267 cv_broadcast(&pd->pd_cv);
268 mutex_exit(&pd->pd_mtx);
269 }
270
271 if (td->td_flags & TRAVERSE_PRE) {
272 err = td->td_func(td->td_spa, NULL, bp, zb, dnp,
273 td->td_arg);
274 if (err == TRAVERSE_VISIT_NO_CHILDREN)
275 return (0);
250 }
251
252 if (pd && !pd->pd_exited &&
253 ((pd->pd_flags & TRAVERSE_PREFETCH_DATA) ||
254 BP_GET_TYPE(bp) == DMU_OT_DNODE || BP_GET_LEVEL(bp) > 0)) {
255 mutex_enter(&pd->pd_mtx);
256 ASSERT(pd->pd_blks_fetched >= 0);
257 while (pd->pd_blks_fetched == 0 && !pd->pd_exited)
258 cv_wait(&pd->pd_cv, &pd->pd_mtx);
259 pd->pd_blks_fetched--;
260 cv_broadcast(&pd->pd_cv);
261 mutex_exit(&pd->pd_mtx);
262 }
263
264 if (td->td_flags & TRAVERSE_PRE) {
265 err = td->td_func(td->td_spa, NULL, bp, zb, dnp,
266 td->td_arg);
267 if (err == TRAVERSE_VISIT_NO_CHILDREN)
268 return (0);
276 if (err == ERESTART)
277 pause = B_TRUE; /* handle pausing at a common point */
278 if (err != 0)
279 goto post;
280 }
281
282 if (BP_GET_LEVEL(bp) > 0) {
283 uint32_t flags = ARC_WAIT;
284 int i;
285 blkptr_t *cbp;
286 int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
287
288 err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
289 ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
290 if (err != 0)
269 if (err != 0)
270 goto post;
271 }
272
273 if (BP_GET_LEVEL(bp) > 0) {
274 uint32_t flags = ARC_WAIT;
275 int i;
276 blkptr_t *cbp;
277 int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
278
279 err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
280 ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
281 if (err != 0)
291 return (err);
282 goto post;
292 cbp = buf->b_data;
293
294 for (i = 0; i < epb; i++) {
295 SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
296 zb->zb_level - 1,
297 zb->zb_blkid * epb + i);
298 traverse_prefetch_metadata(td, &cbp[i], &czb);
299 }
300
301 /* recursively visitbp() blocks below this */
302 for (i = 0; i < epb; i++) {
303 SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
304 zb->zb_level - 1,
305 zb->zb_blkid * epb + i);
306 err = traverse_visitbp(td, dnp, &cbp[i], &czb);
283 cbp = buf->b_data;
284
285 for (i = 0; i < epb; i++) {
286 SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
287 zb->zb_level - 1,
288 zb->zb_blkid * epb + i);
289 traverse_prefetch_metadata(td, &cbp[i], &czb);
290 }
291
292 /* recursively visitbp() blocks below this */
293 for (i = 0; i < epb; i++) {
294 SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
295 zb->zb_level - 1,
296 zb->zb_blkid * epb + i);
297 err = traverse_visitbp(td, dnp, &cbp[i], &czb);
307 if (err != 0) {
308 if (!hard)
309 break;
310 lasterr = err;
311 }
298 if (err != 0)
299 break;
312 }
313 } else if (BP_GET_TYPE(bp) == DMU_OT_DNODE) {
314 uint32_t flags = ARC_WAIT;
315 int i;
316 int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT;
317
318 err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
319 ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
320 if (err != 0)
300 }
301 } else if (BP_GET_TYPE(bp) == DMU_OT_DNODE) {
302 uint32_t flags = ARC_WAIT;
303 int i;
304 int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT;
305
306 err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
307 ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
308 if (err != 0)
321 return (err);
309 goto post;
322 dnp = buf->b_data;
323
324 for (i = 0; i < epb; i++) {
325 prefetch_dnode_metadata(td, &dnp[i], zb->zb_objset,
326 zb->zb_blkid * epb + i);
327 }
328
329 /* recursively visitbp() blocks below this */
330 for (i = 0; i < epb; i++) {
331 err = traverse_dnode(td, &dnp[i], zb->zb_objset,
332 zb->zb_blkid * epb + i);
310 dnp = buf->b_data;
311
312 for (i = 0; i < epb; i++) {
313 prefetch_dnode_metadata(td, &dnp[i], zb->zb_objset,
314 zb->zb_blkid * epb + i);
315 }
316
317 /* recursively visitbp() blocks below this */
318 for (i = 0; i < epb; i++) {
319 err = traverse_dnode(td, &dnp[i], zb->zb_objset,
320 zb->zb_blkid * epb + i);
333 if (err != 0) {
334 if (!hard)
335 break;
336 lasterr = err;
337 }
321 if (err != 0)
322 break;
338 }
339 } else if (BP_GET_TYPE(bp) == DMU_OT_OBJSET) {
340 uint32_t flags = ARC_WAIT;
341 objset_phys_t *osp;
342 dnode_phys_t *dnp;
343
344 err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
345 ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
346 if (err != 0)
323 }
324 } else if (BP_GET_TYPE(bp) == DMU_OT_OBJSET) {
325 uint32_t flags = ARC_WAIT;
326 objset_phys_t *osp;
327 dnode_phys_t *dnp;
328
329 err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
330 ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
331 if (err != 0)
347 return (err);
332 goto post;
348
349 osp = buf->b_data;
350 dnp = &osp->os_meta_dnode;
351 prefetch_dnode_metadata(td, dnp, zb->zb_objset,
352 DMU_META_DNODE_OBJECT);
353 if (arc_buf_size(buf) >= sizeof (objset_phys_t)) {
354 prefetch_dnode_metadata(td, &osp->os_groupused_dnode,
355 zb->zb_objset, DMU_GROUPUSED_OBJECT);
356 prefetch_dnode_metadata(td, &osp->os_userused_dnode,
357 zb->zb_objset, DMU_USERUSED_OBJECT);
358 }
359
360 err = traverse_dnode(td, dnp, zb->zb_objset,
361 DMU_META_DNODE_OBJECT);
333
334 osp = buf->b_data;
335 dnp = &osp->os_meta_dnode;
336 prefetch_dnode_metadata(td, dnp, zb->zb_objset,
337 DMU_META_DNODE_OBJECT);
338 if (arc_buf_size(buf) >= sizeof (objset_phys_t)) {
339 prefetch_dnode_metadata(td, &osp->os_groupused_dnode,
340 zb->zb_objset, DMU_GROUPUSED_OBJECT);
341 prefetch_dnode_metadata(td, &osp->os_userused_dnode,
342 zb->zb_objset, DMU_USERUSED_OBJECT);
343 }
344
345 err = traverse_dnode(td, dnp, zb->zb_objset,
346 DMU_META_DNODE_OBJECT);
362 if (err && hard) {
363 lasterr = err;
364 err = 0;
365 }
366 if (err == 0 && arc_buf_size(buf) >= sizeof (objset_phys_t)) {
367 dnp = &osp->os_groupused_dnode;
368 err = traverse_dnode(td, dnp, zb->zb_objset,
369 DMU_GROUPUSED_OBJECT);
370 }
347 if (err == 0 && arc_buf_size(buf) >= sizeof (objset_phys_t)) {
348 dnp = &osp->os_groupused_dnode;
349 err = traverse_dnode(td, dnp, zb->zb_objset,
350 DMU_GROUPUSED_OBJECT);
351 }
371 if (err && hard) {
372 lasterr = err;
373 err = 0;
374 }
375 if (err == 0 && arc_buf_size(buf) >= sizeof (objset_phys_t)) {
376 dnp = &osp->os_userused_dnode;
377 err = traverse_dnode(td, dnp, zb->zb_objset,
378 DMU_USERUSED_OBJECT);
379 }
380 }
381
382 if (buf)
383 (void) arc_buf_remove_ref(buf, &buf);
384
385post:
352 if (err == 0 && arc_buf_size(buf) >= sizeof (objset_phys_t)) {
353 dnp = &osp->os_userused_dnode;
354 err = traverse_dnode(td, dnp, zb->zb_objset,
355 DMU_USERUSED_OBJECT);
356 }
357 }
358
359 if (buf)
360 (void) arc_buf_remove_ref(buf, &buf);
361
362post:
386 if (err == 0 && (td->td_flags & TRAVERSE_POST)) {
363 if (err == 0 && (td->td_flags & TRAVERSE_POST))
387 err = td->td_func(td->td_spa, NULL, bp, zb, dnp, td->td_arg);
364 err = td->td_func(td->td_spa, NULL, bp, zb, dnp, td->td_arg);
388 if (err == ERESTART)
389 pause = B_TRUE;
365
366 if (hard && (err == EIO || err == ECKSUM)) {
367 /*
368 * Ignore this disk error as requested by the HARD flag,
369 * and continue traversal.
370 */
371 err = 0;
390 }
391
372 }
373
392 if (pause && td->td_resume != NULL) {
393 ASSERT3U(err, ==, ERESTART);
394 ASSERT(!hard);
395 traverse_pause(td, zb);
374 /*
375 * If we are stopping here, set td_resume.
376 */
377 if (td->td_resume != NULL && err != 0 && !td->td_paused) {
378 td->td_resume->zb_objset = zb->zb_objset;
379 td->td_resume->zb_object = zb->zb_object;
380 td->td_resume->zb_level = 0;
381 /*
382 * If we have stopped on an indirect block (e.g. due to
383 * i/o error), we have not visited anything below it.
384 * Set the bookmark to the first level-0 block that we need
385 * to visit. This way, the resuming code does not need to
386 * deal with resuming from indirect blocks.
387 */
388 td->td_resume->zb_blkid = zb->zb_blkid <<
389 (zb->zb_level * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT));
390 td->td_paused = B_TRUE;
396 }
397
391 }
392
398 return (err != 0 ? err : lasterr);
393 return (err);
399}
400
401static void
402prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *dnp,
403 uint64_t objset, uint64_t object)
404{
405 int j;
406 zbookmark_t czb;

--- 8 unchanged lines hidden (view full) ---

415 traverse_prefetch_metadata(td, &dnp->dn_spill, &czb);
416 }
417}
418
419static int
420traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
421 uint64_t objset, uint64_t object)
422{
394}
395
396static void
397prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *dnp,
398 uint64_t objset, uint64_t object)
399{
400 int j;
401 zbookmark_t czb;

--- 8 unchanged lines hidden (view full) ---

410 traverse_prefetch_metadata(td, &dnp->dn_spill, &czb);
411 }
412}
413
414static int
415traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
416 uint64_t objset, uint64_t object)
417{
423 int j, err = 0, lasterr = 0;
418 int j, err = 0;
424 zbookmark_t czb;
419 zbookmark_t czb;
425 boolean_t hard = (td->td_flags & TRAVERSE_HARD);
426
427 for (j = 0; j < dnp->dn_nblkptr; j++) {
428 SET_BOOKMARK(&czb, objset, object, dnp->dn_nlevels - 1, j);
429 err = traverse_visitbp(td, dnp, &dnp->dn_blkptr[j], &czb);
420
421 for (j = 0; j < dnp->dn_nblkptr; j++) {
422 SET_BOOKMARK(&czb, objset, object, dnp->dn_nlevels - 1, j);
423 err = traverse_visitbp(td, dnp, &dnp->dn_blkptr[j], &czb);
430 if (err != 0) {
431 if (!hard)
432 break;
433 lasterr = err;
434 }
424 if (err != 0)
425 break;
435 }
436
437 if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
438 SET_BOOKMARK(&czb, objset, object, 0, DMU_SPILL_BLKID);
439 err = traverse_visitbp(td, dnp, &dnp->dn_spill, &czb);
426 }
427
428 if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
429 SET_BOOKMARK(&czb, objset, object, 0, DMU_SPILL_BLKID);
430 err = traverse_visitbp(td, dnp, &dnp->dn_spill, &czb);
440 if (err != 0) {
441 if (!hard)
442 return (err);
443 lasterr = err;
444 }
445 }
431 }
446 return (err != 0 ? err : lasterr);
432 return (err);
447}
448
449/* ARGSUSED */
450static int
451traverse_prefetcher(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
452 const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
453{
454 prefetch_data_t *pfd = arg;

--- 70 unchanged lines hidden (view full) ---

525 td.td_objset = objset;
526 td.td_rootbp = rootbp;
527 td.td_min_txg = txg_start;
528 td.td_resume = resume;
529 td.td_func = func;
530 td.td_arg = arg;
531 td.td_pfd = &pd;
532 td.td_flags = flags;
433}
434
435/* ARGSUSED */
436static int
437traverse_prefetcher(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
438 const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
439{
440 prefetch_data_t *pfd = arg;

--- 70 unchanged lines hidden (view full) ---

511 td.td_objset = objset;
512 td.td_rootbp = rootbp;
513 td.td_min_txg = txg_start;
514 td.td_resume = resume;
515 td.td_func = func;
516 td.td_arg = arg;
517 td.td_pfd = &pd;
518 td.td_flags = flags;
519 td.td_paused = B_FALSE;
533
534 pd.pd_blks_max = zfs_pd_blks_max;
535 pd.pd_flags = flags;
536 mutex_init(&pd.pd_mtx, NULL, MUTEX_DEFAULT, NULL);
537 cv_init(&pd.pd_cv, NULL, CV_DEFAULT, NULL);
538
539 /* See comment on ZIL traversal in dsl_scan_visitds. */
540 if (ds != NULL && !dsl_dataset_is_snapshot(ds) && !BP_IS_HOLE(rootbp)) {

--- 57 unchanged lines hidden (view full) ---

598
599/*
600 * NB: pool must not be changing on-disk (eg, from zdb or sync context).
601 */
602int
603traverse_pool(spa_t *spa, uint64_t txg_start, int flags,
604 blkptr_cb_t func, void *arg)
605{
520
521 pd.pd_blks_max = zfs_pd_blks_max;
522 pd.pd_flags = flags;
523 mutex_init(&pd.pd_mtx, NULL, MUTEX_DEFAULT, NULL);
524 cv_init(&pd.pd_cv, NULL, CV_DEFAULT, NULL);
525
526 /* See comment on ZIL traversal in dsl_scan_visitds. */
527 if (ds != NULL && !dsl_dataset_is_snapshot(ds) && !BP_IS_HOLE(rootbp)) {

--- 57 unchanged lines hidden (view full) ---

585
586/*
587 * NB: pool must not be changing on-disk (eg, from zdb or sync context).
588 */
589int
590traverse_pool(spa_t *spa, uint64_t txg_start, int flags,
591 blkptr_cb_t func, void *arg)
592{
606 int err, lasterr = 0;
593 int err;
607 uint64_t obj;
608 dsl_pool_t *dp = spa_get_dsl(spa);
609 objset_t *mos = dp->dp_meta_objset;
610 boolean_t hard = (flags & TRAVERSE_HARD);
611
612 /* visit the MOS */
613 err = traverse_impl(spa, NULL, 0, spa_get_rootblkptr(spa),
614 txg_start, NULL, flags, func, arg);
615 if (err != 0)
616 return (err);
617
618 /* visit each dataset */
594 uint64_t obj;
595 dsl_pool_t *dp = spa_get_dsl(spa);
596 objset_t *mos = dp->dp_meta_objset;
597 boolean_t hard = (flags & TRAVERSE_HARD);
598
599 /* visit the MOS */
600 err = traverse_impl(spa, NULL, 0, spa_get_rootblkptr(spa),
601 txg_start, NULL, flags, func, arg);
602 if (err != 0)
603 return (err);
604
605 /* visit each dataset */
619 for (obj = 1; err == 0 || (err != ESRCH && hard);
606 for (obj = 1; err == 0;
620 err = dmu_object_next(mos, &obj, FALSE, txg_start)) {
621 dmu_object_info_t doi;
622
623 err = dmu_object_info(mos, obj, &doi);
624 if (err != 0) {
607 err = dmu_object_next(mos, &obj, FALSE, txg_start)) {
608 dmu_object_info_t doi;
609
610 err = dmu_object_info(mos, obj, &doi);
611 if (err != 0) {
625 if (!hard)
626 return (err);
627 lasterr = err;
628 continue;
612 if (hard)
613 continue;
614 break;
629 }
630
631 if (doi.doi_bonus_type == DMU_OT_DSL_DATASET) {
632 dsl_dataset_t *ds;
633 uint64_t txg = txg_start;
634
635 dsl_pool_config_enter(dp, FTAG);
636 err = dsl_dataset_hold_obj(dp, obj, FTAG, &ds);
637 dsl_pool_config_exit(dp, FTAG);
638 if (err != 0) {
615 }
616
617 if (doi.doi_bonus_type == DMU_OT_DSL_DATASET) {
618 dsl_dataset_t *ds;
619 uint64_t txg = txg_start;
620
621 dsl_pool_config_enter(dp, FTAG);
622 err = dsl_dataset_hold_obj(dp, obj, FTAG, &ds);
623 dsl_pool_config_exit(dp, FTAG);
624 if (err != 0) {
639 if (!hard)
640 return (err);
641 lasterr = err;
642 continue;
625 if (hard)
626 continue;
627 break;
643 }
644 if (ds->ds_phys->ds_prev_snap_txg > txg)
645 txg = ds->ds_phys->ds_prev_snap_txg;
646 err = traverse_dataset(ds, txg, flags, func, arg);
647 dsl_dataset_rele(ds, FTAG);
628 }
629 if (ds->ds_phys->ds_prev_snap_txg > txg)
630 txg = ds->ds_phys->ds_prev_snap_txg;
631 err = traverse_dataset(ds, txg, flags, func, arg);
632 dsl_dataset_rele(ds, FTAG);
648 if (err != 0) {
649 if (!hard)
650 return (err);
651 lasterr = err;
652 }
633 if (err != 0)
634 break;
653 }
654 }
655 if (err == ESRCH)
656 err = 0;
635 }
636 }
637 if (err == ESRCH)
638 err = 0;
657 return (err != 0 ? err : lasterr);
639 return (err);
658}
640}