diff options
| author | Liu Bo <liubo2009@cn.fujitsu.com> | 2012-04-12 16:03:56 -0400 |
|---|---|---|
| committer | Chris Mason <chris.mason@oracle.com> | 2012-04-12 16:03:56 -0400 |
| commit | b89203f74bdfcb15407d54d3f257b16a2ea19e62 (patch) | |
| tree | a0cbfbc0bf259b4382b881a9108b21dc88525389 /fs/btrfs | |
| parent | d95603b262edb53d6016a8df0c150371d4d61e67 (diff) | |
Btrfs: fix eof while discarding extents
We miscalculate the length of extents we're discarding, and it leads to
an eof of device.
Reported-by: Daniel Blueman <daniel@quora.org>
Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/volumes.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a872b48be0ae..759d02486d7c 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -3833,6 +3833,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
| 3833 | int sub_stripes = 0; | 3833 | int sub_stripes = 0; |
| 3834 | u64 stripes_per_dev = 0; | 3834 | u64 stripes_per_dev = 0; |
| 3835 | u32 remaining_stripes = 0; | 3835 | u32 remaining_stripes = 0; |
| 3836 | u32 last_stripe = 0; | ||
| 3836 | 3837 | ||
| 3837 | if (map->type & | 3838 | if (map->type & |
| 3838 | (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) { | 3839 | (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) { |
| @@ -3846,6 +3847,8 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
| 3846 | stripe_nr_orig, | 3847 | stripe_nr_orig, |
| 3847 | factor, | 3848 | factor, |
| 3848 | &remaining_stripes); | 3849 | &remaining_stripes); |
| 3850 | div_u64_rem(stripe_nr_end - 1, factor, &last_stripe); | ||
| 3851 | last_stripe *= sub_stripes; | ||
| 3849 | } | 3852 | } |
| 3850 | 3853 | ||
| 3851 | for (i = 0; i < num_stripes; i++) { | 3854 | for (i = 0; i < num_stripes; i++) { |
| @@ -3858,16 +3861,29 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
| 3858 | BTRFS_BLOCK_GROUP_RAID10)) { | 3861 | BTRFS_BLOCK_GROUP_RAID10)) { |
| 3859 | bbio->stripes[i].length = stripes_per_dev * | 3862 | bbio->stripes[i].length = stripes_per_dev * |
| 3860 | map->stripe_len; | 3863 | map->stripe_len; |
| 3864 | |||
| 3861 | if (i / sub_stripes < remaining_stripes) | 3865 | if (i / sub_stripes < remaining_stripes) |
| 3862 | bbio->stripes[i].length += | 3866 | bbio->stripes[i].length += |
| 3863 | map->stripe_len; | 3867 | map->stripe_len; |
| 3868 | |||
| 3869 | /* | ||
| 3870 | * Special for the first stripe and | ||
| 3871 | * the last stripe: | ||
| 3872 | * | ||
| 3873 | * |-------|...|-------| | ||
| 3874 | * |----------| | ||
| 3875 | * off end_off | ||
| 3876 | */ | ||
| 3864 | if (i < sub_stripes) | 3877 | if (i < sub_stripes) |
| 3865 | bbio->stripes[i].length -= | 3878 | bbio->stripes[i].length -= |
| 3866 | stripe_offset; | 3879 | stripe_offset; |
| 3867 | if ((i / sub_stripes + 1) % | 3880 | |
| 3868 | sub_stripes == remaining_stripes) | 3881 | if (stripe_index >= last_stripe && |
| 3882 | stripe_index <= (last_stripe + | ||
| 3883 | sub_stripes - 1)) | ||
| 3869 | bbio->stripes[i].length -= | 3884 | bbio->stripes[i].length -= |
| 3870 | stripe_end_offset; | 3885 | stripe_end_offset; |
| 3886 | |||
| 3871 | if (i == sub_stripes - 1) | 3887 | if (i == sub_stripes - 1) |
| 3872 | stripe_offset = 0; | 3888 | stripe_offset = 0; |
| 3873 | } else | 3889 | } else |
