Print this page
7367 blkdev: support block size larger than 512
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>

*** 21,30 **** --- 21,31 ---- /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved. * Copyright 2012 Alexey Zaytsev <alexey.zaytsev@gmail.com> All rights reserved. * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 The MathWorks, Inc. All rights reserved. */ #include <sys/types.h> #include <sys/ksynch.h> #include <sys/kmem.h>
*** 751,761 **** ASSERT(bp); xi->i_bp = bp; xi->i_func = func; ! xi->i_blkno = bp->b_lblkno; if (bp->b_bcount == 0) { xi->i_len = 0; xi->i_nblks = 0; xi->i_kaddr = NULL; --- 752,762 ---- ASSERT(bp); xi->i_bp = bp; xi->i_func = func; ! xi->i_blkno = bp->b_lblkno >> (bd->d_blkshift - DEV_BSHIFT); if (bp->b_bcount == 0) { xi->i_len = 0; xi->i_nblks = 0; xi->i_kaddr = NULL;
*** 781,791 **** xi->i_offset = 0; xi->i_num_win = (bp->b_bcount + (bd->d_maxxfer - 1)) / bd->d_maxxfer; xi->i_cur_win = 0; xi->i_len = min(bp->b_bcount, bd->d_maxxfer); ! xi->i_nblks = xi->i_len >> shift; xi->i_kaddr = bp->b_un.b_addr; xi->i_resid = bp->b_bcount; } else { /* --- 782,792 ---- xi->i_offset = 0; xi->i_num_win = (bp->b_bcount + (bd->d_maxxfer - 1)) / bd->d_maxxfer; xi->i_cur_win = 0; xi->i_len = min(bp->b_bcount, bd->d_maxxfer); ! xi->i_nblks = howmany(xi->i_len, (1U << shift)); xi->i_kaddr = bp->b_un.b_addr; xi->i_resid = bp->b_bcount; } else { /*
*** 804,814 **** case DDI_DMA_MAPPED: xi->i_num_win = 1; xi->i_cur_win = 0; xi->i_offset = 0; xi->i_len = bp->b_bcount; ! xi->i_nblks = xi->i_len >> shift; xi->i_resid = bp->b_bcount; rv = 0; break; case DDI_DMA_PARTIAL_MAP: xi->i_cur_win = 0; --- 805,815 ---- case DDI_DMA_MAPPED: xi->i_num_win = 1; xi->i_cur_win = 0; xi->i_offset = 0; xi->i_len = bp->b_bcount; ! xi->i_nblks = howmany(xi->i_len, (1U << shift)); xi->i_resid = bp->b_bcount; rv = 0; break; case DDI_DMA_PARTIAL_MAP: xi->i_cur_win = 0;
*** 816,832 **** if ((ddi_dma_numwin(xi->i_dmah, &xi->i_num_win) != DDI_SUCCESS) || (ddi_dma_getwin(xi->i_dmah, 0, &xi->i_offset, &len, &xi->i_dmac, &xi->i_ndmac) != DDI_SUCCESS) || ! (P2PHASE(len, shift) != 0)) { (void) ddi_dma_unbind_handle(xi->i_dmah); rv = EFAULT; goto done; } xi->i_len = len; ! xi->i_nblks = xi->i_len >> shift; xi->i_resid = bp->b_bcount; rv = 0; break; case DDI_DMA_NORESOURCES: rv = EAGAIN; --- 817,833 ---- if ((ddi_dma_numwin(xi->i_dmah, &xi->i_num_win) != DDI_SUCCESS) || (ddi_dma_getwin(xi->i_dmah, 0, &xi->i_offset, &len, &xi->i_dmac, &xi->i_ndmac) != DDI_SUCCESS) || ! (P2PHASE(len, (1U << DEV_BSHIFT)) != 0)) { (void) ddi_dma_unbind_handle(xi->i_dmah); rv = EFAULT; goto done; } xi->i_len = len; ! xi->i_nblks = howmany(xi->i_len, (1U << shift)); xi->i_resid = bp->b_bcount; rv = 0; break; case DDI_DMA_NORESOURCES: rv = EAGAIN;
*** 1033,1084 **** diskaddr_t psize; bd_t *bd; bd_xfer_impl_t *xi; buf_t *bp; int rv; rw_enter(&bd_lock, RW_READER); part = BDPART(dev); inst = BDINST(dev); if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) { rw_exit(&bd_lock); return (ENXIO); } /* * do cmlb, but do it synchronously unless we already have the * partition (which we probably should.) */ if (cmlb_partinfo(bd->d_cmlbh, part, &psize, &pstart, NULL, NULL, (void *)1)) { rw_exit(&bd_lock); return (ENXIO); } ! if ((blkno + nblk) > psize) { rw_exit(&bd_lock); return (EINVAL); } bp = getrbuf(KM_NOSLEEP); if (bp == NULL) { rw_exit(&bd_lock); return (ENOMEM); } ! bp->b_bcount = nblk << bd->d_blkshift; bp->b_resid = bp->b_bcount; bp->b_lblkno = blkno; bp->b_un.b_addr = caddr; xi = bd_xfer_alloc(bd, bp, bd->d_ops.o_write, KM_NOSLEEP); if (xi == NULL) { rw_exit(&bd_lock); freerbuf(bp); return (ENOMEM); } ! xi->i_blkno = blkno + pstart; xi->i_flags = BD_XFER_POLL; bd_submit(bd, xi); rw_exit(&bd_lock); /* --- 1034,1091 ---- diskaddr_t psize; bd_t *bd; bd_xfer_impl_t *xi; buf_t *bp; int rv; + uint32_t shift; + daddr_t d_blkno; + int d_nblk; rw_enter(&bd_lock, RW_READER); part = BDPART(dev); inst = BDINST(dev); if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) { rw_exit(&bd_lock); return (ENXIO); } + shift = bd->d_blkshift; + d_blkno = blkno >> (shift - DEV_BSHIFT); + d_nblk = howmany((nblk << DEV_BSHIFT), (1U << shift)); /* * do cmlb, but do it synchronously unless we already have the * partition (which we probably should.) */ if (cmlb_partinfo(bd->d_cmlbh, part, &psize, &pstart, NULL, NULL, (void *)1)) { rw_exit(&bd_lock); return (ENXIO); } ! if ((d_blkno + d_nblk) > psize) { rw_exit(&bd_lock); return (EINVAL); } bp = getrbuf(KM_NOSLEEP); if (bp == NULL) { rw_exit(&bd_lock); return (ENOMEM); } ! bp->b_bcount = nblk << DEV_BSHIFT; bp->b_resid = bp->b_bcount; bp->b_lblkno = blkno; bp->b_un.b_addr = caddr; xi = bd_xfer_alloc(bd, bp, bd->d_ops.o_write, KM_NOSLEEP); if (xi == NULL) { rw_exit(&bd_lock); freerbuf(bp); return (ENOMEM); } ! xi->i_blkno = d_blkno + pstart; xi->i_flags = BD_XFER_POLL; bd_submit(bd, xi); rw_exit(&bd_lock); /*
*** 1150,1159 **** --- 1157,1167 ---- diskaddr_t p_nblks; diskaddr_t b_nblks; bd_xfer_impl_t *xi; uint32_t shift; int (*func)(void *, bd_xfer_t *); + diskaddr_t lblkno; part = BDPART(bp->b_edev); inst = BDINST(bp->b_edev); ASSERT(bp);
*** 1172,1196 **** biodone(bp); return (0); } shift = bd->d_blkshift; ! ! if ((P2PHASE(bp->b_bcount, (1U << shift)) != 0) || ! (bp->b_lblkno > p_nblks)) { bioerror(bp, ENXIO); biodone(bp); return (0); } ! b_nblks = bp->b_bcount >> shift; ! if ((bp->b_lblkno == p_nblks) || (bp->b_bcount == 0)) { biodone(bp); return (0); } ! if ((b_nblks + bp->b_lblkno) > p_nblks) { ! bp->b_resid = ((bp->b_lblkno + b_nblks - p_nblks) << shift); bp->b_bcount -= bp->b_resid; } else { bp->b_resid = 0; } func = (bp->b_flags & B_READ) ? bd->d_ops.o_read : bd->d_ops.o_write; --- 1180,1204 ---- biodone(bp); return (0); } shift = bd->d_blkshift; ! lblkno = bp->b_lblkno >> (shift - DEV_BSHIFT); ! if ((P2PHASE(bp->b_bcount, (1U << DEV_BSHIFT)) != 0) || ! (lblkno > p_nblks)) { bioerror(bp, ENXIO); biodone(bp); return (0); } ! b_nblks = howmany(bp->b_bcount, (1U << shift)); ! if ((lblkno == p_nblks) || (bp->b_bcount == 0)) { biodone(bp); return (0); } ! if ((b_nblks + lblkno) > p_nblks) { ! bp->b_resid = ((lblkno + b_nblks - p_nblks) << shift); bp->b_bcount -= bp->b_resid; } else { bp->b_resid = 0; } func = (bp->b_flags & B_READ) ? bd->d_ops.o_read : bd->d_ops.o_write;
*** 1202,1212 **** if (xi == NULL) { /* bd_request_alloc will have done bioerror */ biodone(bp); return (0); } ! xi->i_blkno = bp->b_lblkno + p_lba; bd_submit(bd, xi); return (0); } --- 1210,1220 ---- if (xi == NULL) { /* bd_request_alloc will have done bioerror */ biodone(bp); return (0); } ! xi->i_blkno = lblkno + p_lba; bd_submit(bd, xi); return (0); }
*** 1384,1394 **** */ kmflag = tg_cookie ? KM_NOSLEEP : KM_SLEEP; bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip)); ! if (P2PHASE(length, (1U << bd->d_blkshift)) != 0) { /* We can only transfer whole blocks at a time! */ return (EINVAL); } if ((bp = getrbuf(kmflag)) == NULL) { --- 1392,1402 ---- */ kmflag = tg_cookie ? KM_NOSLEEP : KM_SLEEP; bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip)); ! if (P2PHASE(length, (1U << DEV_BSHIFT)) != 0) { /* We can only transfer whole blocks at a time! */ return (EINVAL); } if ((bp = getrbuf(kmflag)) == NULL) {
*** 1903,1923 **** len = min(bp->b_bcount - xi->i_offset, bd->d_maxxfer); } if ((rv != DDI_SUCCESS) || ! (P2PHASE(len, (1U << xi->i_blkshift) != 0))) { bd_runq_exit(xi, EFAULT); bp->b_resid += xi->i_resid; bd_xfer_free(xi); bioerror(bp, EFAULT); biodone(bp); return; } xi->i_len = len; ! xi->i_nblks = len >> xi->i_blkshift; /* Submit next window to hardware. */ rv = xi->i_func(bd->d_private, &xi->i_public); if (rv != 0) { bd_runq_exit(xi, rv); --- 1911,1931 ---- len = min(bp->b_bcount - xi->i_offset, bd->d_maxxfer); } if ((rv != DDI_SUCCESS) || ! (P2PHASE(len, (1U << DEV_BSHIFT) != 0))) { bd_runq_exit(xi, EFAULT); bp->b_resid += xi->i_resid; bd_xfer_free(xi); bioerror(bp, EFAULT); biodone(bp); return; } xi->i_len = len; ! xi->i_nblks = howmany(len, (1U << xi->i_blkshift)); /* Submit next window to hardware. */ rv = xi->i_func(bd->d_private, &xi->i_public); if (rv != 0) { bd_runq_exit(xi, rv);