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>
This commit is contained in:
111
fs/btrfs/zlib.c
111
fs/btrfs/zlib.c
@@ -218,24 +218,16 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
|
||||
size_t srclen)
|
||||
{
|
||||
struct workspace *workspace = list_entry(ws, struct workspace, list);
|
||||
int ret = 0;
|
||||
int ret = 0, ret2;
|
||||
int wbits = MAX_WBITS;
|
||||
char *data_in;
|
||||
size_t total_out = 0;
|
||||
unsigned long page_bytes_left;
|
||||
unsigned long page_in_index = 0;
|
||||
unsigned long page_out_index = 0;
|
||||
struct page *page_out;
|
||||
unsigned long total_pages_in = (srclen + PAGE_CACHE_SIZE - 1) /
|
||||
PAGE_CACHE_SIZE;
|
||||
unsigned long buf_start;
|
||||
unsigned long buf_offset;
|
||||
unsigned long bytes;
|
||||
unsigned long working_bytes;
|
||||
unsigned long pg_offset;
|
||||
unsigned long start_byte;
|
||||
unsigned long current_buf_start;
|
||||
char *kaddr;
|
||||
|
||||
data_in = kmap(pages_in[page_in_index]);
|
||||
workspace->inf_strm.next_in = data_in;
|
||||
@@ -245,8 +237,6 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
|
||||
workspace->inf_strm.total_out = 0;
|
||||
workspace->inf_strm.next_out = workspace->buf;
|
||||
workspace->inf_strm.avail_out = PAGE_CACHE_SIZE;
|
||||
page_out = bvec[page_out_index].bv_page;
|
||||
page_bytes_left = PAGE_CACHE_SIZE;
|
||||
pg_offset = 0;
|
||||
|
||||
/* If it's deflate, and it's got no preset dictionary, then
|
||||
@@ -268,100 +258,23 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
|
||||
ret = zlib_inflate(&workspace->inf_strm, Z_NO_FLUSH);
|
||||
if (ret != Z_OK && ret != Z_STREAM_END)
|
||||
break;
|
||||
/*
|
||||
* buf start is the byte offset we're of the start of
|
||||
* our workspace buffer
|
||||
*/
|
||||
buf_start = total_out;
|
||||
|
||||
/* total_out is the last byte of the workspace buffer */
|
||||
buf_start = total_out;
|
||||
total_out = workspace->inf_strm.total_out;
|
||||
|
||||
working_bytes = total_out - buf_start;
|
||||
|
||||
/*
|
||||
* start byte is the first byte of the page we're currently
|
||||
* copying into relative to the start of the compressed data.
|
||||
*/
|
||||
start_byte = page_offset(page_out) - disk_start;
|
||||
|
||||
if (working_bytes == 0) {
|
||||
/* we didn't make progress in this inflate
|
||||
* call, we're done
|
||||
*/
|
||||
if (ret != Z_STREAM_END)
|
||||
ret = -1;
|
||||
/* we didn't make progress in this inflate call, we're done */
|
||||
if (buf_start == total_out)
|
||||
break;
|
||||
|
||||
ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
|
||||
total_out, disk_start,
|
||||
bvec, vcnt,
|
||||
&page_out_index, &pg_offset);
|
||||
if (ret2 == 0) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* we haven't yet hit data corresponding to this page */
|
||||
if (total_out <= start_byte)
|
||||
goto next;
|
||||
|
||||
/*
|
||||
* the start of the data we care about is offset into
|
||||
* the middle of our working buffer
|
||||
*/
|
||||
if (total_out > start_byte && buf_start < start_byte) {
|
||||
buf_offset = start_byte - buf_start;
|
||||
working_bytes -= buf_offset;
|
||||
} else {
|
||||
buf_offset = 0;
|
||||
}
|
||||
current_buf_start = buf_start;
|
||||
|
||||
/* copy bytes from the working buffer into the pages */
|
||||
while (working_bytes > 0) {
|
||||
bytes = min(PAGE_CACHE_SIZE - pg_offset,
|
||||
PAGE_CACHE_SIZE - buf_offset);
|
||||
bytes = min(bytes, working_bytes);
|
||||
kaddr = kmap_atomic(page_out, KM_USER0);
|
||||
memcpy(kaddr + pg_offset, workspace->buf + buf_offset,
|
||||
bytes);
|
||||
kunmap_atomic(kaddr, KM_USER0);
|
||||
flush_dcache_page(page_out);
|
||||
|
||||
pg_offset += bytes;
|
||||
page_bytes_left -= bytes;
|
||||
buf_offset += bytes;
|
||||
working_bytes -= bytes;
|
||||
current_buf_start += bytes;
|
||||
|
||||
/* check if we need to pick another page */
|
||||
if (page_bytes_left == 0) {
|
||||
page_out_index++;
|
||||
if (page_out_index >= vcnt) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
page_out = bvec[page_out_index].bv_page;
|
||||
pg_offset = 0;
|
||||
page_bytes_left = PAGE_CACHE_SIZE;
|
||||
start_byte = page_offset(page_out) - disk_start;
|
||||
|
||||
/*
|
||||
* make sure our new page is covered by this
|
||||
* working buffer
|
||||
*/
|
||||
if (total_out <= start_byte)
|
||||
goto next;
|
||||
|
||||
/* the next page in the biovec might not
|
||||
* be adjacent to the last page, but it
|
||||
* might still be found inside this working
|
||||
* buffer. bump our offset pointer
|
||||
*/
|
||||
if (total_out > start_byte &&
|
||||
current_buf_start < start_byte) {
|
||||
buf_offset = start_byte - buf_start;
|
||||
working_bytes = total_out - start_byte;
|
||||
current_buf_start = buf_start +
|
||||
buf_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
next:
|
||||
workspace->inf_strm.next_out = workspace->buf;
|
||||
workspace->inf_strm.avail_out = PAGE_CACHE_SIZE;
|
||||
|
||||
|
Reference in New Issue
Block a user