diff options
Diffstat (limited to 'fs/btrfs/zlib.c')
| -rw-r--r-- | fs/btrfs/zlib.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c index 759fa4e2de8f..fb22fd8d8fb8 100644 --- a/fs/btrfs/zlib.c +++ b/fs/btrfs/zlib.c | |||
| @@ -299,6 +299,8 @@ done: | |||
| 299 | zlib_inflateEnd(&workspace->strm); | 299 | zlib_inflateEnd(&workspace->strm); |
| 300 | if (data_in) | 300 | if (data_in) |
| 301 | kunmap(pages_in[page_in_index]); | 301 | kunmap(pages_in[page_in_index]); |
| 302 | if (!ret) | ||
| 303 | btrfs_clear_biovec_end(bvec, vcnt, page_out_index, pg_offset); | ||
| 302 | return ret; | 304 | return ret; |
| 303 | } | 305 | } |
| 304 | 306 | ||
| @@ -310,10 +312,14 @@ static int zlib_decompress(struct list_head *ws, unsigned char *data_in, | |||
| 310 | struct workspace *workspace = list_entry(ws, struct workspace, list); | 312 | struct workspace *workspace = list_entry(ws, struct workspace, list); |
| 311 | int ret = 0; | 313 | int ret = 0; |
| 312 | int wbits = MAX_WBITS; | 314 | int wbits = MAX_WBITS; |
| 313 | unsigned long bytes_left = destlen; | 315 | unsigned long bytes_left; |
| 314 | unsigned long total_out = 0; | 316 | unsigned long total_out = 0; |
| 317 | unsigned long pg_offset = 0; | ||
| 315 | char *kaddr; | 318 | char *kaddr; |
| 316 | 319 | ||
| 320 | destlen = min_t(unsigned long, destlen, PAGE_SIZE); | ||
| 321 | bytes_left = destlen; | ||
| 322 | |||
| 317 | workspace->strm.next_in = data_in; | 323 | workspace->strm.next_in = data_in; |
| 318 | workspace->strm.avail_in = srclen; | 324 | workspace->strm.avail_in = srclen; |
| 319 | workspace->strm.total_in = 0; | 325 | workspace->strm.total_in = 0; |
| @@ -341,7 +347,6 @@ static int zlib_decompress(struct list_head *ws, unsigned char *data_in, | |||
| 341 | unsigned long buf_start; | 347 | unsigned long buf_start; |
| 342 | unsigned long buf_offset; | 348 | unsigned long buf_offset; |
| 343 | unsigned long bytes; | 349 | unsigned long bytes; |
| 344 | unsigned long pg_offset = 0; | ||
| 345 | 350 | ||
| 346 | ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH); | 351 | ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH); |
| 347 | if (ret != Z_OK && ret != Z_STREAM_END) | 352 | if (ret != Z_OK && ret != Z_STREAM_END) |
| @@ -384,6 +389,17 @@ next: | |||
| 384 | ret = 0; | 389 | ret = 0; |
| 385 | 390 | ||
| 386 | zlib_inflateEnd(&workspace->strm); | 391 | zlib_inflateEnd(&workspace->strm); |
| 392 | |||
| 393 | /* | ||
| 394 | * this should only happen if zlib returned fewer bytes than we | ||
| 395 | * expected. btrfs_get_block is responsible for zeroing from the | ||
| 396 | * end of the inline extent (destlen) to the end of the page | ||
| 397 | */ | ||
| 398 | if (pg_offset < destlen) { | ||
| 399 | kaddr = kmap_atomic(dest_page); | ||
| 400 | memset(kaddr + pg_offset, 0, destlen - pg_offset); | ||
| 401 | kunmap_atomic(kaddr); | ||
| 402 | } | ||
| 387 | return ret; | 403 | return ret; |
| 388 | } | 404 | } |
| 389 | 405 | ||
