aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/xen/blkfront/blkfront.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/xen/blkfront/blkfront.c')
-rw-r--r--sys/dev/xen/blkfront/blkfront.c51
1 files changed, 34 insertions, 17 deletions
diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c
index 2c5862232b41..6bb4e32f1328 100644
--- a/sys/dev/xen/blkfront/blkfront.c
+++ b/sys/dev/xen/blkfront/blkfront.c
@@ -158,7 +158,8 @@ xbd_free_command(struct xbd_command *cm)
static void
xbd_mksegarray(bus_dma_segment_t *segs, int nsegs,
grant_ref_t * gref_head, int otherend_id, int readonly,
- grant_ref_t * sg_ref, struct blkif_request_segment *sg)
+ grant_ref_t * sg_ref, struct blkif_request_segment *sg,
+ unsigned int sector_size)
{
struct blkif_request_segment *last_block_sg = sg + nsegs;
vm_paddr_t buffer_ma;
@@ -166,9 +167,9 @@ xbd_mksegarray(bus_dma_segment_t *segs, int nsegs,
int ref;
while (sg < last_block_sg) {
- KASSERT(segs->ds_addr % (1 << XBD_SECTOR_SHFT) == 0,
+ KASSERT((segs->ds_addr & (sector_size - 1)) == 0,
("XEN disk driver I/O must be sector aligned"));
- KASSERT(segs->ds_len % (1 << XBD_SECTOR_SHFT) == 0,
+ KASSERT((segs->ds_len & (sector_size - 1)) == 0,
("XEN disk driver I/Os must be a multiple of "
"the sector length"));
buffer_ma = segs->ds_addr;
@@ -241,7 +242,8 @@ xbd_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
xbd_mksegarray(segs, nsegs, &cm->cm_gref_head,
xenbus_get_otherend_id(sc->xbd_dev),
cm->cm_operation == BLKIF_OP_WRITE,
- cm->cm_sg_refs, ring_req->seg);
+ cm->cm_sg_refs, ring_req->seg,
+ sc->xbd_disk->d_sectorsize);
} else {
blkif_request_indirect_t *ring_req;
@@ -259,7 +261,8 @@ xbd_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
xbd_mksegarray(segs, nsegs, &cm->cm_gref_head,
xenbus_get_otherend_id(sc->xbd_dev),
cm->cm_operation == BLKIF_OP_WRITE,
- cm->cm_sg_refs, cm->cm_indirectionpages);
+ cm->cm_sg_refs, cm->cm_indirectionpages,
+ sc->xbd_disk->d_sectorsize);
memcpy(ring_req->indirect_grefs, &cm->cm_indirectionrefs,
sizeof(grant_ref_t) * sc->xbd_max_request_indirectpages);
}
@@ -359,7 +362,9 @@ xbd_bio_command(struct xbd_softc *sc)
}
cm->cm_bp = bp;
- cm->cm_sector_number = (blkif_sector_t)bp->bio_pblkno;
+ cm->cm_sector_number =
+ ((blkif_sector_t)bp->bio_pblkno * sc->xbd_disk->d_sectorsize) >>
+ XBD_SECTOR_SHFT;
switch (bp->bio_cmd) {
case BIO_READ:
@@ -631,7 +636,7 @@ xbd_dump(void *arg, void *virtual, off_t offset, size_t length)
cm->cm_data = virtual;
cm->cm_datalen = chunk;
cm->cm_operation = BLKIF_OP_WRITE;
- cm->cm_sector_number = offset / dp->d_sectorsize;
+ cm->cm_sector_number = offset >> XBD_SECTOR_SHFT;
cm->cm_complete = xbd_dump_complete;
xbd_enqueue_cm(cm, XBD_Q_READY);
@@ -1025,7 +1030,19 @@ xbd_instance_create(struct xbd_softc *sc, blkif_sector_t sectors,
sc->xbd_disk->d_stripesize = phys_sector_size;
sc->xbd_disk->d_stripeoffset = 0;
- sc->xbd_disk->d_mediasize = sectors * sector_size;
+ /*
+ * The 'sectors' xenbus node is always in units of 512b, regardless of
+ * the 'sector-size' xenbus node value.
+ */
+ sc->xbd_disk->d_mediasize = sectors << XBD_SECTOR_SHFT;
+ if ((sc->xbd_disk->d_mediasize % sc->xbd_disk->d_sectorsize) != 0) {
+ error = EINVAL;
+ xenbus_dev_fatal(sc->xbd_dev, error,
+ "Disk size (%ju) not a multiple of sector size (%ju)",
+ (uintmax_t)sc->xbd_disk->d_mediasize,
+ (uintmax_t)sc->xbd_disk->d_sectorsize);
+ return (error);
+ }
sc->xbd_disk->d_maxsize = sc->xbd_max_request_size;
sc->xbd_disk->d_flags = DISKFLAG_UNMAPPED_BIO;
if ((sc->xbd_flags & (XBDF_FLUSH|XBDF_BARRIER)) != 0) {
@@ -1064,9 +1081,7 @@ xbd_free(struct xbd_softc *sc)
gnttab_end_foreign_access_references(
sc->xbd_max_request_indirectpages,
&cm->cm_indirectionrefs[0]);
- contigfree(cm->cm_indirectionpages, PAGE_SIZE *
- sc->xbd_max_request_indirectpages,
- M_XENBLOCKFRONT);
+ free(cm->cm_indirectionpages, M_XENBLOCKFRONT);
cm->cm_indirectionpages = NULL;
}
@@ -1312,7 +1327,7 @@ xbd_connect(struct xbd_softc *sc)
/* Allocate datastructures based on negotiated values. */
err = bus_dma_tag_create(
bus_get_dma_tag(sc->xbd_dev), /* parent */
- 512, PAGE_SIZE, /* algnmnt, boundary */
+ sector_size, PAGE_SIZE, /* algnmnt, boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
@@ -1373,9 +1388,7 @@ xbd_connect(struct xbd_softc *sc)
break;
}
if (j < sc->xbd_max_request_indirectpages) {
- contigfree(indirectpages,
- PAGE_SIZE * sc->xbd_max_request_indirectpages,
- M_XENBLOCKFRONT);
+ free(indirectpages, M_XENBLOCKFRONT);
break;
}
cm->cm_indirectionpages = indirectpages;
@@ -1384,13 +1397,17 @@ xbd_connect(struct xbd_softc *sc)
if (sc->xbd_disk == NULL) {
device_printf(dev, "%juMB <%s> at %s",
- (uintmax_t) sectors / (1048576 / sector_size),
+ (uintmax_t)((sectors << XBD_SECTOR_SHFT) / 1048576),
device_get_desc(dev),
xenbus_get_node(dev));
bus_print_child_footer(device_get_parent(dev), dev);
- xbd_instance_create(sc, sectors, sc->xbd_vdevice, binfo,
+ err = xbd_instance_create(sc, sectors, sc->xbd_vdevice, binfo,
sector_size, phys_sector_size);
+ if (err != 0) {
+ xenbus_dev_fatal(dev, err, "Unable to create instance");
+ return;
+ }
}
(void)xenbus_set_state(dev, XenbusStateConnected);