diff options
| author | Chris Mason <clm@fb.com> | 2014-11-30 16:56:33 +0300 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-11-30 20:33:51 +0300 | 
| commit | 2f19cad94cee3c9bd52d0c9ca584ef506302fb7c (patch) | |
| tree | ca1a69874842c86904ff6b66cb7430c818f2baa4 /fs/btrfs/compression.c | |
| parent | 7a5a4f978750756755dc839014e13d1b088ccc8e (diff) | |
| download | linux-2f19cad94cee3c9bd52d0c9ca584ef506302fb7c.tar.xz | |
btrfs: zero out left over bytes after processing compression streams
Don Bailey noticed that our page zeroing for compression at end-io time
isn't complete.  This reworks a patch from Linus to push the zeroing
into the zlib and lzo specific functions instead of trying to handle the
corners inside btrfs_decompress_buf2page
Signed-off-by: Chris Mason <clm@fb.com>
Reviewed-by: Josef Bacik <jbacik@fb.com>
Reported-by: Don A. Bailey <donb@securitymouse.com>
cc: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/btrfs/compression.c')
| -rw-r--r-- | fs/btrfs/compression.c | 33 | 
1 files changed, 31 insertions, 2 deletions
| diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index d3220d31d3cb..dcd9be32ac57 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -1011,8 +1011,6 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,  		bytes = min(bytes, working_bytes);  		kaddr = kmap_atomic(page_out);  		memcpy(kaddr + *pg_offset, buf + buf_offset, bytes); -		if (*pg_index == (vcnt - 1) && *pg_offset == 0) -			memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);  		kunmap_atomic(kaddr);  		flush_dcache_page(page_out); @@ -1054,3 +1052,34 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,  	return 1;  } + +/* + * When uncompressing data, we need to make sure and zero any parts of + * the biovec that were not filled in by the decompression code.  pg_index + * and pg_offset indicate the last page and the last offset of that page + * that have been filled in.  This will zero everything remaining in the + * biovec. + */ +void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt, +				   unsigned long pg_index, +				   unsigned long pg_offset) +{ +	while (pg_index < vcnt) { +		struct page *page = bvec[pg_index].bv_page; +		unsigned long off = bvec[pg_index].bv_offset; +		unsigned long len = bvec[pg_index].bv_len; + +		if (pg_offset < off) +			pg_offset = off; +		if (pg_offset < off + len) { +			unsigned long bytes = off + len - pg_offset; +			char *kaddr; + +			kaddr = kmap_atomic(page); +			memset(kaddr + pg_offset, 0, bytes); +			kunmap_atomic(kaddr); +		} +		pg_index++; +		pg_offset = 0; +	} +} | 
