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} |