Commit 98310e581e098514867573031b2bfa4ba89c0d93
Committed by
Linus Torvalds
1 parent
6e873ec71d
Exists in
master
and in
7 other branches
cramfs: propagate uncompression errors
Decompression errors can arise due to corruption of compressed blocks on flash or in memory. This patch propagates errors detected during decompression back to the block layer. Signed-off-by: David VomLehn <dvomlehn@cisco.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 27 additions and 11 deletions Side-by-side Diff
fs/cramfs/inode.c
... | ... | @@ -459,11 +459,14 @@ |
459 | 459 | static int cramfs_readpage(struct file *file, struct page * page) |
460 | 460 | { |
461 | 461 | struct inode *inode = page->mapping->host; |
462 | - u32 maxblock, bytes_filled; | |
462 | + u32 maxblock; | |
463 | + int bytes_filled; | |
463 | 464 | void *pgdata; |
464 | 465 | |
465 | 466 | maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
466 | 467 | bytes_filled = 0; |
468 | + pgdata = kmap(page); | |
469 | + | |
467 | 470 | if (page->index < maxblock) { |
468 | 471 | struct super_block *sb = inode->i_sb; |
469 | 472 | u32 blkptr_offset = OFFSET(inode) + page->index*4; |
470 | 473 | |
471 | 474 | |
472 | 475 | |
473 | 476 | |
474 | 477 | |
475 | 478 | |
476 | 479 | |
... | ... | @@ -472,28 +475,41 @@ |
472 | 475 | start_offset = OFFSET(inode) + maxblock*4; |
473 | 476 | mutex_lock(&read_mutex); |
474 | 477 | if (page->index) |
475 | - start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4); | |
476 | - compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset); | |
478 | + start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, | |
479 | + 4); | |
480 | + compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - | |
481 | + start_offset); | |
477 | 482 | mutex_unlock(&read_mutex); |
478 | - pgdata = kmap(page); | |
483 | + | |
479 | 484 | if (compr_len == 0) |
480 | 485 | ; /* hole */ |
481 | - else if (compr_len > (PAGE_CACHE_SIZE << 1)) | |
482 | - printk(KERN_ERR "cramfs: bad compressed blocksize %u\n", compr_len); | |
483 | - else { | |
486 | + else if (unlikely(compr_len > (PAGE_CACHE_SIZE << 1))) { | |
487 | + pr_err("cramfs: bad compressed blocksize %u\n", | |
488 | + compr_len); | |
489 | + goto err; | |
490 | + } else { | |
484 | 491 | mutex_lock(&read_mutex); |
485 | 492 | bytes_filled = cramfs_uncompress_block(pgdata, |
486 | 493 | PAGE_CACHE_SIZE, |
487 | 494 | cramfs_read(sb, start_offset, compr_len), |
488 | 495 | compr_len); |
489 | 496 | mutex_unlock(&read_mutex); |
497 | + if (unlikely(bytes_filled < 0)) | |
498 | + goto err; | |
490 | 499 | } |
491 | - } else | |
492 | - pgdata = kmap(page); | |
500 | + } | |
501 | + | |
493 | 502 | memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled); |
494 | - kunmap(page); | |
495 | 503 | flush_dcache_page(page); |
504 | + kunmap(page); | |
496 | 505 | SetPageUptodate(page); |
506 | + unlock_page(page); | |
507 | + return 0; | |
508 | + | |
509 | +err: | |
510 | + kunmap(page); | |
511 | + ClearPageUptodate(page); | |
512 | + SetPageError(page); | |
497 | 513 | unlock_page(page); |
498 | 514 | return 0; |
499 | 515 | } |