summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/camcontrol/camcontrol.817
-rw-r--r--sbin/camcontrol/camcontrol.c47
-rw-r--r--sys/cam/cam_ccb.h2
-rw-r--r--sys/cam/cam_xpt.c5
-rw-r--r--sys/cam/scsi/scsi_da.c9
5 files changed, 76 insertions, 4 deletions
diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8
index 1a6c686..40a821a 100644
--- a/sbin/camcontrol/camcontrol.8
+++ b/sbin/camcontrol/camcontrol.8
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 6, 2015
+.Dd April 26, 2016
.Dt CAMCONTROL 8
.Os
.Sh NAME
@@ -98,6 +98,9 @@
.Op device id
.Op generic args
.Nm
+.Ic reprobe
+.Op device id
+.Nm
.Ic rescan
.Aq all | bus Ns Op :target:lun
.Nm
@@ -518,6 +521,12 @@ are not specified).
Print out the last logical block or the size of the device only, and omit
the blocksize.
.El
+.Pp
+Note that this command only displays the information, it does not update
+the kernel data structures.
+Use the
+.Nm
+reprobe subcommand to do that.
.It Ic start
Send the SCSI Start/Stop Unit (0x1B) command to the given device with the
start bit set.
@@ -539,6 +548,12 @@ The user
may specify a scan of all busses, a single bus, or a lun.
Scanning all luns
on a target is not supported.
+.It Ic reprobe
+Tell the kernel to refresh the information about the device and
+notify the upper layer,
+.Xr GEOM 4 .
+This includes sending the SCSI READ CAPACITY command and updating
+the disk size visible to the rest of the system.
.It Ic reset
Tell the kernel to reset all busses in the system (with the
.Ar all
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index 4383506..91d849f 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -100,7 +100,8 @@ typedef enum {
CAM_CMD_APM = 0x00000021,
CAM_CMD_AAM = 0x00000022,
CAM_CMD_ATTRIB = 0x00000023,
- CAM_CMD_OPCODES = 0x00000024
+ CAM_CMD_OPCODES = 0x00000024,
+ CAM_CMD_REPROBE = 0x00000025
} cam_cmdmask;
typedef enum {
@@ -190,6 +191,7 @@ static struct camcontrol_opts option_table[] = {
{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
{"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
{"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
+ {"reprobe", CAM_CMD_REPROBE, CAM_ARG_NONE, NULL},
#endif /* MINIMALISTIC */
{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
@@ -328,6 +330,7 @@ static int scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
static int scsiopcodes(struct cam_device *device, int argc, char **argv,
char *combinedopt, int retry_count, int timeout,
int verbose);
+static int scsireprobe(struct cam_device *device);
#endif /* MINIMALISTIC */
#ifndef min
@@ -8662,6 +8665,42 @@ bailout:
#endif /* MINIMALISTIC */
+static int
+scsireprobe(struct cam_device *device)
+{
+ union ccb *ccb;
+ int retval = 0;
+
+ ccb = cam_getccb(device);
+
+ if (ccb == NULL) {
+ warnx("%s: error allocating ccb", __func__);
+ return (1);
+ }
+
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
+
+ ccb->ccb_h.func_code = XPT_REPROBE_LUN;
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ warn("error sending XPT_REPROBE_LUN CCB");
+ retval = 1;
+ goto bailout;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
+ retval = 1;
+ goto bailout;
+ }
+
+bailout:
+ cam_freeccb(ccb);
+
+ return (retval);
+}
+
void
usage(int printlong)
{
@@ -8681,6 +8720,7 @@ usage(int printlong)
" camcontrol stop [dev_id][generic args]\n"
" camcontrol load [dev_id][generic args]\n"
" camcontrol eject [dev_id][generic args]\n"
+" camcontrol reprobe [dev_id][generic args]\n"
#endif /* MINIMALISTIC */
" camcontrol rescan <all | bus[:target:lun]>\n"
" camcontrol reset <all | bus[:target:lun]>\n"
@@ -8753,6 +8793,7 @@ usage(int printlong)
"stop send a Stop Unit command to the device\n"
"load send a Start Unit command to the device with the load bit set\n"
"eject send a Stop Unit command to the device with the eject bit set\n"
+"reprobe update capacity information of the given device\n"
"rescan rescan all busses, the given bus, or bus:target:lun\n"
"reset reset all busses, the given bus, or bus:target:lun\n"
"defects read the defect list of the specified device\n"
@@ -9298,6 +9339,10 @@ main(int argc, char **argv)
error = scsiopcodes(cam_dev, argc, argv, combinedopt,
retry_count, timeout, arglist & CAM_ARG_VERBOSE);
break;
+ case CAM_CMD_REPROBE:
+ error = scsireprobe(cam_dev);
+ break;
+
#endif /* MINIMALISTIC */
case CAM_CMD_USAGE:
usage(1);
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 12d3803..c350526 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -230,6 +230,8 @@ typedef enum {
/* Notify Host Target driver of event */
XPT_NOTIFY_ACKNOWLEDGE = 0x37 | XPT_FC_QUEUED | XPT_FC_USER_CCB,
/* Acknowledgement of event */
+ XPT_REPROBE_LUN = 0x38 | XPT_FC_QUEUED | XPT_FC_USER_CCB,
+ /* Query device capacity and notify GEOM */
/* Vendor Unique codes: 0x80->0x8F */
XPT_VUNIQUE = 0x80
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 39ff577..f174671 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -2991,6 +2991,11 @@ call_sim:
xpt_freeze_devq(path, 1);
start_ccb->ccb_h.status = CAM_REQ_CMP;
break;
+ case XPT_REPROBE_LUN:
+ xpt_async(AC_INQ_CHANGED, path, NULL);
+ start_ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(start_ccb);
+ break;
default:
case XPT_SDEV_TYPE:
case XPT_TERM_IO:
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 5393721..44057d5 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -1758,6 +1758,11 @@ daasync(void *callback_arg, u_int32_t code,
ccbh->ccb_state |= DA_CCB_RETRY_UA;
break;
}
+ case AC_INQ_CHANGED:
+ softc = (struct da_softc *)periph->softc;
+ softc->flags &= ~DA_FLAG_PROBED;
+ dareprobe(periph);
+ break;
default:
break;
}
@@ -2239,8 +2244,8 @@ daregister(struct cam_periph *periph, void *arg)
* would be to not attach the device on failure.
*/
xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
- AC_ADVINFO_CHANGED | AC_SCSI_AEN | AC_UNIT_ATTENTION,
- daasync, periph, periph->path);
+ AC_ADVINFO_CHANGED | AC_SCSI_AEN | AC_UNIT_ATTENTION |
+ AC_INQ_CHANGED, daasync, periph, periph->path);
/*
* Emit an attribute changed notification just in case
OpenPOWER on IntegriCloud