g_uzip.c (269456) | g_uzip.c (266220) |
---|---|
1/*- 2 * Copyright (c) 2004 Max Khon | 1/*- 2 * Copyright (c) 2004 Max Khon |
3 * Copyright (c) 2014 Juniper Networks, Inc. | |
4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright --- 9 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> | 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 9 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: stable/10/sys/geom/uzip/g_uzip.c 269456 2014-08-03 03:06:00Z marcel $"); | 28__FBSDID("$FreeBSD: stable/10/sys/geom/uzip/g_uzip.c 266220 2014-05-16 14:28:55Z loos $"); |
30 31#include <sys/param.h> 32#include <sys/bio.h> 33#include <sys/endian.h> 34#include <sys/errno.h> 35#include <sys/kernel.h> 36#include <sys/lock.h> 37#include <sys/mutex.h> --- 44 unchanged lines hidden (view full) --- 82 83 struct mtx last_mtx; 84 uint32_t last_blk; /* last blk no */ 85 char *last_buf; /* last blk data */ 86 int req_total; /* total requests */ 87 int req_cached; /* cached requests */ 88}; 89 | 29 30#include <sys/param.h> 31#include <sys/bio.h> 32#include <sys/endian.h> 33#include <sys/errno.h> 34#include <sys/kernel.h> 35#include <sys/lock.h> 36#include <sys/mutex.h> --- 44 unchanged lines hidden (view full) --- 81 82 struct mtx last_mtx; 83 uint32_t last_blk; /* last blk no */ 84 char *last_buf; /* last blk data */ 85 int req_total; /* total requests */ 86 int req_cached; /* cached requests */ 87}; 88 |
90static void g_uzip_done(struct bio *bp); 91 | |
92static void 93g_uzip_softc_free(struct g_uzip_softc *sc, struct g_geom *gp) 94{ 95 96 if (gp != NULL) { 97 printf("%s: %d requests, %d cached\n", 98 gp->name, sc->req_total, sc->req_cached); 99 } --- 18 unchanged lines hidden (view full) --- 118 119static void 120z_free(void *nil, void *ptr) 121{ 122 123 free(ptr, M_GEOM_UZIP); 124} 125 | 89static void 90g_uzip_softc_free(struct g_uzip_softc *sc, struct g_geom *gp) 91{ 92 93 if (gp != NULL) { 94 printf("%s: %d requests, %d cached\n", 95 gp->name, sc->req_total, sc->req_cached); 96 } --- 18 unchanged lines hidden (view full) --- 115 116static void 117z_free(void *nil, void *ptr) 118{ 119 120 free(ptr, M_GEOM_UZIP); 121} 122 |
126static int 127g_uzip_cached(struct g_geom *gp, struct bio *bp) 128{ 129 struct g_uzip_softc *sc; 130 off_t ofs; 131 size_t blk, blkofs, usz; 132 133 sc = gp->softc; 134 ofs = bp->bio_offset + bp->bio_completed; 135 blk = ofs / sc->blksz; 136 mtx_lock(&sc->last_mtx); 137 if (blk == sc->last_blk) { 138 blkofs = ofs % sc->blksz; 139 usz = sc->blksz - blkofs; 140 if (bp->bio_resid < usz) 141 usz = bp->bio_resid; 142 memcpy(bp->bio_data + bp->bio_completed, sc->last_buf + blkofs, 143 usz); 144 sc->req_cached++; 145 mtx_unlock(&sc->last_mtx); 146 147 DPRINTF(("%s/%s: %p: offset=%jd: got %jd bytes from cache\n", 148 __func__, gp->name, bp, (intmax_t)ofs, (intmax_t)usz)); 149 150 bp->bio_completed += usz; 151 bp->bio_resid -= usz; 152 153 if (bp->bio_resid == 0) { 154 g_io_deliver(bp, 0); 155 return (1); 156 } 157 } else 158 mtx_unlock(&sc->last_mtx); 159 160 return (0); 161} 162 163static int 164g_uzip_request(struct g_geom *gp, struct bio *bp) 165{ 166 struct g_uzip_softc *sc; 167 struct bio *bp2; 168 struct g_consumer *cp; 169 struct g_provider *pp; 170 off_t ofs; 171 size_t start_blk, end_blk; 172 173 if (g_uzip_cached(gp, bp) != 0) 174 return (1); 175 176 sc = gp->softc; 177 178 bp2 = g_clone_bio(bp); 179 if (bp2 == NULL) { 180 g_io_deliver(bp, ENOMEM); 181 return (1); 182 } 183 bp2->bio_done = g_uzip_done; 184 185 cp = LIST_FIRST(&gp->consumer); 186 pp = cp->provider; 187 188 ofs = bp->bio_offset + bp->bio_completed; 189 start_blk = ofs / sc->blksz; 190 KASSERT(start_blk < sc->nblocks, ("start_blk out of range")); 191 end_blk = (ofs + bp->bio_resid + sc->blksz - 1) / sc->blksz; 192 KASSERT(end_blk <= sc->nblocks, ("end_blk out of range")); 193 194 DPRINTF(("%s/%s: %p: start=%u (%jd), end=%u (%jd)\n", 195 __func__, gp->name, bp, 196 (u_int)start_blk, (intmax_t)sc->offsets[start_blk], 197 (u_int)end_blk, (intmax_t)sc->offsets[end_blk])); 198 199 bp2->bio_offset = sc->offsets[start_blk] - 200 sc->offsets[start_blk] % pp->sectorsize; 201 while (1) { 202 bp2->bio_length = sc->offsets[end_blk] - bp2->bio_offset; 203 bp2->bio_length = (bp2->bio_length + pp->sectorsize - 1) / 204 pp->sectorsize * pp->sectorsize; 205 if (bp2->bio_length <= MAXPHYS) 206 break; 207 208 end_blk--; 209 } 210 211 bp2->bio_data = malloc(bp2->bio_length, M_GEOM_UZIP, M_NOWAIT); 212 if (bp2->bio_data == NULL) { 213 g_destroy_bio(bp2); 214 g_io_deliver(bp, ENOMEM); 215 return (1); 216 } 217 218 DPRINTF(("%s/%s: %p: reading %jd bytes from offset %jd\n", 219 __func__, gp->name, bp, 220 (intmax_t)bp2->bio_length, (intmax_t)bp2->bio_offset)); 221 222 g_io_request(bp2, cp); 223 return (0); 224} 225 | |
226static void 227g_uzip_done(struct bio *bp) 228{ | 123static void 124g_uzip_done(struct bio *bp) 125{ |
229 z_stream zs; | 126 int err; |
230 struct bio *bp2; | 127 struct bio *bp2; |
231 struct g_provider *pp; | 128 z_stream zs; 129 struct g_provider *pp, *pp2; |
232 struct g_consumer *cp; 233 struct g_geom *gp; 234 struct g_uzip_softc *sc; | 130 struct g_consumer *cp; 131 struct g_geom *gp; 132 struct g_uzip_softc *sc; |
235 char *data, *data2; 236 off_t ofs; 237 size_t blk, blkofs, len, ulen; | 133 off_t iolen, pos, upos; 134 uint32_t start_blk, i; 135 size_t bsize; |
238 239 bp2 = bp->bio_parent; | 136 137 bp2 = bp->bio_parent; |
240 gp = bp2->bio_to->geom; | 138 pp = bp2->bio_to; 139 gp = pp->geom; 140 cp = LIST_FIRST(&gp->consumer); 141 pp2 = cp->provider; |
241 sc = gp->softc; | 142 sc = gp->softc; |
143 DPRINTF(("%s: done\n", gp->name)); |
|
242 | 144 |
243 cp = LIST_FIRST(&gp->consumer); 244 pp = cp->provider; 245 | |
246 bp2->bio_error = bp->bio_error; 247 if (bp2->bio_error != 0) 248 goto done; 249 | 145 bp2->bio_error = bp->bio_error; 146 if (bp2->bio_error != 0) 147 goto done; 148 |
250 /* Make sure there's forward progress. */ 251 if (bp->bio_completed == 0) { 252 bp2->bio_error = ECANCELED; 253 goto done; 254 } 255 | 149 /* 150 * Uncompress data. 151 */ |
256 zs.zalloc = z_alloc; 257 zs.zfree = z_free; | 152 zs.zalloc = z_alloc; 153 zs.zfree = z_free; |
258 if (inflateInit(&zs) != Z_OK) { 259 bp2->bio_error = EILSEQ; | 154 err = inflateInit(&zs); 155 if (err != Z_OK) { 156 bp2->bio_error = EIO; |
260 goto done; 261 } | 157 goto done; 158 } |
159 start_blk = bp2->bio_offset / sc->blksz; 160 bsize = pp2->sectorsize; 161 iolen = bp->bio_completed; 162 pos = sc->offsets[start_blk] % bsize; 163 upos = 0; 164 DPRINTF(("%s: done: start_blk %d, pos %jd, upos %jd, iolen %jd " 165 "(%jd, %d, %zd)\n", 166 gp->name, start_blk, (intmax_t)pos, (intmax_t)upos, 167 (intmax_t)iolen, (intmax_t)bp2->bio_offset, sc->blksz, bsize)); 168 for (i = start_blk; upos < bp2->bio_length; i++) { 169 off_t len, ulen, uoff; |
|
262 | 170 |
263 ofs = bp2->bio_offset + bp2->bio_completed; 264 blk = ofs / sc->blksz; 265 blkofs = ofs % sc->blksz; 266 data = bp->bio_data + sc->offsets[blk] % pp->sectorsize; 267 data2 = bp2->bio_data + bp2->bio_completed; 268 while (bp->bio_completed && bp2->bio_resid) { 269 ulen = MIN(sc->blksz - blkofs, bp2->bio_resid); 270 len = sc->offsets[blk + 1] - sc->offsets[blk]; 271 DPRINTF(("%s/%s: %p/%ju: data2=%p, ulen=%u, data=%p, len=%u\n", 272 __func__, gp->name, gp, bp->bio_completed, 273 data2, (u_int)ulen, data, (u_int)len)); | 171 uoff = i == start_blk ? bp2->bio_offset % sc->blksz : 0; 172 ulen = MIN(sc->blksz - uoff, bp2->bio_length - upos); 173 len = sc->offsets[i + 1] - sc->offsets[i]; 174 |
274 if (len == 0) { 275 /* All zero block: no cache update */ | 175 if (len == 0) { 176 /* All zero block: no cache update */ |
276 bzero(data2, ulen); 277 } else if (len <= bp->bio_completed) { 278 zs.next_in = data; 279 zs.avail_in = len; 280 zs.next_out = sc->last_buf; 281 zs.avail_out = sc->blksz; 282 mtx_lock(&sc->last_mtx); 283 if (inflate(&zs, Z_FINISH) != Z_STREAM_END) { 284 sc->last_blk = -1; 285 mtx_unlock(&sc->last_mtx); 286 inflateEnd(&zs); 287 bp2->bio_error = EILSEQ; 288 goto done; 289 } 290 sc->last_blk = blk; 291 memcpy(data2, sc->last_buf + blkofs, ulen); 292 mtx_unlock(&sc->last_mtx); 293 if (inflateReset(&zs) != Z_OK) { 294 inflateEnd(&zs); 295 bp2->bio_error = EILSEQ; 296 goto done; 297 } 298 data += len; 299 } else | 177 bzero(bp2->bio_data + upos, ulen); 178 upos += ulen; 179 bp2->bio_completed += ulen; 180 continue; 181 } 182 if (len > iolen) { 183 DPRINTF(("%s: done: early termination: len (%jd) > " 184 "iolen (%jd)\n", 185 gp->name, (intmax_t)len, (intmax_t)iolen)); |
300 break; | 186 break; |
187 } 188 zs.next_in = bp->bio_data + pos; 189 zs.avail_in = len; 190 zs.next_out = sc->last_buf; 191 zs.avail_out = sc->blksz; 192 mtx_lock(&sc->last_mtx); 193 err = inflate(&zs, Z_FINISH); 194 if (err != Z_STREAM_END) { 195 sc->last_blk = -1; 196 mtx_unlock(&sc->last_mtx); 197 DPRINTF(("%s: done: inflate failed (%jd + %jd -> %jd + %jd + %jd)\n", 198 gp->name, (intmax_t)pos, (intmax_t)len, 199 (intmax_t)uoff, (intmax_t)upos, (intmax_t)ulen)); 200 inflateEnd(&zs); 201 bp2->bio_error = EIO; 202 goto done; 203 } 204 sc->last_blk = i; 205 DPRINTF(("%s: done: inflated %jd + %jd -> %jd + %jd + %jd\n", 206 gp->name, (intmax_t)pos, (intmax_t)len, (intmax_t)uoff, 207 (intmax_t)upos, (intmax_t)ulen)); 208 memcpy(bp2->bio_data + upos, sc->last_buf + uoff, ulen); 209 mtx_unlock(&sc->last_mtx); |
|
301 | 210 |
302 data2 += ulen; | 211 pos += len; 212 iolen -= len; 213 upos += ulen; |
303 bp2->bio_completed += ulen; | 214 bp2->bio_completed += ulen; |
304 bp2->bio_resid -= ulen; 305 bp->bio_completed -= len; 306 blkofs = 0; 307 blk++; | 215 err = inflateReset(&zs); 216 if (err != Z_OK) { 217 inflateEnd(&zs); 218 bp2->bio_error = EIO; 219 goto done; 220 } |
308 } | 221 } |
222 err = inflateEnd(&zs); 223 if (err != Z_OK) { 224 bp2->bio_error = EIO; 225 goto done; 226 } |
|
309 | 227 |
310 if (inflateEnd(&zs) != Z_OK) 311 bp2->bio_error = EILSEQ; 312 | |
313done: | 228done: |
314 /* Finish processing the request. */ | 229 /* 230 * Finish processing the request. 231 */ 232 DPRINTF(("%s: done: (%d, %jd, %ld)\n", 233 gp->name, bp2->bio_error, (intmax_t)bp2->bio_completed, 234 bp2->bio_resid)); |
315 free(bp->bio_data, M_GEOM_UZIP); 316 g_destroy_bio(bp); | 235 free(bp->bio_data, M_GEOM_UZIP); 236 g_destroy_bio(bp); |
317 if (bp2->bio_error != 0 || bp2->bio_resid == 0) 318 g_io_deliver(bp2, bp2->bio_error); 319 else 320 g_uzip_request(gp, bp2); | 237 g_io_deliver(bp2, bp2->bio_error); |
321} 322 323static void 324g_uzip_start(struct bio *bp) 325{ | 238} 239 240static void 241g_uzip_start(struct bio *bp) 242{ |
326 struct g_provider *pp; | 243 struct bio *bp2; 244 struct g_provider *pp, *pp2; |
327 struct g_geom *gp; | 245 struct g_geom *gp; |
246 struct g_consumer *cp; |
|
328 struct g_uzip_softc *sc; | 247 struct g_uzip_softc *sc; |
248 uint32_t start_blk, end_blk; 249 size_t bsize; |
|
329 330 pp = bp->bio_to; 331 gp = pp->geom; | 250 251 pp = bp->bio_to; 252 gp = pp->geom; |
253 DPRINTF(("%s: start (%d)\n", gp->name, bp->bio_cmd)); |
|
332 | 254 |
333 DPRINTF(("%s/%s: %p: cmd=%d, offset=%jd, length=%jd, buffer=%p\n", 334 __func__, gp->name, bp, bp->bio_cmd, (intmax_t)bp->bio_offset, 335 (intmax_t)bp->bio_length, bp->bio_data)); | 255 if (bp->bio_cmd != BIO_READ) { 256 g_io_deliver(bp, EOPNOTSUPP); 257 return; 258 } |
336 | 259 |
260 cp = LIST_FIRST(&gp->consumer); 261 pp2 = cp->provider; |
|
337 sc = gp->softc; | 262 sc = gp->softc; |
263 264 start_blk = bp->bio_offset / sc->blksz; 265 end_blk = (bp->bio_offset + bp->bio_length + sc->blksz - 1) / sc->blksz; 266 KASSERT(start_blk < sc->nblocks, ("start_blk out of range")); 267 KASSERT(end_blk <= sc->nblocks, ("end_blk out of range")); 268 |
|
338 sc->req_total++; | 269 sc->req_total++; |
270 if (start_blk + 1 == end_blk) { 271 mtx_lock(&sc->last_mtx); 272 if (start_blk == sc->last_blk) { 273 off_t uoff; |
|
339 | 274 |
340 if (bp->bio_cmd != BIO_READ) { 341 g_io_deliver(bp, EOPNOTSUPP); | 275 uoff = bp->bio_offset % sc->blksz; 276 KASSERT(bp->bio_length <= sc->blksz - uoff, 277 ("cached data error")); 278 memcpy(bp->bio_data, sc->last_buf + uoff, 279 bp->bio_length); 280 sc->req_cached++; 281 mtx_unlock(&sc->last_mtx); 282 283 DPRINTF(("%s: start: cached 0 + %jd, %jd + 0 + %jd\n", 284 gp->name, (intmax_t)bp->bio_length, (intmax_t)uoff, 285 (intmax_t)bp->bio_length)); 286 bp->bio_completed = bp->bio_length; 287 g_io_deliver(bp, 0); 288 return; 289 } 290 mtx_unlock(&sc->last_mtx); 291 } 292 293 bp2 = g_clone_bio(bp); 294 if (bp2 == NULL) { 295 g_io_deliver(bp, ENOMEM); |
342 return; 343 } | 296 return; 297 } |
298 bp2->bio_done = g_uzip_done; 299 DPRINTF(("%s: start (%d..%d), %s: %d + %jd, %s: %d + %jd\n", 300 gp->name, start_blk, end_blk, 301 pp->name, pp->sectorsize, (intmax_t)pp->mediasize, 302 pp2->name, pp2->sectorsize, (intmax_t)pp2->mediasize)); 303 bsize = pp2->sectorsize; 304 bp2->bio_offset = sc->offsets[start_blk] - sc->offsets[start_blk] % bsize; 305 while (1) { 306 bp2->bio_length = sc->offsets[end_blk] - bp2->bio_offset; 307 bp2->bio_length = (bp2->bio_length + bsize - 1) / bsize * bsize; 308 if (bp2->bio_length < MAXPHYS) 309 break; |
|
344 | 310 |
345 bp->bio_resid = bp->bio_length; 346 bp->bio_completed = 0; | 311 end_blk--; 312 DPRINTF(("%s: bio_length (%jd) > MAXPHYS: lowering end_blk " 313 "to %u\n", gp->name, (intmax_t)bp2->bio_length, end_blk)); 314 } 315 DPRINTF(("%s: start %jd + %jd -> %ju + %ju -> %jd + %jd\n", 316 gp->name, 317 (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length, 318 (uintmax_t)sc->offsets[start_blk], 319 (uintmax_t)sc->offsets[end_blk] - sc->offsets[start_blk], 320 (intmax_t)bp2->bio_offset, (intmax_t)bp2->bio_length)); 321 bp2->bio_data = malloc(bp2->bio_length, M_GEOM_UZIP, M_NOWAIT); 322 if (bp2->bio_data == NULL) { 323 g_destroy_bio(bp2); 324 g_io_deliver(bp, ENOMEM); 325 return; 326 } |
347 | 327 |
348 g_uzip_request(gp, bp); | 328 g_io_request(bp2, cp); 329 DPRINTF(("%s: start ok\n", gp->name)); |
349} 350 351static void 352g_uzip_orphan(struct g_consumer *cp) 353{ 354 struct g_geom *gp; 355 356 g_trace(G_T_TOPOLOGY, "%s(%p/%s)", __func__, cp, cp->provider->name); --- 224 unchanged lines hidden --- | 330} 331 332static void 333g_uzip_orphan(struct g_consumer *cp) 334{ 335 struct g_geom *gp; 336 337 g_trace(G_T_TOPOLOGY, "%s(%p/%s)", __func__, cp, cp->provider->name); --- 224 unchanged lines hidden --- |