aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/lzo.c
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2010-11-08 02:22:19 -0500
committerLi Zefan <lizf@cn.fujitsu.com>2010-12-22 10:15:50 -0500
commit3a39c18d63fec35f49df577d4b2a4e29c2212f22 (patch)
tree78b8c032e18e2231c18e89ac3f8f5746abdb119c /fs/btrfs/lzo.c
parent1a419d85a76853d7d04e9b6280a80e96770bf3e3 (diff)
btrfs: Extract duplicate decompress code
Add a common function to copy decompressed data from working buffer to bio pages. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/lzo.c')
-rw-r--r--fs/btrfs/lzo.c101
1 files changed, 6 insertions, 95 deletions
diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
index 523b144e2aec..cc9b450399df 100644
--- a/fs/btrfs/lzo.c
+++ b/fs/btrfs/lzo.c
@@ -260,12 +260,10 @@ static int lzo_decompress_biovec(struct list_head *ws,
260 size_t srclen) 260 size_t srclen)
261{ 261{
262 struct workspace *workspace = list_entry(ws, struct workspace, list); 262 struct workspace *workspace = list_entry(ws, struct workspace, list);
263 int ret = 0; 263 int ret = 0, ret2;
264 char *data_in; 264 char *data_in;
265 unsigned long page_bytes_left;
266 unsigned long page_in_index = 0; 265 unsigned long page_in_index = 0;
267 unsigned long page_out_index = 0; 266 unsigned long page_out_index = 0;
268 struct page *page_out;
269 unsigned long total_pages_in = (srclen + PAGE_CACHE_SIZE - 1) / 267 unsigned long total_pages_in = (srclen + PAGE_CACHE_SIZE - 1) /
270 PAGE_CACHE_SIZE; 268 PAGE_CACHE_SIZE;
271 unsigned long buf_start; 269 unsigned long buf_start;
@@ -273,9 +271,6 @@ static int lzo_decompress_biovec(struct list_head *ws,
273 unsigned long bytes; 271 unsigned long bytes;
274 unsigned long working_bytes; 272 unsigned long working_bytes;
275 unsigned long pg_offset; 273 unsigned long pg_offset;
276 unsigned long start_byte;
277 unsigned long current_buf_start;
278 char *kaddr;
279 274
280 size_t in_len; 275 size_t in_len;
281 size_t out_len; 276 size_t out_len;
@@ -295,8 +290,6 @@ static int lzo_decompress_biovec(struct list_head *ws,
295 in_page_bytes_left = PAGE_CACHE_SIZE - LZO_LEN; 290 in_page_bytes_left = PAGE_CACHE_SIZE - LZO_LEN;
296 291
297 tot_out = 0; 292 tot_out = 0;
298 page_out = bvec[0].bv_page;
299 page_bytes_left = PAGE_CACHE_SIZE;
300 pg_offset = 0; 293 pg_offset = 0;
301 294
302 while (tot_in < tot_len) { 295 while (tot_in < tot_len) {
@@ -359,97 +352,15 @@ cont:
359 break; 352 break;
360 } 353 }
361 354
362 /*
363 * buf start is the byte offset we're of the start of
364 * our workspace buffer
365 */
366 buf_start = tot_out; 355 buf_start = tot_out;
367
368 /* tot_out is the last byte of the workspace buffer */
369 tot_out += out_len; 356 tot_out += out_len;
370 357
371 working_bytes = tot_out - buf_start; 358 ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
372 359 tot_out, disk_start,
373 /* 360 bvec, vcnt,
374 * start_byte is the first byte of the page we're currently 361 &page_out_index, &pg_offset);
375 * copying into relative to the start of the compressed data. 362 if (ret2 == 0)
376 */
377 start_byte = page_offset(page_out) - disk_start;
378
379 if (working_bytes == 0) {
380 /* we didn't make progress in this inflate
381 * call, we're done
382 */
383 break; 363 break;
384 }
385
386 /* we haven't yet hit data corresponding to this page */
387 if (tot_out <= start_byte)
388 continue;
389
390 /*
391 * the start of the data we care about is offset into
392 * the middle of our working buffer
393 */
394 if (tot_out > start_byte && buf_start < start_byte) {
395 buf_offset = start_byte - buf_start;
396 working_bytes -= buf_offset;
397 } else {
398 buf_offset = 0;
399 }
400 current_buf_start = buf_start;
401
402 /* copy bytes from the working buffer into the pages */
403 while (working_bytes > 0) {
404 bytes = min(PAGE_CACHE_SIZE - pg_offset,
405 PAGE_CACHE_SIZE - buf_offset);
406 bytes = min(bytes, working_bytes);
407 kaddr = kmap_atomic(page_out, KM_USER0);
408 memcpy(kaddr + pg_offset, workspace->buf + buf_offset,
409 bytes);
410 kunmap_atomic(kaddr, KM_USER0);
411 flush_dcache_page(page_out);
412
413 pg_offset += bytes;
414 page_bytes_left -= bytes;
415 buf_offset += bytes;
416 working_bytes -= bytes;
417 current_buf_start += bytes;
418
419 /* check if we need to pick another page */
420 if (page_bytes_left == 0) {
421 page_out_index++;
422 if (page_out_index >= vcnt) {
423 ret = 0;
424 goto done;
425 }
426
427 page_out = bvec[page_out_index].bv_page;
428 pg_offset = 0;
429 page_bytes_left = PAGE_CACHE_SIZE;
430 start_byte = page_offset(page_out) - disk_start;
431
432 /*
433 * make sure our new page is covered by this
434 * working buffer
435 */
436 if (tot_out <= start_byte)
437 break;
438
439 /* the next page in the biovec might not
440 * be adjacent to the last page, but it
441 * might still be found inside this working
442 * buffer. bump our offset pointer
443 */
444 if (tot_out > start_byte &&
445 current_buf_start < start_byte) {
446 buf_offset = start_byte - buf_start;
447 working_bytes = tot_out - start_byte;
448 current_buf_start = buf_start +
449 buf_offset;
450 }
451 }
452 }
453 } 364 }
454done: 365done:
455 if (data_in) 366 if (data_in)