Use the new xpt_rescan function to truly now have dynamic

attachment of new devices that arrive (and we notice them
via async Fibre Channel events). We've always had the
right thing (of sorts) happen when devices go away- this
is the corollary function that makes multipath failover
actually work.

MFC after:	2 weeks
This commit is contained in:
Matt Jacob 2007-02-23 05:51:57 +00:00
parent 9e6461a2d8
commit ffcf6651a0
3 changed files with 76 additions and 13 deletions

View File

@ -2129,21 +2129,44 @@ isp_watchdog(void *arg)
#if __FreeBSD_version >= 500000
#define isp_make_here(isp, tgt) isp_announce(isp, tgt, AC_FOUND_DEVICE)
#define isp_make_gone(isp, tgt) isp_announce(isp, tgt, AC_LOST_DEVICE)
/*
* Support function for Announcement
* Support functions for Found/Lost
*/
static void
isp_announce(ispsoftc_t *isp, int tgt, int action)
isp_make_here(ispsoftc_t *isp, int tgt)
{
struct cam_path *tmppath;
union ccb *ccb;
ISPLOCK_2_CAMLOCK(mpt);
/*
* Allocate a CCB, create a wildcard path for this bus,
* and schedule a rescan.
*/
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) {
isp_prt(isp, ISP_LOGWARN, "unable to alloc CCB for rescan");
CAMLOCK_2_ISPLOCK(mpt);
return;
}
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
cam_sim_path(isp->isp_sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
CAMLOCK_2_ISPLOCK(mpt);
isp_prt(isp, ISP_LOGWARN, "unable to create path for rescan");
xpt_free_ccb(ccb);
return;
}
xpt_rescan(ccb);
CAMLOCK_2_ISPLOCK(mpt);
}
static void
isp_make_gone(ispsoftc_t *isp, int tgt)
{
struct cam_path *tp;
ISPLOCK_2_CAMLOCK(isp);
if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim), tgt,
if (xpt_create_path(&tp, NULL, cam_sim_path(isp->isp_sim), tgt,
CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
xpt_async(action, tmppath, NULL);
xpt_free_path(tmppath);
xpt_async(AC_LOST_DEVICE, tp, NULL);
xpt_free_path(tp);
}
CAMLOCK_2_ISPLOCK(isp);
}
@ -3651,9 +3674,9 @@ isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
}
if (isp->isp_osinfo.mboxcmd_done == 0) {
isp_prt(isp, ISP_LOGWARN,
"%s Mailbox Command (0x%x) Timeout",
"%s Mailbox Command (0x%x) Timeout (%uus)",
isp->isp_osinfo.mbox_sleep_ok? "Interrupting" : "Polled",
isp->isp_lastmbxcmd);
isp->isp_lastmbxcmd, usecs);
mbp->param[0] = MBOX_TIMEOUT;
isp->isp_osinfo.mboxcmd_done = 1;
}

View File

@ -2083,13 +2083,44 @@ mpt_cam_event(struct mpt_softc *mpt, request_t *req,
break;
case MPI_EVENT_RESCAN:
{
union ccb *ccb;
uint32_t pathid;
/*
* In general this means a device has been added to the loop.
*/
mpt_prt(mpt, "Rescan Port: %d\n", (data0 >> 8) & 0xff);
/* xpt_async(AC_FOUND_DEVICE, path, NULL); */
break;
if (mpt->ready == 0) {
break;
}
if (mpt->phydisk_sim) {
pathid = cam_sim_path(mpt->phydisk_sim);;
} else {
pathid = cam_sim_path(mpt->sim);
}
MPTLOCK_2_CAMLOCK(mpt);
/*
* Allocate a CCB, create a wildcard path for this bus,
* and schedule a rescan.
*/
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) {
mpt_prt(mpt, "unable to alloc CCB for rescan\n");
CAMLOCK_2_MPTLOCK(mpt);
break;
}
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, pathid,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
CAMLOCK_2_MPTLOCK(mpt);
mpt_prt(mpt, "unable to create path for rescan\n");
xpt_free_ccb(ccb);
break;
}
xpt_rescan(ccb);
CAMLOCK_2_MPTLOCK(mpt);
break;
}
case MPI_EVENT_LINK_STATUS_CHANGE:
mpt_prt(mpt, "Port %d: LinkState: %s\n",
(data1 >> 8) & 0xff,
@ -2909,6 +2940,13 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
mpt_set_ccb_status(ccb, CAM_REQ_INVALID);
break;
}
#ifdef MPT_TEST_MULTIPATH
if (mpt->failure_id == ccb->ccb_h.target_id) {
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
mpt_set_ccb_status(ccb, CAM_SEL_TIMEOUT);
break;
}
#endif
ccb->csio.scsi_status = SCSI_STATUS_OK;
mpt_start(sim, ccb);
return;

View File

@ -101,6 +101,8 @@
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt.h>
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_debug.h>
#include <cam/scsi/scsi_all.h>