Print this page
NEX-8020 illumos nvme changes
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-6131 support EUI64 in blkdev
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-5236 harmless off-by-one in blkdev
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-4427 blkdev should provide the device_error kstat for iostat -E
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
NEX-4424 kstat module needs cleanup
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
NEX-4420 format(1M) should be able to use device inquiry properties
Reviewed by: Dan McDonald <danmcd@omniti.com>
NEX-4419 blkdev and blkdev drivers should provide inquiry properties
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
port of illumos-3878
    3878 blkdev needs to support DKIOCGMEDIAINFOEXT
    Reviewed by: Saso Kiselkov <skiselkov.ml@gmail.com>
    Reviewed by: Garrett D'Amore <garrett@damore.org>
    Approved by: Garrett D'Amore <garrett@damore.org>
port of illumos-2911
    2911 blkdev-related panic on DEBUG kernels
    Reviewed by: Richard Lowe <richlowe@richlowe.net>
    Reviewed by: Garrett D'Amore <garrett@damore.org>
    Approved by: Garrett D'Amore <garrett@damore.org>
Adding AoE support to nza-kernel


  33 #include <sys/errno.h>
  34 #include <sys/open.h>
  35 #include <sys/buf.h>
  36 #include <sys/uio.h>
  37 #include <sys/aio_req.h>
  38 #include <sys/cred.h>
  39 #include <sys/modctl.h>
  40 #include <sys/cmlb.h>
  41 #include <sys/conf.h>
  42 #include <sys/devops.h>
  43 #include <sys/list.h>
  44 #include <sys/sysmacros.h>
  45 #include <sys/dkio.h>
  46 #include <sys/vtoc.h>
  47 #include <sys/scsi/scsi.h>        /* for DTYPE_DIRECT */
  48 #include <sys/kstat.h>
  49 #include <sys/fs/dv_node.h>
  50 #include <sys/ddi.h>
  51 #include <sys/sunddi.h>
  52 #include <sys/note.h>

  53 #include <sys/blkdev.h>
  54 #include <sys/scsi/impl/inquiry.h>
  55 
  56 #define BD_MAXPART      64
  57 #define BDINST(dev)     (getminor(dev) / BD_MAXPART)
  58 #define BDPART(dev)     (getminor(dev) % BD_MAXPART)
  59 
  60 typedef struct bd bd_t;
  61 typedef struct bd_xfer_impl bd_xfer_impl_t;
  62 
  63 struct bd {
  64         void            *d_private;
  65         dev_info_t      *d_dip;
  66         kmutex_t        d_ocmutex;
  67         kmutex_t        d_iomutex;
  68         kmutex_t        *d_errmutex;
  69         kmutex_t        d_statemutex;
  70         kcondvar_t      d_statecv;
  71         enum dkio_state d_state;
  72         cmlb_handle_t   d_cmlbh;


 155 static int bd_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
 156 static int bd_dump(dev_t, caddr_t, daddr_t, int);
 157 static int bd_read(dev_t, struct uio *, cred_t *);
 158 static int bd_write(dev_t, struct uio *, cred_t *);
 159 static int bd_aread(dev_t, struct aio_req *, cred_t *);
 160 static int bd_awrite(dev_t, struct aio_req *, cred_t *);
 161 static int bd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
 162     caddr_t, int *);
 163 
 164 static int bd_tg_rdwr(dev_info_t *, uchar_t, void *, diskaddr_t, size_t,
 165     void *);
 166 static int bd_tg_getinfo(dev_info_t *, int, void *, void *);
 167 static int bd_xfer_ctor(void *, void *, int);
 168 static void bd_xfer_dtor(void *, void *);
 169 static void bd_sched(bd_t *);
 170 static void bd_submit(bd_t *, bd_xfer_impl_t *);
 171 static void bd_runq_exit(bd_xfer_impl_t *, int);
 172 static void bd_update_state(bd_t *);
 173 static int bd_check_state(bd_t *, enum dkio_state *);
 174 static int bd_flush_write_cache(bd_t *, struct dk_callback *);

 175 static int bd_check_uio(dev_t, struct uio *);
 176 
 177 struct cmlb_tg_ops bd_tg_ops = {
 178         TG_DK_OPS_VERSION_1,
 179         bd_tg_rdwr,
 180         bd_tg_getinfo,
 181 };
 182 
 183 static struct cb_ops bd_cb_ops = {
 184         bd_open,                /* open */
 185         bd_close,               /* close */
 186         bd_strategy,            /* strategy */
 187         nodev,                  /* print */
 188         bd_dump,                /* dump */
 189         bd_read,                /* read */
 190         bd_write,               /* write */
 191         bd_ioctl,               /* ioctl */
 192         nodev,                  /* devmap */
 193         nodev,                  /* mmap */
 194         nodev,                  /* segmap */


 858 bd_xfer_free(bd_xfer_impl_t *xi)
 859 {
 860         if (xi->i_dmah) {
 861                 (void) ddi_dma_unbind_handle(xi->i_dmah);
 862         }
 863         kmem_cache_free(xi->i_bd->d_cache, xi);
 864 }
 865 
 866 static int
 867 bd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
 868 {
 869         dev_t           dev = *devp;
 870         bd_t            *bd;
 871         minor_t         part;
 872         minor_t         inst;
 873         uint64_t        mask;
 874         boolean_t       ndelay;
 875         int             rv;
 876         diskaddr_t      nblks;
 877         diskaddr_t      lba;

 878 
 879         _NOTE(ARGUNUSED(credp));
 880 
 881         part = BDPART(dev);
 882         inst = BDINST(dev);
 883 
 884         if (otyp >= OTYPCNT)
 885                 return (EINVAL);
 886 
 887         ndelay = (flag & (FNDELAY | FNONBLOCK)) ? B_TRUE : B_FALSE;
 888 
 889         /*
 890          * Block any DR events from changing the set of registered
 891          * devices while we function.
 892          */
 893         rw_enter(&bd_lock, RW_READER);
 894         if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
 895                 rw_exit(&bd_lock);
 896                 return (ENXIO);
 897         }


 930                  * disk label.
 931                  */
 932                 rv = ENXIO;
 933                 goto done;
 934         }
 935 
 936         if ((flag & FWRITE) && bd->d_rdonly) {
 937                 rv = EROFS;
 938                 goto done;
 939         }
 940 
 941         if ((bd->d_open_excl) & (mask)) {
 942                 rv = EBUSY;
 943                 goto done;
 944         }
 945         if (flag & FEXCL) {
 946                 if (bd->d_open_lyr[part]) {
 947                         rv = EBUSY;
 948                         goto done;
 949                 }
 950                 for (int i = 0; i < OTYP_LYR; i++) {
 951                         if (bd->d_open_reg[i] & mask) {
 952                                 rv = EBUSY;
 953                                 goto done;
 954                         }
 955                 }
 956         }
 957 
 958         if (otyp == OTYP_LYR) {
 959                 bd->d_open_lyr[part]++;
 960         } else {
 961                 bd->d_open_reg[otyp] |= mask;
 962         }
 963         if (flag & FEXCL) {
 964                 bd->d_open_excl |= mask;
 965         }
 966 
 967         rv = 0;
 968 done:
 969         mutex_exit(&bd->d_ocmutex);
 970         rw_exit(&bd_lock);
 971 
 972         return (rv);
 973 }
 974 
 975 static int
 976 bd_close(dev_t dev, int flag, int otyp, cred_t *credp)
 977 {
 978         bd_t            *bd;
 979         minor_t         inst;
 980         minor_t         part;
 981         uint64_t        mask;
 982         boolean_t       last = B_TRUE;

 983 
 984         _NOTE(ARGUNUSED(flag));
 985         _NOTE(ARGUNUSED(credp));
 986 
 987         part = BDPART(dev);
 988         inst = BDINST(dev);
 989 
 990         ASSERT(part < 64);
 991         mask = (1U << part);
 992 
 993         rw_enter(&bd_lock, RW_READER);
 994 
 995         if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
 996                 rw_exit(&bd_lock);
 997                 return (ENXIO);
 998         }
 999 
1000         mutex_enter(&bd->d_ocmutex);
1001         if (bd->d_open_excl & mask) {
1002                 bd->d_open_excl &= ~mask;
1003         }
1004         if (otyp == OTYP_LYR) {
1005                 bd->d_open_lyr[part]--;
1006         } else {
1007                 bd->d_open_reg[otyp] &= ~mask;
1008         }
1009         for (int i = 0; i < 64; i++) {
1010                 if (bd->d_open_lyr[part]) {
1011                         last = B_FALSE;
1012                 }
1013         }
1014         for (int i = 0; last && (i < OTYP_LYR); i++) {
1015                 if (bd->d_open_reg[i]) {
1016                         last = B_FALSE;
1017                 }
1018         }
1019         mutex_exit(&bd->d_ocmutex);
1020 
1021         if (last) {
1022                 cmlb_invalidate(bd->d_cmlbh, 0);
1023         }
1024         rw_exit(&bd_lock);
1025 
1026         return (0);
1027 }
1028 
1029 static int
1030 bd_dump(dev_t dev, caddr_t caddr, daddr_t blkno, int nblk)
1031 {
1032         minor_t         inst;
1033         minor_t         part;
1034         diskaddr_t      pstart;


1372                         return (EFAULT);
1373                 }
1374                 if ((rv = bd_check_state(bd, &state)) != 0) {
1375                         return (rv);
1376                 }
1377                 if (ddi_copyout(&state, ptr, sizeof (state), flag)) {
1378                         return (EFAULT);
1379                 }
1380                 return (0);
1381         }
1382         case DKIOCFLUSHWRITECACHE: {
1383                 struct dk_callback *dkc = NULL;
1384 
1385                 if (flag & FKIOCTL)
1386                         dkc = (void *)arg;
1387 
1388                 rv = bd_flush_write_cache(bd, dkc);
1389                 return (rv);
1390         }
1391 




























1392         default:
1393                 break;
1394 
1395         }
1396         return (ENOTTY);
1397 }
1398 
1399 static int
1400 bd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1401     char *name, caddr_t valuep, int *lengthp)
1402 {
1403         bd_t    *bd;
1404 
1405         bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip));
1406         if (bd == NULL)
1407                 return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1408                     name, valuep, lengthp));
1409 
1410         return (cmlb_prop_op(bd->d_cmlbh, dev, dip, prop_op, mod_flags, name,
1411             valuep, lengthp, BDPART(dev), 0));


1733                 freerbuf(bp);
1734                 return (rv);
1735         }
1736 
1737         /* Make an asynchronous flush, but only if there is a callback */
1738         if (dkc != NULL && dkc->dkc_callback != NULL) {
1739                 /* Make a private copy of the callback structure */
1740                 dc = kmem_alloc(sizeof (*dc), KM_SLEEP);
1741                 *dc = *dkc;
1742                 bp->b_private = dc;
1743                 bp->b_iodone = bd_flush_write_cache_done;
1744 
1745                 bd_submit(bd, xi);
1746                 return (0);
1747         }
1748 
1749         /* In case there is no callback, perform a synchronous flush */
1750         bd_submit(bd, xi);
1751         (void) biowait(bp);
1752         rv = geterror(bp);



































1753         freerbuf(bp);
1754 
1755         return (rv);
1756 }
1757 
1758 /*
1759  * Nexus support.
1760  */
1761 int
1762 bd_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
1763     void *arg, void *result)
1764 {
1765         bd_handle_t     hdl;
1766 
1767         switch (ctlop) {
1768         case DDI_CTLOPS_REPORTDEV:
1769                 cmn_err(CE_CONT, "?Block device: %s@%s, %s%d\n",
1770                     ddi_node_name(rdip), ddi_get_name_addr(rdip),
1771                     ddi_driver_name(rdip), ddi_get_instance(rdip));
1772                 return (DDI_SUCCESS);




  33 #include <sys/errno.h>
  34 #include <sys/open.h>
  35 #include <sys/buf.h>
  36 #include <sys/uio.h>
  37 #include <sys/aio_req.h>
  38 #include <sys/cred.h>
  39 #include <sys/modctl.h>
  40 #include <sys/cmlb.h>
  41 #include <sys/conf.h>
  42 #include <sys/devops.h>
  43 #include <sys/list.h>
  44 #include <sys/sysmacros.h>
  45 #include <sys/dkio.h>
  46 #include <sys/vtoc.h>
  47 #include <sys/scsi/scsi.h>        /* for DTYPE_DIRECT */
  48 #include <sys/kstat.h>
  49 #include <sys/fs/dv_node.h>
  50 #include <sys/ddi.h>
  51 #include <sys/sunddi.h>
  52 #include <sys/note.h>
  53 #include <sys/mhd.h>
  54 #include <sys/blkdev.h>
  55 #include <sys/scsi/impl/inquiry.h>
  56 
  57 #define BD_MAXPART      64
  58 #define BDINST(dev)     (getminor(dev) / BD_MAXPART)
  59 #define BDPART(dev)     (getminor(dev) % BD_MAXPART)
  60 
  61 typedef struct bd bd_t;
  62 typedef struct bd_xfer_impl bd_xfer_impl_t;
  63 
  64 struct bd {
  65         void            *d_private;
  66         dev_info_t      *d_dip;
  67         kmutex_t        d_ocmutex;
  68         kmutex_t        d_iomutex;
  69         kmutex_t        *d_errmutex;
  70         kmutex_t        d_statemutex;
  71         kcondvar_t      d_statecv;
  72         enum dkio_state d_state;
  73         cmlb_handle_t   d_cmlbh;


 156 static int bd_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
 157 static int bd_dump(dev_t, caddr_t, daddr_t, int);
 158 static int bd_read(dev_t, struct uio *, cred_t *);
 159 static int bd_write(dev_t, struct uio *, cred_t *);
 160 static int bd_aread(dev_t, struct aio_req *, cred_t *);
 161 static int bd_awrite(dev_t, struct aio_req *, cred_t *);
 162 static int bd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
 163     caddr_t, int *);
 164 
 165 static int bd_tg_rdwr(dev_info_t *, uchar_t, void *, diskaddr_t, size_t,
 166     void *);
 167 static int bd_tg_getinfo(dev_info_t *, int, void *, void *);
 168 static int bd_xfer_ctor(void *, void *, int);
 169 static void bd_xfer_dtor(void *, void *);
 170 static void bd_sched(bd_t *);
 171 static void bd_submit(bd_t *, bd_xfer_impl_t *);
 172 static void bd_runq_exit(bd_xfer_impl_t *, int);
 173 static void bd_update_state(bd_t *);
 174 static int bd_check_state(bd_t *, enum dkio_state *);
 175 static int bd_flush_write_cache(bd_t *, struct dk_callback *);
 176 static int bd_reserve(bd_t *bd, int);
 177 static int bd_check_uio(dev_t, struct uio *);
 178 
 179 struct cmlb_tg_ops bd_tg_ops = {
 180         TG_DK_OPS_VERSION_1,
 181         bd_tg_rdwr,
 182         bd_tg_getinfo,
 183 };
 184 
 185 static struct cb_ops bd_cb_ops = {
 186         bd_open,                /* open */
 187         bd_close,               /* close */
 188         bd_strategy,            /* strategy */
 189         nodev,                  /* print */
 190         bd_dump,                /* dump */
 191         bd_read,                /* read */
 192         bd_write,               /* write */
 193         bd_ioctl,               /* ioctl */
 194         nodev,                  /* devmap */
 195         nodev,                  /* mmap */
 196         nodev,                  /* segmap */


 860 bd_xfer_free(bd_xfer_impl_t *xi)
 861 {
 862         if (xi->i_dmah) {
 863                 (void) ddi_dma_unbind_handle(xi->i_dmah);
 864         }
 865         kmem_cache_free(xi->i_bd->d_cache, xi);
 866 }
 867 
 868 static int
 869 bd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
 870 {
 871         dev_t           dev = *devp;
 872         bd_t            *bd;
 873         minor_t         part;
 874         minor_t         inst;
 875         uint64_t        mask;
 876         boolean_t       ndelay;
 877         int             rv;
 878         diskaddr_t      nblks;
 879         diskaddr_t      lba;
 880         int             i;
 881 
 882         _NOTE(ARGUNUSED(credp));
 883 
 884         part = BDPART(dev);
 885         inst = BDINST(dev);
 886 
 887         if (otyp >= OTYPCNT)
 888                 return (EINVAL);
 889 
 890         ndelay = (flag & (FNDELAY | FNONBLOCK)) ? B_TRUE : B_FALSE;
 891 
 892         /*
 893          * Block any DR events from changing the set of registered
 894          * devices while we function.
 895          */
 896         rw_enter(&bd_lock, RW_READER);
 897         if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
 898                 rw_exit(&bd_lock);
 899                 return (ENXIO);
 900         }


 933                  * disk label.
 934                  */
 935                 rv = ENXIO;
 936                 goto done;
 937         }
 938 
 939         if ((flag & FWRITE) && bd->d_rdonly) {
 940                 rv = EROFS;
 941                 goto done;
 942         }
 943 
 944         if ((bd->d_open_excl) & (mask)) {
 945                 rv = EBUSY;
 946                 goto done;
 947         }
 948         if (flag & FEXCL) {
 949                 if (bd->d_open_lyr[part]) {
 950                         rv = EBUSY;
 951                         goto done;
 952                 }
 953                 for (i = 0; i < OTYP_LYR; i++) {
 954                         if (bd->d_open_reg[i] & mask) {
 955                                 rv = EBUSY;
 956                                 goto done;
 957                         }
 958                 }
 959         }
 960 
 961         if (otyp == OTYP_LYR) {
 962                 bd->d_open_lyr[part]++;
 963         } else {
 964                 bd->d_open_reg[otyp] |= mask;
 965         }
 966         if (flag & FEXCL) {
 967                 bd->d_open_excl |= mask;
 968         }
 969 
 970         rv = 0;
 971 done:
 972         mutex_exit(&bd->d_ocmutex);
 973         rw_exit(&bd_lock);
 974 
 975         return (rv);
 976 }
 977 
 978 static int
 979 bd_close(dev_t dev, int flag, int otyp, cred_t *credp)
 980 {
 981         bd_t            *bd;
 982         minor_t         inst;
 983         minor_t         part;
 984         uint64_t        mask;
 985         boolean_t       last = B_TRUE;
 986         int             i;
 987 
 988         _NOTE(ARGUNUSED(flag));
 989         _NOTE(ARGUNUSED(credp));
 990 
 991         part = BDPART(dev);
 992         inst = BDINST(dev);
 993 
 994         ASSERT(part < 64);
 995         mask = (1U << part);
 996 
 997         rw_enter(&bd_lock, RW_READER);
 998 
 999         if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
1000                 rw_exit(&bd_lock);
1001                 return (ENXIO);
1002         }
1003 
1004         mutex_enter(&bd->d_ocmutex);
1005         if (bd->d_open_excl & mask) {
1006                 bd->d_open_excl &= ~mask;
1007         }
1008         if (otyp == OTYP_LYR) {
1009                 bd->d_open_lyr[part]--;
1010         } else {
1011                 bd->d_open_reg[otyp] &= ~mask;
1012         }
1013         for (i = 0; i < 64; i++) {
1014                 if (bd->d_open_lyr[part]) {
1015                         last = B_FALSE;
1016                 }
1017         }
1018         for (i = 0; last && (i < OTYP_LYR); i++) {
1019                 if (bd->d_open_reg[i]) {
1020                         last = B_FALSE;
1021                 }
1022         }
1023         mutex_exit(&bd->d_ocmutex);
1024 
1025         if (last) {
1026                 cmlb_invalidate(bd->d_cmlbh, 0);
1027         }
1028         rw_exit(&bd_lock);
1029 
1030         return (0);
1031 }
1032 
1033 static int
1034 bd_dump(dev_t dev, caddr_t caddr, daddr_t blkno, int nblk)
1035 {
1036         minor_t         inst;
1037         minor_t         part;
1038         diskaddr_t      pstart;


1376                         return (EFAULT);
1377                 }
1378                 if ((rv = bd_check_state(bd, &state)) != 0) {
1379                         return (rv);
1380                 }
1381                 if (ddi_copyout(&state, ptr, sizeof (state), flag)) {
1382                         return (EFAULT);
1383                 }
1384                 return (0);
1385         }
1386         case DKIOCFLUSHWRITECACHE: {
1387                 struct dk_callback *dkc = NULL;
1388 
1389                 if (flag & FKIOCTL)
1390                         dkc = (void *)arg;
1391 
1392                 rv = bd_flush_write_cache(bd, dkc);
1393                 return (rv);
1394         }
1395 
1396         case MHIOCTKOWN:
1397         {
1398                 return (bd_reserve(bd, BD_XFER_MHD_TKOWN));
1399         }
1400 
1401         case MHIOCRELEASE:
1402         {
1403                 return (bd_reserve(bd, BD_XFER_MHD_RELEASE));
1404         }
1405 
1406         case MHIOCSTATUS:
1407         {
1408                 rv = bd_reserve(bd, BD_XFER_MHD_STATUS);
1409                 if (rvalp != NULL)
1410                         *rvalp = rv == 0 ? 0: 1;
1411                 return (0);
1412         }
1413 
1414         case MHIOCQRESERVE:
1415         {
1416                 return (bd_reserve(bd, BD_XFER_MHD_QRESERVE));
1417         }
1418 
1419         case MHIOCENFAILFAST:
1420         {
1421                 return (bd_reserve(bd, BD_XFER_MHD_ENFAILFAST));
1422         }
1423 
1424         default:
1425                 break;
1426 
1427         }
1428         return (ENOTTY);
1429 }
1430 
1431 static int
1432 bd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1433     char *name, caddr_t valuep, int *lengthp)
1434 {
1435         bd_t    *bd;
1436 
1437         bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip));
1438         if (bd == NULL)
1439                 return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1440                     name, valuep, lengthp));
1441 
1442         return (cmlb_prop_op(bd->d_cmlbh, dev, dip, prop_op, mod_flags, name,
1443             valuep, lengthp, BDPART(dev), 0));


1765                 freerbuf(bp);
1766                 return (rv);
1767         }
1768 
1769         /* Make an asynchronous flush, but only if there is a callback */
1770         if (dkc != NULL && dkc->dkc_callback != NULL) {
1771                 /* Make a private copy of the callback structure */
1772                 dc = kmem_alloc(sizeof (*dc), KM_SLEEP);
1773                 *dc = *dkc;
1774                 bp->b_private = dc;
1775                 bp->b_iodone = bd_flush_write_cache_done;
1776 
1777                 bd_submit(bd, xi);
1778                 return (0);
1779         }
1780 
1781         /* In case there is no callback, perform a synchronous flush */
1782         bd_submit(bd, xi);
1783         (void) biowait(bp);
1784         rv = geterror(bp);
1785         freerbuf(bp);
1786 
1787         return (rv);
1788 }
1789 
1790 static int
1791 bd_reserve(bd_t *bd, int flag)
1792 {
1793         buf_t                   *bp;
1794         bd_xfer_impl_t          *xi;
1795         int                     rv;
1796 
1797         if (bd->d_ops.o_reserve == NULL) {
1798                 return (ENOTSUP);
1799         }
1800         if ((bp = getrbuf(KM_SLEEP)) == NULL) {
1801                 return (ENOMEM);
1802         }
1803         bp->b_resid = 0;
1804         bp->b_bcount = 0;
1805 
1806         xi = bd_xfer_alloc(bd, bp, bd->d_ops.o_reserve, KM_SLEEP);
1807         if (xi == NULL) {
1808                 rv = geterror(bp);
1809                 freerbuf(bp);
1810                 return (rv);
1811         }
1812 
1813         xi->i_flags = flag;
1814 
1815         bd_submit(bd, xi);
1816 
1817         /* wait synchronously */
1818         (void) biowait(bp);
1819         rv = geterror(bp);
1820         freerbuf(bp);
1821 
1822         return (rv);
1823 }
1824 
1825 /*
1826  * Nexus support.
1827  */
1828 int
1829 bd_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
1830     void *arg, void *result)
1831 {
1832         bd_handle_t     hdl;
1833 
1834         switch (ctlop) {
1835         case DDI_CTLOPS_REPORTDEV:
1836                 cmn_err(CE_CONT, "?Block device: %s@%s, %s%d\n",
1837                     ddi_node_name(rdip), ddi_get_name_addr(rdip),
1838                     ddi_driver_name(rdip), ddi_get_instance(rdip));
1839                 return (DDI_SUCCESS);