diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-06-17 15:49:04 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.cz> | 2015-06-17 16:10:18 +0200 |
commit | eb81f8d263ce7f5341561221f3b8b8a0ec8701dc (patch) | |
tree | 94970b97ce29fd2245520476e29b7cee57c03f6e /btrfs-calc-size.c | |
parent | 1bbd40a1bb79906ce112b07baf389e9824dca543 (diff) |
btrfs-progs: map-logical: Rework map-logical logics
[BUG]
The original map-logical has the following problems:
1) Assert if we pass any tree root bytenr.
The problem is easy to trigger, here the number 29622272 is the bytenr of tree root:
# btrfs-map-logical -l 29622272 /dev/sda6
mirror 1 logical 29622272 physical 38010880 device /dev/sda6
mirror 2 logical 29622272 physical 1111752704 device /dev/sda6
extent_io.c:582: free_extent_buffer: Assertion `eb->refs < 0` failed.
btrfs-map-logical[0x41c464]
btrfs-map-logical(free_extent_buffer+0xc0)[0x41cf10]
btrfs-map-logical(btrfs_release_all_roots+0x59)[0x40e649]
btrfs-map-logical(close_ctree+0x1aa)[0x40f51a]
btrfs-map-logical(main+0x387)[0x4077c7]
/usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f80a5562790]
btrfs-map-logical(_start+0x29)[0x4078f9]
The problem is that, btrfs-map-logical always use sectorsize as default
block size to call alloc_extent_buffer.
And when it failes to find the block with the same size, it will free
the extent buffer in a incorrect method(Free and create a new one with
refs == 1).
2) Will return map result for non-exist extent.
# btrfs-map-logical -l 1 -b 123456 /dev/sda6
mirror 1 logical 1 physical 1 device /dev/sda6
mirror 1 logical 4097 physical 4097 device /dev/sda6
mirror 1 logical 8193 physical 8193 device /dev/sda6
...
Normally, before bytenr 12582912, there should be no extent as that's
the mkfs time temp metadata/system chunk.
But map-logical will still map them out.
Not to mention the 1 offset among all results.
[FIX]
This patch will rework the whole map logical by the following methods:
1) Always do things inside a extent
Even under the following case, map logical will only return covered
range in existing extents.
|<------ range given ------->|
|<-Extent A->| |<-Extent B->| |<---Extent C->|
Result:
|<-->| |<---------->| |<-->|
So with this patch, we will search extent tree to ensure all operation
are inside a extent before we do some stupid things.
2) No direct call on alloc_extent_buffer function.
That low-level function shouldn't be called at such high level.
It's only designed for low-level tree operation.
So in this patch we will only use safe high level functions avoid such
problem.
[RESULT]
With this patch, no assert will be triggered and better handle on
non-exist extents.
# btrfs-map-logical -l 29622272 /dev/sda6
mirror 1 logical 29622272 physical 38010880 device /dev/sda6
mirror 2 logical 29622272 physical 1111752704 device /dev/sda6
# btrfs-map-logical -l 1 -b 123456 /dev/sda6
No extent found at range [1,123457)
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Diffstat (limited to 'btrfs-calc-size.c')
0 files changed, 0 insertions, 0 deletions