aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorNeel Natu <neel@FreeBSD.org>2015-05-12 00:30:39 +0000
committerNeel Natu <neel@FreeBSD.org>2015-05-12 00:30:39 +0000
commit4e43c1e8b54fc45800681d80ddc49307ed9050ad (patch)
tree53b54865dc8d1788f0264851cd78729930edf4cc /usr.sbin
parentbe59bc7ae9f905cd5cddca6136c398c714b1efd6 (diff)
Notes
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bhyve/bhyve.821
-rw-r--r--usr.sbin/bhyve/block_if.c74
2 files changed, 69 insertions, 26 deletions
diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8
index e3cf36b9e937..ee0f2caf001e 100644
--- a/usr.sbin/bhyve/bhyve.8
+++ b/usr.sbin/bhyve/bhyve.8
@@ -193,8 +193,13 @@ format.
.Pp
Block storage devices:
.Bl -tag -width 10n
-.It Pa /filename Ns Oo , Ns Li nocache Oc Ns Oo , Ns Li direct Oc Ns Oo , Ns Li ro Oc
-.It Pa /dev/xxx Ns Oo , Ns Ar nocache Oc Ns Oo , Ns Ar direct Oc Ns Oo , Ns Ar ro Oc
+.It Pa /filename Ns Oo , Ns Ar block-device-options Oc
+.It Pa /dev/xxx Ns Oo , Ns Ar block-device-options Oc
+.El
+.Pp
+The
+.Ar block-device-options
+are:
.Bl -tag -width 8n
.It Li nocache
Open the file with
@@ -204,14 +209,10 @@ Open the file using
.Dv O_SYNC .
.It Li ro
Force the file to be opened read-only.
-.El
-.Pp
-The
-.Li nocache ,
-.Li direct ,
-and
-.Li ro
-options are not available for virtio block devices.
+.It Li sectorsize= Ns Ar logical Ns Oo / Ns Ar physical Oc
+Specify the logical and physical sector sizes of the emulated disk.
+The physical sector size is optional and is equal to the logical sector size
+if not explicitly specified.
.El
.Pp
TTY devices:
diff --git a/usr.sbin/bhyve/block_if.c b/usr.sbin/bhyve/block_if.c
index bcb1617d4c09..ef8e11e2755e 100644
--- a/usr.sbin/bhyve/block_if.c
+++ b/usr.sbin/bhyve/block_if.c
@@ -392,16 +392,18 @@ blockif_open(const char *optstr, const char *ident)
{
char tname[MAXCOMLEN + 1];
char name[MAXPATHLEN];
- char *nopt, *xopts;
+ char *nopt, *xopts, *cp;
struct blockif_ctxt *bc;
struct stat sbuf;
struct diocgattr_arg arg;
off_t size, psectsz, psectoff;
int extra, fd, i, sectsz;
- int nocache, sync, ro, candelete, geom;
+ int nocache, sync, ro, candelete, geom, ssopt, pssopt;
pthread_once(&blockif_once, blockif_init);
+ fd = -1;
+ ssopt = 0;
nocache = 0;
sync = 0;
ro = 0;
@@ -410,16 +412,25 @@ blockif_open(const char *optstr, const char *ident)
* The first element in the optstring is always a pathname.
* Optional elements follow
*/
- nopt = strdup(optstr);
- for (xopts = strtok(nopt, ",");
- xopts != NULL;
- xopts = strtok(NULL, ",")) {
- if (!strcmp(xopts, "nocache"))
+ nopt = xopts = strdup(optstr);
+ while (xopts != NULL) {
+ cp = strsep(&xopts, ",");
+ if (cp == nopt) /* file or device pathname */
+ continue;
+ else if (!strcmp(cp, "nocache"))
nocache = 1;
- else if (!strcmp(xopts, "sync"))
+ else if (!strcmp(cp, "sync") || !strcmp(cp, "direct"))
sync = 1;
- else if (!strcmp(xopts, "ro"))
+ else if (!strcmp(cp, "ro"))
ro = 1;
+ else if (sscanf(cp, "sectorsize=%d/%d", &ssopt, &pssopt) == 2)
+ ;
+ else if (sscanf(cp, "sectorsize=%d", &ssopt) == 1)
+ pssopt = ssopt;
+ else {
+ fprintf(stderr, "Invalid device option \"%s\"\n", cp);
+ goto err;
+ }
}
extra = 0;
@@ -437,13 +448,12 @@ blockif_open(const char *optstr, const char *ident)
if (fd < 0) {
perror("Could not open backing file");
- return (NULL);
+ goto err;
}
if (fstat(fd, &sbuf) < 0) {
perror("Could not stat backing file");
- close(fd);
- return (NULL);
+ goto err;
}
/*
@@ -457,8 +467,7 @@ blockif_open(const char *optstr, const char *ident)
if (ioctl(fd, DIOCGMEDIASIZE, &size) < 0 ||
ioctl(fd, DIOCGSECTORSIZE, &sectsz)) {
perror("Could not fetch dev blk/sector size");
- close(fd);
- return (NULL);
+ goto err;
}
assert(size != 0);
assert(sectsz != 0);
@@ -473,10 +482,39 @@ blockif_open(const char *optstr, const char *ident)
} else
psectsz = sbuf.st_blksize;
+ if (ssopt != 0) {
+ if (!powerof2(ssopt) || !powerof2(pssopt) || ssopt < 512 ||
+ ssopt > pssopt) {
+ fprintf(stderr, "Invalid sector size %d/%d\n",
+ ssopt, pssopt);
+ goto err;
+ }
+
+ /*
+ * Some backend drivers (e.g. cd0, ada0) require that the I/O
+ * size be a multiple of the device's sector size.
+ *
+ * Validate that the emulated sector size complies with this
+ * requirement.
+ */
+ if (S_ISCHR(sbuf.st_mode)) {
+ if (ssopt < sectsz || (ssopt % sectsz) != 0) {
+ fprintf(stderr, "Sector size %d incompatible "
+ "with underlying device sector size %d\n",
+ ssopt, sectsz);
+ goto err;
+ }
+ }
+
+ sectsz = ssopt;
+ psectsz = pssopt;
+ psectoff = 0;
+ }
+
bc = calloc(1, sizeof(struct blockif_ctxt));
if (bc == NULL) {
- close(fd);
- return (NULL);
+ perror("calloc");
+ goto err;
}
bc->bc_magic = BLOCKIF_SIG;
@@ -506,6 +544,10 @@ blockif_open(const char *optstr, const char *ident)
}
return (bc);
+err:
+ if (fd >= 0)
+ close(fd);
+ return (NULL);
}
static int