FreeBSD/sys/cam/ctl/ctl.c
/*
 * This routine (with one exception) checks LUN flags that can be set by
 * commands ahead of us in the OOA queue.  These flags have to be checked
 * when a command initially comes in, and when we pull a command off the
 * blocked queue and are preparing to execute it.  The reason we have to
 * check these flags for commands on the blocked queue is that the LUN
 * state may have been changed by a command ahead of us while we're on the
 * blocked queue.
 *
 * Ordering is somewhat important with these checks, so please pay
 * careful attention to the placement of any new checks.
 */
This routine (with one exception) checks LUN flags that can be set by
commands ahead of us in the OOA queue.  These flags have to be checked
when a command initially comes in, and when we pull a command off the
blocked queue and are preparing to execute it.  The reason we have to
check these flags for commands on the blocked queue is that the LUN
state may have been changed by a command ahead of us while we're on the
blocked queue.

Ordering is somewhat important with these checks, so please pay
careful attention to the placement of any new checks.
This routine ( with one exception ) checks LUN flags that can be set by commands ahead of us in the OOA queue . These flags have to be checked when a command initially comes in and when we pull a command off the blocked queue and are preparing to execute it . The reason we have to check these flags for commands on the blocked queue is that the LUN state may have been changed by a command ahead of us while we ' re on the blocked queue . Ordering is somewhat important with these checks so please pay careful attention to the placement of any new checks .
static int
ctl_scsiio_lun_check(struct ctl_lun *lun,
    const struct ctl_cmd_entry *entry, struct ctl_scsiio *ctsio)
{
	struct ctl_softc *softc = lun->ctl_softc;
	int retval;
	uint32_t residx;
	retval = 0;
	mtx_assert(&lun->lun_lock, MA_OWNED);
	if ((lun->flags & CTL_LUN_PRIMARY_SC) == 0) {
		if (softc->ha_link == CTL_HA_LINK_OFFLINE &&
		    (entry->flags & CTL_CMD_FLAG_OK_ON_UNAVAIL) == 0) {
			ctl_set_lun_unavail(ctsio);
			retval = 1;
			goto bailout;
		}
		if ((lun->flags & CTL_LUN_PEER_SC_PRIMARY) == 0 &&
		    (entry->flags & CTL_CMD_FLAG_OK_ON_UNAVAIL) == 0) {
			ctl_set_lun_transit(ctsio);
			retval = 1;
			goto bailout;
		}
		if (softc->ha_mode == CTL_HA_MODE_ACT_STBY &&
		    (entry->flags & CTL_CMD_FLAG_OK_ON_STANDBY) == 0) {
			ctl_set_lun_standby(ctsio);
			retval = 1;
			goto bailout;
		}
		if (softc->ha_mode == CTL_HA_MODE_XFER)
			goto bailout;
	}
	if (entry->pattern & CTL_LUN_PAT_WRITE) {
		if (lun->be_lun &&
		    lun->be_lun->flags & CTL_LUN_FLAG_READONLY) {
			ctl_set_hw_write_protected(ctsio);
			retval = 1;
			goto bailout;
		}
		if ((lun->mode_pages.control_page[CTL_PAGE_CURRENT]
		    .eca_and_aen & SCP_SWP) != 0) {
			ctl_set_sense(ctsio,  1,
			     SSD_KEY_DATA_PROTECT,
			     0x27,  0x02, SSD_ELEM_NONE);
			retval = 1;
			goto bailout;
		}
	}
	residx = ctl_get_initindex(&ctsio->io_hdr.nexus);
	if ((lun->flags & CTL_LUN_RESERVED)
	 && ((entry->flags & CTL_CMD_FLAG_ALLOW_ON_RESV) == 0)) {
		if (lun->res_idx != residx) {
			ctl_set_reservation_conflict(ctsio);
			retval = 1;
			goto bailout;
		}
	}
	if ((lun->flags & CTL_LUN_PR_RESERVED) == 0 ||
	    (entry->flags & CTL_CMD_FLAG_ALLOW_ON_PR_RESV)) {
		;
	} else if ((entry->flags & CTL_CMD_FLAG_ALLOW_ON_PR_WRESV) &&
	    (lun->pr_res_type == SPR_TYPE_WR_EX ||
	     lun->pr_res_type == SPR_TYPE_WR_EX_RO ||
	     lun->pr_res_type == SPR_TYPE_WR_EX_AR)) {
		;
	} else {
		if (ctl_get_prkey(lun, residx) == 0 ||
		    (residx != lun->pr_res_idx && lun->pr_res_type < 4)) {
			ctl_set_reservation_conflict(ctsio);
			retval = 1;
			goto bailout;
		}
	}
	if ((entry->flags & CTL_CMD_FLAG_OK_ON_NO_MEDIA) == 0) {
		if (lun->flags & CTL_LUN_EJECTED)
			ctl_set_lun_ejected(ctsio);
		else if (lun->flags & CTL_LUN_NO_MEDIA) {
			if (lun->flags & CTL_LUN_REMOVABLE)
				ctl_set_lun_no_media(ctsio);
			else
				ctl_set_lun_int_reqd(ctsio);
		} else if (lun->flags & CTL_LUN_STOPPED)
			ctl_set_lun_stopped(ctsio);
		else
			goto bailout;
		retval = 1;
		goto bailout;
	}
bailout:
	return (retval);
}
static int ctl_scsiio_lun_check ( struct ctl_lun * lun , const struct ctl_cmd_entry * entry , struct ctl_scsiio * ctsio ) { struct ctl_softc * softc = lun -> ctl_softc ; int retval ; uint32_t residx ; retval = 0 ; mtx_assert ( & lun -> lun_lock , MA_OWNED ) ; if ( ( lun -> flags & CTL_LUN_PRIMARY_SC ) == 0 ) { if ( softc -> ha_link == CTL_HA_LINK_OFFLINE && ( entry -> flags & CTL_CMD_FLAG_OK_ON_UNAVAIL ) == 0 ) { ctl_set_lun_unavail ( ctsio ) ; retval = 1 ; goto bailout ; } if ( ( lun -> flags & CTL_LUN_PEER_SC_PRIMARY ) == 0 && ( entry -> flags & CTL_CMD_FLAG_OK_ON_UNAVAIL ) == 0 ) { ctl_set_lun_transit ( ctsio ) ; retval = 1 ; goto bailout ; } if ( softc -> ha_mode == CTL_HA_MODE_ACT_STBY && ( entry -> flags & CTL_CMD_FLAG_OK_ON_STANDBY ) == 0 ) { ctl_set_lun_standby ( ctsio ) ; retval = 1 ; goto bailout ; } if ( softc -> ha_mode == CTL_HA_MODE_XFER ) goto bailout ; } if ( entry -> pattern & CTL_LUN_PAT_WRITE ) { if ( lun -> be_lun && lun -> be_lun -> flags & CTL_LUN_FLAG_READONLY ) { ctl_set_hw_write_protected ( ctsio ) ; retval = 1 ; goto bailout ; } if ( ( lun -> mode_pages . control_page [ CTL_PAGE_CURRENT ] . eca_and_aen & SCP_SWP ) != 0 ) { ctl_set_sense ( ctsio , 1 , SSD_KEY_DATA_PROTECT , 0x27 , 0x02 , SSD_ELEM_NONE ) ; retval = 1 ; goto bailout ; } } residx = ctl_get_initindex ( & ctsio -> io_hdr . nexus ) ; if ( ( lun -> flags & CTL_LUN_RESERVED ) && ( ( entry -> flags & CTL_CMD_FLAG_ALLOW_ON_RESV ) == 0 ) ) { if ( lun -> res_idx != residx ) { ctl_set_reservation_conflict ( ctsio ) ; retval = 1 ; goto bailout ; } } if ( ( lun -> flags & CTL_LUN_PR_RESERVED ) == 0 || ( entry -> flags & CTL_CMD_FLAG_ALLOW_ON_PR_RESV ) ) { ; } else if ( ( entry -> flags & CTL_CMD_FLAG_ALLOW_ON_PR_WRESV ) && ( lun -> pr_res_type == SPR_TYPE_WR_EX || lun -> pr_res_type == SPR_TYPE_WR_EX_RO || lun -> pr_res_type == SPR_TYPE_WR_EX_AR ) ) { ; } else { if ( ctl_get_prkey ( lun , residx ) == 0 || ( residx != lun -> pr_res_idx && lun -> pr_res_type < 4 ) ) { ctl_set_reservation_conflict ( ctsio ) ; retval = 1 ; goto bailout ; } } if ( ( entry -> flags & CTL_CMD_FLAG_OK_ON_NO_MEDIA ) == 0 ) { if ( lun -> flags & CTL_LUN_EJECTED ) ctl_set_lun_ejected ( ctsio ) ; else if ( lun -> flags & CTL_LUN_NO_MEDIA ) { if ( lun -> flags & CTL_LUN_REMOVABLE ) ctl_set_lun_no_media ( ctsio ) ; else ctl_set_lun_int_reqd ( ctsio ) ; } else if ( lun -> flags & CTL_LUN_STOPPED ) ctl_set_lun_stopped ( ctsio ) ; else goto bailout ; retval = 1 ; goto bailout ; } bailout : return ( retval ) ; }
This routine (with one exception) checks LUN flags that can be set by
 commands ahead of us in the OOA queue.
This routine ( with one exception ) checks LUN flags that can be set by commands ahead of us in the OOA queue .
/*
	 * If this shelf is a secondary shelf controller, we may have to
	 * reject some commands disallowed by HA mode and link state.
	 */ /* The rest of checks are only done on executing side */ /*current_error*/ /*sense_key*/ /*asc*/ /*ascq*/ /*
	 * Check for a reservation conflict.  If this command isn't allowed
	 * even on reserved LUNs, and if this initiator isn't the one who
	 * reserved us, reject the command with a reservation conflict.
	 */ /* No reservation or command is allowed. */ /* The command is allowed for Write Exclusive resv. */ /*
		 * if we aren't registered or it's a res holder type
		 * reservation and this isn't the res holder then set a
		 * conflict.
		 */