diff options
author | plougher <plougher> | 2008-10-22 02:21:38 +0000 |
---|---|---|
committer | plougher <plougher> | 2008-10-22 02:21:38 +0000 |
commit | 181adfffd2f45ab3d484ae598b8a21f9a784eafc (patch) | |
tree | a9991996aec0b3249a237fdb3e8584962b605e32 /kernel | |
parent | e3b55c1dd792b9161da42ff539a14c5c4afd0fbf (diff) | |
download | squashfs-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.c | 7 | ||||
-rw-r--r-- | kernel/fs/squashfs/dir.c | 38 | ||||
-rw-r--r-- | kernel/fs/squashfs/export.c | 8 | ||||
-rw-r--r-- | kernel/fs/squashfs/file.c | 43 | ||||
-rw-r--r-- | kernel/fs/squashfs/fragment.c | 7 | ||||
-rw-r--r-- | kernel/fs/squashfs/id.c | 8 | ||||
-rw-r--r-- | kernel/fs/squashfs/inode.c | 37 | ||||
-rw-r--r-- | kernel/fs/squashfs/namei.c | 32 | ||||
-rw-r--r-- | kernel/fs/squashfs/symlink.c | 2 |
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); |