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);
|