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 majord...@vger.kernel.org
> 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to