Message ID | 20200803070630.33234-1-wqu@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs-progs: volumes: check stripe end against device boundary | expand |
On 2020/8/3 下午3:06, Qu Wenruo wrote: > There is a report of kernel generationg READ bio access beyond device > boundary. > > To make sure it's not caused by on-disk chunk items, add extra stripe > check against device total_bytes so that btrfs check can detect such > problem early on. To add more info on this, kernel can already detects such problem at mount time, by verify_one_dev_extent() on each dev extent read and compare it against existing chunks. Thus there is no need to enhance kernel already. Thanks, Qu > > Signed-off-by: Qu Wenruo <wqu@suse.com> > --- > volumes.c | 29 +++++++++++++++++++++++++++++ > 1 file changed, 29 insertions(+) > > diff --git a/volumes.c b/volumes.c > index 538f799e7211..0467dd63d5cb 100644 > --- a/volumes.c > +++ b/volumes.c > @@ -1843,6 +1843,7 @@ int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, > u64 type; > u32 chunk_ondisk_size; > u32 sectorsize = fs_info->sectorsize; > + int i; > > /* > * Basic chunk item size check. Note that btrfs_chunk already contains > @@ -1953,6 +1954,34 @@ int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, > return -EIO; > } > > + /* > + * Stripe check against device boundary > + */ > + for (i = 0; i < num_stripes; i++) { > + struct btrfs_device *dev; > + u64 physical; > + u64 devid; > + u64 stripe_len; > + > + devid = btrfs_stripe_devid_nr(leaf, chunk, i); > + physical = btrfs_stripe_offset_nr(leaf, chunk, i); > + stripe_len = calc_stripe_length(type, length, num_stripes); > + dev = btrfs_find_device(fs_info, devid, NULL, NULL); > + /* > + * Device not found? Then we may be in the bootstrap process for > + * system chunks. Skip. > + */ > + if (!dev) > + continue; > + if (physical + stripe_len > dev->total_bytes) { > + error( > +"chunk %llu stripe %d is beyond device boundary: devid %llu total_bytes %llu stripe start %llu len %llu", > + logical, i, devid, dev->total_bytes, physical, > + stripe_len); > + return -EUCLEAN; > + } > + } > + > return 0; > } > >
diff --git a/volumes.c b/volumes.c index 538f799e7211..0467dd63d5cb 100644 --- a/volumes.c +++ b/volumes.c @@ -1843,6 +1843,7 @@ int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, u64 type; u32 chunk_ondisk_size; u32 sectorsize = fs_info->sectorsize; + int i; /* * Basic chunk item size check. Note that btrfs_chunk already contains @@ -1953,6 +1954,34 @@ int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, return -EIO; } + /* + * Stripe check against device boundary + */ + for (i = 0; i < num_stripes; i++) { + struct btrfs_device *dev; + u64 physical; + u64 devid; + u64 stripe_len; + + devid = btrfs_stripe_devid_nr(leaf, chunk, i); + physical = btrfs_stripe_offset_nr(leaf, chunk, i); + stripe_len = calc_stripe_length(type, length, num_stripes); + dev = btrfs_find_device(fs_info, devid, NULL, NULL); + /* + * Device not found? Then we may be in the bootstrap process for + * system chunks. Skip. + */ + if (!dev) + continue; + if (physical + stripe_len > dev->total_bytes) { + error( +"chunk %llu stripe %d is beyond device boundary: devid %llu total_bytes %llu stripe start %llu len %llu", + logical, i, devid, dev->total_bytes, physical, + stripe_len); + return -EUCLEAN; + } + } + return 0; }
There is a report of kernel generationg READ bio access beyond device boundary. To make sure it's not caused by on-disk chunk items, add extra stripe check against device total_bytes so that btrfs check can detect such problem early on. Signed-off-by: Qu Wenruo <wqu@suse.com> --- volumes.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)