Tue Dec 13 13:32:16 2011 UTC ()
- gc old aio implementation
- set busy before scheduling softint not after
- try not to write past end of backing file
- if B_PHYS flag is set, pread/write with bounce buffer and copyout/copyin
- use the correct offset in ld_thunkbus_dump


(jmcneill)
diff -r1.20 -r1.21 src/sys/arch/usermode/dev/ld_thunkbus.c

cvs diff -r1.20 -r1.21 src/sys/arch/usermode/dev/ld_thunkbus.c (expand / switch to unified diff)

--- src/sys/arch/usermode/dev/ld_thunkbus.c 2011/12/09 17:21:45 1.20
+++ src/sys/arch/usermode/dev/ld_thunkbus.c 2011/12/13 13:32:15 1.21
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ld_thunkbus.c,v 1.20 2011/12/09 17:21:45 reinoud Exp $ */ 1/* $NetBSD: ld_thunkbus.c,v 1.21 2011/12/13 13:32:15 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -17,97 +17,90 @@ @@ -17,97 +17,90 @@
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: ld_thunkbus.c,v 1.20 2011/12/09 17:21:45 reinoud Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: ld_thunkbus.c,v 1.21 2011/12/13 13:32:15 jmcneill Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/proc.h> 33#include <sys/proc.h>
34#include <sys/systm.h> 34#include <sys/systm.h>
35#include <sys/device.h> 35#include <sys/device.h>
36#include <sys/buf.h> 36#include <sys/buf.h>
37#include <sys/disk.h> 37#include <sys/disk.h>
38#include <sys/kmem.h> 38#include <sys/kmem.h>
39 39
40#include <dev/ldvar.h> 40#include <dev/ldvar.h>
41 41
42#include <machine/mainbus.h> 42#include <machine/mainbus.h>
43#include <machine/thunk.h> 43#include <machine/thunk.h>
44#include <machine/intr.h> 44#include <machine/intr.h>
45 45
46static int ld_thunkbus_match(device_t, cfdata_t, void *); 46static int ld_thunkbus_match(device_t, cfdata_t, void *);
47static void ld_thunkbus_attach(device_t, device_t, void *); 47static void ld_thunkbus_attach(device_t, device_t, void *);
48 48
49static int ld_thunkbus_ldstart(struct ld_softc *, struct buf *); 49static int ld_thunkbus_ldstart(struct ld_softc *, struct buf *);
50static int ld_thunkbus_lddump(struct ld_softc *, void *, int, int); 50static int ld_thunkbus_lddump(struct ld_softc *, void *, int, int);
51static int ld_thunkbus_ldflush(struct ld_softc *, int); 51static int ld_thunkbus_ldflush(struct ld_softc *, int);
52 52
53//#define LD_USE_AIO 
54 
55#ifdef LD_USE_AIO 
56static void ld_thunkbus_sig(int, siginfo_t *, void *); 
57#endif 
58static void ld_thunkbus_complete(void *arg); 53static void ld_thunkbus_complete(void *arg);
59 54
60struct ld_thunkbus_softc; 55struct ld_thunkbus_softc;
61 56
62struct ld_thunkbus_transfer { 57struct ld_thunkbus_transfer {
63 struct ld_thunkbus_softc *tt_sc; 58 struct ld_thunkbus_softc *tt_sc;
64 struct aiocb tt_aio; 
65 struct buf *tt_bp; 59 struct buf *tt_bp;
66}; 60};
67 61
68struct ld_thunkbus_softc { 62struct ld_thunkbus_softc {
69 struct ld_softc sc_ld; 63 struct ld_softc sc_ld;
70 64
71 int sc_fd; 65 int sc_fd;
72 void *sc_ih; 66 void *sc_ih;
73 67
 68 uint8_t sc_bbuf[MAXBSIZE];
 69
74 struct ld_thunkbus_transfer sc_tt; 70 struct ld_thunkbus_transfer sc_tt;
75 bool busy; 71 bool busy;
76}; 72};
77 73
78CFATTACH_DECL_NEW(ld_thunkbus, sizeof(struct ld_thunkbus_softc), 74CFATTACH_DECL_NEW(ld_thunkbus, sizeof(struct ld_thunkbus_softc),
79 ld_thunkbus_match, ld_thunkbus_attach, NULL, NULL); 75 ld_thunkbus_match, ld_thunkbus_attach, NULL, NULL);
80 76
81static int 77static int
82ld_thunkbus_match(device_t parent, cfdata_t match, void *opaque) 78ld_thunkbus_match(device_t parent, cfdata_t match, void *opaque)
83{ 79{
84 struct thunkbus_attach_args *taa = opaque; 80 struct thunkbus_attach_args *taa = opaque;
85 81
86 if (taa->taa_type != THUNKBUS_TYPE_DISKIMAGE) 82 if (taa->taa_type != THUNKBUS_TYPE_DISKIMAGE)
87 return 0; 83 return 0;
88 84
89 return 1; 85 return 1;
90} 86}
91 87
92static void 88static void
93ld_thunkbus_attach(device_t parent, device_t self, void *opaque) 89ld_thunkbus_attach(device_t parent, device_t self, void *opaque)
94{ 90{
95 struct ld_thunkbus_softc *sc = device_private(self); 91 struct ld_thunkbus_softc *sc = device_private(self);
96 struct ld_softc *ld = &sc->sc_ld; 92 struct ld_softc *ld = &sc->sc_ld;
97 struct thunkbus_attach_args *taa = opaque; 93 struct thunkbus_attach_args *taa = opaque;
98#ifdef LD_USE_AIO 
99 struct sigaction sa; 
100#endif 
101 const char *path = taa->u.diskimage.path; 94 const char *path = taa->u.diskimage.path;
102 ssize_t size, blksize; 95 ssize_t size, blksize;
103 96
104 ld->sc_dv = self; 97 ld->sc_dv = self;
105 98
106 sc->sc_fd = thunk_open(path, O_RDWR, 0); 99 sc->sc_fd = thunk_open(path, O_RDWR, 0);
107 if (sc->sc_fd == -1) { 100 if (sc->sc_fd == -1) {
108 aprint_error(": couldn't open %s: %d\n", path, thunk_geterrno()); 101 aprint_error(": couldn't open %s: %d\n", path, thunk_geterrno());
109 return; 102 return;
110 } 103 }
111 if (thunk_fstat_getsize(sc->sc_fd, &size, &blksize) == -1) { 104 if (thunk_fstat_getsize(sc->sc_fd, &size, &blksize) == -1) {
112 aprint_error(": couldn't stat %s: %d\n", path, thunk_geterrno()); 105 aprint_error(": couldn't stat %s: %d\n", path, thunk_geterrno());
113 return; 106 return;
@@ -116,169 +109,131 @@ ld_thunkbus_attach(device_t parent, devi @@ -116,169 +109,131 @@ ld_thunkbus_attach(device_t parent, devi
116 aprint_naive("\n"); 109 aprint_naive("\n");
117 aprint_normal(": %s (%lld)\n", path, (long long)size); 110 aprint_normal(": %s (%lld)\n", path, (long long)size);
118 111
119 ld->sc_flags = LDF_ENABLED; 112 ld->sc_flags = LDF_ENABLED;
120 ld->sc_maxxfer = blksize; 113 ld->sc_maxxfer = blksize;
121 ld->sc_secsize = 512; 114 ld->sc_secsize = 512;
122 ld->sc_secperunit = size / ld->sc_secsize; 115 ld->sc_secperunit = size / ld->sc_secsize;
123 ld->sc_maxqueuecnt = 1; 116 ld->sc_maxqueuecnt = 1;
124 ld->sc_start = ld_thunkbus_ldstart; 117 ld->sc_start = ld_thunkbus_ldstart;
125 ld->sc_dump = ld_thunkbus_lddump; 118 ld->sc_dump = ld_thunkbus_lddump;
126 ld->sc_flush = ld_thunkbus_ldflush; 119 ld->sc_flush = ld_thunkbus_ldflush;
127 120
128 sc->sc_ih = softint_establish(SOFTINT_BIO, 121 sc->sc_ih = softint_establish(SOFTINT_BIO,
129 ld_thunkbus_complete, sc); 122 ld_thunkbus_complete, ld);
130 
131#ifdef LD_USE_AIO 
132 sa.sa_flags = SA_RESTART | SA_SIGINFO; 
133 sa.sa_sigaction = ld_thunkbus_sig; 
134 thunk_sigemptyset(&sa.sa_mask); 
135// thunk_sigaddset(&sa.sa_mask, SIGALRM); 
136 if (thunk_sigaction(SIGIO, &sa, NULL) == -1) 
137 panic("couldn't register SIGIO handler: %d", thunk_geterrno()); 
138#endif 
139 123
140 sc->busy = false; 124 sc->busy = false;
141 125
142 ldattach(ld); 126 ldattach(ld);
143} 127}
144 128
145#ifdef LD_USE_AIO 
146static void 
147ld_thunkbus_sig(int sig, siginfo_t *info, void *ctx) 
148{ 
149 struct ld_thunkbus_transfer *tt = NULL; 
150 struct ld_thunkbus_softc *sc; 
151 
152 curcpu()->ci_idepth++; 
153 
154 if (info->si_signo == SIGIO) { 
155 if (info->si_code == SI_ASYNCIO) 
156 tt = info->si_value.sival_ptr; 
157 if (tt) { 
158 sc = tt->tt_sc; 
159 spl_intr(IPL_BIO, softint_schedule, sc->sc_ih); 
160 // spl_intr(IPL_BIO, ld_thunkbus_complete, sc); 
161 // softint_schedule(sc->sc_ih); 
162 } 
163 } 
164 
165 curcpu()->ci_idepth--; 
166} 
167#endif 
168 
169static int 129static int
170ld_thunkbus_ldstart(struct ld_softc *ld, struct buf *bp) 130ld_thunkbus_ldstart(struct ld_softc *ld, struct buf *bp)
171{ 131{
172 struct ld_thunkbus_softc *sc = (struct ld_thunkbus_softc *)ld; 132 struct ld_thunkbus_softc *sc = (struct ld_thunkbus_softc *)ld;
173 struct ld_thunkbus_transfer *tt = &sc->sc_tt; 133 struct ld_thunkbus_transfer *tt = &sc->sc_tt;
174 int error; 134 int error;
175 135
176 tt->tt_sc = sc; 136 tt->tt_sc = sc;
177 tt->tt_bp = bp; 137 tt->tt_bp = bp;
178 memset(&tt->tt_aio, 0, sizeof(tt->tt_aio)); 
179 tt->tt_aio.aio_fildes = sc->sc_fd; 
180 tt->tt_aio.aio_buf = bp->b_data; 
181 tt->tt_aio.aio_nbytes = bp->b_bcount; 
182 tt->tt_aio.aio_offset = bp->b_rawblkno * ld->sc_secsize; 
183 
184 tt->tt_aio.aio_sigevent.sigev_notify = SIGEV_SIGNAL; 
185 tt->tt_aio.aio_sigevent.sigev_signo = SIGIO; 
186 tt->tt_aio.aio_sigevent.sigev_value.sival_ptr = tt; 
187#ifdef LD_USE_AIO 
188#if 0 
189 device_printf(sc->sc_ld.sc_dv, "%s addr %p, off=%lld, count=%lld\n", 
190 (bp->b_flags & B_READ) ? "rd" : "wr", 
191 bp->b_data, 
192 (long long)bp->b_rawblkno, 
193 (long long)bp->b_bcount); 
194#endif 
195 if (sc->busy) 
196 panic("%s: reentry", __func__); 
197 sc->busy = true; 
198 138
199 if (bp->b_flags & B_READ) 
200 error = thunk_aio_read(&tt->tt_aio); 
201 else 
202 error = thunk_aio_write(&tt->tt_aio); 
203#else 
204 /* let the softint do the work */ 139 /* let the softint do the work */
205 spl_intr(IPL_BIO, softint_schedule, sc->sc_ih); 
206 sc->busy = true; 140 sc->busy = true;
 141 spl_intr(IPL_BIO, softint_schedule, sc->sc_ih);
207 error = 0; 142 error = 0;
208#endif 143
209 return error == -1 ? thunk_geterrno() : 0; 144 return error == -1 ? thunk_geterrno() : 0;
210} 145}
211 146
212static void 147static void
213ld_thunkbus_complete(void *arg) 148ld_thunkbus_complete(void *arg)
214{ 149{
215 struct ld_thunkbus_softc *sc = arg; 150 struct ld_softc *ld = arg;
 151 struct ld_thunkbus_softc *sc = (struct ld_thunkbus_softc *)ld;
216 struct ld_thunkbus_transfer *tt = &sc->sc_tt; 152 struct ld_thunkbus_transfer *tt = &sc->sc_tt;
217 struct buf *bp = tt->tt_bp; 153 struct buf *bp = tt->tt_bp;
 154 off_t offset = bp->b_rawblkno * ld->sc_secsize;
 155 void *bbuf = sc->sc_bbuf;
 156 size_t ret;
218 157
219 if (!sc->busy) 158 if (!sc->busy)
220 panic("%s: but not busy?\n", __func__); 159 panic("%s: but not busy?\n", __func__);
221 160
222#ifdef LD_USE_AIO 161 if (offset < 0 ||
223 if (thunk_aio_error(&tt->tt_aio) == 0 && 162 offset + bp->b_bcount > ld->sc_secsize * ld->sc_secperunit) {
224 thunk_aio_return(&tt->tt_aio) != -1) { 163 bp->b_error = EIO;
225 bp->b_resid = 0; 
226 } else { 
227 bp->b_error = thunk_geterrno(); 
228 bp->b_resid = bp->b_bcount; 164 bp->b_resid = bp->b_bcount;
 165 goto done;
229 } 166 }
230#else 167
231 size_t ret; 168 //printf("ld: %s %u @ %lld -> %p (flags 0x%08x)\n", bp->b_flags & B_READ ? "read" : "write",
232 off_t offset = tt->tt_aio.aio_offset; 169 // (unsigned int)bp->b_bcount, (long long)offset, bp->b_data, bp->b_flags);
233 170
234 /* read/write the request */ 171 /* read/write the request */
235 if (bp->b_flags & B_READ) 172 if (bp->b_flags & B_READ) {
236 ret = thunk_pread(sc->sc_fd, bp->b_data, bp->b_bcount, offset); 173 if (bp->b_flags & B_PHYS) {
237 else 174 /* read to bounce buffer and copy out */
238 ret = thunk_pwrite(sc->sc_fd, bp->b_data, bp->b_bcount, offset); 175 ret = thunk_pread(sc->sc_fd, bbuf, bp->b_bcount, offset);
 176 if (ret > 0)
 177 copyout(bbuf, bp->b_data, ret);
 178 } else {
 179 /* just read it */
 180 ret = thunk_pread(sc->sc_fd, bp->b_data, bp->b_bcount, offset);
 181 }
 182 } else {
 183 if (bp->b_flags & B_PHYS) {
 184 /* copy in to bounce buffer and write it */
 185 copyin(bp->b_data, bbuf, bp->b_bcount);
 186 ret = thunk_pwrite(sc->sc_fd, bbuf, bp->b_bcount, offset);
 187 } else {
 188 /* just write it */
 189 ret = thunk_pwrite(sc->sc_fd, bp->b_data, bp->b_bcount, offset);
 190 }
 191 }
 192
 193 //if (ret == -1)
 194 // printf("ld: errno = %d\n", thunk_geterrno());
239 195
240 /* setup return params */ 196 /* setup return params */
241 if ((ret >= 0) && (ret == bp->b_bcount)) { 197 if ((ret >= 0) && (ret == bp->b_bcount)) {
242 bp->b_resid = 0; 198 bp->b_resid = 0;
243 } else { 199 } else {
244 bp->b_error = thunk_geterrno(); 200 bp->b_error = thunk_geterrno();
245 bp->b_resid = bp->b_bcount; 201 bp->b_resid = bp->b_bcount;
246 } 202 }
247#endif 
248 203
 204done:
249 dprintf_debug("\tfin\n"); 205 dprintf_debug("\tfin\n");
250 if (bp->b_error) 206 if (bp->b_error)
251 dprintf_debug("error!\n"); 207 dprintf_debug("error!\n");
252 208
253 sc->busy = false; 209 sc->busy = false;
254 lddone(&sc->sc_ld, bp); 210 lddone(&sc->sc_ld, bp);
255} 211}
256 212
257static int 213static int
258ld_thunkbus_lddump(struct ld_softc *ld, void *data, int blkno, int blkcnt) 214ld_thunkbus_lddump(struct ld_softc *ld, void *data, int blkno, int blkcnt)
259{ 215{
260 struct ld_thunkbus_softc *sc = (struct ld_thunkbus_softc *)ld; 216 struct ld_thunkbus_softc *sc = (struct ld_thunkbus_softc *)ld;
261 ssize_t len; 217 ssize_t len;
262 218
263 len = thunk_pwrite(sc->sc_fd, data, blkcnt, blkno); 219 len = thunk_pwrite(sc->sc_fd, data, blkcnt, blkno * ld->sc_secsize);
264 if (len == -1) 220 if (len == -1)
265 return thunk_geterrno(); 221 return thunk_geterrno();
266 else if (len != blkcnt) { 222 else if (len != blkcnt) {
267 device_printf(ld->sc_dv, "%s failed (short xfer)\n", __func__); 223 device_printf(ld->sc_dv, "%s failed (short xfer)\n", __func__);
268 return EIO; 224 return EIO;
269 } 225 }
270 226
271 return 0; 227 return 0;
272} 228}
273 229
274static int 230static int
275ld_thunkbus_ldflush(struct ld_softc *ld, int flags) 231ld_thunkbus_ldflush(struct ld_softc *ld, int flags)
276{ 232{
277 struct ld_thunkbus_softc *sc = (struct ld_thunkbus_softc *)ld; 233 struct ld_thunkbus_softc *sc = (struct ld_thunkbus_softc *)ld;
278 234
279 if (thunk_fsync(sc->sc_fd) == -1) 235 if (thunk_fsync(sc->sc_fd) == -1)
280 return thunk_geterrno(); 236 return thunk_geterrno();
281 237
282 return 0; 238 return 0;
283} 239}
284