diff options
Diffstat (limited to 'usr/src/uts/common/xen/io/xdf.c')
| -rw-r--r-- | usr/src/uts/common/xen/io/xdf.c | 93 |
1 files changed, 70 insertions, 23 deletions
diff --git a/usr/src/uts/common/xen/io/xdf.c b/usr/src/uts/common/xen/io/xdf.c index 109421797d..ef50b2bec7 100644 --- a/usr/src/uts/common/xen/io/xdf.c +++ b/usr/src/uts/common/xen/io/xdf.c @@ -478,7 +478,6 @@ vreq_setup(xdf_t *vdp, v_req_t *vreq) if (!ALIGNED_XFER(bp)) { if (bp->b_flags & (B_PAGEIO | B_PHYS)) bp_mapin(bp); - rc = ddi_dma_mem_alloc(vreq->v_memdmahdl, roundup(bp->b_bcount, XB_BSIZE), &xc_acc_attr, DDI_DMA_STREAMING, xdf_dmacallback, (caddr_t)vdp, @@ -1638,11 +1637,13 @@ xdf_get_flush_block(xdf_t *vdp) /* * Get a DEV_BSIZE aligned bufer */ - vdp->xdf_flush_mem = kmem_alloc(DEV_BSIZE * 2, KM_SLEEP); + vdp->xdf_flush_mem = kmem_alloc(vdp->xdf_xdev_secsize * 2, KM_SLEEP); vdp->xdf_cache_flush_block = - (char *)P2ROUNDUP((uintptr_t)(vdp->xdf_flush_mem), DEV_BSIZE); + (char *)P2ROUNDUP((uintptr_t)(vdp->xdf_flush_mem), + (int)vdp->xdf_xdev_secsize); + if (xdf_lb_rdwr(vdp->xdf_dip, TG_READ, vdp->xdf_cache_flush_block, - xdf_flush_block, DEV_BSIZE, NULL) != 0) + xdf_flush_block, vdp->xdf_xdev_secsize, NULL) != 0) return (DDI_FAILURE); return (DDI_SUCCESS); } @@ -1746,7 +1747,7 @@ xdf_synthetic_pgeom(dev_info_t *dip, cmlb_geom_t *geomp) geomp->g_acyl = 0; geomp->g_nhead = XDF_NHEADS; geomp->g_nsect = XDF_NSECTS; - geomp->g_secsize = XB_BSIZE; + geomp->g_secsize = vdp->xdf_xdev_secsize; geomp->g_capacity = vdp->xdf_xdev_nblocks; geomp->g_intrlv = 0; geomp->g_rpm = 7200; @@ -1764,6 +1765,7 @@ xdf_setstate_connected(xdf_t *vdp) dev_info_t *dip = vdp->xdf_dip; cmlb_geom_t pgeom; diskaddr_t nblocks = 0; + uint_t secsize = 0; char *oename, *xsname, *str; uint_t dinfo; @@ -1793,6 +1795,7 @@ xdf_setstate_connected(xdf_t *vdp) */ if (xenbus_gather(XBT_NULL, oename, XBP_SECTORS, "%"SCNu64, &nblocks, + XBP_SECTOR_SIZE, "%u", &secsize, XBP_INFO, "%u", &dinfo, NULL) != 0) { cmn_err(CE_WARN, "xdf@%s: xdf_setstate_connected: " @@ -1808,7 +1811,10 @@ xdf_setstate_connected(xdf_t *vdp) dinfo |= VDISK_CDROM; strfree(str); + if (secsize == 0 || !(ISP2(secsize / DEV_BSIZE))) + secsize = DEV_BSIZE; vdp->xdf_xdev_nblocks = nblocks; + vdp->xdf_xdev_secsize = secsize; #ifdef _ILP32 if (vdp->xdf_xdev_nblocks > DK_MAX_BLOCKS) { cmn_err(CE_WARN, "xdf@%s: xdf_setstate_connected: " @@ -2373,6 +2379,14 @@ xdf_lb_getattribute(dev_info_t *dip, tg_attribute_t *tgattributep) int xdf_lb_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie) { + int instance; + xdf_t *vdp; + + instance = ddi_get_instance(dip); + + if ((vdp = ddi_get_soft_state(xdf_ssp, instance)) == NULL) + return (ENXIO); + switch (cmd) { case TG_GETPHYGEOM: return (xdf_lb_getpgeom(dip, (cmlb_geom_t *)arg)); @@ -2381,7 +2395,9 @@ xdf_lb_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie) case TG_GETCAPACITY: return (xdf_lb_getcap(dip, (diskaddr_t *)arg)); case TG_GETBLOCKSIZE: - *(uint32_t *)arg = XB_BSIZE; + mutex_enter(&vdp->xdf_cb_lk); + *(uint32_t *)arg = vdp->xdf_xdev_secsize; + mutex_exit(&vdp->xdf_cb_lk); return (0); case TG_GETATTR: return (xdf_lb_getattribute(dip, (tg_attribute_t *)arg)); @@ -2404,7 +2420,8 @@ xdf_lb_rdwr(dev_info_t *dip, uchar_t cmd, void *bufp, /* We don't allow IO from the oe_change callback thread */ ASSERT(curthread != vdp->xdf_oe_change_thread); - if ((start + (reqlen >> DEV_BSHIFT)) > vdp->xdf_pgeom.g_capacity) + if ((start + ((reqlen / (vdp->xdf_xdev_secsize / DEV_BSIZE)) + >> DEV_BSHIFT)) > vdp->xdf_pgeom.g_capacity) return (EINVAL); bp = getrbuf(KM_SLEEP); @@ -2412,9 +2429,10 @@ xdf_lb_rdwr(dev_info_t *dip, uchar_t cmd, void *bufp, bp->b_flags = B_BUSY | B_READ; else bp->b_flags = B_BUSY | B_WRITE; + bp->b_un.b_addr = bufp; bp->b_bcount = reqlen; - bp->b_blkno = start; + bp->b_blkno = start * (vdp->xdf_xdev_secsize / DEV_BSIZE); bp->b_edev = DDI_DEV_T_NONE; /* don't have dev_t */ mutex_enter(&vdp->xdf_dev_lk); @@ -2582,7 +2600,7 @@ xdf_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, case DKIOCGMEDIAINFO: { struct dk_minfo media_info; - media_info.dki_lbsize = DEV_BSIZE; + media_info.dki_lbsize = vdp->xdf_xdev_secsize; media_info.dki_capacity = vdp->xdf_pgeom.g_capacity; if (XD_IS_CD(vdp)) media_info.dki_media_type = DK_CDROM; @@ -2664,7 +2682,7 @@ xdf_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, !xdf_barrier_flush_disable) { rv = xdf_lb_rdwr(vdp->xdf_dip, TG_WRITE, vdp->xdf_cache_flush_block, xdf_flush_block, - DEV_BSIZE, (void *)dev); + vdp->xdf_xdev_secsize, (void *)dev); } else { return (ENOTTY); } @@ -2686,6 +2704,7 @@ xdf_strategy(struct buf *bp) xdf_t *vdp; minor_t minor; diskaddr_t p_blkct, p_blkst; + daddr_t blkno; ulong_t nblks; int part; @@ -2726,16 +2745,24 @@ xdf_strategy(struct buf *bp) mutex_enter(&vdp->xdf_dev_lk); } + /* + * Adjust the real blkno and bcount according to the underline + * physical sector size. + */ + blkno = bp->b_blkno / (vdp->xdf_xdev_secsize / XB_BSIZE); + /* check for a starting block beyond the disk or partition limit */ - if (bp->b_blkno > p_blkct) { + if (blkno > p_blkct) { DPRINTF(IO_DBG, ("xdf@%s: block %lld exceeds VBD size %"PRIu64, - vdp->xdf_addr, (longlong_t)bp->b_blkno, (uint64_t)p_blkct)); + vdp->xdf_addr, (longlong_t)blkno, (uint64_t)p_blkct)); + mutex_exit(&vdp->xdf_dev_lk); xdf_io_err(bp, EINVAL, 0); return (0); } /* Legacy: don't set error flag at this case */ - if (bp->b_blkno == p_blkct) { + if (blkno == p_blkct) { + mutex_exit(&vdp->xdf_dev_lk); bp->b_resid = bp->b_bcount; biodone(bp); return (0); @@ -2747,14 +2774,29 @@ xdf_strategy(struct buf *bp) bp->av_back = bp->av_forw = NULL; /* Adjust for partial transfer, this will result in an error later */ - nblks = bp->b_bcount >> XB_BSHIFT; - if ((bp->b_blkno + nblks) > p_blkct) { - bp->b_resid = ((bp->b_blkno + nblks) - p_blkct) << XB_BSHIFT; + if (vdp->xdf_xdev_secsize != 0 && + vdp->xdf_xdev_secsize != XB_BSIZE) { + nblks = bp->b_bcount / vdp->xdf_xdev_secsize; + } else { + nblks = bp->b_bcount >> XB_BSHIFT; + } + + if ((blkno + nblks) > p_blkct) { + if (vdp->xdf_xdev_secsize != 0 && + vdp->xdf_xdev_secsize != XB_BSIZE) { + bp->b_resid = + ((blkno + nblks) - p_blkct) * + vdp->xdf_xdev_secsize; + } else { + bp->b_resid = + ((blkno + nblks) - p_blkct) << + XB_BSHIFT; + } bp->b_bcount -= bp->b_resid; } DPRINTF(IO_DBG, ("xdf@%s: strategy blk %lld len %lu\n", - vdp->xdf_addr, (longlong_t)bp->b_blkno, (ulong_t)bp->b_bcount)); + vdp->xdf_addr, (longlong_t)blkno, (ulong_t)bp->b_bcount)); /* Fix up the buf struct */ bp->b_flags |= B_BUSY; @@ -2792,6 +2834,9 @@ xdf_read(dev_t dev, struct uio *uiop, cred_t *credp) NULL, NULL, NULL, NULL)) return (ENXIO); + if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) + return (ENOSPC); + if (U_INVAL(uiop)) return (EINVAL); @@ -2822,7 +2867,7 @@ xdf_write(dev_t dev, struct uio *uiop, cred_t *credp) NULL, NULL, NULL, NULL)) return (ENXIO); - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt)) + if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) return (ENOSPC); if (U_INVAL(uiop)) @@ -2853,7 +2898,7 @@ xdf_aread(dev_t dev, struct aio_req *aiop, cred_t *credp) NULL, NULL, NULL, NULL)) return (ENXIO); - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt)) + if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) return (ENOSPC); if (U_INVAL(uiop)) @@ -2884,7 +2929,7 @@ xdf_awrite(dev_t dev, struct aio_req *aiop, cred_t *credp) NULL, NULL, NULL, NULL)) return (ENXIO); - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt)) + if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) return (ENOSPC); if (U_INVAL(uiop)) @@ -2921,9 +2966,11 @@ xdf_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) NULL, NULL, NULL)) return (ENXIO); - if ((blkno + nblk) > p_blkcnt) { + if ((blkno + nblk) > + (p_blkcnt * (vdp->xdf_xdev_secsize / XB_BSIZE))) { cmn_err(CE_WARN, "xdf@%s: block %ld exceeds VBD size %"PRIu64, - vdp->xdf_addr, blkno + nblk, (uint64_t)p_blkcnt); + vdp->xdf_addr, (daddr_t)((blkno + nblk) / + (vdp->xdf_xdev_secsize / XB_BSIZE)), (uint64_t)p_blkcnt); return (EINVAL); } @@ -3451,7 +3498,7 @@ xdf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) mutex_destroy(&vdp->xdf_cb_lk); mutex_destroy(&vdp->xdf_dev_lk); if (vdp->xdf_cache_flush_block != NULL) - kmem_free(vdp->xdf_flush_mem, 2 * DEV_BSIZE); + kmem_free(vdp->xdf_flush_mem, 2 * vdp->xdf_xdev_secsize); ddi_soft_state_free(xdf_ssp, instance); return (DDI_SUCCESS); } |
