diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2010-11-08 02:22:19 -0500 |
---|---|---|
committer | Li Zefan <lizf@cn.fujitsu.com> | 2010-12-22 10:15:50 -0500 |
commit | 3a39c18d63fec35f49df577d4b2a4e29c2212f22 (patch) | |
tree | 78b8c032e18e2231c18e89ac3f8f5746abdb119c /fs/btrfs/lzo.c | |
parent | 1a419d85a76853d7d04e9b6280a80e96770bf3e3 (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.c | 101 |
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 | } |
454 | done: | 365 | done: |
455 | if (data_in) | 366 | if (data_in) |