dmu_traverse.c (219089) | dmu_traverse.c (236884) |
---|---|
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 --- 6 unchanged lines hidden (view full) --- 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. | 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 --- 6 unchanged lines hidden (view full) --- 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
23 * Copyright (c) 2012 by Delphix. All rights reserved. |
|
23 */ 24 25#include <sys/zfs_context.h> 26#include <sys/dmu_objset.h> 27#include <sys/dmu_traverse.h> 28#include <sys/dsl_dataset.h> 29#include <sys/dsl_dir.h> 30#include <sys/dsl_pool.h> --- 17 unchanged lines hidden (view full) --- 48 boolean_t pd_exited; 49} prefetch_data_t; 50 51typedef struct traverse_data { 52 spa_t *td_spa; 53 uint64_t td_objset; 54 blkptr_t *td_rootbp; 55 uint64_t td_min_txg; | 24 */ 25 26#include <sys/zfs_context.h> 27#include <sys/dmu_objset.h> 28#include <sys/dmu_traverse.h> 29#include <sys/dsl_dataset.h> 30#include <sys/dsl_dir.h> 31#include <sys/dsl_pool.h> --- 17 unchanged lines hidden (view full) --- 49 boolean_t pd_exited; 50} prefetch_data_t; 51 52typedef struct traverse_data { 53 spa_t *td_spa; 54 uint64_t td_objset; 55 blkptr_t *td_rootbp; 56 uint64_t td_min_txg; |
57 zbookmark_t *td_resume; |
|
56 int td_flags; 57 prefetch_data_t *td_pfd; 58 blkptr_cb_t *td_func; 59 void *td_arg; 60} traverse_data_t; 61 62static int traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp, 63 arc_buf_t *buf, uint64_t objset, uint64_t object); --- 59 unchanged lines hidden (view full) --- 123 zilog = zil_alloc(spa_get_dsl(td->td_spa)->dp_meta_objset, zh); 124 125 (void) zil_parse(zilog, traverse_zil_block, traverse_zil_record, td, 126 claim_txg); 127 128 zil_free(zilog); 129} 130 | 58 int td_flags; 59 prefetch_data_t *td_pfd; 60 blkptr_cb_t *td_func; 61 void *td_arg; 62} traverse_data_t; 63 64static int traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp, 65 arc_buf_t *buf, uint64_t objset, uint64_t object); --- 59 unchanged lines hidden (view full) --- 125 zilog = zil_alloc(spa_get_dsl(td->td_spa)->dp_meta_objset, zh); 126 127 (void) zil_parse(zilog, traverse_zil_block, traverse_zil_record, td, 128 claim_txg); 129 130 zil_free(zilog); 131} 132 |
133typedef enum resume_skip { 134 RESUME_SKIP_ALL, 135 RESUME_SKIP_NONE, 136 RESUME_SKIP_CHILDREN 137} resume_skip_t; 138 139/* 140 * Returns RESUME_SKIP_ALL if td indicates that we are resuming a traversal and 141 * the block indicated by zb does not need to be visited at all. Returns 142 * RESUME_SKIP_CHILDREN if we are resuming a post traversal and we reach the 143 * resume point. This indicates that this block should be visited but not its 144 * children (since they must have been visited in a previous traversal). 145 * Otherwise returns RESUME_SKIP_NONE. 146 */ 147static resume_skip_t 148resume_skip_check(traverse_data_t *td, const dnode_phys_t *dnp, 149 const zbookmark_t *zb) 150{ 151 if (td->td_resume != NULL && !ZB_IS_ZERO(td->td_resume)) { 152 /* 153 * If we already visited this bp & everything below, 154 * don't bother doing it again. 155 */ 156 if (zbookmark_is_before(dnp, zb, td->td_resume)) 157 return (RESUME_SKIP_ALL); 158 159 /* 160 * If we found the block we're trying to resume from, zero 161 * the bookmark out to indicate that we have resumed. 162 */ 163 ASSERT3U(zb->zb_object, <=, td->td_resume->zb_object); 164 if (bcmp(zb, td->td_resume, sizeof (*zb)) == 0) { 165 bzero(td->td_resume, sizeof (*zb)); 166 if (td->td_flags & TRAVERSE_POST) 167 return (RESUME_SKIP_CHILDREN); 168 } 169 } 170 return (RESUME_SKIP_NONE); 171} 172 173static void 174traverse_pause(traverse_data_t *td, const zbookmark_t *zb) 175{ 176 ASSERT(td->td_resume != NULL); 177 ASSERT3U(zb->zb_level, ==, 0); 178 bcopy(zb, td->td_resume, sizeof (*td->td_resume)); 179} 180 |
|
131static int 132traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, 133 arc_buf_t *pbuf, blkptr_t *bp, const zbookmark_t *zb) 134{ 135 zbookmark_t czb; 136 int err = 0, lasterr = 0; 137 arc_buf_t *buf = NULL; 138 prefetch_data_t *pd = td->td_pfd; 139 boolean_t hard = td->td_flags & TRAVERSE_HARD; | 181static int 182traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, 183 arc_buf_t *pbuf, blkptr_t *bp, const zbookmark_t *zb) 184{ 185 zbookmark_t czb; 186 int err = 0, lasterr = 0; 187 arc_buf_t *buf = NULL; 188 prefetch_data_t *pd = td->td_pfd; 189 boolean_t hard = td->td_flags & TRAVERSE_HARD; |
190 boolean_t pause = B_FALSE; |
|
140 | 191 |
141 if (bp->blk_birth == 0) { | 192 switch (resume_skip_check(td, dnp, zb)) { 193 case RESUME_SKIP_ALL: 194 return (0); 195 case RESUME_SKIP_CHILDREN: 196 goto post; 197 case RESUME_SKIP_NONE: 198 break; 199 default: 200 ASSERT(0); 201 } 202 203 if (BP_IS_HOLE(bp)) { |
142 err = td->td_func(td->td_spa, NULL, NULL, pbuf, zb, dnp, 143 td->td_arg); 144 return (err); 145 } 146 147 if (bp->blk_birth <= td->td_min_txg) 148 return (0); 149 --- 9 unchanged lines hidden (view full) --- 159 mutex_exit(&pd->pd_mtx); 160 } 161 162 if (td->td_flags & TRAVERSE_PRE) { 163 err = td->td_func(td->td_spa, NULL, bp, pbuf, zb, dnp, 164 td->td_arg); 165 if (err == TRAVERSE_VISIT_NO_CHILDREN) 166 return (0); | 204 err = td->td_func(td->td_spa, NULL, NULL, pbuf, zb, dnp, 205 td->td_arg); 206 return (err); 207 } 208 209 if (bp->blk_birth <= td->td_min_txg) 210 return (0); 211 --- 9 unchanged lines hidden (view full) --- 221 mutex_exit(&pd->pd_mtx); 222 } 223 224 if (td->td_flags & TRAVERSE_PRE) { 225 err = td->td_func(td->td_spa, NULL, bp, pbuf, zb, dnp, 226 td->td_arg); 227 if (err == TRAVERSE_VISIT_NO_CHILDREN) 228 return (0); |
167 if (err) 168 return (err); | 229 if (err == ERESTART) 230 pause = B_TRUE; /* handle pausing at a common point */ 231 if (err != 0) 232 goto post; |
169 } 170 171 if (BP_GET_LEVEL(bp) > 0) { 172 uint32_t flags = ARC_WAIT; 173 int i; 174 blkptr_t *cbp; 175 int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT; 176 --- 71 unchanged lines hidden (view full) --- 248 err = traverse_dnode(td, dnp, buf, zb->zb_objset, 249 DMU_GROUPUSED_OBJECT); 250 } 251 } 252 253 if (buf) 254 (void) arc_buf_remove_ref(buf, &buf); 255 | 233 } 234 235 if (BP_GET_LEVEL(bp) > 0) { 236 uint32_t flags = ARC_WAIT; 237 int i; 238 blkptr_t *cbp; 239 int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT; 240 --- 71 unchanged lines hidden (view full) --- 312 err = traverse_dnode(td, dnp, buf, zb->zb_objset, 313 DMU_GROUPUSED_OBJECT); 314 } 315 } 316 317 if (buf) 318 (void) arc_buf_remove_ref(buf, &buf); 319 |
320post: |
|
256 if (err == 0 && lasterr == 0 && (td->td_flags & TRAVERSE_POST)) { 257 err = td->td_func(td->td_spa, NULL, bp, pbuf, zb, dnp, 258 td->td_arg); | 321 if (err == 0 && lasterr == 0 && (td->td_flags & TRAVERSE_POST)) { 322 err = td->td_func(td->td_spa, NULL, bp, pbuf, zb, dnp, 323 td->td_arg); |
324 if (err == ERESTART) 325 pause = B_TRUE; |
|
259 } 260 | 326 } 327 |
328 if (pause && td->td_resume != NULL) { 329 ASSERT3U(err, ==, ERESTART); 330 ASSERT(!hard); 331 traverse_pause(td, zb); 332 } 333 |
|
261 return (err != 0 ? err : lasterr); 262} 263 264static int 265traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp, 266 arc_buf_t *buf, uint64_t objset, uint64_t object) 267{ 268 int j, err = 0, lasterr = 0; --- 79 unchanged lines hidden (view full) --- 348 mutex_exit(&td_main->td_pfd->pd_mtx); 349} 350 351/* 352 * NB: dataset must not be changing on-disk (eg, is a snapshot or we are 353 * in syncing context). 354 */ 355static int | 334 return (err != 0 ? err : lasterr); 335} 336 337static int 338traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp, 339 arc_buf_t *buf, uint64_t objset, uint64_t object) 340{ 341 int j, err = 0, lasterr = 0; --- 79 unchanged lines hidden (view full) --- 421 mutex_exit(&td_main->td_pfd->pd_mtx); 422} 423 424/* 425 * NB: dataset must not be changing on-disk (eg, is a snapshot or we are 426 * in syncing context). 427 */ 428static int |
356traverse_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *rootbp, 357 uint64_t txg_start, int flags, blkptr_cb_t func, void *arg) | 429traverse_impl(spa_t *spa, dsl_dataset_t *ds, uint64_t objset, blkptr_t *rootbp, 430 uint64_t txg_start, zbookmark_t *resume, int flags, 431 blkptr_cb_t func, void *arg) |
358{ 359 traverse_data_t td; 360 prefetch_data_t pd = { 0 }; 361 zbookmark_t czb; 362 int err; 363 | 432{ 433 traverse_data_t td; 434 prefetch_data_t pd = { 0 }; 435 zbookmark_t czb; 436 int err; 437 |
438 ASSERT(ds == NULL || objset == ds->ds_object); 439 ASSERT(!(flags & TRAVERSE_PRE) || !(flags & TRAVERSE_POST)); 440 |
|
364 td.td_spa = spa; | 441 td.td_spa = spa; |
365 td.td_objset = ds ? ds->ds_object : 0; | 442 td.td_objset = objset; |
366 td.td_rootbp = rootbp; 367 td.td_min_txg = txg_start; | 443 td.td_rootbp = rootbp; 444 td.td_min_txg = txg_start; |
445 td.td_resume = resume; |
|
368 td.td_func = func; 369 td.td_arg = arg; 370 td.td_pfd = &pd; 371 td.td_flags = flags; 372 373 pd.pd_blks_max = zfs_pd_blks_max; 374 pd.pd_flags = flags; 375 mutex_init(&pd.pd_mtx, NULL, MUTEX_DEFAULT, NULL); --- 35 unchanged lines hidden (view full) --- 411/* 412 * NB: dataset must not be changing on-disk (eg, is a snapshot or we are 413 * in syncing context). 414 */ 415int 416traverse_dataset(dsl_dataset_t *ds, uint64_t txg_start, int flags, 417 blkptr_cb_t func, void *arg) 418{ | 446 td.td_func = func; 447 td.td_arg = arg; 448 td.td_pfd = &pd; 449 td.td_flags = flags; 450 451 pd.pd_blks_max = zfs_pd_blks_max; 452 pd.pd_flags = flags; 453 mutex_init(&pd.pd_mtx, NULL, MUTEX_DEFAULT, NULL); --- 35 unchanged lines hidden (view full) --- 489/* 490 * NB: dataset must not be changing on-disk (eg, is a snapshot or we are 491 * in syncing context). 492 */ 493int 494traverse_dataset(dsl_dataset_t *ds, uint64_t txg_start, int flags, 495 blkptr_cb_t func, void *arg) 496{ |
419 return (traverse_impl(ds->ds_dir->dd_pool->dp_spa, ds, 420 &ds->ds_phys->ds_bp, txg_start, flags, func, arg)); | 497 return (traverse_impl(ds->ds_dir->dd_pool->dp_spa, ds, ds->ds_object, 498 &ds->ds_phys->ds_bp, txg_start, NULL, flags, func, arg)); |
421} 422 | 499} 500 |
501int 502traverse_dataset_destroyed(spa_t *spa, blkptr_t *blkptr, 503 uint64_t txg_start, zbookmark_t *resume, int flags, 504 blkptr_cb_t func, void *arg) 505{ 506 return (traverse_impl(spa, NULL, ZB_DESTROYED_OBJSET, 507 blkptr, txg_start, resume, flags, func, arg)); 508} 509 |
|
423/* 424 * NB: pool must not be changing on-disk (eg, from zdb or sync context). 425 */ 426int 427traverse_pool(spa_t *spa, uint64_t txg_start, int flags, 428 blkptr_cb_t func, void *arg) 429{ 430 int err, lasterr = 0; 431 uint64_t obj; 432 dsl_pool_t *dp = spa_get_dsl(spa); 433 objset_t *mos = dp->dp_meta_objset; 434 boolean_t hard = (flags & TRAVERSE_HARD); 435 436 /* visit the MOS */ | 510/* 511 * NB: pool must not be changing on-disk (eg, from zdb or sync context). 512 */ 513int 514traverse_pool(spa_t *spa, uint64_t txg_start, int flags, 515 blkptr_cb_t func, void *arg) 516{ 517 int err, lasterr = 0; 518 uint64_t obj; 519 dsl_pool_t *dp = spa_get_dsl(spa); 520 objset_t *mos = dp->dp_meta_objset; 521 boolean_t hard = (flags & TRAVERSE_HARD); 522 523 /* visit the MOS */ |
437 err = traverse_impl(spa, NULL, spa_get_rootblkptr(spa), 438 txg_start, flags, func, arg); | 524 err = traverse_impl(spa, NULL, 0, spa_get_rootblkptr(spa), 525 txg_start, NULL, flags, func, arg); |
439 if (err) 440 return (err); 441 442 /* visit each dataset */ 443 for (obj = 1; err == 0 || (err != ESRCH && hard); 444 err = dmu_object_next(mos, &obj, FALSE, txg_start)) { 445 dmu_object_info_t doi; 446 --- 36 unchanged lines hidden --- | 526 if (err) 527 return (err); 528 529 /* visit each dataset */ 530 for (obj = 1; err == 0 || (err != ESRCH && hard); 531 err = dmu_object_next(mos, &obj, FALSE, txg_start)) { 532 dmu_object_info_t doi; 533 --- 36 unchanged lines hidden --- |