Fix Bus Device Resets from userland, and specifically from camcontrol.
camcontrol was setup to use the old scheme of going through the xpt(4) device, which never worked properly (and has been disabled for a while). camcontrol now sends BDRs through the pass(4) device, and XPT_RESET_DEV CCBs are put on the device queue in the transport layer, as they should be. Submitted by: luoqi Reviewed by: ken
This commit is contained in:
parent
27490905ca
commit
10e1cf639d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=52703
@ -1029,6 +1029,7 @@ static int
|
||||
scanlun_or_reset_dev(int bus, int target, int lun, int scan)
|
||||
{
|
||||
union ccb ccb;
|
||||
struct cam_device *device;
|
||||
int fd;
|
||||
|
||||
if (bus < 0) {
|
||||
@ -1046,31 +1047,60 @@ scanlun_or_reset_dev(int bus, int target, int lun, int scan)
|
||||
return(1);
|
||||
}
|
||||
|
||||
if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
|
||||
warnx("error opening tranport layer device %s\n",
|
||||
XPT_DEVICE);
|
||||
warn("%s", XPT_DEVICE);
|
||||
return(1);
|
||||
fd = -1;
|
||||
|
||||
bzero(&ccb, sizeof(union ccb));
|
||||
|
||||
if (scan) {
|
||||
if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
|
||||
warnx("error opening tranport layer device %s\n",
|
||||
XPT_DEVICE);
|
||||
warn("%s", XPT_DEVICE);
|
||||
return(1);
|
||||
}
|
||||
} else {
|
||||
device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
|
||||
if (device == NULL) {
|
||||
warnx("%s", cam_errbuf);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
|
||||
ccb.ccb_h.path_id = bus;
|
||||
ccb.ccb_h.target_id = target;
|
||||
ccb.ccb_h.target_lun = lun;
|
||||
ccb.ccb_h.timeout = 5000;
|
||||
ccb.crcn.flags = CAM_FLAG_NONE;
|
||||
|
||||
/* run this at a low priority */
|
||||
ccb.ccb_h.pinfo.priority = 5;
|
||||
|
||||
if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
|
||||
warn("CAMIOCOMMAND ioctl failed");
|
||||
close(fd);
|
||||
return(1);
|
||||
if (scan) {
|
||||
if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
|
||||
warn("CAMIOCOMMAND ioctl failed");
|
||||
close(fd);
|
||||
return(1);
|
||||
}
|
||||
} else {
|
||||
if (cam_send_ccb(device, &ccb) < 0) {
|
||||
warn("error sending XPT_RESET_DEV CCB");
|
||||
cam_close_device(device);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
if (scan)
|
||||
close(fd);
|
||||
else
|
||||
cam_close_device(device);
|
||||
|
||||
if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
||||
/*
|
||||
* An error code of CAM_BDR_SENT is normal for a BDR request.
|
||||
*/
|
||||
if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
|
||||
|| ((!scan)
|
||||
&& ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
|
||||
fprintf(stdout, "%s of %d:%d:%d was successful\n",
|
||||
scan? "Re-scan" : "Reset", bus, target, lun);
|
||||
return(0);
|
||||
|
@ -2764,6 +2764,7 @@ xpt_action(union ccb *start_ccb)
|
||||
start_ccb->csio.sense_resid = 0;
|
||||
start_ccb->csio.resid = 0;
|
||||
/* FALLTHROUGH */
|
||||
case XPT_RESET_DEV:
|
||||
case XPT_ENG_EXEC:
|
||||
{
|
||||
struct cam_path *path;
|
||||
@ -2874,7 +2875,6 @@ xpt_action(union ccb *start_ccb)
|
||||
*/
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
case XPT_RESET_DEV:
|
||||
case XPT_ACCEPT_TARGET_IO:
|
||||
case XPT_EN_LUN:
|
||||
case XPT_IMMED_NOTIFY:
|
||||
|
Loading…
Reference in New Issue
Block a user