Report logical/physical sector sizes for virtual SATA disk.

MFC after:	2 weeks
This commit is contained in:
Alexander Motin 2015-03-05 12:21:12 +00:00
parent 297c4868dd
commit 94682383d9
3 changed files with 36 additions and 3 deletions

View File

@ -83,6 +83,8 @@ struct blockif_ctxt {
int bc_rdonly;
off_t bc_size;
int bc_sectsz;
int bc_psectsz;
int bc_psectoff;
pthread_t bc_btid;
pthread_mutex_t bc_mtx;
pthread_cond_t bc_cond;
@ -268,7 +270,7 @@ blockif_open(const char *optstr, const char *ident)
char *nopt, *xopts;
struct blockif_ctxt *bc;
struct stat sbuf;
off_t size;
off_t size, psectsz, psectoff;
int extra, fd, i, sectsz;
int nocache, sync, ro;
@ -323,6 +325,7 @@ blockif_open(const char *optstr, const char *ident)
*/
size = sbuf.st_size;
sectsz = DEV_BSIZE;
psectsz = psectoff = 0;
if (S_ISCHR(sbuf.st_mode)) {
if (ioctl(fd, DIOCGMEDIASIZE, &size) < 0 ||
ioctl(fd, DIOCGSECTORSIZE, &sectsz)) {
@ -332,7 +335,10 @@ blockif_open(const char *optstr, const char *ident)
}
assert(size != 0);
assert(sectsz != 0);
}
if (ioctl(fd, DIOCGSTRIPESIZE, &psectsz) == 0 && psectsz > 0)
ioctl(fd, DIOCGSTRIPEOFFSET, &psectoff);
} else
psectsz = sbuf.st_blksize;
bc = calloc(1, sizeof(struct blockif_ctxt));
if (bc == NULL) {
@ -345,6 +351,8 @@ blockif_open(const char *optstr, const char *ident)
bc->bc_rdonly = ro;
bc->bc_size = size;
bc->bc_sectsz = sectsz;
bc->bc_psectsz = psectsz;
bc->bc_psectoff = psectoff;
pthread_mutex_init(&bc->bc_mtx, NULL);
pthread_cond_init(&bc->bc_cond, NULL);
TAILQ_INIT(&bc->bc_freeq);
@ -595,6 +603,15 @@ blockif_sectsz(struct blockif_ctxt *bc)
return (bc->bc_sectsz);
}
void
blockif_psectsz(struct blockif_ctxt *bc, int *size, int *off)
{
assert(bc->bc_magic == BLOCKIF_SIG);
*size = bc->bc_psectsz;
*off = bc->bc_psectoff;
}
int
blockif_queuesz(struct blockif_ctxt *bc)
{

View File

@ -55,6 +55,7 @@ off_t blockif_size(struct blockif_ctxt *bc);
void blockif_chs(struct blockif_ctxt *bc, uint16_t *c, uint8_t *h,
uint8_t *s);
int blockif_sectsz(struct blockif_ctxt *bc);
void blockif_psectsz(struct blockif_ctxt *bc, int *size, int *off);
int blockif_queuesz(struct blockif_ctxt *bc);
int blockif_is_ro(struct blockif_ctxt *bc);
int blockif_read(struct blockif_ctxt *bc, struct blockif_req *breq);

View File

@ -684,11 +684,14 @@ handle_identify(struct ahci_port *p, int slot, uint8_t *cfis)
} else {
uint16_t buf[256];
uint64_t sectors;
int sectsz, psectsz, psectoff;
uint16_t cyl;
uint8_t sech, heads;
sectors = blockif_size(p->bctx) / blockif_sectsz(p->bctx);
sectsz = blockif_sectsz(p->bctx);
sectors = blockif_size(p->bctx) / sectsz;
blockif_chs(p->bctx, &cyl, &heads, &sech);
blockif_psectsz(p->bctx, &psectsz, &psectoff);
memset(buf, 0, sizeof(buf));
buf[0] = 0x0040;
buf[1] = cyl;
@ -733,6 +736,18 @@ handle_identify(struct ahci_port *p, int slot, uint8_t *cfis)
buf[101] = (sectors >> 16);
buf[102] = (sectors >> 32);
buf[103] = (sectors >> 48);
buf[106] = 0x4000;
buf[209] = 0x4000;
if (psectsz > sectsz) {
buf[106] |= 0x2000;
buf[106] |= ffsl(psectsz / sectsz) - 1;
buf[209] |= (psectoff / sectsz);
}
if (sectsz > 512) {
buf[106] |= 0x1000;
buf[117] = sectsz / 2;
buf[118] = ((sectsz / 2) >> 16);
}
ahci_write_fis_piosetup(p);
write_prdt(p, slot, cfis, (void *)buf, sizeof(buf));
p->tfd = ATA_S_DSC | ATA_S_READY;