Deleted Added
full compact
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 ---