aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/zlib.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/zlib.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/zlib.c')
-rw-r--r--fs/btrfs/zlib.c111
1 files changed, 12 insertions, 99 deletions
diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c
index 9a3e693917f2..f5ec2d44150d 100644
--- a/fs/btrfs/zlib.c
+++ b/fs/btrfs/zlib.c
@@ -218,24 +218,16 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
218 size_t srclen) 218 size_t srclen)
219{ 219{
220 struct workspace *workspace = list_entry(ws, struct workspace, list); 220 struct workspace *workspace = list_entry(ws, struct workspace, list);
221 int ret = 0; 221 int ret = 0, ret2;
222 int wbits = MAX_WBITS; 222 int wbits = MAX_WBITS;
223 char *data_in; 223 char *data_in;
224 size_t total_out = 0; 224 size_t total_out = 0;
225 unsigned long page_bytes_left;
226 unsigned long page_in_index = 0; 225 unsigned long page_in_index = 0;
227 unsigned long page_out_index = 0; 226 unsigned long page_out_index = 0;
228 struct page *page_out;
229 unsigned long total_pages_in = (srclen + PAGE_CACHE_SIZE - 1) / 227 unsigned long total_pages_in = (srclen + PAGE_CACHE_SIZE - 1) /
230 PAGE_CACHE_SIZE; 228 PAGE_CACHE_SIZE;
231 unsigned long buf_start; 229 unsigned long buf_start;
232 unsigned long buf_offset;
233 unsigned long bytes;
234 unsigned long working_bytes;
235 unsigned long pg_offset; 230 unsigned long pg_offset;
236 unsigned long start_byte;
237 unsigned long current_buf_start;
238 char *kaddr;
239 231
240 data_in = kmap(pages_in[page_in_index]); 232 data_in = kmap(pages_in[page_in_index]);
241 workspace->inf_strm.next_in = data_in; 233 workspace->inf_strm.next_in = data_in;
@@ -245,8 +237,6 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
245 workspace->inf_strm.total_out = 0; 237 workspace->inf_strm.total_out = 0;
246 workspace->inf_strm.next_out = workspace->buf; 238 workspace->inf_strm.next_out = workspace->buf;
247 workspace->inf_strm.avail_out = PAGE_CACHE_SIZE; 239 workspace->inf_strm.avail_out = PAGE_CACHE_SIZE;
248 page_out = bvec[page_out_index].bv_page;
249 page_bytes_left = PAGE_CACHE_SIZE;
250 pg_offset = 0; 240 pg_offset = 0;
251 241
252 /* If it's deflate, and it's got no preset dictionary, then 242 /* 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,
268 ret = zlib_inflate(&workspace->inf_strm, Z_NO_FLUSH); 258 ret = zlib_inflate(&workspace->inf_strm, Z_NO_FLUSH);
269 if (ret != Z_OK && ret != Z_STREAM_END) 259 if (ret != Z_OK && ret != Z_STREAM_END)
270 break; 260 break;
271 /*
272 * buf start is the byte offset we're of the start of
273 * our workspace buffer
274 */
275 buf_start = total_out;
276 261
277 /* total_out is the last byte of the workspace buffer */ 262 buf_start = total_out;
278 total_out = workspace->inf_strm.total_out; 263 total_out = workspace->inf_strm.total_out;
279 264
280 working_bytes = total_out - buf_start; 265 /* we didn't make progress in this inflate call, we're done */
281 266 if (buf_start == total_out)
282 /*
283 * start byte is the first byte of the page we're currently
284 * copying into relative to the start of the compressed data.
285 */
286 start_byte = page_offset(page_out) - disk_start;
287
288 if (working_bytes == 0) {
289 /* we didn't make progress in this inflate
290 * call, we're done
291 */
292 if (ret != Z_STREAM_END)
293 ret = -1;
294 break; 267 break;
295 }
296 268
297 /* we haven't yet hit data corresponding to this page */ 269 ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
298 if (total_out <= start_byte) 270 total_out, disk_start,
299 goto next; 271 bvec, vcnt,
300 272 &page_out_index, &pg_offset);
301 /* 273 if (ret2 == 0) {
302 * the start of the data we care about is offset into 274 ret = 0;
303 * the middle of our working buffer 275 goto done;
304 */
305 if (total_out > start_byte && buf_start < start_byte) {
306 buf_offset = start_byte - buf_start;
307 working_bytes -= buf_offset;
308 } else {
309 buf_offset = 0;
310 }
311 current_buf_start = buf_start;
312
313 /* copy bytes from the working buffer into the pages */
314 while (working_bytes > 0) {
315 bytes = min(PAGE_CACHE_SIZE - pg_offset,
316 PAGE_CACHE_SIZE - buf_offset);
317 bytes = min(bytes, working_bytes);
318 kaddr = kmap_atomic(page_out, KM_USER0);
319 memcpy(kaddr + pg_offset, workspace->buf + buf_offset,
320 bytes);
321 kunmap_atomic(kaddr, KM_USER0);
322 flush_dcache_page(page_out);
323
324 pg_offset += bytes;
325 page_bytes_left -= bytes;
326 buf_offset += bytes;
327 working_bytes -= bytes;
328 current_buf_start += bytes;
329
330 /* check if we need to pick another page */
331 if (page_bytes_left == 0) {
332 page_out_index++;
333 if (page_out_index >= vcnt) {
334 ret = 0;
335 goto done;
336 }
337
338 page_out = bvec[page_out_index].bv_page;
339 pg_offset = 0;
340 page_bytes_left = PAGE_CACHE_SIZE;
341 start_byte = page_offset(page_out) - disk_start;
342
343 /*
344 * make sure our new page is covered by this
345 * working buffer
346 */
347 if (total_out <= start_byte)
348 goto next;
349
350 /* the next page in the biovec might not
351 * be adjacent to the last page, but it
352 * might still be found inside this working
353 * buffer. bump our offset pointer
354 */
355 if (total_out > start_byte &&
356 current_buf_start < start_byte) {
357 buf_offset = start_byte - buf_start;
358 working_bytes = total_out - start_byte;
359 current_buf_start = buf_start +
360 buf_offset;
361 }
362 }
363 } 276 }
364next: 277
365 workspace->inf_strm.next_out = workspace->buf; 278 workspace->inf_strm.next_out = workspace->buf;
366 workspace->inf_strm.avail_out = PAGE_CACHE_SIZE; 279 workspace->inf_strm.avail_out = PAGE_CACHE_SIZE;
367 280