summaryrefslogtreecommitdiffstats
path: root/sbin/camcontrol
diff options
context:
space:
mode:
authortruckman <truckman@FreeBSD.org>2016-07-06 17:42:09 +0000
committertruckman <truckman@FreeBSD.org>2016-07-06 17:42:09 +0000
commit15fb55aa670314e87deb319e02abdf4bcbac078b (patch)
treee5a053590127ee21f62d5aa6351638cd94471089 /sbin/camcontrol
parent3f7fb5e22f97fffdae5ca551fbca392a7e6eccf7 (diff)
downloadFreeBSD-src-15fb55aa670314e87deb319e02abdf4bcbac078b.zip
FreeBSD-src-15fb55aa670314e87deb319e02abdf4bcbac078b.tar.gz
MFC r299371 (by trasz)
Add "camcontrol reprobe" subcommand, and implement it for da(4). This makes it possible to manually force updating capacity data after the disk got resized. Without it it might be neccessary to reboot before FreeBSD notices updated disk size under eg VMWare. Differential Revision: https://reviews.freebsd.org/D6108
Diffstat (limited to 'sbin/camcontrol')
-rw-r--r--sbin/camcontrol/camcontrol.817
-rw-r--r--sbin/camcontrol/camcontrol.c47
2 files changed, 62 insertions, 2 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);
OpenPOWER on IntegriCloud