Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
bb803951
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
bb803951
编写于
3月 01, 2007
作者:
C
Chris Mason
提交者:
David Woodhouse
3月 01, 2007
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Btrfs: merge on the way down during deletes
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
0f70abe2
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
200 addition
and
220 deletion
+200
-220
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+200
-220
未找到文件。
fs/btrfs/ctree.c
浏览文件 @
bb803951
...
...
@@ -10,11 +10,10 @@ static int split_node(struct ctree_root *root, struct ctree_path *path,
int
level
);
static
int
split_leaf
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
data_size
);
static
int
push_node_left
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
);
static
int
push_node_right
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
);
static
int
del_ptr
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
);
static
int
push_node_left
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
dst
,
struct
tree_buffer
*
src
);
static
int
del_ptr
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
,
int
slot
);
inline
void
init_path
(
struct
ctree_path
*
p
)
{
...
...
@@ -192,6 +191,138 @@ int bin_search(struct node *c, struct key *key, int *slot)
return
-
1
;
}
struct
tree_buffer
*
read_node_slot
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
parent_buf
,
int
slot
)
{
struct
node
*
node
=
&
parent_buf
->
node
;
if
(
slot
<
0
)
return
NULL
;
if
(
slot
>=
node
->
header
.
nritems
)
return
NULL
;
return
read_tree_block
(
root
,
node
->
blockptrs
[
slot
]);
}
static
int
balance_level
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
)
{
struct
tree_buffer
*
right_buf
;
struct
tree_buffer
*
mid_buf
;
struct
tree_buffer
*
left_buf
;
struct
tree_buffer
*
parent_buf
=
NULL
;
struct
node
*
right
=
NULL
;
struct
node
*
mid
;
struct
node
*
left
=
NULL
;
struct
node
*
parent
=
NULL
;
int
ret
=
0
;
int
wret
;
int
pslot
;
int
used
=
0
;
int
count
;
int
orig_slot
=
path
->
slots
[
level
];
if
(
level
==
0
)
return
0
;
mid_buf
=
path
->
nodes
[
level
];
mid
=
&
mid_buf
->
node
;
if
(
level
<
MAX_LEVEL
-
1
)
parent_buf
=
path
->
nodes
[
level
+
1
];
pslot
=
path
->
slots
[
level
+
1
];
if
(
!
parent_buf
)
{
struct
tree_buffer
*
child
;
u64
blocknr
=
mid_buf
->
blocknr
;
if
(
mid
->
header
.
nritems
!=
1
)
return
0
;
/* promote the child to a root */
child
=
read_node_slot
(
root
,
mid_buf
,
0
);
BUG_ON
(
!
child
);
root
->
node
=
child
;
path
->
nodes
[
level
]
=
NULL
;
/* once for the path */
tree_block_release
(
root
,
mid_buf
);
/* once for the root ptr */
tree_block_release
(
root
,
mid_buf
);
return
free_extent
(
root
,
blocknr
,
1
);
}
parent
=
&
parent_buf
->
node
;
if
(
mid
->
header
.
nritems
>
NODEPTRS_PER_BLOCK
/
4
)
return
0
;
// print_tree(root, root->node);
left_buf
=
read_node_slot
(
root
,
parent_buf
,
pslot
-
1
);
right_buf
=
read_node_slot
(
root
,
parent_buf
,
pslot
+
1
);
if
(
right_buf
)
{
right
=
&
right_buf
->
node
;
used
=
right
->
header
.
nritems
;
count
=
1
;
}
if
(
left_buf
)
{
left
=
&
left_buf
->
node
;
used
+=
left
->
header
.
nritems
;
orig_slot
+=
left
->
header
.
nritems
;
count
++
;
}
if
(
left_buf
)
push_node_left
(
root
,
left_buf
,
mid_buf
);
if
(
right_buf
)
{
push_node_left
(
root
,
mid_buf
,
right_buf
);
if
(
right
->
header
.
nritems
==
0
)
{
u64
blocknr
=
right_buf
->
blocknr
;
tree_block_release
(
root
,
right_buf
);
right_buf
=
NULL
;
right
=
NULL
;
wret
=
del_ptr
(
root
,
path
,
level
+
1
,
pslot
+
1
);
if
(
wret
)
ret
=
wret
;
wret
=
free_extent
(
root
,
blocknr
,
1
);
if
(
wret
)
ret
=
wret
;
}
else
{
memcpy
(
parent
->
keys
+
pslot
+
1
,
right
->
keys
,
sizeof
(
struct
key
));
}
}
if
(
mid
->
header
.
nritems
==
0
)
{
u64
blocknr
=
mid_buf
->
blocknr
;
tree_block_release
(
root
,
mid_buf
);
mid_buf
=
NULL
;
mid
=
NULL
;
wret
=
del_ptr
(
root
,
path
,
level
+
1
,
pslot
);
if
(
wret
)
ret
=
wret
;
wret
=
free_extent
(
root
,
blocknr
,
1
);
if
(
wret
)
ret
=
wret
;
}
else
memcpy
(
parent
->
keys
+
pslot
,
mid
->
keys
,
sizeof
(
struct
key
));
if
(
left_buf
)
{
if
(
left
->
header
.
nritems
>=
orig_slot
)
{
left_buf
->
count
++
;
// released below
path
->
nodes
[
level
]
=
left_buf
;
path
->
slots
[
level
+
1
]
-=
1
;
path
->
slots
[
level
]
=
orig_slot
;
if
(
mid_buf
)
tree_block_release
(
root
,
mid_buf
);
}
else
{
orig_slot
-=
left
->
header
.
nritems
;
path
->
slots
[
level
]
=
orig_slot
;
}
}
if
(
right_buf
)
tree_block_release
(
root
,
right_buf
);
if
(
left_buf
)
tree_block_release
(
root
,
left_buf
);
return
ret
;
}
/*
* look for key in the tree. path is filled in with nodes along the way
* if key is found, we return zero and you can find the item in the leaf
...
...
@@ -208,12 +339,14 @@ int bin_search(struct node *c, struct key *key, int *slot)
int
search_slot
(
struct
ctree_root
*
root
,
struct
key
*
key
,
struct
ctree_path
*
p
,
int
ins_len
)
{
struct
tree_buffer
*
b
=
root
->
node
;
struct
tree_buffer
*
b
;
struct
node
*
c
;
int
slot
;
int
ret
;
int
level
;
again:
b
=
root
->
node
;
b
->
count
++
;
while
(
b
)
{
c
=
&
b
->
node
;
...
...
@@ -236,9 +369,17 @@ int search_slot(struct ctree_root *root, struct key *key,
b
=
p
->
nodes
[
level
];
c
=
&
b
->
node
;
slot
=
p
->
slots
[
level
];
}
else
if
(
ins_len
<
0
)
{
int
sret
=
balance_level
(
root
,
p
,
level
);
if
(
sret
)
return
sret
;
b
=
p
->
nodes
[
level
];
if
(
!
b
)
goto
again
;
c
=
&
b
->
node
;
slot
=
p
->
slots
[
level
];
}
b
=
read_tree_block
(
root
,
c
->
blockptrs
[
slot
]);
continue
;
}
else
{
struct
leaf
*
l
=
(
struct
leaf
*
)
c
;
p
->
slots
[
level
]
=
slot
;
...
...
@@ -249,9 +390,11 @@ int search_slot(struct ctree_root *root, struct key *key,
if
(
sret
)
return
sret
;
}
BUG_ON
(
root
->
node
->
count
==
1
);
return
ret
;
}
}
BUG_ON
(
root
->
node
->
count
==
1
);
return
1
;
}
...
...
@@ -301,163 +444,49 @@ static int fixup_low_keys(struct ctree_root *root,
* returns 0 if some ptrs were pushed left, < 0 if there was some horrible
* error, and > 0 if there was no room in the left hand block.
*/
static
int
push_node_left
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
)
static
int
push_node_left
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
dst_buf
,
struct
tree_buffer
*
src_buf
)
{
int
slot
;
struct
node
*
left
;
struct
node
*
right
;
struct
node
*
src
=
&
src_buf
->
node
;
struct
node
*
dst
=
&
dst_buf
->
node
;
int
push_items
=
0
;
int
left_nritems
;
int
right_nritems
;
struct
tree_buffer
*
t
;
struct
tree_buffer
*
right_buf
;
int
src_nritems
;
int
dst_nritems
;
int
ret
=
0
;
int
wret
;
if
(
level
==
MAX_LEVEL
-
1
||
path
->
nodes
[
level
+
1
]
==
0
)
return
1
;
slot
=
path
->
slots
[
level
+
1
];
if
(
slot
==
0
)
return
1
;
t
=
read_tree_block
(
root
,
path
->
nodes
[
level
+
1
]
->
node
.
blockptrs
[
slot
-
1
]);
left
=
&
t
->
node
;
right_buf
=
path
->
nodes
[
level
];
right
=
&
right_buf
->
node
;
left_nritems
=
left
->
header
.
nritems
;
right_nritems
=
right
->
header
.
nritems
;
push_items
=
NODEPTRS_PER_BLOCK
-
(
left_nritems
+
1
);
src_nritems
=
src
->
header
.
nritems
;
dst_nritems
=
dst
->
header
.
nritems
;
push_items
=
NODEPTRS_PER_BLOCK
-
dst_nritems
;
if
(
push_items
<=
0
)
{
tree_block_release
(
root
,
t
);
return
1
;
}
if
(
right
_nritems
<
push_items
)
push_items
=
right
_nritems
;
memcpy
(
left
->
keys
+
left_nritems
,
right
->
keys
,
if
(
src
_nritems
<
push_items
)
push_items
=
src
_nritems
;
memcpy
(
dst
->
keys
+
dst_nritems
,
src
->
keys
,
push_items
*
sizeof
(
struct
key
));
memcpy
(
left
->
blockptrs
+
left_nritems
,
right
->
blockptrs
,
memcpy
(
dst
->
blockptrs
+
dst_nritems
,
src
->
blockptrs
,
push_items
*
sizeof
(
u64
));
memmove
(
right
->
keys
,
right
->
keys
+
push_items
,
(
right_nritems
-
push_items
)
*
sizeof
(
struct
key
));
memmove
(
right
->
blockptrs
,
right
->
blockptrs
+
push_items
,
(
right_nritems
-
push_items
)
*
sizeof
(
u64
));
right
->
header
.
nritems
-=
push_items
;
left
->
header
.
nritems
+=
push_items
;
/* adjust the pointers going up the tree */
wret
=
fixup_low_keys
(
root
,
path
,
right
->
keys
,
level
+
1
);
if
(
wret
<
0
)
ret
=
wret
;
if
(
push_items
<
src_nritems
)
{
memmove
(
src
->
keys
,
src
->
keys
+
push_items
,
(
src_nritems
-
push_items
)
*
sizeof
(
struct
key
));
memmove
(
src
->
blockptrs
,
src
->
blockptrs
+
push_items
,
(
src_nritems
-
push_items
)
*
sizeof
(
u64
));
}
src
->
header
.
nritems
-=
push_items
;
dst
->
header
.
nritems
+=
push_items
;
wret
=
write_tree_block
(
root
,
t
);
wret
=
write_tree_block
(
root
,
src_buf
);
if
(
wret
<
0
)
ret
=
wret
;
wret
=
write_tree_block
(
root
,
righ
t_buf
);
wret
=
write_tree_block
(
root
,
ds
t_buf
);
if
(
wret
<
0
)
ret
=
wret
;
/* then fixup the leaf pointer in the path */
if
(
path
->
slots
[
level
]
<
push_items
)
{
path
->
slots
[
level
]
+=
left_nritems
;
tree_block_release
(
root
,
path
->
nodes
[
level
]);
path
->
nodes
[
level
]
=
t
;
path
->
slots
[
level
+
1
]
-=
1
;
}
else
{
path
->
slots
[
level
]
-=
push_items
;
tree_block_release
(
root
,
t
);
}
return
ret
;
}
/*
* try to push data from one node into the next node right in the
* tree. The src node is found at specified level in the path.
* If some bytes were pushed, return 0, otherwise return 1.
*
* Lower nodes/leaves in the path are not touched, higher nodes may
* be modified to reflect the push.
*
* The path is altered to reflect the push.
*
* returns 0 if some ptrs were pushed, < 0 if there was some horrible
* error, and > 0 if there was no room in the right hand block.
*/
static
int
push_node_right
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
)
{
int
slot
;
struct
tree_buffer
*
t
;
struct
tree_buffer
*
src_buffer
;
struct
node
*
dst
;
struct
node
*
src
;
int
push_items
=
0
;
int
dst_nritems
;
int
src_nritems
;
/* can't push from the root */
if
(
level
==
MAX_LEVEL
-
1
||
path
->
nodes
[
level
+
1
]
==
0
)
return
1
;
/* only try to push inside the node higher up */
slot
=
path
->
slots
[
level
+
1
];
if
(
slot
==
NODEPTRS_PER_BLOCK
-
1
)
return
1
;
if
(
slot
>=
path
->
nodes
[
level
+
1
]
->
node
.
header
.
nritems
-
1
)
return
1
;
t
=
read_tree_block
(
root
,
path
->
nodes
[
level
+
1
]
->
node
.
blockptrs
[
slot
+
1
]);
dst
=
&
t
->
node
;
src_buffer
=
path
->
nodes
[
level
];
src
=
&
src_buffer
->
node
;
dst_nritems
=
dst
->
header
.
nritems
;
src_nritems
=
src
->
header
.
nritems
;
push_items
=
NODEPTRS_PER_BLOCK
-
(
dst_nritems
+
1
);
if
(
push_items
<=
0
)
{
tree_block_release
(
root
,
t
);
return
1
;
}
if
(
src_nritems
<
push_items
)
push_items
=
src_nritems
;
memmove
(
dst
->
keys
+
push_items
,
dst
->
keys
,
dst_nritems
*
sizeof
(
struct
key
));
memcpy
(
dst
->
keys
,
src
->
keys
+
src_nritems
-
push_items
,
push_items
*
sizeof
(
struct
key
));
memmove
(
dst
->
blockptrs
+
push_items
,
dst
->
blockptrs
,
dst_nritems
*
sizeof
(
u64
));
memcpy
(
dst
->
blockptrs
,
src
->
blockptrs
+
src_nritems
-
push_items
,
push_items
*
sizeof
(
u64
));
src
->
header
.
nritems
-=
push_items
;
dst
->
header
.
nritems
+=
push_items
;
/* adjust the pointers going up the tree */
memcpy
(
path
->
nodes
[
level
+
1
]
->
node
.
keys
+
path
->
slots
[
level
+
1
]
+
1
,
dst
->
keys
,
sizeof
(
struct
key
));
write_tree_block
(
root
,
path
->
nodes
[
level
+
1
]);
write_tree_block
(
root
,
t
);
write_tree_block
(
root
,
src_buffer
);
/* then fixup the pointers in the path */
if
(
path
->
slots
[
level
]
>=
src
->
header
.
nritems
)
{
path
->
slots
[
level
]
-=
src
->
header
.
nritems
;
tree_block_release
(
root
,
path
->
nodes
[
level
]);
path
->
nodes
[
level
]
=
t
;
path
->
slots
[
level
+
1
]
+=
1
;
}
else
{
tree_block_release
(
root
,
t
);
}
return
0
;
}
/*
* helper function to insert a new root level in the tree.
* A new node is allocated, and a single item is inserted to
...
...
@@ -558,16 +587,6 @@ static int split_node(struct ctree_root *root, struct ctree_path *path,
int
ret
;
int
wret
;
ret
=
push_node_left
(
root
,
path
,
level
);
if
(
!
ret
)
return
0
;
if
(
ret
<
0
)
return
ret
;
ret
=
push_node_right
(
root
,
path
,
level
);
if
(
!
ret
)
return
0
;
if
(
ret
<
0
)
return
ret
;
t
=
path
->
nodes
[
level
];
c
=
&
t
->
node
;
if
(
t
==
root
->
node
)
{
...
...
@@ -1011,6 +1030,7 @@ int insert_item(struct ctree_root *root, struct key *key,
if
(
leaf_free_space
(
leaf
)
<
0
)
BUG
();
check_leaf
(
&
path
,
0
);
release_path
(
root
,
&
path
);
return
ret
;
}
...
...
@@ -1022,22 +1042,16 @@ int insert_item(struct ctree_root *root, struct key *key,
* continuing all the way the root if required. The root is converted into
* a leaf if all the nodes are emptied.
*/
static
int
del_ptr
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
)
static
int
del_ptr
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
,
int
slot
)
{
int
slot
;
struct
tree_buffer
*
t
;
struct
node
*
node
;
struct
tree_buffer
*
parent
=
path
->
nodes
[
level
];
int
nritems
;
u64
blocknr
;
int
wret
;
int
ret
=
0
;
int
wret
;
while
(
1
)
{
t
=
path
->
nodes
[
level
];
if
(
!
t
)
break
;
node
=
&
t
->
node
;
slot
=
path
->
slots
[
level
];
node
=
&
parent
->
node
;
nritems
=
node
->
header
.
nritems
;
if
(
slot
!=
nritems
-
1
)
{
...
...
@@ -1048,51 +1062,18 @@ static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level)
sizeof
(
u64
)
*
(
nritems
-
slot
-
1
));
}
node
->
header
.
nritems
--
;
blocknr
=
t
->
blocknr
;
write_tree_block
(
root
,
t
);
if
(
node
->
header
.
nritems
!=
0
)
{
int
tslot
;
if
(
slot
==
0
)
{
wret
=
fixup_low_keys
(
root
,
path
,
node
->
keys
,
level
+
1
);
if
(
wret
)
ret
=
wret
;
}
tslot
=
path
->
slots
[
level
+
1
];
t
->
count
++
;
wret
=
push_node_left
(
root
,
path
,
level
);
if
(
wret
<
0
)
{
ret
=
wret
;
break
;
}
if
(
node
->
header
.
nritems
!=
0
)
{
wret
=
push_node_right
(
root
,
path
,
level
);
if
(
wret
<
0
)
{
ret
=
wret
;
break
;
}
}
path
->
slots
[
level
+
1
]
=
tslot
;
if
(
node
->
header
.
nritems
!=
0
)
{
tree_block_release
(
root
,
t
);
break
;
}
tree_block_release
(
root
,
t
);
}
if
(
t
==
root
->
node
)
{
if
(
node
->
header
.
nritems
==
0
&&
parent
==
root
->
node
)
{
BUG_ON
(
node_level
(
root
->
node
->
node
.
header
.
flags
)
!=
1
);
/* just turn the root into a leaf and break */
root
->
node
->
node
.
header
.
flags
=
node_level
(
0
);
write_tree_block
(
root
,
t
);
break
;
}
level
++
;
wret
=
free_extent
(
root
,
blocknr
,
1
);
}
else
if
(
slot
==
0
)
{
wret
=
fixup_low_keys
(
root
,
path
,
node
->
keys
,
level
+
1
);
if
(
wret
)
ret
=
wret
;
if
(
!
path
->
nodes
[
level
])
BUG
();
}
wret
=
write_tree_block
(
root
,
parent
);
if
(
wret
)
ret
=
wret
;
return
ret
;
}
...
...
@@ -1135,7 +1116,7 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
leaf
->
header
.
flags
=
node_level
(
0
);
write_tree_block
(
root
,
leaf_buf
);
}
else
{
wret
=
del_ptr
(
root
,
path
,
1
);
wret
=
del_ptr
(
root
,
path
,
1
,
path
->
slots
[
1
]
);
if
(
wret
)
ret
=
wret
;
wret
=
free_extent
(
root
,
leaf_buf
->
blocknr
,
1
);
...
...
@@ -1172,8 +1153,7 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
}
if
(
leaf
->
header
.
nritems
==
0
)
{
u64
blocknr
=
leaf_buf
->
blocknr
;
path
->
slots
[
1
]
=
slot
;
wret
=
del_ptr
(
root
,
path
,
1
);
wret
=
del_ptr
(
root
,
path
,
1
,
slot
);
if
(
wret
)
ret
=
wret
;
tree_block_release
(
root
,
leaf_buf
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录