FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_mirror.c
/*
 * Try to find a vdev whose DTL doesn't contain the block we want to read
 * prefering vdevs based on determined load.
 *
 * If we can't, try the read on any vdev we haven't already tried.
 */
Try to find a vdev whose DTL doesn't contain the block we want to read
prefering vdevs based on determined load.

If we can't, try the read on any vdev we haven't already tried.
Try to find a vdev whose DTL doesn ' t contain the block we want to read prefering vdevs based on determined load . If we can ' t try the read on any vdev we haven ' t already tried .
static int
vdev_mirror_child_select(zio_t *zio)
{
	mirror_map_t *mm = zio->io_vsd;
	uint64_t txg = zio->io_txg;
	int c, lowest_load;
	ASSERT(zio->io_bp == NULL || BP_PHYSICAL_BIRTH(zio->io_bp) == txg);
	lowest_load = INT_MAX;
	mm->mm_preferred_cnt = 0;
	for (c = 0; c < mm->mm_children; c++) {
		mirror_child_t *mc;
		mc = &mm->mm_child[c];
		if (mc->mc_tried || mc->mc_skipped)
			continue;
		if (!vdev_readable(mc->mc_vd)) {
			mc->mc_error = SET_ERROR(ENXIO);
			mc->mc_tried = 1;	
			mc->mc_skipped = 1;
			continue;
		}
		if (vdev_dtl_contains(mc->mc_vd, DTL_MISSING, txg, 1)) {
			mc->mc_error = SET_ERROR(ESTALE);
			mc->mc_skipped = 1;
			mc->mc_speculative = 1;
			continue;
		}
		mc->mc_load = vdev_mirror_load(mm, mc->mc_vd, mc->mc_offset);
		if (mc->mc_load > lowest_load)
			continue;
		if (mc->mc_load < lowest_load) {
			lowest_load = mc->mc_load;
			mm->mm_preferred_cnt = 0;
		}
		mm->mm_preferred[mm->mm_preferred_cnt] = c;
		mm->mm_preferred_cnt++;
	}
	if (mm->mm_preferred_cnt == 1) {
		vdev_queue_register_lastoffset(
		    mm->mm_child[mm->mm_preferred[0]].mc_vd, zio);
		return (mm->mm_preferred[0]);
	}
	if (mm->mm_preferred_cnt > 1) {
		int c = vdev_mirror_preferred_child_randomize(zio);
		vdev_queue_register_lastoffset(mm->mm_child[c].mc_vd, zio);
		return (c);
	}
	for (c = 0; c < mm->mm_children; c++) {
		if (!mm->mm_child[c].mc_tried) {
			vdev_queue_register_lastoffset(mm->mm_child[c].mc_vd,
			    zio);
			return (c);
		}
	}
	return (-1);
}
static int vdev_mirror_child_select ( zio_t * zio ) { mirror_map_t * mm = zio -> io_vsd ; uint64_t txg = zio -> io_txg ; int c , lowest_load ; ASSERT ( zio -> io_bp == NULL || BP_PHYSICAL_BIRTH ( zio -> io_bp ) == txg ) ; lowest_load = INT_MAX ; mm -> mm_preferred_cnt = 0 ; for ( c = 0 ; c < mm -> mm_children ; c ++ ) { mirror_child_t * mc ; mc = & mm -> mm_child [ c ] ; if ( mc -> mc_tried || mc -> mc_skipped ) continue ; if ( ! vdev_readable ( mc -> mc_vd ) ) { mc -> mc_error = SET_ERROR ( ENXIO ) ; mc -> mc_tried = 1 ; mc -> mc_skipped = 1 ; continue ; } if ( vdev_dtl_contains ( mc -> mc_vd , DTL_MISSING , txg , 1 ) ) { mc -> mc_error = SET_ERROR ( ESTALE ) ; mc -> mc_skipped = 1 ; mc -> mc_speculative = 1 ; continue ; } mc -> mc_load = vdev_mirror_load ( mm , mc -> mc_vd , mc -> mc_offset ) ; if ( mc -> mc_load > lowest_load ) continue ; if ( mc -> mc_load < lowest_load ) { lowest_load = mc -> mc_load ; mm -> mm_preferred_cnt = 0 ; } mm -> mm_preferred [ mm -> mm_preferred_cnt ] = c ; mm -> mm_preferred_cnt ++ ; } if ( mm -> mm_preferred_cnt == 1 ) { vdev_queue_register_lastoffset ( mm -> mm_child [ mm -> mm_preferred [ 0 ] ] . mc_vd , zio ) ; return ( mm -> mm_preferred [ 0 ] ) ; } if ( mm -> mm_preferred_cnt > 1 ) { int c = vdev_mirror_preferred_child_randomize ( zio ) ; vdev_queue_register_lastoffset ( mm -> mm_child [ c ] . mc_vd , zio ) ; return ( c ) ; } for ( c = 0 ; c < mm -> mm_children ; c ++ ) { if ( ! mm -> mm_child [ c ] . mc_tried ) { vdev_queue_register_lastoffset ( mm -> mm_child [ c ] . mc_vd , zio ) ; return ( c ) ; } } return ( -1 ) ; }
Try to find a vdev whose DTL doesn't contain the block we want to read
 prefering vdevs based on determined load.
Try to find a vdev whose DTL doesn ' t contain the block we want to read prefering vdevs based on determined load .
/* don't even try */ /*
	 * Every device is either missing or has this txg in its DTL.
	 * Look for any child we haven't already tried before giving up.
	 */ /*
	 * Every child failed.  There's no place left to look.
	 */