ext4: Fix handling of sparse files

A sparse file may have regions not mapped by any extents, at the start
or at the end of the file, or anywhere between, thus not finding a
matching extent region is never an error.

Found by python filesystem tests.

Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
This commit is contained in:
Stefan Brüns 2016-11-05 22:17:14 +01:00 committed by Tom Rini
parent d8c1e0331a
commit f81db56f2f

View File

@ -1617,12 +1617,13 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock)
- get_fs()->dev_desc->log2blksz; - get_fs()->dev_desc->log2blksz;
if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) { if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) {
long int startblock, endblock;
char *buf = zalloc(blksz); char *buf = zalloc(blksz);
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
struct ext4_extent_header *ext_block; struct ext4_extent_header *ext_block;
struct ext4_extent *extent; struct ext4_extent *extent;
int i = -1; int i;
ext_block = ext_block =
ext4fs_get_extent_block(ext4fs_root, buf, ext4fs_get_extent_block(ext4fs_root, buf,
(struct ext4_extent_header *) (struct ext4_extent_header *)
@ -1636,28 +1637,26 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock)
extent = (struct ext4_extent *)(ext_block + 1); extent = (struct ext4_extent *)(ext_block + 1);
do { for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) {
i++; startblock = le32_to_cpu(extent[i].ee_block);
if (i >= le16_to_cpu(ext_block->eh_entries)) endblock = startblock + le16_to_cpu(extent[i].ee_len);
break;
} while (fileblock >= le32_to_cpu(extent[i].ee_block)); if (startblock > fileblock) {
if (--i >= 0) { /* Sparse file */
fileblock -= le32_to_cpu(extent[i].ee_block);
if (fileblock >= le16_to_cpu(extent[i].ee_len)) {
free(buf); free(buf);
return 0; return 0;
}
start = le16_to_cpu(extent[i].ee_start_hi); } else if (fileblock < endblock) {
start = (start << 32) + start = le16_to_cpu(extent[i].ee_start_hi);
start = (start << 32) +
le32_to_cpu(extent[i].ee_start_lo); le32_to_cpu(extent[i].ee_start_lo);
free(buf); free(buf);
return fileblock + start; return (fileblock - startblock) + start;
}
} }
printf("Extent Error\n");
free(buf); free(buf);
return -1; return 0;
} }
/* Direct blocks. */ /* Direct blocks. */