summaryrefslogtreecommitdiff
path: root/fs/cramfs/inode.c
diff options
context:
space:
mode:
authorDavid VomLehn <dvomlehn@cisco.com>2009-04-02 16:59:15 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-02 19:05:07 -0700
commit98310e581e098514867573031b2bfa4ba89c0d93 (patch)
treeb4eeec1516af4be7bd7f3f64dbf49f80e84b2bca /fs/cramfs/inode.c
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/cramfs/inode.c')
-rw-r--r--fs/cramfs/inode.c36
1 files changed, 26 insertions, 10 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
static int cramfs_readpage(struct file *file, struct page * page)
{
struct inode *inode = page->mapping->host;
- u32 maxblock, bytes_filled;
+ u32 maxblock;
+ int bytes_filled;
void *pgdata;
maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
bytes_filled = 0;
+ pgdata = kmap(page);
+
if (page->index < maxblock) {
struct super_block *sb = inode->i_sb;
u32 blkptr_offset = OFFSET(inode) + page->index*4;
@@ -472,30 +475,43 @@ static int cramfs_readpage(struct file *file, struct page * page)
start_offset = OFFSET(inode) + maxblock*4;
mutex_lock(&read_mutex);
if (page->index)
- start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4);
- compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset);
+ start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4,
+ 4);
+ compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) -
+ start_offset);
mutex_unlock(&read_mutex);
- pgdata = kmap(page);
+
if (compr_len == 0)
; /* hole */
- else if (compr_len > (PAGE_CACHE_SIZE << 1))
- printk(KERN_ERR "cramfs: bad compressed blocksize %u\n", compr_len);
- else {
+ else if (unlikely(compr_len > (PAGE_CACHE_SIZE << 1))) {
+ pr_err("cramfs: bad compressed blocksize %u\n",
+ compr_len);
+ goto err;
+ } else {
mutex_lock(&read_mutex);
bytes_filled = cramfs_uncompress_block(pgdata,
PAGE_CACHE_SIZE,
cramfs_read(sb, start_offset, compr_len),
compr_len);
mutex_unlock(&read_mutex);
+ if (unlikely(bytes_filled < 0))
+ goto err;
}
- } else
- pgdata = kmap(page);
+ }
+
memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled);
- kunmap(page);
flush_dcache_page(page);
+ kunmap(page);
SetPageUptodate(page);
unlock_page(page);
return 0;
+
+err:
+ kunmap(page);
+ ClearPageUptodate(page);
+ SetPageError(page);
+ unlock_page(page);
+ return 0;
}
static const struct address_space_operations cramfs_aops = {