Ejemplo n.º 1
0
static boolean_t
dsl_scan_check_resume(dsl_scan_t *scn, const dnode_phys_t *dnp,
    const zbookmark_t *zb)
{
	/*
	 * We never skip over user/group accounting objects (obj<0)
	 */
	if (!ZB_IS_ZERO(&scn->scn_phys.scn_bookmark) &&
	    (int64_t)zb->zb_object >= 0) {
		/*
		 * If we already visited this bp & everything below (in
		 * a prior txg sync), don't bother doing it again.
		 */
		if (zbookmark_is_before(dnp, zb, &scn->scn_phys.scn_bookmark))
			return (B_TRUE);

		/*
		 * If we found the block we're trying to resume from, or
		 * we went past it to a different object, zero it out to
		 * indicate that it's OK to start checking for pausing
		 * again.
		 */
		if (bcmp(zb, &scn->scn_phys.scn_bookmark, sizeof (*zb)) == 0 ||
		    zb->zb_object > scn->scn_phys.scn_bookmark.zb_object) {
			dprintf("resuming at %llx/%llx/%llx/%llx\n",
			    (longlong_t)zb->zb_objset,
			    (longlong_t)zb->zb_object,
			    (longlong_t)zb->zb_level,
			    (longlong_t)zb->zb_blkid);
			bzero(&scn->scn_phys.scn_bookmark, sizeof (*zb));
		}
	}
	return (B_FALSE);
}
Ejemplo n.º 2
0
/*
 * Returns RESUME_SKIP_ALL if td indicates that we are resuming a traversal and
 * the block indicated by zb does not need to be visited at all. Returns
 * RESUME_SKIP_CHILDREN if we are resuming a post traversal and we reach the
 * resume point. This indicates that this block should be visited but not its
 * children (since they must have been visited in a previous traversal).
 * Otherwise returns RESUME_SKIP_NONE.
 */
static resume_skip_t
resume_skip_check(traverse_data_t *td, const dnode_phys_t *dnp,
    const zbookmark_t *zb)
{
	if (td->td_resume != NULL && !ZB_IS_ZERO(td->td_resume)) {
		/*
		 * If we already visited this bp & everything below,
		 * don't bother doing it again.
		 */
		if (zbookmark_is_before(dnp, zb, td->td_resume))
			return (RESUME_SKIP_ALL);

		/*
		 * If we found the block we're trying to resume from, zero
		 * the bookmark out to indicate that we have resumed.
		 */
		ASSERT3U(zb->zb_object, <=, td->td_resume->zb_object);
		if (bcmp(zb, td->td_resume, sizeof (*zb)) == 0) {
			bzero(td->td_resume, sizeof (*zb));
			if (td->td_flags & TRAVERSE_POST)
				return (RESUME_SKIP_CHILDREN);
		}
	}
	return (RESUME_SKIP_NONE);
}
Ejemplo n.º 3
0
static boolean_t
dsl_scan_check_pause(dsl_scan_t *scn, const zbookmark_t *zb)
{
	uint64_t elapsed_nanosecs;
	int mintime;

	/* we never skip user/group accounting objects */
	if (zb && (int64_t)zb->zb_object < 0)
		return (B_FALSE);

	if (scn->scn_pausing)
		return (B_TRUE); /* we're already pausing */

	if (!ZB_IS_ZERO(&scn->scn_phys.scn_bookmark))
		return (B_FALSE); /* we're resuming */

	/* We only know how to resume from level-0 blocks. */
	if (zb && zb->zb_level != 0)
		return (B_FALSE);

	mintime = (scn->scn_phys.scn_func == POOL_SCAN_RESILVER) ?
	    zfs_resilver_min_time_ms : zfs_scan_min_time_ms;
	elapsed_nanosecs = gethrtime() - scn->scn_sync_start_time;
	if (elapsed_nanosecs / NANOSEC > zfs_txg_timeout ||
	    (NSEC2MSEC(elapsed_nanosecs) > mintime &&
	    txg_sync_waiting(scn->scn_dp)) ||
	    spa_shutting_down(scn->scn_dp->dp_spa)) {
		if (zb) {
			dprintf("pausing at bookmark %llx/%llx/%llx/%llx\n",
			    (longlong_t)zb->zb_objset,
			    (longlong_t)zb->zb_object,
			    (longlong_t)zb->zb_level,
			    (longlong_t)zb->zb_blkid);
			scn->scn_phys.scn_bookmark = *zb;
		}
		dprintf("pausing at DDT bookmark %llx/%llx/%llx/%llx\n",
		    (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_class,
		    (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_type,
		    (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_checksum,
		    (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_cursor);
		scn->scn_pausing = B_TRUE;
		return (B_TRUE);
	}
	return (B_FALSE);
}
Ejemplo n.º 4
0
static void
traverse_prefetch_metadata(traverse_data_t *td,
    const blkptr_t *bp, const zbookmark_t *zb)
{
	uint32_t flags = ARC_NOWAIT | ARC_PREFETCH;

	if (!(td->td_flags & TRAVERSE_PREFETCH_METADATA))
		return;
	/*
	 * If we are in the process of resuming, don't prefetch, because
	 * some children will not be needed (and in fact may have already
	 * been freed).
	 */
	if (td->td_resume != NULL && !ZB_IS_ZERO(td->td_resume))
		return;
	if (BP_IS_HOLE(bp) || bp->blk_birth <= td->td_min_txg)
		return;
	if (BP_GET_LEVEL(bp) == 0 && BP_GET_TYPE(bp) != DMU_OT_DNODE)
		return;

	(void) arc_read(NULL, td->td_spa, bp, NULL, NULL,
	    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
}