FreeBSD/sys/cam/ctl/ctl.c
/*
 * Serialize a command that went down the "wrong" side, and so was sent to
 * this controller for execution.  The logic is a little different than the
 * standard case in ctl_scsiio_precheck().  Errors in this case need to get
 * sent back to the other side, but in the success case, we execute the
 * command on this side (XFER mode) or tell the other side to execute it
 * (SER_ONLY mode).
 */
Serialize a command that went down the "wrong" side, and so was sent to
this controller for execution.  The logic is a little different than the
standard case in ctl_scsiio_precheck().  Errors in this case need to get
sent back to the other side, but in the success case, we execute the
command on this side (XFER mode) or tell the other side to execute it
(SER_ONLY mode).
Serialize a command that went down the " wrong " side and so was sent to this controller for execution . The logic is a little different than the standard case in ctl_scsiio_precheck () . Errors in this case need to get sent back to the other side but in the success case we execute the command on this side ( XFER mode ) or tell the other side to execute it ( SER_ONLY mode ) .
static int
ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio)
{
	struct ctl_softc *softc = control_softc;
	union ctl_ha_msg msg_info;
	struct ctl_port *port;
	struct ctl_lun *lun;
	const struct ctl_cmd_entry *entry;
	int retval = 0;
	uint32_t targ_lun;
	targ_lun = ctsio->io_hdr.nexus.targ_mapped_lun;
	mtx_lock(&softc->ctl_lock);
	port = ctl_io_port(&ctsio->io_hdr);
	if (port == NULL || (port->status & CTL_PORT_STATUS_ONLINE) == 0) {
		ctl_set_internal_failure(ctsio,  0,
					  1);
		goto badjuju;
	}
	if ((targ_lun < CTL_MAX_LUNS) &&
	    ((lun = softc->ctl_luns[targ_lun]) != NULL)) {
		mtx_lock(&lun->lun_lock);
		mtx_unlock(&softc->ctl_lock);
		if (lun->flags & CTL_LUN_DISABLED) {
			mtx_unlock(&lun->lun_lock);
			lun = NULL;
		}
	} else {
		mtx_unlock(&softc->ctl_lock);
		lun = NULL;
	}
	if (lun == NULL) {
		ctl_set_busy(ctsio);
		goto badjuju;
	}
	entry = ctl_get_cmd_entry(ctsio, NULL);
	if (ctl_scsiio_lun_check(lun, entry, ctsio) != 0) {
		mtx_unlock(&lun->lun_lock);
		goto badjuju;
	}
	ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr = lun;
	ctsio->io_hdr.ctl_private[CTL_PRIV_BACKEND_LUN].ptr = lun->be_lun;
#ifdef CTL_TIME_IO
	if (TAILQ_EMPTY(&lun->ooa_queue))
		lun->idle_time += getsbinuptime() - lun->last_busy;
#endif
	TAILQ_INSERT_TAIL(&lun->ooa_queue, &ctsio->io_hdr, ooa_links);
	switch (ctl_check_ooa(lun, (union ctl_io *)ctsio,
		(union ctl_io *)TAILQ_PREV(&ctsio->io_hdr, ctl_ooaq,
		 ooa_links))) {
	case CTL_ACTION_BLOCK:
		ctsio->io_hdr.flags |= CTL_FLAG_BLOCKED;
		TAILQ_INSERT_TAIL(&lun->blocked_queue, &ctsio->io_hdr,
				  blocked_links);
		mtx_unlock(&lun->lun_lock);
		break;
	case CTL_ACTION_PASS:
	case CTL_ACTION_SKIP:
		if (softc->ha_mode == CTL_HA_MODE_XFER) {
			ctsio->io_hdr.flags |= CTL_FLAG_IS_WAS_ON_RTR;
			ctl_enqueue_rtr((union ctl_io *)ctsio);
			mtx_unlock(&lun->lun_lock);
		} else {
			ctsio->io_hdr.flags &= ~CTL_FLAG_IO_ACTIVE;
			mtx_unlock(&lun->lun_lock);
			msg_info.hdr.original_sc = ctsio->io_hdr.original_sc;
			msg_info.hdr.serializing_sc = (union ctl_io *)ctsio;
			msg_info.hdr.msg_type = CTL_MSG_R2R;
			ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info,
			    sizeof(msg_info.hdr), M_WAITOK);
		}
		break;
	case CTL_ACTION_OVERLAP:
		TAILQ_REMOVE(&lun->ooa_queue, &ctsio->io_hdr, ooa_links);
		mtx_unlock(&lun->lun_lock);
		ctl_set_overlapped_cmd(ctsio);
		goto badjuju;
	case CTL_ACTION_OVERLAP_TAG:
		TAILQ_REMOVE(&lun->ooa_queue, &ctsio->io_hdr, ooa_links);
		mtx_unlock(&lun->lun_lock);
		ctl_set_overlapped_tag(ctsio, ctsio->tag_num);
		goto badjuju;
	case CTL_ACTION_ERROR:
	default:
		TAILQ_REMOVE(&lun->ooa_queue, &ctsio->io_hdr, ooa_links);
		mtx_unlock(&lun->lun_lock);
		ctl_set_internal_failure(ctsio,  0,
					  0);
badjuju:
		ctl_copy_sense_data_back((union ctl_io *)ctsio, &msg_info);
		msg_info.hdr.original_sc = ctsio->io_hdr.original_sc;
		msg_info.hdr.serializing_sc = NULL;
		msg_info.hdr.msg_type = CTL_MSG_BAD_JUJU;
		ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info,
		    sizeof(msg_info.scsi), M_WAITOK);
		retval = 1;
		break;
	}
	return (retval);
}
static int ctl_serialize_other_sc_cmd ( struct ctl_scsiio * ctsio ) { struct ctl_softc * softc = control_softc ; union ctl_ha_msg msg_info ; struct ctl_port * port ; struct ctl_lun * lun ; const struct ctl_cmd_entry * entry ; int retval = 0 ; uint32_t targ_lun ; targ_lun = ctsio -> io_hdr . nexus . targ_mapped_lun ; mtx_lock ( & softc -> ctl_lock ) ; port = ctl_io_port ( & ctsio -> io_hdr ) ; if ( port == NULL || ( port -> status & CTL_PORT_STATUS_ONLINE ) == 0 ) { ctl_set_internal_failure ( ctsio , 0 , 1 ) ; goto badjuju ; } if ( ( targ_lun < CTL_MAX_LUNS ) && ( ( lun = softc -> ctl_luns [ targ_lun ] ) != NULL ) ) { mtx_lock ( & lun -> lun_lock ) ; mtx_unlock ( & softc -> ctl_lock ) ; if ( lun -> flags & CTL_LUN_DISABLED ) { mtx_unlock ( & lun -> lun_lock ) ; lun = NULL ; } } else { mtx_unlock ( & softc -> ctl_lock ) ; lun = NULL ; } if ( lun == NULL ) { ctl_set_busy ( ctsio ) ; goto badjuju ; } entry = ctl_get_cmd_entry ( ctsio , NULL ) ; if ( ctl_scsiio_lun_check ( lun , entry , ctsio ) != 0 ) { mtx_unlock ( & lun -> lun_lock ) ; goto badjuju ; } ctsio -> io_hdr . ctl_private [ CTL_PRIV_LUN ] . ptr = lun ; ctsio -> io_hdr . ctl_private [ CTL_PRIV_BACKEND_LUN ] . ptr = lun -> be_lun ; #ifdef CTL_TIME_IO if ( TAILQ_EMPTY ( & lun -> ooa_queue ) ) lun -> idle_time += getsbinuptime ( ) - lun -> last_busy ; #endif TAILQ_INSERT_TAIL ( & lun -> ooa_queue , & ctsio -> io_hdr , ooa_links ) ; switch ( ctl_check_ooa ( lun , ( union ctl_io * ) ctsio , ( union ctl_io * ) TAILQ_PREV ( & ctsio -> io_hdr , ctl_ooaq , ooa_links ) ) ) { case CTL_ACTION_BLOCK : ctsio -> io_hdr . flags |= CTL_FLAG_BLOCKED ; TAILQ_INSERT_TAIL ( & lun -> blocked_queue , & ctsio -> io_hdr , blocked_links ) ; mtx_unlock ( & lun -> lun_lock ) ; break ; case CTL_ACTION_PASS : case CTL_ACTION_SKIP : if ( softc -> ha_mode == CTL_HA_MODE_XFER ) { ctsio -> io_hdr . flags |= CTL_FLAG_IS_WAS_ON_RTR ; ctl_enqueue_rtr ( ( union ctl_io * ) ctsio ) ; mtx_unlock ( & lun -> lun_lock ) ; } else { ctsio -> io_hdr . flags &= ~ CTL_FLAG_IO_ACTIVE ; mtx_unlock ( & lun -> lun_lock ) ; msg_info . hdr . original_sc = ctsio -> io_hdr . original_sc ; msg_info . hdr . serializing_sc = ( union ctl_io * ) ctsio ; msg_info . hdr . msg_type = CTL_MSG_R2R ; ctl_ha_msg_send ( CTL_HA_CHAN_CTL , & msg_info , sizeof ( msg_info . hdr ) , M_WAITOK ) ; } break ; case CTL_ACTION_OVERLAP : TAILQ_REMOVE ( & lun -> ooa_queue , & ctsio -> io_hdr , ooa_links ) ; mtx_unlock ( & lun -> lun_lock ) ; ctl_set_overlapped_cmd ( ctsio ) ; goto badjuju ; case CTL_ACTION_OVERLAP_TAG : TAILQ_REMOVE ( & lun -> ooa_queue , & ctsio -> io_hdr , ooa_links ) ; mtx_unlock ( & lun -> lun_lock ) ; ctl_set_overlapped_tag ( ctsio , ctsio -> tag_num ) ; goto badjuju ; case CTL_ACTION_ERROR : default : TAILQ_REMOVE ( & lun -> ooa_queue , & ctsio -> io_hdr , ooa_links ) ; mtx_unlock ( & lun -> lun_lock ) ; ctl_set_internal_failure ( ctsio , 0 , 0 ) ; badjuju : ctl_copy_sense_data_back ( ( union ctl_io * ) ctsio , & msg_info ) ; msg_info . hdr . original_sc = ctsio -> io_hdr . original_sc ; msg_info . hdr . serializing_sc = NULL ; msg_info . hdr . msg_type = CTL_MSG_BAD_JUJU ; ctl_ha_msg_send ( CTL_HA_CHAN_CTL , & msg_info , sizeof ( msg_info . scsi ) , M_WAITOK ) ; retval = 1 ; break ; } return ( retval ) ; }
Serialize a command that went down the "wrong" side, and so was sent to
 this controller for execution.
Serialize a command that went down the " wrong " side and so was sent to this controller for execution .
/* Make sure that we know about this port. */ /*sks_valid*/ /*retry_count*/ /* Make sure that we know about this LUN. */ /*
		 * If the LUN is invalid, pretend that it doesn't exist.
		 * It will go away as soon as all pending I/O has been
		 * completed.
		 */ /*
		 * The other node would not send this request to us unless
		 * received announce that we are primary node for this LUN.
		 * If this LUN does not exist now, it is probably result of
		 * a race, so respond to initiator in the most opaque way.
		 */ /*
	 * Every I/O goes into the OOA queue for a
	 * particular LUN, and stays there until completion.
	 */ /* send msg back to other side */ /*sks_valid*/ /*retry_count*/