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>
This commit is contained in:
committed by
Linus Torvalds
parent
6e873ec71d
commit
98310e581e
@@ -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)
|
static int cramfs_readpage(struct file *file, struct page * page)
|
||||||
{
|
{
|
||||||
struct inode *inode = page->mapping->host;
|
struct inode *inode = page->mapping->host;
|
||||||
u32 maxblock, bytes_filled;
|
u32 maxblock;
|
||||||
|
int bytes_filled;
|
||||||
void *pgdata;
|
void *pgdata;
|
||||||
|
|
||||||
maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
|
maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
|
||||||
bytes_filled = 0;
|
bytes_filled = 0;
|
||||||
|
pgdata = kmap(page);
|
||||||
|
|
||||||
if (page->index < maxblock) {
|
if (page->index < maxblock) {
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
u32 blkptr_offset = OFFSET(inode) + page->index*4;
|
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;
|
start_offset = OFFSET(inode) + maxblock*4;
|
||||||
mutex_lock(&read_mutex);
|
mutex_lock(&read_mutex);
|
||||||
if (page->index)
|
if (page->index)
|
||||||
start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4);
|
start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4,
|
||||||
compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset);
|
4);
|
||||||
|
compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) -
|
||||||
|
start_offset);
|
||||||
mutex_unlock(&read_mutex);
|
mutex_unlock(&read_mutex);
|
||||||
pgdata = kmap(page);
|
|
||||||
if (compr_len == 0)
|
if (compr_len == 0)
|
||||||
; /* hole */
|
; /* hole */
|
||||||
else if (compr_len > (PAGE_CACHE_SIZE << 1))
|
else if (unlikely(compr_len > (PAGE_CACHE_SIZE << 1))) {
|
||||||
printk(KERN_ERR "cramfs: bad compressed blocksize %u\n", compr_len);
|
pr_err("cramfs: bad compressed blocksize %u\n",
|
||||||
else {
|
compr_len);
|
||||||
|
goto err;
|
||||||
|
} else {
|
||||||
mutex_lock(&read_mutex);
|
mutex_lock(&read_mutex);
|
||||||
bytes_filled = cramfs_uncompress_block(pgdata,
|
bytes_filled = cramfs_uncompress_block(pgdata,
|
||||||
PAGE_CACHE_SIZE,
|
PAGE_CACHE_SIZE,
|
||||||
cramfs_read(sb, start_offset, compr_len),
|
cramfs_read(sb, start_offset, compr_len),
|
||||||
compr_len);
|
compr_len);
|
||||||
mutex_unlock(&read_mutex);
|
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);
|
memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled);
|
||||||
kunmap(page);
|
|
||||||
flush_dcache_page(page);
|
flush_dcache_page(page);
|
||||||
|
kunmap(page);
|
||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
kunmap(page);
|
||||||
|
ClearPageUptodate(page);
|
||||||
|
SetPageError(page);
|
||||||
|
unlock_page(page);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct address_space_operations cramfs_aops = {
|
static const struct address_space_operations cramfs_aops = {
|
||||||
|
@@ -50,7 +50,7 @@ int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
|
|||||||
err:
|
err:
|
||||||
printk("Error %d while decompressing!\n", err);
|
printk("Error %d while decompressing!\n", err);
|
||||||
printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
|
printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
|
||||||
return 0;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cramfs_uncompress_init(void)
|
int cramfs_uncompress_init(void)
|
||||||
|
Reference in New Issue
Block a user