Yan Zheng
2007-Oct-23  02:58 UTC
[btrfs-devel]A bug related to btrfs_search_slot and btrfs_extend_item
Hello,
When we want to extent the size of some item in the tree, the typical
function call sequence is:
      ...
      btrfs_search_slot((trans, root, key, path,  size_to_extent, 1);
      ...
     btrfs_extend_item(trans, root, path, size_to_extent);
There is a flaw in codes like this, to guarantee a leaf has enough
free space, 'btrfs_search_slot' may call 'split_leaf' which
split the
leaf or insert a empty leaf. When 'split_leaf' insert a empty leaf,
the lowest level of the btrfs_path points to the empty leaf. After
'btrfs_search_slot' return, 'btrfs_extend_item' is called, it
will be
in trouble to extent a non-exist item.
Here is the test on a new formated btrfs with 8k node/leaf size.
kernel module is build by the codes from btrfs-unstable trees at
October 19.
--
[root@localhost btrfs]# dd if=/dev/zero bs=4k count=1 of=1 2>/dev/null
[root@localhost btrfs]# dd if=/dev/zero bs=4k count=1 of=2 2>/dev/null
[root@localhost btrfs]# dd if=/dev/zero bs=2k count=1 of=3 2>/dev/null
[root@localhost btrfs]# sync && debug-tree /dev/sdb1
...
leaf 36864 ptrs 13 free space 3139 generation 2 owner 3
...
leaf 69632 ptrs 3 free space 1772 generation 2 owner 3
        item 0 key (7 12 0) itemoff 4008 itemsize 4105
                inline extent data size 4096
        item 1 key (8 1 0) itemoff 3904 itemsize 104
                inode generation 0 size 2048 block group 0 mode 100644 links 1
        item 2 key (8 12 0) itemoff 1847 itemsize 2057
                inline extent data size 2048
...
Now the tree has a root node and two leaves, the first item in the
second leaf is a inline extent. If we extent the inline extent to 6k,
'split_leaf' will insert a new leaf.
--
[root@localhost btrfs]# dd conv=notrunc if=/dev/zero bs=2k count=1 seek=2 of=2
...
Kernel Oops
...
(attachment is the full output of debug-tree)
I feel this bug may also occur when extent a csum/dir item. Maybe
btrfs_search_slot needs a new parameter, so that it knows what next
operation is (insert item or extent item).
Regards
YZ
-------------- next part --------------
A non-text attachment was scrubbed...
Name: debug-tree.output
Type: application/octet-stream
Size: 5863 bytes
Desc: not available
Url :
http://oss.oracle.com/pipermail/btrfs-devel/attachments/20071023/c2268f80/debug-tree.obj
Chris Mason
2007-Oct-23  06:19 UTC
[btrfs-devel]A bug related to btrfs_search_slot and btrfs_extend_item
On Tue, 23 Oct 2007 17:58:25 +0800 "Yan Zheng" <yanzheng@21cn.com> wrote:> Hello, > > When we want to extent the size of some item in the tree, the typical > function call sequence is: > ... > btrfs_search_slot((trans, root, key, path, size_to_extent, 1); > ... > btrfs_extend_item(trans, root, path, size_to_extent); > > There is a flaw in codes like this, to guarantee a leaf has enough > free space, 'btrfs_search_slot' may call 'split_leaf' which split the > leaf or insert a empty leaf. When 'split_leaf' insert a empty leaf, > the lowest level of the btrfs_path points to the empty leaf. After > 'btrfs_search_slot' return, 'btrfs_extend_item' is called, it will be > in trouble to extent a non-exist item.Yes, I've fixed a few mistakes in this area, but I think you're right, I need to add a parameter to search_slot that indicates insert vs extend. Thanks for this test case! -chris