diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/disk-io.c | 49 | ||||
-rw-r--r-- | fs/squashfs/sqfs.c | 16 |
2 files changed, 38 insertions, 27 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3f0d9f1c11..7eaa7e9496 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -541,34 +541,39 @@ struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, int read_extent_data(struct btrfs_fs_info *fs_info, char *data, u64 logical, u64 *len, int mirror) { - u64 offset = 0; + u64 orig_len = *len; + u64 cur = logical; struct btrfs_multi_bio *multi = NULL; struct btrfs_device *device; int ret = 0; - u64 max_len = *len; - ret = btrfs_map_block(fs_info, READ, logical, len, &multi, mirror, - NULL); - if (ret) { - fprintf(stderr, "Couldn't map the block %llu\n", - logical + offset); - goto err; - } - device = multi->stripes[0].dev; - - if (*len > max_len) - *len = max_len; - if (!device->desc || !device->part) { - ret = -EIO; - goto err; - } + while (cur < logical + orig_len) { + u64 cur_len = logical + orig_len - cur; - ret = __btrfs_devread(device->desc, device->part, data, *len, - multi->stripes[0].physical); - if (ret != *len) - ret = -EIO; - else + ret = btrfs_map_block(fs_info, READ, cur, &cur_len, &multi, + mirror, NULL); + if (ret) { + error("Couldn't map the block %llu", cur); + goto err; + } + device = multi->stripes[0].dev; + if (!device->desc || !device->part) { + error("devid %llu is missing", device->devid); + ret = -EIO; + goto err; + } + ret = __btrfs_devread(device->desc, device->part, + data + (cur - logical), cur_len, + multi->stripes[0].physical); + if (ret != cur_len) { + error("read failed on devid %llu physical %llu", + device->devid, multi->stripes[0].physical); + ret = -EIO; + goto err; + } + cur += cur_len; ret = 0; + } err: kfree(multi); return ret; diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index 4226621923..1430e671a5 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -100,7 +100,7 @@ static int sqfs_calc_n_blks(__le64 start, __le64 end, u64 *offset) static int sqfs_frag_lookup(u32 inode_fragment_index, struct squashfs_fragment_block_entry *e) { - u64 start, n_blks, src_len, table_offset, start_block; + u64 start, end, exp_tbl, n_blks, src_len, table_offset, start_block; unsigned char *metadata_buffer, *metadata, *table; struct squashfs_fragment_block_entry *entries; struct squashfs_super_block *sblk = ctxt.sblk; @@ -115,11 +115,17 @@ static int sqfs_frag_lookup(u32 inode_fragment_index, if (inode_fragment_index >= get_unaligned_le32(&sblk->fragments)) return -EINVAL; - start = get_unaligned_le64(&sblk->fragment_table_start) / - ctxt.cur_dev->blksz; + start = get_unaligned_le64(&sblk->fragment_table_start); + end = get_unaligned_le64(&sblk->id_table_start); + exp_tbl = get_unaligned_le64(&sblk->export_table_start); + + if (exp_tbl > start && exp_tbl < end) + end = exp_tbl; + n_blks = sqfs_calc_n_blks(sblk->fragment_table_start, - sblk->export_table_start, - &table_offset); + cpu_to_le64(end), &table_offset); + + start /= ctxt.cur_dev->blksz; /* Allocate a proper sized buffer to store the fragment index table */ table = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz); |