| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ccd.c,v 1.189 2022/03/28 12:48:35 riastradh Exp $ */ | | 1 | /* $NetBSD: ccd.c,v 1.189.4.1 2024/04/18 18:24:31 martin Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1996, 1997, 1998, 1999, 2007, 2009 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1996, 1997, 1998, 1999, 2007, 2009 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe, and by Andrew Doran. | | 8 | * by Jason R. Thorpe, and by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -78,27 +78,27 @@ | | | @@ -78,27 +78,27 @@ |
78 | * sc_stop, sc_bufq and b_resid from master buffers. | | 78 | * sc_stop, sc_bufq and b_resid from master buffers. |
79 | * | | 79 | * |
80 | * => a combination of CCDF_INITED, sc_inflight, and sc_iolock is used to | | 80 | * => a combination of CCDF_INITED, sc_inflight, and sc_iolock is used to |
81 | * serialize I/O and configuration changes. | | 81 | * serialize I/O and configuration changes. |
82 | * | | 82 | * |
83 | * => the in-core disk label does not change while the device is open. | | 83 | * => the in-core disk label does not change while the device is open. |
84 | * | | 84 | * |
85 | * On memory consumption: ccd fans out I/O requests and so needs to | | 85 | * On memory consumption: ccd fans out I/O requests and so needs to |
86 | * allocate memory. If the system is desperately low on memory, we | | 86 | * allocate memory. If the system is desperately low on memory, we |
87 | * single thread I/O. | | 87 | * single thread I/O. |
88 | */ | | 88 | */ |
89 | | | 89 | |
90 | #include <sys/cdefs.h> | | 90 | #include <sys/cdefs.h> |
91 | __KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.189 2022/03/28 12:48:35 riastradh Exp $"); | | 91 | __KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.189.4.1 2024/04/18 18:24:31 martin Exp $"); |
92 | | | 92 | |
93 | #include <sys/param.h> | | 93 | #include <sys/param.h> |
94 | #include <sys/systm.h> | | 94 | #include <sys/systm.h> |
95 | #include <sys/kernel.h> | | 95 | #include <sys/kernel.h> |
96 | #include <sys/proc.h> | | 96 | #include <sys/proc.h> |
97 | #include <sys/errno.h> | | 97 | #include <sys/errno.h> |
98 | #include <sys/buf.h> | | 98 | #include <sys/buf.h> |
99 | #include <sys/kmem.h> | | 99 | #include <sys/kmem.h> |
100 | #include <sys/pool.h> | | 100 | #include <sys/pool.h> |
101 | #include <sys/module.h> | | 101 | #include <sys/module.h> |
102 | #include <sys/namei.h> | | 102 | #include <sys/namei.h> |
103 | #include <sys/stat.h> | | 103 | #include <sys/stat.h> |
104 | #include <sys/ioctl.h> | | 104 | #include <sys/ioctl.h> |
| @@ -142,47 +142,47 @@ int ccddebug = 0x00; | | | @@ -142,47 +142,47 @@ int ccddebug = 0x00; |
142 | #define ccdunit(x) DISKUNIT(x) | | 142 | #define ccdunit(x) DISKUNIT(x) |
143 | | | 143 | |
144 | struct ccdbuf { | | 144 | struct ccdbuf { |
145 | struct buf cb_buf; /* new I/O buf */ | | 145 | struct buf cb_buf; /* new I/O buf */ |
146 | struct buf *cb_obp; /* ptr. to original I/O buf */ | | 146 | struct buf *cb_obp; /* ptr. to original I/O buf */ |
147 | struct ccd_softc *cb_sc; /* pointer to ccd softc */ | | 147 | struct ccd_softc *cb_sc; /* pointer to ccd softc */ |
148 | int cb_comp; /* target component */ | | 148 | int cb_comp; /* target component */ |
149 | SIMPLEQ_ENTRY(ccdbuf) cb_q; /* fifo of component buffers */ | | 149 | SIMPLEQ_ENTRY(ccdbuf) cb_q; /* fifo of component buffers */ |
150 | }; | | 150 | }; |
151 | | | 151 | |
152 | /* component buffer pool */ | | 152 | /* component buffer pool */ |
153 | static pool_cache_t ccd_cache; | | 153 | static pool_cache_t ccd_cache; |
154 | | | 154 | |
155 | #define CCD_GETBUF() pool_cache_get(ccd_cache, PR_WAITOK) | | 155 | #define CCD_GETBUF(wait) pool_cache_get(ccd_cache, wait) |
156 | #define CCD_PUTBUF(cbp) pool_cache_put(ccd_cache, cbp) | | 156 | #define CCD_PUTBUF(cbp) pool_cache_put(ccd_cache, cbp) |
157 | | | 157 | |
158 | #define CCDLABELDEV(dev) \ | | 158 | #define CCDLABELDEV(dev) \ |
159 | (MAKEDISKDEV(major((dev)), ccdunit((dev)), RAW_PART)) | | 159 | (MAKEDISKDEV(major((dev)), ccdunit((dev)), RAW_PART)) |
160 | | | 160 | |
161 | /* called by main() at boot time */ | | 161 | /* called by main() at boot time */ |
162 | void ccddetach(void); | | 162 | void ccddetach(void); |
163 | | | 163 | |
164 | /* called by biodone() at interrupt time */ | | 164 | /* called by biodone() at interrupt time */ |
165 | static void ccdiodone(struct buf *); | | 165 | static void ccdiodone(struct buf *); |
166 | | | 166 | |
167 | static void ccdinterleave(struct ccd_softc *); | | 167 | static void ccdinterleave(struct ccd_softc *); |
168 | static int ccdinit(struct ccd_softc *, char **, struct vnode **, | | 168 | static int ccdinit(struct ccd_softc *, char **, struct vnode **, |
169 | struct lwp *); | | 169 | struct lwp *); |
170 | static struct ccdbuf *ccdbuffer(struct ccd_softc *, struct buf *, | | 170 | static struct ccdbuf *ccdbuffer(struct ccd_softc *, struct buf *, |
171 | daddr_t, void *, long); | | 171 | daddr_t, void *, long, int); |
172 | static void ccdgetdefaultlabel(struct ccd_softc *, struct disklabel *); | | 172 | static void ccdgetdefaultlabel(struct ccd_softc *, struct disklabel *); |
173 | static void ccdgetdisklabel(dev_t); | | 173 | static void ccdgetdisklabel(dev_t); |
174 | static void ccdmakedisklabel(struct ccd_softc *); | | 174 | static void ccdmakedisklabel(struct ccd_softc *); |
175 | static void ccdstart(struct ccd_softc *); | | 175 | static int ccdstart(struct ccd_softc *, struct buf *, int); |
176 | static void ccdthread(void *); | | 176 | static void ccdthread(void *); |
177 | | | 177 | |
178 | static dev_type_open(ccdopen); | | 178 | static dev_type_open(ccdopen); |
179 | static dev_type_close(ccdclose); | | 179 | static dev_type_close(ccdclose); |
180 | static dev_type_read(ccdread); | | 180 | static dev_type_read(ccdread); |
181 | static dev_type_write(ccdwrite); | | 181 | static dev_type_write(ccdwrite); |
182 | static dev_type_ioctl(ccdioctl); | | 182 | static dev_type_ioctl(ccdioctl); |
183 | static dev_type_strategy(ccdstrategy); | | 183 | static dev_type_strategy(ccdstrategy); |
184 | static dev_type_size(ccdsize); | | 184 | static dev_type_size(ccdsize); |
185 | | | 185 | |
186 | const struct bdevsw ccd_bdevsw = { | | 186 | const struct bdevsw ccd_bdevsw = { |
187 | .d_open = ccdopen, | | 187 | .d_open = ccdopen, |
188 | .d_close = ccdclose, | | 188 | .d_close = ccdclose, |
| @@ -692,64 +692,54 @@ ccdclose(dev_t dev, int flags, int fmt, | | | @@ -692,64 +692,54 @@ ccdclose(dev_t dev, int flags, int fmt, |
692 | } | | 692 | } |
693 | cs->sc_dkdev.dk_openmask = | | 693 | cs->sc_dkdev.dk_openmask = |
694 | cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; | | 694 | cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; |
695 | | | 695 | |
696 | if (cs->sc_dkdev.dk_openmask == 0) { | | 696 | if (cs->sc_dkdev.dk_openmask == 0) { |
697 | if ((cs->sc_flags & CCDF_KLABEL) == 0) | | 697 | if ((cs->sc_flags & CCDF_KLABEL) == 0) |
698 | cs->sc_flags &= ~CCDF_VLABEL; | | 698 | cs->sc_flags &= ~CCDF_VLABEL; |
699 | } | | 699 | } |
700 | | | 700 | |
701 | mutex_exit(&cs->sc_dvlock); | | 701 | mutex_exit(&cs->sc_dvlock); |
702 | return (0); | | 702 | return (0); |
703 | } | | 703 | } |
704 | | | 704 | |
705 | static bool | | | |
706 | ccdbackoff(struct ccd_softc *cs) | | | |
707 | { | | | |
708 | | | | |
709 | /* XXX Arbitrary, should be a uvm call. */ | | | |
710 | return uvm_availmem(true) < (uvmexp.freemin >> 1) && | | | |
711 | disk_isbusy(&cs->sc_dkdev); | | | |
712 | } | | | |
713 | | | | |
714 | static void | | 705 | static void |
715 | ccdthread(void *cookie) | | 706 | ccdthread(void *cookie) |
716 | { | | 707 | { |
| | | 708 | int error; |
717 | struct ccd_softc *cs; | | 709 | struct ccd_softc *cs; |
| | | 710 | struct buf *bp; |
718 | | | 711 | |
719 | cs = cookie; | | 712 | cs = cookie; |
720 | | | 713 | |
721 | #ifdef DEBUG | | 714 | #ifdef DEBUG |
722 | if (ccddebug & CCDB_FOLLOW) | | 715 | if (ccddebug & CCDB_FOLLOW) |
723 | printf("ccdthread: hello\n"); | | 716 | printf("ccdthread: hello\n"); |
724 | #endif | | 717 | #endif |
725 | | | 718 | |
726 | mutex_enter(cs->sc_iolock); | | 719 | mutex_enter(cs->sc_iolock); |
727 | while (__predict_true(!cs->sc_zap)) { | | 720 | while (__predict_true(!cs->sc_zap)) { |
728 | if (bufq_peek(cs->sc_bufq) == NULL) { | | 721 | bp = bufq_get(cs->sc_bufq); |
| | | 722 | if (bp == NULL) { |
729 | /* Nothing to do. */ | | 723 | /* Nothing to do. */ |
730 | cv_wait(&cs->sc_push, cs->sc_iolock); | | 724 | cv_wait(&cs->sc_push, cs->sc_iolock); |
731 | continue; | | 725 | continue; |
732 | } | | 726 | } |
733 | if (ccdbackoff(cs)) { | | | |
734 | /* Wait for memory to become available. */ | | | |
735 | (void)cv_timedwait(&cs->sc_push, cs->sc_iolock, 1); | | | |
736 | continue; | | | |
737 | } | | | |
738 | #ifdef DEBUG | | 727 | #ifdef DEBUG |
739 | if (ccddebug & CCDB_FOLLOW) | | 728 | if (ccddebug & CCDB_FOLLOW) |
740 | printf("ccdthread: dispatching I/O\n"); | | 729 | printf("ccdthread: dispatching I/O\n"); |
741 | #endif | | 730 | #endif |
742 | ccdstart(cs); | | 731 | error = ccdstart(cs, bp, PR_WAITOK); |
| | | 732 | KASSERT(error == 0); |
743 | mutex_enter(cs->sc_iolock); | | 733 | mutex_enter(cs->sc_iolock); |
744 | } | | 734 | } |
745 | cs->sc_thread = NULL; | | 735 | cs->sc_thread = NULL; |
746 | mutex_exit(cs->sc_iolock); | | 736 | mutex_exit(cs->sc_iolock); |
747 | #ifdef DEBUG | | 737 | #ifdef DEBUG |
748 | if (ccddebug & CCDB_FOLLOW) | | 738 | if (ccddebug & CCDB_FOLLOW) |
749 | printf("ccdthread: goodbye\n"); | | 739 | printf("ccdthread: goodbye\n"); |
750 | #endif | | 740 | #endif |
751 | kthread_exit(0); | | 741 | kthread_exit(0); |
752 | } | | 742 | } |
753 | | | 743 | |
754 | static void | | 744 | static void |
755 | ccdstrategy(struct buf *bp) | | 745 | ccdstrategy(struct buf *bp) |
| @@ -767,55 +757,48 @@ ccdstrategy(struct buf *bp) | | | @@ -767,55 +757,48 @@ ccdstrategy(struct buf *bp) |
767 | /* Synchronize with device init/uninit. */ | | 757 | /* Synchronize with device init/uninit. */ |
768 | if (__predict_false((cs->sc_flags & CCDF_INITED) == 0)) { | | 758 | if (__predict_false((cs->sc_flags & CCDF_INITED) == 0)) { |
769 | mutex_exit(cs->sc_iolock); | | 759 | mutex_exit(cs->sc_iolock); |
770 | #ifdef DEBUG | | 760 | #ifdef DEBUG |
771 | if (ccddebug & CCDB_FOLLOW) | | 761 | if (ccddebug & CCDB_FOLLOW) |
772 | printf("ccdstrategy: unit %d: not inited\n", unit); | | 762 | printf("ccdstrategy: unit %d: not inited\n", unit); |
773 | #endif | | 763 | #endif |
774 | bp->b_error = ENXIO; | | 764 | bp->b_error = ENXIO; |
775 | bp->b_resid = bp->b_bcount; | | 765 | bp->b_resid = bp->b_bcount; |
776 | biodone(bp); | | 766 | biodone(bp); |
777 | return; | | 767 | return; |
778 | } | | 768 | } |
779 | | | 769 | |
780 | /* Defer to thread if system is low on memory. */ | | 770 | if (ccdstart(cs, bp, PR_NOWAIT) != 0) { |
781 | bufq_put(cs->sc_bufq, bp); | | 771 | /* Defer to thread if system is low on memory. */ |
782 | if (__predict_false(ccdbackoff(cs))) { | | 772 | bufq_put(cs->sc_bufq, bp); |
| | | 773 | cv_broadcast(&cs->sc_push); |
783 | mutex_exit(cs->sc_iolock); | | 774 | mutex_exit(cs->sc_iolock); |
784 | #ifdef DEBUG | | | |
785 | if (ccddebug & CCDB_FOLLOW) | | | |
786 | printf("ccdstrategy: holding off on I/O\n"); | | | |
787 | #endif | | | |
788 | return; | | | |
789 | } | | 775 | } |
790 | ccdstart(cs); | | | |
791 | } | | 776 | } |
792 | | | 777 | |
793 | static void | | 778 | static int |
794 | ccdstart(struct ccd_softc *cs) | | 779 | ccdstart(struct ccd_softc *cs, struct buf *bp, int wait) |
795 | { | | 780 | { |
796 | daddr_t blkno; | | 781 | daddr_t blkno; |
797 | int wlabel; | | 782 | int wlabel; |
798 | struct disklabel *lp; | | 783 | struct disklabel *lp; |
799 | long bcount, rcount; | | 784 | long bcount, rcount; |
800 | struct ccdbuf *cbp; | | 785 | struct ccdbuf *cbp; |
801 | char *addr; | | 786 | char *addr; |
802 | daddr_t bn; | | 787 | daddr_t bn; |
803 | vnode_t *vp; | | 788 | vnode_t *vp; |
804 | buf_t *bp; | | 789 | SIMPLEQ_HEAD(, ccdbuf) cbufq; |
805 | | | 790 | |
806 | KASSERT(mutex_owned(cs->sc_iolock)); | | 791 | KASSERT(mutex_owned(cs->sc_iolock)); |
807 | | | | |
808 | bp = bufq_get(cs->sc_bufq); | | | |
809 | KASSERT(bp != NULL); | | 792 | KASSERT(bp != NULL); |
810 | | | 793 | |
811 | disk_busy(&cs->sc_dkdev); | | 794 | disk_busy(&cs->sc_dkdev); |
812 | | | 795 | |
813 | #ifdef DEBUG | | 796 | #ifdef DEBUG |
814 | if (ccddebug & CCDB_FOLLOW) | | 797 | if (ccddebug & CCDB_FOLLOW) |
815 | printf("ccdstart(%s, %p)\n", cs->sc_xname, bp); | | 798 | printf("ccdstart(%s, %p)\n", cs->sc_xname, bp); |
816 | #endif | | 799 | #endif |
817 | | | 800 | |
818 | /* If it's a nil transfer, wake up the top half now. */ | | 801 | /* If it's a nil transfer, wake up the top half now. */ |
819 | if (bp->b_bcount == 0) | | 802 | if (bp->b_bcount == 0) |
820 | goto done; | | 803 | goto done; |
821 | | | 804 | |
| @@ -826,60 +809,78 @@ ccdstart(struct ccd_softc *cs) | | | @@ -826,60 +809,78 @@ ccdstart(struct ccd_softc *cs) |
826 | * error, the bounds check will flag that for us. Convert | | 809 | * error, the bounds check will flag that for us. Convert |
827 | * the partition relative block number to an absolute. | | 810 | * the partition relative block number to an absolute. |
828 | */ | | 811 | */ |
829 | blkno = bp->b_blkno; | | 812 | blkno = bp->b_blkno; |
830 | wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING); | | 813 | wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING); |
831 | if (DISKPART(bp->b_dev) != RAW_PART) { | | 814 | if (DISKPART(bp->b_dev) != RAW_PART) { |
832 | if (bounds_check_with_label(&cs->sc_dkdev, bp, wlabel) <= 0) | | 815 | if (bounds_check_with_label(&cs->sc_dkdev, bp, wlabel) <= 0) |
833 | goto done; | | 816 | goto done; |
834 | blkno += lp->d_partitions[DISKPART(bp->b_dev)].p_offset; | | 817 | blkno += lp->d_partitions[DISKPART(bp->b_dev)].p_offset; |
835 | } | | 818 | } |
836 | mutex_exit(cs->sc_iolock); | | 819 | mutex_exit(cs->sc_iolock); |
837 | bp->b_rawblkno = blkno; | | 820 | bp->b_rawblkno = blkno; |
838 | | | 821 | |
839 | /* Allocate the component buffers and start I/O! */ | | 822 | /* Allocate the component buffers. */ |
| | | 823 | SIMPLEQ_INIT(&cbufq); |
840 | bp->b_resid = bp->b_bcount; | | 824 | bp->b_resid = bp->b_bcount; |
841 | bn = bp->b_rawblkno; | | 825 | bn = bp->b_rawblkno; |
842 | addr = bp->b_data; | | 826 | addr = bp->b_data; |
843 | for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { | | 827 | for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { |
844 | cbp = ccdbuffer(cs, bp, bn, addr, bcount); | | 828 | cbp = ccdbuffer(cs, bp, bn, addr, bcount, wait); |
| | | 829 | KASSERT(cbp != NULL || wait == PR_NOWAIT); |
| | | 830 | if (cbp == NULL) { |
| | | 831 | while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) { |
| | | 832 | SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q); |
| | | 833 | CCD_PUTBUF(cbp); |
| | | 834 | } |
| | | 835 | mutex_enter(cs->sc_iolock); |
| | | 836 | disk_unbusy(&cs->sc_dkdev, 0, 0); |
| | | 837 | return ENOMEM; |
| | | 838 | } |
| | | 839 | SIMPLEQ_INSERT_TAIL(&cbufq, cbp, cb_q); |
845 | rcount = cbp->cb_buf.b_bcount; | | 840 | rcount = cbp->cb_buf.b_bcount; |
846 | bn += btodb(rcount); | | 841 | bn += btodb(rcount); |
847 | addr += rcount; | | 842 | addr += rcount; |
| | | 843 | } |
| | | 844 | |
| | | 845 | /* All buffers set up, now fire off the requests. */ |
| | | 846 | while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) { |
| | | 847 | SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q); |
848 | vp = cbp->cb_buf.b_vp; | | 848 | vp = cbp->cb_buf.b_vp; |
849 | if ((cbp->cb_buf.b_flags & B_READ) == 0) { | | 849 | if ((cbp->cb_buf.b_flags & B_READ) == 0) { |
850 | mutex_enter(vp->v_interlock); | | 850 | mutex_enter(vp->v_interlock); |
851 | vp->v_numoutput++; | | 851 | vp->v_numoutput++; |
852 | mutex_exit(vp->v_interlock); | | 852 | mutex_exit(vp->v_interlock); |
853 | } | | 853 | } |
854 | (void)VOP_STRATEGY(vp, &cbp->cb_buf); | | 854 | (void)VOP_STRATEGY(vp, &cbp->cb_buf); |
855 | } | | 855 | } |
856 | return; | | 856 | return 0; |
857 | | | 857 | |
858 | done: | | 858 | done: |
859 | disk_unbusy(&cs->sc_dkdev, 0, 0); | | 859 | disk_unbusy(&cs->sc_dkdev, 0, 0); |
860 | cv_broadcast(&cs->sc_stop); | | 860 | cv_broadcast(&cs->sc_stop); |
861 | cv_broadcast(&cs->sc_push); | | 861 | cv_broadcast(&cs->sc_push); |
862 | mutex_exit(cs->sc_iolock); | | 862 | mutex_exit(cs->sc_iolock); |
863 | bp->b_resid = bp->b_bcount; | | 863 | bp->b_resid = bp->b_bcount; |
864 | biodone(bp); | | 864 | biodone(bp); |
| | | 865 | return 0; |
865 | } | | 866 | } |
866 | | | 867 | |
867 | /* | | 868 | /* |
868 | * Build a component buffer header. | | 869 | * Build a component buffer header. |
869 | */ | | 870 | */ |
870 | static struct ccdbuf * | | 871 | static struct ccdbuf * |
871 | ccdbuffer(struct ccd_softc *cs, struct buf *bp, daddr_t bn, void *addr, | | 872 | ccdbuffer(struct ccd_softc *cs, struct buf *bp, daddr_t bn, void *addr, |
872 | long bcount) | | 873 | long bcount, int wait) |
873 | { | | 874 | { |
874 | struct ccdcinfo *ci; | | 875 | struct ccdcinfo *ci; |
875 | struct ccdbuf *cbp; | | 876 | struct ccdbuf *cbp; |
876 | daddr_t cbn, cboff; | | 877 | daddr_t cbn, cboff; |
877 | u_int64_t cbc; | | 878 | u_int64_t cbc; |
878 | int ccdisk; | | 879 | int ccdisk; |
879 | | | 880 | |
880 | #ifdef DEBUG | | 881 | #ifdef DEBUG |
881 | if (ccddebug & CCDB_IO) | | 882 | if (ccddebug & CCDB_IO) |
882 | printf("ccdbuffer(%p, %p, %" PRId64 ", %p, %ld)\n", | | 883 | printf("ccdbuffer(%p, %p, %" PRId64 ", %p, %ld)\n", |
883 | cs, bp, bn, addr, bcount); | | 884 | cs, bp, bn, addr, bcount); |
884 | #endif | | 885 | #endif |
885 | /* | | 886 | /* |
| @@ -919,28 +920,29 @@ ccdbuffer(struct ccd_softc *cs, struct b | | | @@ -919,28 +920,29 @@ ccdbuffer(struct ccd_softc *cs, struct b |
919 | ccdisk = ii->ii_index[0]; | | 920 | ccdisk = ii->ii_index[0]; |
920 | cbn = ii->ii_startoff + off; | | 921 | cbn = ii->ii_startoff + off; |
921 | } else { | | 922 | } else { |
922 | ccdisk = ii->ii_index[off % ii->ii_ndisk]; | | 923 | ccdisk = ii->ii_index[off % ii->ii_ndisk]; |
923 | cbn = ii->ii_startoff + off / ii->ii_ndisk; | | 924 | cbn = ii->ii_startoff + off / ii->ii_ndisk; |
924 | } | | 925 | } |
925 | cbn *= cs->sc_ileave; | | 926 | cbn *= cs->sc_ileave; |
926 | ci = &cs->sc_cinfo[ccdisk]; | | 927 | ci = &cs->sc_cinfo[ccdisk]; |
927 | } | | 928 | } |
928 | | | 929 | |
929 | /* | | 930 | /* |
930 | * Fill in the component buf structure. | | 931 | * Fill in the component buf structure. |
931 | */ | | 932 | */ |
932 | cbp = CCD_GETBUF(); | | 933 | cbp = CCD_GETBUF(wait); |
933 | KASSERT(cbp != NULL); | | 934 | if (cbp == NULL) |
| | | 935 | return NULL; |
934 | buf_init(&cbp->cb_buf); | | 936 | buf_init(&cbp->cb_buf); |
935 | cbp->cb_buf.b_flags = bp->b_flags; | | 937 | cbp->cb_buf.b_flags = bp->b_flags; |
936 | cbp->cb_buf.b_oflags = bp->b_oflags; | | 938 | cbp->cb_buf.b_oflags = bp->b_oflags; |
937 | cbp->cb_buf.b_cflags = bp->b_cflags; | | 939 | cbp->cb_buf.b_cflags = bp->b_cflags; |
938 | cbp->cb_buf.b_iodone = ccdiodone; | | 940 | cbp->cb_buf.b_iodone = ccdiodone; |
939 | cbp->cb_buf.b_proc = bp->b_proc; | | 941 | cbp->cb_buf.b_proc = bp->b_proc; |
940 | cbp->cb_buf.b_dev = ci->ci_dev; | | 942 | cbp->cb_buf.b_dev = ci->ci_dev; |
941 | cbp->cb_buf.b_blkno = cbn + cboff; | | 943 | cbp->cb_buf.b_blkno = cbn + cboff; |
942 | cbp->cb_buf.b_data = addr; | | 944 | cbp->cb_buf.b_data = addr; |
943 | cbp->cb_buf.b_vp = ci->ci_vp; | | 945 | cbp->cb_buf.b_vp = ci->ci_vp; |
944 | cbp->cb_buf.b_objlock = ci->ci_vp->v_interlock; | | 946 | cbp->cb_buf.b_objlock = ci->ci_vp->v_interlock; |
945 | if (cs->sc_ileave == 0) | | 947 | if (cs->sc_ileave == 0) |
946 | cbc = dbtob((u_int64_t)(ci->ci_size - cbn)); | | 948 | cbc = dbtob((u_int64_t)(ci->ci_size - cbn)); |