aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorplougher <plougher>2008-10-22 02:21:38 +0000
committerplougher <plougher>2008-10-22 02:21:38 +0000
commit181adfffd2f45ab3d484ae598b8a21f9a784eafc (patch)
treea9991996aec0b3249a237fdb3e8584962b605e32 /kernel
parente3b55c1dd792b9161da42ff539a14c5c4afd0fbf (diff)
downloadsquashfs-tools-181adfffd2f45ab3d484ae598b8a21f9a784eafc.tar.gz
Third round, change squashfs_read_metadata to return negative errors.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/fs/squashfs/cache.c7
-rw-r--r--kernel/fs/squashfs/dir.c38
-rw-r--r--kernel/fs/squashfs/export.c8
-rw-r--r--kernel/fs/squashfs/file.c43
-rw-r--r--kernel/fs/squashfs/fragment.c7
-rw-r--r--kernel/fs/squashfs/id.c8
-rw-r--r--kernel/fs/squashfs/inode.c37
-rw-r--r--kernel/fs/squashfs/namei.c32
-rw-r--r--kernel/fs/squashfs/symlink.c2
9 files changed, 117 insertions, 65 deletions
diff --git a/kernel/fs/squashfs/cache.c b/kernel/fs/squashfs/cache.c
index 82b6bbb..52032af 100644
--- a/kernel/fs/squashfs/cache.c
+++ b/kernel/fs/squashfs/cache.c
@@ -264,8 +264,11 @@ int squashfs_read_metadata(struct super_block *s, void *buffer,
entry = squashfs_cache_get(s, msblk->block_cache, *block, 0);
bytes = entry->length - *offset;
- if (entry->error || bytes < 1) {
- return_length = 0;
+ if (entry->error) {
+ return_length = entry->error;
+ goto finish;
+ } else if (bytes < 1) {
+ return_length = -EIO;
goto finish;
} else if (bytes >= length) {
if (buffer)
diff --git a/kernel/fs/squashfs/dir.c b/kernel/fs/squashfs/dir.c
index 99229a1..740800a 100644
--- a/kernel/fs/squashfs/dir.c
+++ b/kernel/fs/squashfs/dir.c
@@ -44,6 +44,10 @@ static const unsigned char squashfs_filetype_table[] = {
/*
* Lookup offset (f_pos) in the directory index, returning the
* metadata block containing it.
+ *
+ * If we get an error reading the index then return the part of the index
+ * (if any) we have managed to read - the index isn't essential, just
+ * quicker.
*/
static int get_dir_index_using_offset(struct super_block *s,
long long *next_block, unsigned int *next_offset,
@@ -51,7 +55,7 @@ static int get_dir_index_using_offset(struct super_block *s,
long long f_pos)
{
struct squashfs_sb_info *msblk = s->s_fs_info;
- int i, index, length = 0;
+ int err, i, index, length = 0;
struct squashfs_dir_index dir_index;
TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %lld\n",
@@ -67,15 +71,22 @@ static int get_dir_index_using_offset(struct super_block *s,
goto finish;
for (i = 0; i < i_count; i++) {
- squashfs_read_metadata(s, &dir_index, &index_start,
- &index_offset, sizeof(dir_index));
+ err = squashfs_read_metadata(s, &dir_index, &index_start,
+ &index_offset, sizeof(dir_index));
+ if (err < 0)
+ break;
index = le32_to_cpu(dir_index.index);
if (index > f_pos)
+ /*
+ * Found the index we're looking for.
+ */
break;
- squashfs_read_metadata(s, NULL, &index_start, &index_offset,
- le32_to_cpu(dir_index.size) + 1);
+ err = squashfs_read_metadata(s, NULL, &index_start,
+ &index_offset, le32_to_cpu(dir_index.size) + 1);
+ if (err < 0)
+ break;
length = index;
*next_block = le32_to_cpu(dir_index.start_block) +
@@ -99,7 +110,7 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
long long next_block = SQUASHFS_I(i)->start_block +
msblk->directory_table_start;
int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count, size,
- type;
+ type, err;
unsigned int inode_number;
struct squashfs_dir_header dirh;
struct squashfs_dir_entry *dire;
@@ -157,8 +168,9 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
/*
* Read directory header
*/
- if (!squashfs_read_metadata(i->i_sb, &dirh, &next_block,
- &next_offset, sizeof(dirh)))
+ err = squashfs_read_metadata(i->i_sb, &dirh, &next_block,
+ &next_offset, sizeof(dirh));
+ if (err < 0)
goto failed_read;
length += sizeof(dirh);
@@ -168,14 +180,16 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
/*
* Read directory entry.
*/
- if (!squashfs_read_metadata(i->i_sb, dire, &next_block,
- &next_offset, sizeof(*dire)))
+ err = squashfs_read_metadata(i->i_sb, dire, &next_block,
+ &next_offset, sizeof(*dire));
+ if (err < 0)
goto failed_read;
size = le16_to_cpu(dire->size) + 1;
- if (!squashfs_read_metadata(i->i_sb, dire->name,
- &next_block, &next_offset, size))
+ err = squashfs_read_metadata(i->i_sb, dire->name,
+ &next_block, &next_offset, size);
+ if (err < 0)
goto failed_read;
length += sizeof(*dire) + size;
diff --git a/kernel/fs/squashfs/export.c b/kernel/fs/squashfs/export.c
index f7c089c..35c4cfc 100644
--- a/kernel/fs/squashfs/export.c
+++ b/kernel/fs/squashfs/export.c
@@ -56,11 +56,13 @@ static long long squashfs_inode_lookup(struct super_block *s, int ino)
int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);
long long start = le64_to_cpu(msblk->inode_lookup_table[blk]);
__le64 inode;
+ int err;
TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);
- if (!squashfs_read_metadata(s, &inode, &start, &offset, sizeof(inode)))
- return SQUASHFS_INVALID_BLK;
+ err = squashfs_read_metadata(s, &inode, &start, &offset, sizeof(inode));
+ if (err < 0)
+ return err;
TRACE("squashfs_inode_lookup, inode = 0x%llx\n", le64_to_cpu(inode));
return le64_to_cpu(inode);
@@ -76,7 +78,7 @@ static struct dentry *squashfs_export_iget(struct super_block *s,
TRACE("Entered squashfs_export_iget\n");
inode = squashfs_inode_lookup(s, inode_number);
- if (inode != SQUASHFS_INVALID_BLK)
+ if (inode >= 0)
dentry = d_obtain_alias(squashfs_iget(s, inode, inode_number));
return dentry;
diff --git a/kernel/fs/squashfs/file.c b/kernel/fs/squashfs/file.c
index 162e708..f398e85 100644
--- a/kernel/fs/squashfs/file.c
+++ b/kernel/fs/squashfs/file.c
@@ -174,21 +174,22 @@ static void release_meta_index(struct inode *inode, struct meta_index *meta)
static long long read_indexes(struct super_block *s, int n,
long long *start_block, int *offset)
{
- int i;
+ int err, i;
long long block = 0;
__le32 *blist = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
if (blist == NULL) {
ERROR("read_indexes: Failed to allocate block_list\n");
+ err = -ENOMEM;
goto failure;
}
while (n) {
int blocks = min_t(int, n, PAGE_CACHE_SIZE >> 2);
- int res = squashfs_read_metadata(s, blist, start_block,
- offset, blocks << 2);
- if (res == 0) {
+ err = squashfs_read_metadata(s, blist, start_block,
+ offset, blocks << 2);
+ if (err < 0) {
ERROR("read_indexes: reading block [%llx:%x]\n",
*start_block, *offset);
goto failure;
@@ -206,7 +207,7 @@ static long long read_indexes(struct super_block *s, int n,
failure:
kfree(blist);
- return -1;
+ return err;
}
@@ -246,7 +247,7 @@ static int fill_meta_index(struct inode *inode, int index,
long long cur_index_block = SQUASHFS_I(inode)->block_list_start;
int cur_offset = SQUASHFS_I(inode)->offset;
long long cur_data_block = SQUASHFS_I(inode)->start_block;
- int i;
+ int err, i;
/*
* Scale index to cache index (cache slot entry)
@@ -261,8 +262,6 @@ static int fill_meta_index(struct inode *inode, int index,
if (meta == NULL)
goto all_done;
} else {
- if (meta->entries == 0)
- goto failed;
offset = index < meta->offset + meta->entries ? index :
meta->offset + meta->entries - 1;
meta_entry = &meta->meta_entry[offset - meta->offset];
@@ -289,8 +288,16 @@ static int fill_meta_index(struct inode *inode, int index,
long long res = read_indexes(inode->i_sb, blocks,
&cur_index_block, &cur_offset);
- if (res == -1)
+ if (res < 0) {
+ if (meta->entries == 0)
+ /*
+ * Don't leave an empty slot on read
+ * error allocated to this inode...
+ */
+ meta->inode_number = 0;
+ err = res;
goto failed;
+ }
cur_data_block += res;
meta_entry = &meta->meta_entry[i - meta->offset];
@@ -320,7 +327,7 @@ all_done:
failed:
release_meta_index(inode, meta);
- return -1;
+ return err;
}
@@ -331,7 +338,7 @@ failed:
static long long read_blocklist(struct inode *inode, int index,
unsigned int *bsize)
{
- long long start, block, blks;
+ long long start, block = 0, blks;
int offset;
__le32 size;
int res = fill_meta_index(inode, index, &start, &offset, &block);
@@ -340,7 +347,7 @@ static long long read_blocklist(struct inode *inode, int index,
" 0x%x, block 0x%llx\n", res, index, start, offset,
block);
- if (res == -1)
+ if (res < 0)
goto failure;
/*
@@ -351,8 +358,10 @@ static long long read_blocklist(struct inode *inode, int index,
*/
if (res < index) {
blks = read_indexes(inode->i_sb, index - res, &start, &offset);
- if (blks == -1)
+ if (blks < 0) {
+ res = blks;
goto failure;
+ }
block += blks;
}
@@ -361,14 +370,14 @@ static long long read_blocklist(struct inode *inode, int index,
*/
res = squashfs_read_metadata(inode->i_sb, &size, &start, &offset,
sizeof(size));
- if (res == 0)
+ if (res < 0)
goto failure;
*bsize = le32_to_cpu(size);
return block;
failure:
- return -1;
+ return res;
}
@@ -377,7 +386,7 @@ static int squashfs_readpage(struct file *file, struct page *page)
struct inode *inode = page->mapping->host;
struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
long long block;
- unsigned int bsize, i;
+ unsigned int bsize = 0, i;
int bytes, index = page->index >> (msblk->block_log - PAGE_CACHE_SHIFT);
struct squashfs_cache_entry *fragment = NULL;
void *pageaddr, *data_ptr = msblk->read_page;
@@ -402,7 +411,7 @@ static int squashfs_readpage(struct file *file, struct page *page)
* to get location and block size.
*/
block = read_blocklist(inode, index, &bsize);
- if (block == -1)
+ if (block < 0)
goto error_out;
if (bsize == 0) { /* hole */
diff --git a/kernel/fs/squashfs/fragment.c b/kernel/fs/squashfs/fragment.c
index 09abcb8..af1e37f 100644
--- a/kernel/fs/squashfs/fragment.c
+++ b/kernel/fs/squashfs/fragment.c
@@ -51,10 +51,11 @@ int get_fragment_location(struct super_block *s, unsigned int fragment,
int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
long long start_block = le64_to_cpu(msblk->fragment_index[block]);
struct squashfs_fragment_entry fragment_entry;
- int size = -EIO;
+ int size;
- if (!squashfs_read_metadata(s, &fragment_entry, &start_block, &offset,
- sizeof(fragment_entry)))
+ size = squashfs_read_metadata(s, &fragment_entry, &start_block, &offset,
+ sizeof(fragment_entry));
+ if (size < 0)
goto out;
*fragment_block = le64_to_cpu(fragment_entry.start_block);
diff --git a/kernel/fs/squashfs/id.c b/kernel/fs/squashfs/id.c
index 6ab0db1..f9510cd 100644
--- a/kernel/fs/squashfs/id.c
+++ b/kernel/fs/squashfs/id.c
@@ -48,10 +48,12 @@ int squashfs_get_id(struct super_block *s, unsigned int index, unsigned int *id)
int offset = SQUASHFS_ID_BLOCK_OFFSET(index);
long long start_block = le64_to_cpu(msblk->id_table[block]);
__le32 disk_id;
+ int err;
- if (!squashfs_read_metadata(s, &disk_id, &start_block, &offset,
- sizeof(disk_id)))
- return -EIO;
+ err = squashfs_read_metadata(s, &disk_id, &start_block, &offset,
+ sizeof(disk_id));
+ if (err < 0)
+ return err;
*id = le32_to_cpu(disk_id);
return 0;
diff --git a/kernel/fs/squashfs/inode.c b/kernel/fs/squashfs/inode.c
index 7f2cef2..ccc09cc 100644
--- a/kernel/fs/squashfs/inode.c
+++ b/kernel/fs/squashfs/inode.c
@@ -120,7 +120,8 @@ int squashfs_read_inode(struct inode *i, long long inode)
/*
* Read inode base common to all inode types.
*/
- if (!squashfs_read_metadata(s, inodeb, &block, &offset, sizeof(*inodeb)))
+ err = squashfs_read_metadata(s, inodeb, &block, &offset, sizeof(*inodeb));
+ if (err < 0)
goto failed_read;
err = squashfs_new_inode(s, i, inodeb);
@@ -137,7 +138,9 @@ int squashfs_read_inode(struct inode *i, long long inode)
long long frag_blk;
struct squashfs_reg_inode *inodep = &id.reg;
- if (!squashfs_read_metadata(s, inodep, &block, &offset, sizeof(*inodep)))
+ err = squashfs_read_metadata(s, inodep, &block, &offset,
+ sizeof(*inodep));
+ if (err < 0)
goto failed_read;
frag = le32_to_cpu(inodep->fragment);
@@ -177,8 +180,9 @@ int squashfs_read_inode(struct inode *i, long long inode)
long long frag_blk;
struct squashfs_lreg_inode *inodep = &id.lreg;
- if (!squashfs_read_metadata(s, inodep, &block, &offset,
- sizeof(*inodep)))
+ err = squashfs_read_metadata(s, inodep, &block, &offset,
+ sizeof(*inodep));
+ if (err < 0)
goto failed_read;
frag = le32_to_cpu(inodep->fragment);
@@ -218,8 +222,9 @@ int squashfs_read_inode(struct inode *i, long long inode)
case SQUASHFS_DIR_TYPE: {
struct squashfs_dir_inode *inodep = &id.dir;
- if (!squashfs_read_metadata(s, inodep, &block, &offset,
- sizeof(*inodep)))
+ err = squashfs_read_metadata(s, inodep, &block, &offset,
+ sizeof(*inodep));
+ if (err < 0)
goto failed_read;
i->i_nlink = le32_to_cpu(inodep->nlink);
@@ -241,8 +246,9 @@ int squashfs_read_inode(struct inode *i, long long inode)
case SQUASHFS_LDIR_TYPE: {
struct squashfs_ldir_inode *inodep = &id.ldir;
- if (!squashfs_read_metadata(s, inodep, &block, &offset,
- sizeof(*inodep)))
+ err = squashfs_read_metadata(s, inodep, &block, &offset,
+ sizeof(*inodep));
+ if (err < 0)
goto failed_read;
i->i_nlink = le32_to_cpu(inodep->nlink);
@@ -266,8 +272,9 @@ int squashfs_read_inode(struct inode *i, long long inode)
case SQUASHFS_SYMLINK_TYPE: {
struct squashfs_symlink_inode *inodep = &id.symlink;
- if (!squashfs_read_metadata(s, inodep, &block, &offset,
- sizeof(*inodep)))
+ err = squashfs_read_metadata(s, inodep, &block, &offset,
+ sizeof(*inodep));
+ if (err < 0)
goto failed_read;
i->i_nlink = le32_to_cpu(inodep->nlink);
@@ -288,8 +295,9 @@ int squashfs_read_inode(struct inode *i, long long inode)
struct squashfs_dev_inode *inodep = &id.dev;
unsigned int rdev;
- if (!squashfs_read_metadata(s, inodep, &block, &offset,
- sizeof(*inodep)))
+ err = squashfs_read_metadata(s, inodep, &block, &offset,
+ sizeof(*inodep));
+ if (err < 0)
goto failed_read;
i->i_nlink = le32_to_cpu(inodep->nlink);
@@ -306,8 +314,9 @@ int squashfs_read_inode(struct inode *i, long long inode)
case SQUASHFS_SOCKET_TYPE: {
struct squashfs_ipc_inode *inodep = &id.ipc;
- if (!squashfs_read_metadata(s, inodep, &block, &offset,
- sizeof(*inodep)))
+ err = squashfs_read_metadata(s, inodep, &block, &offset,
+ sizeof(*inodep));
+ if (err < 0)
goto failed_read;
i->i_nlink = le32_to_cpu(inodep->nlink);
diff --git a/kernel/fs/squashfs/namei.c b/kernel/fs/squashfs/namei.c
index 5c8dd29..880be1d 100644
--- a/kernel/fs/squashfs/namei.c
+++ b/kernel/fs/squashfs/namei.c
@@ -67,6 +67,10 @@
/*
* Lookup name in the directory index, returning the location of the metadata
* block containing it, and the directory index this represents.
+ *
+ * If we get an error reading the index then return the part of the index
+ * (if any) we have managed to read - the index isn't essential, just
+ * quicker.
*/
static int get_dir_index_using_name(struct super_block *s,
long long *next_block, unsigned int *next_offset,
@@ -74,7 +78,7 @@ static int get_dir_index_using_name(struct super_block *s,
int i_count, const char *name, int len)
{
struct squashfs_sb_info *msblk = s->s_fs_info;
- int i, size, length = 0;
+ int i, size, length = 0, err;
struct squashfs_dir_index *index;
char *str;
@@ -91,13 +95,18 @@ static int get_dir_index_using_name(struct super_block *s,
str[len] = '\0';
for (i = 0; i < i_count; i++) {
- squashfs_read_metadata(s, index, &index_start, &index_offset,
- sizeof(*index));
+ err = squashfs_read_metadata(s, index, &index_start,
+ &index_offset, sizeof(*index));
+ if (err < 0)
+ break;
+
size = le32_to_cpu(index->size) + 1;
- squashfs_read_metadata(s, index->name, &index_start,
+ err = squashfs_read_metadata(s, index->name, &index_start,
&index_offset, size);
+ if (err < 0)
+ break;
index->name[size] = '\0';
@@ -162,8 +171,9 @@ static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
/*
* Read directory header.
*/
- if (!squashfs_read_metadata(i->i_sb, &dirh, &next_block,
- &next_offset, sizeof(dirh)))
+ err = squashfs_read_metadata(i->i_sb, &dirh, &next_block,
+ &next_offset, sizeof(dirh));
+ if (err < 0)
goto read_failure;
length += sizeof(dirh);
@@ -173,14 +183,16 @@ static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
/*
* Read directory entry.
*/
- if (!squashfs_read_metadata(i->i_sb, dire, &next_block,
- &next_offset, sizeof(*dire)))
+ err = squashfs_read_metadata(i->i_sb, dire, &next_block,
+ &next_offset, sizeof(*dire));
+ if (err < 0)
goto read_failure;
size = le16_to_cpu(dire->size) + 1;
- if (!squashfs_read_metadata(i->i_sb, dire->name,
- &next_block, &next_offset, size))
+ err = squashfs_read_metadata(i->i_sb, dire->name,
+ &next_block, &next_offset, size);
+ if (err < 0)
goto read_failure;
length += sizeof(*dire) + size;
diff --git a/kernel/fs/squashfs/symlink.c b/kernel/fs/squashfs/symlink.c
index 1c2a07f..0881d3a 100644
--- a/kernel/fs/squashfs/symlink.c
+++ b/kernel/fs/squashfs/symlink.c
@@ -64,7 +64,7 @@ static int squashfs_symlink_readpage(struct file *file, struct page *page)
*/
if (index) {
bytes = squashfs_read_metadata(s, NULL, &block, &offset, index);
- if (bytes == 0) {
+ if (bytes < 0) {
ERROR("Unable to read symlink [%llx:%x]\n",
SQUASHFS_I(inode)->start_block,
SQUASHFS_I(inode)->offset);