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
This commit is contained in:
parent
be59bc7ae9
commit
4e43c1e8b5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=282788
@ -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:
|
||||
|
@ -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, §sz)) {
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user