aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavid VomLehn <dvomlehn@cisco.com>2009-04-02 19:59:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-02 22:05:07 -0400
commit98310e581e098514867573031b2bfa4ba89c0d93 (patch)
treeb4eeec1516af4be7bd7f3f64dbf49f80e84b2bca /fs
parent6e873ec71d091f52510f6aa9bc71d4732438522a (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/cramfs/inode.c36
-rw-r--r--fs/cramfs/uncompress.c2
2 files changed, 27 insertions, 11 deletions
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index a07338d2d140..46e52980b98a 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -459,11 +459,14 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s
459static int cramfs_readpage(struct file *file, struct page * page) 459static int cramfs_readpage(struct file *file, struct page * page)
460{ 460{
461 struct inode *inode = page->mapping->host; 461 struct inode *inode = page->mapping->host;
462 u32 maxblock, bytes_filled; 462 u32 maxblock;
463 int bytes_filled;
463 void *pgdata; 464 void *pgdata;
464 465
465 maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 466 maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
466 bytes_filled = 0; 467 bytes_filled = 0;
468 pgdata = kmap(page);
469
467 if (page->index < maxblock) { 470 if (page->index < maxblock) {
468 struct super_block *sb = inode->i_sb; 471 struct super_block *sb = inode->i_sb;
469 u32 blkptr_offset = OFFSET(inode) + page->index*4; 472 u32 blkptr_offset = OFFSET(inode) + page->index*4;
@@ -472,30 +475,43 @@ static int cramfs_readpage(struct file *file, struct page * page)
472 start_offset = OFFSET(inode) + maxblock*4; 475 start_offset = OFFSET(inode) + maxblock*4;
473 mutex_lock(&read_mutex); 476 mutex_lock(&read_mutex);
474 if (page->index) 477 if (page->index)
475 start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4); 478 start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4,
476 compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset); 479 4);
480 compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) -
481 start_offset);
477 mutex_unlock(&read_mutex); 482 mutex_unlock(&read_mutex);
478 pgdata = kmap(page); 483
479 if (compr_len == 0) 484 if (compr_len == 0)
480 ; /* hole */ 485 ; /* hole */
481 else if (compr_len > (PAGE_CACHE_SIZE << 1)) 486 else if (unlikely(compr_len > (PAGE_CACHE_SIZE << 1))) {
482 printk(KERN_ERR "cramfs: bad compressed blocksize %u\n", compr_len); 487 pr_err("cramfs: bad compressed blocksize %u\n",
483 else { 488 compr_len);
489 goto err;
490 } else {
484 mutex_lock(&read_mutex); 491 mutex_lock(&read_mutex);
485 bytes_filled = cramfs_uncompress_block(pgdata, 492 bytes_filled = cramfs_uncompress_block(pgdata,
486 PAGE_CACHE_SIZE, 493 PAGE_CACHE_SIZE,
487 cramfs_read(sb, start_offset, compr_len), 494 cramfs_read(sb, start_offset, compr_len),
488 compr_len); 495 compr_len);
489 mutex_unlock(&read_mutex); 496 mutex_unlock(&read_mutex);
497 if (unlikely(bytes_filled < 0))
498 goto err;
490 } 499 }
491 } else 500 }
492 pgdata = kmap(page); 501
493 memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled); 502 memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled);
494 kunmap(page);
495 flush_dcache_page(page); 503 flush_dcache_page(page);
504 kunmap(page);
496 SetPageUptodate(page); 505 SetPageUptodate(page);
497 unlock_page(page); 506 unlock_page(page);
498 return 0; 507 return 0;
508
509err:
510 kunmap(page);
511 ClearPageUptodate(page);
512 SetPageError(page);
513 unlock_page(page);
514 return 0;
499} 515}
500 516
501static const struct address_space_operations cramfs_aops = { 517static const struct address_space_operations cramfs_aops = {
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c
index fc3ccb74626f..023329800d2e 100644
--- a/fs/cramfs/uncompress.c
+++ b/fs/cramfs/uncompress.c
@@ -50,7 +50,7 @@ int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
50err: 50err:
51 printk("Error %d while decompressing!\n", err); 51 printk("Error %d while decompressing!\n", err);
52 printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen); 52 printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
53 return 0; 53 return -EIO;
54} 54}
55 55
56int cramfs_uncompress_init(void) 56int cramfs_uncompress_init(void)