| 
    FreeBSD ZFS 
   The Zettabyte File System 
   | 
 
#include <sys/dsl_scan.h>#include <sys/dsl_pool.h>#include <sys/dsl_dataset.h>#include <sys/dsl_prop.h>#include <sys/dsl_dir.h>#include <sys/dsl_synctask.h>#include <sys/dnode.h>#include <sys/dmu_tx.h>#include <sys/dmu_objset.h>#include <sys/arc.h>#include <sys/zap.h>#include <sys/zio.h>#include <sys/zfs_context.h>#include <sys/fs/zfs.h>#include <sys/zfs_znode.h>#include <sys/spa_impl.h>#include <sys/vdev_impl.h>#include <sys/zil_impl.h>#include <sys/zio_checksum.h>#include <sys/ddt.h>#include <sys/sa.h>#include <sys/sa_impl.h>#include <sys/zfeature.h>#include <sys/zfs_vfsops.h>
Go to the source code of this file.
Data Structures | |
| struct | zil_scan_arg | 
| struct | enqueue_clones_arg | 
Defines | |
| #define | DSL_SCAN_IS_SCRUB_RESILVER(scn) | 
Typedefs | |
| typedef int( | scan_cb_t )(dsl_pool_t *, const blkptr_t *, const zbookmark_t *) | 
| typedef struct zil_scan_arg | zil_scan_arg_t | 
Functions | |
| static void | dsl_scan_sync_state (dsl_scan_t *, dmu_tx_t *tx) | 
| SYSCTL_DECL (_vfs_zfs) | |
| TUNABLE_INT ("vfs.zfs.top_maxinflight",&zfs_top_maxinflight) | |
| SYSCTL_UINT (_vfs_zfs, OID_AUTO, top_maxinflight, CTLFLAG_RW,&zfs_top_maxinflight, 0,"Maximum I/Os per top-level vdev") | |
| TUNABLE_INT ("vfs.zfs.resilver_delay",&zfs_resilver_delay) | |
| SYSCTL_UINT (_vfs_zfs, OID_AUTO, resilver_delay, CTLFLAG_RW,&zfs_resilver_delay, 0,"Number of ticks to delay resilver") | |
| TUNABLE_INT ("vfs.zfs.scrub_delay",&zfs_scrub_delay) | |
| SYSCTL_UINT (_vfs_zfs, OID_AUTO, scrub_delay, CTLFLAG_RW,&zfs_scrub_delay, 0,"Number of ticks to delay scrub") | |
| TUNABLE_INT ("vfs.zfs.scan_idle",&zfs_scan_idle) | |
| SYSCTL_UINT (_vfs_zfs, OID_AUTO, scan_idle, CTLFLAG_RW,&zfs_scan_idle, 0,"Idle scan window in clock ticks") | |
| TUNABLE_INT ("vfs.zfs.scan_min_time_ms",&zfs_scan_min_time_ms) | |
| SYSCTL_UINT (_vfs_zfs, OID_AUTO, scan_min_time_ms, CTLFLAG_RW,&zfs_scan_min_time_ms, 0,"Min millisecs to scrub per txg") | |
| TUNABLE_INT ("vfs.zfs.free_min_time_ms",&zfs_free_min_time_ms) | |
| SYSCTL_UINT (_vfs_zfs, OID_AUTO, free_min_time_ms, CTLFLAG_RW,&zfs_free_min_time_ms, 0,"Min millisecs to free per txg") | |
| TUNABLE_INT ("vfs.zfs.resilver_min_time_ms",&zfs_resilver_min_time_ms) | |
| SYSCTL_UINT (_vfs_zfs, OID_AUTO, resilver_min_time_ms, CTLFLAG_RW,&zfs_resilver_min_time_ms, 0,"Min millisecs to resilver per txg") | |
| TUNABLE_INT ("vfs.zfs.no_scrub_io",&zfs_no_scrub_io) | |
| SYSCTL_INT (_vfs_zfs, OID_AUTO, no_scrub_io, CTLFLAG_RW,&zfs_no_scrub_io, 0,"Disable scrub I/O") | |
| TUNABLE_INT ("vfs.zfs.no_scrub_prefetch",&zfs_no_scrub_prefetch) | |
| SYSCTL_INT (_vfs_zfs, OID_AUTO, no_scrub_prefetch, CTLFLAG_RW,&zfs_no_scrub_prefetch, 0,"Disable scrub prefetching") | |
| int | dsl_scan_init (dsl_pool_t *dp, uint64_t txg) | 
| void | dsl_scan_fini (dsl_pool_t *dp) | 
| static int | dsl_scan_setup_check (void *arg1, void *arg2, dmu_tx_t *tx) | 
| static void | dsl_scan_setup_sync (void *arg1, void *arg2, dmu_tx_t *tx) | 
| static void | dsl_scan_done (dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx) | 
| static int | dsl_scan_cancel_check (void *arg1, void *arg2, dmu_tx_t *tx) | 
| static void | dsl_scan_cancel_sync (void *arg1, void *arg2, dmu_tx_t *tx) | 
| int | dsl_scan_cancel (dsl_pool_t *dp) | 
| static void | dsl_scan_visitbp (blkptr_t *bp, const zbookmark_t *zb, dnode_phys_t *dnp, arc_buf_t *pbuf, dsl_dataset_t *ds, dsl_scan_t *scn, dmu_objset_type_t ostype, dmu_tx_t *tx) | 
| static void | dsl_scan_visitdnode (dsl_scan_t *, dsl_dataset_t *ds, dmu_objset_type_t ostype, dnode_phys_t *dnp, arc_buf_t *buf, uint64_t object, dmu_tx_t *tx) | 
| void | dsl_free (dsl_pool_t *dp, uint64_t txg, const blkptr_t *bp) | 
| void | dsl_free_sync (zio_t *pio, dsl_pool_t *dp, uint64_t txg, const blkptr_t *bpp) | 
| int | dsl_read (zio_t *pio, spa_t *spa, const blkptr_t *bpp, arc_buf_t *pbuf, arc_done_func_t *done, void *private, int priority, int zio_flags, uint32_t *arc_flags, const zbookmark_t *zb) | 
| int | dsl_read_nolock (zio_t *pio, spa_t *spa, const blkptr_t *bpp, arc_done_func_t *done, void *private, int priority, int zio_flags, uint32_t *arc_flags, const zbookmark_t *zb) | 
| static uint64_t | dsl_scan_ds_maxtxg (dsl_dataset_t *ds) | 
| static boolean_t | dsl_scan_check_pause (dsl_scan_t *scn, const zbookmark_t *zb) | 
| static int | dsl_scan_zil_block (zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg) | 
| static int | dsl_scan_zil_record (zilog_t *zilog, lr_t *lrc, void *arg, uint64_t claim_txg) | 
| static void | dsl_scan_zil (dsl_pool_t *dp, zil_header_t *zh) | 
| static void | dsl_scan_prefetch (dsl_scan_t *scn, arc_buf_t *buf, blkptr_t *bp, uint64_t objset, uint64_t object, uint64_t blkid) | 
| static boolean_t | dsl_scan_check_resume (dsl_scan_t *scn, const dnode_phys_t *dnp, const zbookmark_t *zb) | 
| static int | dsl_scan_recurse (dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype, dnode_phys_t *dnp, const blkptr_t *bp, const zbookmark_t *zb, dmu_tx_t *tx, arc_buf_t **bufp) | 
| static void | dsl_scan_visit_rootbp (dsl_scan_t *scn, dsl_dataset_t *ds, blkptr_t *bp, dmu_tx_t *tx) | 
| void | dsl_scan_ds_destroyed (dsl_dataset_t *ds, dmu_tx_t *tx) | 
| void | dsl_scan_ds_snapshotted (dsl_dataset_t *ds, dmu_tx_t *tx) | 
| void | dsl_scan_ds_clone_swapped (dsl_dataset_t *ds1, dsl_dataset_t *ds2, dmu_tx_t *tx) | 
| static int | enqueue_clones_cb (spa_t *spa, uint64_t dsobj, const char *dsname, void *arg) | 
| static void | dsl_scan_visitds (dsl_scan_t *scn, uint64_t dsobj, dmu_tx_t *tx) | 
| static int | enqueue_cb (spa_t *spa, uint64_t dsobj, const char *dsname, void *arg) | 
| static void | dsl_scan_ddt (dsl_scan_t *scn, dmu_tx_t *tx) | 
| Scrub/dedup interaction.   | |
| void | dsl_scan_ddt_entry (dsl_scan_t *scn, enum zio_checksum checksum, ddt_entry_t *dde, dmu_tx_t *tx) | 
| static void | dsl_scan_visit (dsl_scan_t *scn, dmu_tx_t *tx) | 
| static boolean_t | dsl_scan_free_should_pause (dsl_scan_t *scn) | 
| static int | dsl_scan_free_block_cb (void *arg, const blkptr_t *bp, dmu_tx_t *tx) | 
| boolean_t | dsl_scan_active (dsl_scan_t *scn) | 
| void | dsl_scan_sync (dsl_pool_t *dp, dmu_tx_t *tx) | 
| void | dsl_resilver_restart (dsl_pool_t *dp, uint64_t txg) | 
| This will start a new scan, or restart an existing one.   | |
| boolean_t | dsl_scan_resilvering (dsl_pool_t *dp) | 
| static void | count_block (zfs_all_blkstats_t *zab, const blkptr_t *bp) | 
| static void | dsl_scan_scrub_done (zio_t *zio) | 
| static int | dsl_scan_scrub_cb (dsl_pool_t *dp, const blkptr_t *bp, const zbookmark_t *zb) | 
| int | dsl_scan (dsl_pool_t *dp, pool_scan_func_t func) | 
Variables | |
| static scan_cb_t | dsl_scan_defrag_cb | 
| static scan_cb_t | dsl_scan_scrub_cb | 
| static scan_cb_t | dsl_scan_remove_cb | 
| static dsl_syncfunc_t | dsl_scan_cancel_sync | 
| unsigned int | zfs_top_maxinflight = 32 | 
| maximum I/Os per top-level   | |
| unsigned int | zfs_resilver_delay = 2 | 
| number of ticks to delay resilver   | |
| unsigned int | zfs_scrub_delay = 4 | 
| number of ticks to delay scrub   | |
| unsigned int | zfs_scan_idle = 50 | 
| idle window in clock ticks   | |
| unsigned int | zfs_scan_min_time_ms = 1000 | 
| min millisecs to scrub per txg   | |
| unsigned int | zfs_free_min_time_ms = 1000 | 
| min millisecs to free per txg   | |
| unsigned int | zfs_resilver_min_time_ms = 3000 | 
| min millisecs to resilver per txg   | |
| boolean_t | zfs_no_scrub_io = B_FALSE | 
| set to disable scrub i/o   | |
| boolean_t | zfs_no_scrub_prefetch = B_FALSE | 
| set to disable scrub prefetching   | |
| enum ddt_class | zfs_scrub_ddt_class_max = DDT_CLASS_DUPLICATE | 
| int | zfs_txg_timeout | 
| max seconds worth of delta per txg   | |
| static scan_cb_t * | scan_funcs [POOL_SCAN_FUNCS] | 
| #define DSL_SCAN_IS_SCRUB_RESILVER | ( | scn | ) | 
((scn)->scn_phys.scn_func == POOL_SCAN_SCRUB || \
        (scn)->scn_phys.scn_func == POOL_SCAN_RESILVER)
Definition at line 109 of file dsl_scan.c.
| typedef int( scan_cb_t)(dsl_pool_t *, const blkptr_t *, const zbookmark_t *) | 
Definition at line 53 of file dsl_scan.c.
| typedef struct zil_scan_arg zil_scan_arg_t | 
| static void count_block | ( | zfs_all_blkstats_t * | zab, | 
| const blkptr_t * | bp | ||
| ) |  [static] | 
        
Definition at line 1603 of file dsl_scan.c.
| void dsl_free | ( | dsl_pool_t * | dp, | 
| uint64_t | txg, | ||
| const blkptr_t * | bp | ||
| ) | 
Definition at line 392 of file dsl_scan.c.
| void dsl_free_sync | ( | zio_t * | pio, | 
| dsl_pool_t * | dp, | ||
| uint64_t | txg, | ||
| const blkptr_t * | bpp | ||
| ) | 
Definition at line 398 of file dsl_scan.c.
| int dsl_read | ( | zio_t * | pio, | 
| spa_t * | spa, | ||
| const blkptr_t * | bpp, | ||
| arc_buf_t * | pbuf, | ||
| arc_done_func_t * | done, | ||
| void * | private, | ||
| int | priority, | ||
| int | zio_flags, | ||
| uint32_t * | arc_flags, | ||
| const zbookmark_t * | zb | ||
| ) | 
Definition at line 406 of file dsl_scan.c.
| int dsl_read_nolock | ( | zio_t * | pio, | 
| spa_t * | spa, | ||
| const blkptr_t * | bpp, | ||
| arc_done_func_t * | done, | ||
| void * | private, | ||
| int | priority, | ||
| int | zio_flags, | ||
| uint32_t * | arc_flags, | ||
| const zbookmark_t * | zb | ||
| ) | 
Definition at line 415 of file dsl_scan.c.
| void dsl_resilver_restart | ( | dsl_pool_t * | dp, | 
| uint64_t | txg | ||
| ) | 
This will start a new scan, or restart an existing one.
Definition at line 1575 of file dsl_scan.c.
| int dsl_scan | ( | dsl_pool_t * | dp, | 
| pool_scan_func_t | func | ||
| ) | 
Definition at line 1763 of file dsl_scan.c.
| boolean_t dsl_scan_active | ( | dsl_scan_t * | scn | ) | 
Definition at line 1406 of file dsl_scan.c.
| int dsl_scan_cancel | ( | dsl_pool_t * | dp | ) | 
Definition at line 373 of file dsl_scan.c.
| static int dsl_scan_cancel_check | ( | void * | arg1, | 
| void * | arg2, | ||
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 353 of file dsl_scan.c.
| static void dsl_scan_cancel_sync | ( | void * | arg1, | 
| void * | arg2, | ||
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 364 of file dsl_scan.c.
| static boolean_t dsl_scan_check_pause | ( | dsl_scan_t * | scn, | 
| const zbookmark_t * | zb | ||
| ) |  [static] | 
        
Definition at line 442 of file dsl_scan.c.
| static boolean_t dsl_scan_check_resume | ( | dsl_scan_t * | scn, | 
| const dnode_phys_t * | dnp, | ||
| const zbookmark_t * | zb | ||
| ) |  [static] | 
        
Definition at line 603 of file dsl_scan.c.
| static void dsl_scan_ddt | ( | dsl_scan_t * | scn, | 
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Scrub/dedup interaction.
If there are N references to a deduped block, we don't want to scrub it N times -- ideally, we should scrub it exactly once.
We leverage the fact that the dde's replication class (enum ddt_class) is ordered from highest replication class (DDT_CLASS_DITTO) to lowest (DDT_CLASS_UNIQUE) so that we may walk the DDT in that order.
To prevent excess scrubbing, the scrub begins by walking the DDT to find all blocks with refcnt > 1, and scrubs each of these once. Since there are two replication classes which contain blocks with refcnt > 1, we scrub the highest replication class (DDT_CLASS_DITTO) first. Finally the top-down scrub begins, only visiting blocks with refcnt == 1.
There would be nothing more to say if a block's refcnt couldn't change during a scrub, but of course it can so we must account for changes in a block's replication class.
Here's an example of what can occur:
If a block has refcnt > 1 during the DDT scrub phase, but has refcnt == 1 when visited during the top-down scrub phase, it will be scrubbed twice. This negates our scrub optimization, but is otherwise harmless.
If a block has refcnt == 1 during the DDT scrub phase, but has refcnt > 1 on each visit during the top-down scrub phase, it will never be scrubbed. To catch this, ddt_sync_entry() notifies the scrub code whenever a block's reference class transitions to a higher level (i.e DDT_CLASS_UNIQUE to DDT_CLASS_DUPLICATE); if it transitions from refcnt == 1 to refcnt > 1 while a scrub is in progress, it scrubs the block right then.
Definition at line 1224 of file dsl_scan.c.
| void dsl_scan_ddt_entry | ( | dsl_scan_t * | scn, | 
| enum zio_checksum | checksum, | ||
| ddt_entry_t * | dde, | ||
| dmu_tx_t * | tx | ||
| ) | 
Definition at line 1264 of file dsl_scan.c.
| static void dsl_scan_done | ( | dsl_scan_t * | scn, | 
| boolean_t | complete, | ||
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 273 of file dsl_scan.c.
| void dsl_scan_ds_clone_swapped | ( | dsl_dataset_t * | ds1, | 
| dsl_dataset_t * | ds2, | ||
| dmu_tx_t * | tx | ||
| ) | 
Definition at line 948 of file dsl_scan.c.
| void dsl_scan_ds_destroyed | ( | dsl_dataset_t * | ds, | 
| dmu_tx_t * | tx | ||
| ) | 
Definition at line 853 of file dsl_scan.c.
| static uint64_t dsl_scan_ds_maxtxg | ( | dsl_dataset_t * | ds | ) |  [static] | 
        
Definition at line 424 of file dsl_scan.c.
| void dsl_scan_ds_snapshotted | ( | dsl_dataset_t * | ds, | 
| dmu_tx_t * | tx | ||
| ) | 
Definition at line 914 of file dsl_scan.c.
| void dsl_scan_fini | ( | dsl_pool_t * | dp | ) | 
Definition at line 182 of file dsl_scan.c.
Definition at line 1386 of file dsl_scan.c.
| static boolean_t dsl_scan_free_should_pause | ( | dsl_scan_t * | scn | ) |  [static] | 
        
Definition at line 1374 of file dsl_scan.c.
| int dsl_scan_init | ( | dsl_pool_t * | dp, | 
| uint64_t | txg | ||
| ) | 
Definition at line 123 of file dsl_scan.c.
| static void dsl_scan_prefetch | ( | dsl_scan_t * | scn, | 
| arc_buf_t * | buf, | ||
| blkptr_t * | bp, | ||
| uint64_t | objset, | ||
| uint64_t | object, | ||
| uint64_t | blkid | ||
| ) |  [static] | 
        
Definition at line 578 of file dsl_scan.c.
| static int dsl_scan_recurse | ( | dsl_scan_t * | scn, | 
| dsl_dataset_t * | ds, | ||
| dmu_objset_type_t | ostype, | ||
| dnode_phys_t * | dnp, | ||
| const blkptr_t * | bp, | ||
| const zbookmark_t * | zb, | ||
| dmu_tx_t * | tx, | ||
| arc_buf_t ** | bufp | ||
| ) |  [static] | 
        
Definition at line 643 of file dsl_scan.c.
| boolean_t dsl_scan_resilvering | ( | dsl_pool_t * | dp | ) | 
Definition at line 1592 of file dsl_scan.c.
| static int dsl_scan_scrub_cb | ( | dsl_pool_t * | dp, | 
| const blkptr_t * | bp, | ||
| const zbookmark_t * | zb | ||
| ) |  [static] | 
        
Definition at line 1669 of file dsl_scan.c.
| static void dsl_scan_scrub_done | ( | zio_t * | zio | ) |  [static] | 
        
Definition at line 1651 of file dsl_scan.c.
| static int dsl_scan_setup_check | ( | void * | arg1, | 
| void * | arg2, | ||
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 192 of file dsl_scan.c.
| static void dsl_scan_setup_sync | ( | void * | arg1, | 
| void * | arg2, | ||
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 204 of file dsl_scan.c.
| void dsl_scan_sync | ( | dsl_pool_t * | dp, | 
| dmu_tx_t * | tx | ||
| ) | 
Definition at line 1431 of file dsl_scan.c.
| static void dsl_scan_sync_state | ( | dsl_scan_t * | scn, | 
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 433 of file dsl_scan.c.
| static void dsl_scan_visit | ( | dsl_scan_t * | scn, | 
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 1287 of file dsl_scan.c.
| static void dsl_scan_visit_rootbp | ( | dsl_scan_t * | scn, | 
| dsl_dataset_t * | ds, | ||
| blkptr_t * | bp, | ||
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 839 of file dsl_scan.c.
| static void dsl_scan_visitbp | ( | blkptr_t * | bp, | 
| const zbookmark_t * | zb, | ||
| dnode_phys_t * | dnp, | ||
| arc_buf_t * | pbuf, | ||
| dsl_dataset_t * | ds, | ||
| dsl_scan_t * | scn, | ||
| dmu_objset_type_t | ostype, | ||
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 778 of file dsl_scan.c.
| static void dsl_scan_visitdnode | ( | dsl_scan_t * | scn, | 
| dsl_dataset_t * | ds, | ||
| dmu_objset_type_t | ostype, | ||
| dnode_phys_t * | dnp, | ||
| arc_buf_t * | buf, | ||
| uint64_t | object, | ||
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 749 of file dsl_scan.c.
| static void dsl_scan_visitds | ( | dsl_scan_t * | scn, | 
| uint64_t | dsobj, | ||
| dmu_tx_t * | tx | ||
| ) |  [static] | 
        
Definition at line 1048 of file dsl_scan.c.
| static void dsl_scan_zil | ( | dsl_pool_t * | dp, | 
| zil_header_t * | zh | ||
| ) |  [static] | 
        
Definition at line 555 of file dsl_scan.c.
| static int dsl_scan_zil_block | ( | zilog_t * | zilog, | 
| blkptr_t * | bp, | ||
| void * | arg, | ||
| uint64_t | claim_txg | ||
| ) |  [static] | 
        
Definition at line 494 of file dsl_scan.c.
| static int dsl_scan_zil_record | ( | zilog_t * | zilog, | 
| lr_t * | lrc, | ||
| void * | arg, | ||
| uint64_t | claim_txg | ||
| ) |  [static] | 
        
Definition at line 523 of file dsl_scan.c.
| static int enqueue_cb | ( | spa_t * | spa, | 
| uint64_t | dsobj, | ||
| const char * | dsname, | ||
| void * | arg | ||
| ) |  [static] | 
        
Definition at line 1151 of file dsl_scan.c.
| static int enqueue_clones_cb | ( | spa_t * | spa, | 
| uint64_t | dsobj, | ||
| const char * | dsname, | ||
| void * | arg | ||
| ) |  [static] | 
        
Definition at line 1016 of file dsl_scan.c.
dsl_syncfunc_t dsl_scan_cancel_sync [static] | 
        
Definition at line 58 of file dsl_scan.c.
scan_cb_t dsl_scan_defrag_cb [static] | 
        
Definition at line 55 of file dsl_scan.c.
scan_cb_t dsl_scan_remove_cb [static] | 
        
Definition at line 57 of file dsl_scan.c.
scan_cb_t dsl_scan_scrub_cb [static] | 
        
Definition at line 56 of file dsl_scan.c.
scan_cb_t* scan_funcs[POOL_SCAN_FUNCS] [static] | 
        
 {
        NULL,
        dsl_scan_scrub_cb,      
        dsl_scan_scrub_cb,      
}
Definition at line 116 of file dsl_scan.c.
| enum ddt_class zfs_scrub_ddt_class_max = DDT_CLASS_DUPLICATE | 
Definition at line 107 of file dsl_scan.c.
 1.7.3