On Fri, Feb 24, 2017 at 01:52:31PM +0800, Qu Wenruo wrote:
> +static int check_image_file_extents(struct btrfs_root *image_root, u64 ino,
> + u64 total_size, char *reserved_ranges[])
> +{
> + struct btrfs_key key;
> + struct btrfs_path path;
> + struct btrfs_fs_info *fs_info = image_root->fs_info;
> + u64 checked_bytes = 0;
> + int ret;
> +
> + key.objectid = ino;
> + key.offset = 0;
> + key.type = BTRFS_EXTENT_DATA_KEY;
> +
> + btrfs_init_path(&path);
> + ret = btrfs_search_slot(NULL, image_root, &key, &path, 0, 0);
> + /*
> + * It's possible that some fs doesn't store any(including sb)
> + * data into 0~1M range, and NO_HOLES is enabled.
> + *
> + * So only needs to check ret < 0 case
> + */
> + if (ret < 0) {
> + error("failed to iterate file extents at offset 0: %s",
> + strerror(-ret));
> + btrfs_release_path(&path);
> + return ret;
> + }
> +
> + /* Loop from the first file extents */
> + while (1) {
> + struct btrfs_file_extent_item *fi;
> + struct extent_buffer *leaf = path.nodes[0];
> + u64 disk_bytenr;
> + u64 file_offset;
> + u64 ram_bytes;
> + int slot = path.slots[0];
> +
> + if (slot >= btrfs_header_nritems(leaf))
> + goto next;
> + btrfs_item_key_to_cpu(leaf, &key, slot);
> +
> + /*
> + * Iteration is done, exit normally, we have extra check out of
> + * the loop
> + */
> + if (key.objectid != ino || key.type != BTRFS_EXTENT_DATA_KEY) {
> + ret = 0;
> + break;
> + }
> + file_offset = key.offset;
> + fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
> + if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG) {
> + ret = -EINVAL;
> + error(
> + "ino %llu offset %llu doesn't have a regular file extent",
> + ino, file_offset);
> + break;
> + }
> + if (btrfs_file_extent_compression(leaf, fi) ||
> + btrfs_file_extent_encryption(leaf, fi) ||
> + btrfs_file_extent_other_encoding(leaf, fi)) {
> + ret = -EINVAL;
> + error(
> + "ino %llu offset %llu doesn't have a plain file extent",
> + ino, file_offset);
> + break;
> + }
> +
> + disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
> + ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
> +
> + checked_bytes += ram_bytes;
> + /* Skip hole */
> + if (disk_bytenr == 0)
> + goto next;
> +
> + /*
> + * Most file extent must be 1:1 mapped, which means 2 things:
> + * 1) File extent file offset == disk_bytenr
> + * 2) That data chunk's logical == chunk's physical
> + *
> + * So file extent's file offset == physical position on disk.
> + *
> + * And after rolling back btrfs reserved range, other part
> + * remains what old fs used to be.
> + */
> + if (file_offset != disk_bytenr ||
> + !is_chunk_direct_mapped(fs_info, disk_bytenr)) {
> + /*
> + * Only file extent in btrfs reserved ranges are allow
> + * non-1:1 mapped
> + */
> + if (!is_subset_of_reserved_ranges(file_offset,
> + ram_bytes)) {
> + ret = -EINVAL;
> + error(
> + "ino %llu offset %llu file extent should not be relocated",
> + ino, file_offset);
> + break;
> + }
> + }
> +next:
> + ret = btrfs_next_item(image_root, &path);
> + if (ret) {
> + if (ret > 0)
> + ret = 0;
> + break;
> + }
> + }
> + btrfs_release_path(&path);
> + /*
> + * For HOLES mode (without NO_HOLES), we must ensure file extents
> + * cover the whole range of the image
> + */
> + if (!ret && !btrfs_fs_incompat(fs_info, NO_HOLES)) {
> + if (checked_bytes != total_size) {
> + ret = -EINVAL;
> + error("inode %llu has some file extents not checked",
> + ino);
Coverity complains that ret is set but not used, and it looks like the
code is not supposed to continue, ie. missing goto or return.
> + }
> + }
> +
> + /* So far so good, read out old data located in btrfs reserved ranges */
> + ret = read_reserved_ranges(image_root, ino, total_size,
> + reserved_ranges);
> + return ret;
> +}
> +
> static int do_rollback(const char *devname)
> {
> int fd = -1;
> --
> 2.11.1
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html