Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 May 2015 00:30:39 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r282788 - head/usr.sbin/bhyve
Message-ID:  <201505120030.t4C0UdHR085904@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Tue May 12 00:30:39 2015
New Revision: 282788
URL: https://svnweb.freebsd.org/changeset/base/282788

Log:
  Allow configuration of the sector size advertised to the guest.
  
  The default behavior is to infer the logical and physical sector sizes from
  the block device backend. However older versions of Windows only work with
  specific logical/physical combinations:
  - Vista and Windows 7:	512/512
  - Windows 7 SP1:	512/512 or 512/4096
  
  For this reason allow the sector size to be specified using the following
  block device option: sectorsize=logical[/physical]
  
  Reported by:	Leon Dang (ldang@nahannisys.com)
  Reviewed by:	grehan
  MFC after:	2 weeks

Modified:
  head/usr.sbin/bhyve/bhyve.8
  head/usr.sbin/bhyve/block_if.c

Modified: head/usr.sbin/bhyve/bhyve.8
==============================================================================
--- head/usr.sbin/bhyve/bhyve.8	Tue May 12 00:27:52 2015	(r282787)
+++ head/usr.sbin/bhyve/bhyve.8	Tue May 12 00:30:39 2015	(r282788)
@@ -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:

Modified: head/usr.sbin/bhyve/block_if.c
==============================================================================
--- head/usr.sbin/bhyve/block_if.c	Tue May 12 00:27:52 2015	(r282787)
+++ head/usr.sbin/bhyve/block_if.c	Tue May 12 00:30:39 2015	(r282788)
@@ -392,16 +392,18 @@ blockif_open(const char *optstr, const c
 {
 	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 c
 	 * 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 c
 
 	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 c
 		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 c
 	} 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 c
 	}
 
 	return (bc);
+err:
+	if (fd >= 0)
+		close(fd);
+	return (NULL);
 }
 
 static int



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505120030.t4C0UdHR085904>