Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gsplhtlxg
clone-Linux
提交
5c680ed6
C
clone-Linux
项目概览
gsplhtlxg
/
clone-Linux
通知
2
Star
0
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
clone-Linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5c680ed6
编写于
2月 22, 2007
作者:
C
Chris Mason
提交者:
David Woodhouse
2月 22, 2007
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Btrfs: switch to early splits
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
cfaa7295
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
120 addition
and
146 deletion
+120
-146
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+118
-145
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+2
-1
未找到文件。
fs/btrfs/ctree.c
浏览文件 @
5c680ed6
...
...
@@ -5,7 +5,12 @@
#include "ctree.h"
#include "disk-io.h"
#define SEARCH_READ 0
#define SEARCH_WRITE 1
static
int
refill_alloc_extent
(
struct
ctree_root
*
root
);
int
split_node
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
);
int
split_leaf
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
data_size
);
static
inline
void
init_path
(
struct
ctree_path
*
p
)
{
...
...
@@ -125,14 +130,14 @@ int bin_search(struct node *c, struct key *key, int *slot)
* If the key isn't found, the path points to the slot where it should
* be inserted.
*/
int
search_slot
(
struct
ctree_root
*
root
,
struct
key
*
key
,
struct
ctree_path
*
p
)
int
search_slot
(
struct
ctree_root
*
root
,
struct
key
*
key
,
struct
ctree_path
*
p
,
int
ins_len
)
{
struct
tree_buffer
*
b
=
root
->
node
;
struct
node
*
c
;
int
slot
;
int
ret
;
int
level
;
b
->
count
++
;
while
(
b
)
{
c
=
&
b
->
node
;
...
...
@@ -143,10 +148,26 @@ int search_slot(struct ctree_root *root, struct key *key, struct ctree_path *p)
if
(
ret
&&
slot
>
0
)
slot
-=
1
;
p
->
slots
[
level
]
=
slot
;
if
(
ins_len
&&
c
->
header
.
nritems
==
NODEPTRS_PER_BLOCK
)
{
int
sret
=
split_node
(
root
,
p
,
level
);
BUG_ON
(
sret
>
0
);
if
(
sret
)
return
sret
;
b
=
p
->
nodes
[
level
];
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
;
if
(
ins_len
&&
leaf_free_space
(
l
)
<
sizeof
(
struct
item
)
+
ins_len
)
{
int
sret
=
split_leaf
(
root
,
p
,
ins_len
);
BUG_ON
(
sret
>
0
);
if
(
sret
)
return
sret
;
}
return
ret
;
}
}
...
...
@@ -331,50 +352,54 @@ int push_node_right(struct ctree_root *root, struct ctree_path *path, int level)
return
0
;
}
static
int
insert_new_root
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
)
{
struct
tree_buffer
*
t
;
struct
node
*
lower
;
struct
node
*
c
;
struct
key
*
lower_key
;
BUG_ON
(
path
->
nodes
[
level
]);
BUG_ON
(
path
->
nodes
[
level
-
1
]
!=
root
->
node
);
t
=
alloc_free_block
(
root
);
c
=
&
t
->
node
;
memset
(
c
,
0
,
sizeof
(
c
));
c
->
header
.
nritems
=
1
;
c
->
header
.
flags
=
node_level
(
level
);
c
->
header
.
blocknr
=
t
->
blocknr
;
c
->
header
.
parentid
=
root
->
node
->
node
.
header
.
parentid
;
lower
=
&
path
->
nodes
[
level
-
1
]
->
node
;
if
(
is_leaf
(
lower
->
header
.
flags
))
lower_key
=
&
((
struct
leaf
*
)
lower
)
->
items
[
0
].
key
;
else
lower_key
=
lower
->
keys
;
memcpy
(
c
->
keys
,
lower_key
,
sizeof
(
struct
key
));
c
->
blockptrs
[
0
]
=
path
->
nodes
[
level
-
1
]
->
blocknr
;
/* the super has an extra ref to root->node */
tree_block_release
(
root
,
root
->
node
);
root
->
node
=
t
;
t
->
count
++
;
write_tree_block
(
root
,
t
);
path
->
nodes
[
level
]
=
t
;
path
->
slots
[
level
]
=
0
;
return
0
;
}
/*
* worker function to insert a single pointer in a node.
* the node should have enough room for the pointer already
* slot and level indicate where you want the key to go, and
* blocknr is the block the key points to.
*/
int
__
insert_ptr
(
struct
ctree_root
*
root
,
int
insert_ptr
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
struct
key
*
key
,
u64
blocknr
,
int
slot
,
int
level
)
{
struct
node
*
c
;
struct
node
*
lower
;
struct
key
*
lower_key
;
int
nritems
;
/* need a new root */
if
(
!
path
->
nodes
[
level
])
{
struct
tree_buffer
*
t
;
t
=
alloc_free_block
(
root
);
c
=
&
t
->
node
;
memset
(
c
,
0
,
sizeof
(
c
));
c
->
header
.
nritems
=
2
;
c
->
header
.
flags
=
node_level
(
level
);
c
->
header
.
blocknr
=
t
->
blocknr
;
c
->
header
.
parentid
=
root
->
node
->
node
.
header
.
parentid
;
lower
=
&
path
->
nodes
[
level
-
1
]
->
node
;
if
(
is_leaf
(
lower
->
header
.
flags
))
lower_key
=
&
((
struct
leaf
*
)
lower
)
->
items
[
0
].
key
;
else
lower_key
=
lower
->
keys
;
memcpy
(
c
->
keys
,
lower_key
,
sizeof
(
struct
key
));
memcpy
(
c
->
keys
+
1
,
key
,
sizeof
(
struct
key
));
c
->
blockptrs
[
0
]
=
path
->
nodes
[
level
-
1
]
->
blocknr
;
c
->
blockptrs
[
1
]
=
blocknr
;
/* the super has an extra ref to root->node */
tree_block_release
(
root
,
root
->
node
);
root
->
node
=
t
;
t
->
count
++
;
write_tree_block
(
root
,
t
);
path
->
nodes
[
level
]
=
t
;
path
->
slots
[
level
]
=
0
;
if
(
c
->
keys
[
1
].
objectid
==
0
)
BUG
();
return
0
;
}
BUG_ON
(
!
path
->
nodes
[
level
]);
lower
=
&
path
->
nodes
[
level
]
->
node
;
nritems
=
lower
->
header
.
nritems
;
if
(
slot
>
nritems
)
...
...
@@ -396,93 +421,54 @@ int __insert_ptr(struct ctree_root *root,
return
0
;
}
/*
* insert a key,blocknr pair into the tree at a given level
* If the node at that level in the path doesn't have room,
* it is split or shifted as appropriate.
*/
int
insert_ptr
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
struct
key
*
key
,
u64
blocknr
,
int
level
)
int
split_node
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
,
int
level
)
{
struct
tree_buffer
*
t
=
path
->
nodes
[
level
];
struct
node
*
c
=
&
path
->
nodes
[
level
]
->
node
;
struct
node
*
b
;
struct
tree_buffer
*
b_buffer
;
struct
tree_buffer
*
bal
[
MAX_LEVEL
];
int
bal_level
=
level
;
struct
tree_buffer
*
t
;
struct
node
*
c
;
struct
tree_buffer
*
split_buffer
;
struct
node
*
split
;
int
mid
;
int
bal_start
=
-
1
;
/*
* check to see if we need to make room in the node for this
* pointer. If we do, keep walking the tree, making sure there
* is enough room in each level for the required insertions.
*
* The bal array is filled in with any nodes to be inserted
* due to splitting. Once we've done all the splitting required
* do the inserts based on the data in the bal array.
*/
memset
(
bal
,
0
,
sizeof
(
bal
));
while
(
t
&&
t
->
node
.
header
.
nritems
==
NODEPTRS_PER_BLOCK
)
{
c
=
&
t
->
node
;
if
(
push_node_left
(
root
,
path
,
node_level
(
c
->
header
.
flags
))
==
0
)
break
;
if
(
push_node_right
(
root
,
path
,
node_level
(
c
->
header
.
flags
))
==
0
)
break
;
bal_start
=
bal_level
;
if
(
bal_level
==
MAX_LEVEL
-
1
)
BUG
();
b_buffer
=
alloc_free_block
(
root
);
b
=
&
b_buffer
->
node
;
b
->
header
.
flags
=
c
->
header
.
flags
;
b
->
header
.
blocknr
=
b_buffer
->
blocknr
;
b
->
header
.
parentid
=
root
->
node
->
node
.
header
.
parentid
;
mid
=
(
c
->
header
.
nritems
+
1
)
/
2
;
memcpy
(
b
->
keys
,
c
->
keys
+
mid
,
(
c
->
header
.
nritems
-
mid
)
*
sizeof
(
struct
key
));
memcpy
(
b
->
blockptrs
,
c
->
blockptrs
+
mid
,
(
c
->
header
.
nritems
-
mid
)
*
sizeof
(
u64
));
b
->
header
.
nritems
=
c
->
header
.
nritems
-
mid
;
c
->
header
.
nritems
=
mid
;
write_tree_block
(
root
,
t
);
write_tree_block
(
root
,
b_buffer
);
int
ret
;
bal
[
bal_level
]
=
b_buffer
;
if
(
bal_level
==
MAX_LEVEL
-
1
)
break
;
bal_level
+=
1
;
t
=
path
->
nodes
[
bal_level
];
ret
=
push_node_left
(
root
,
path
,
level
);
if
(
!
ret
)
return
0
;
ret
=
push_node_right
(
root
,
path
,
level
);
if
(
!
ret
)
return
0
;
t
=
path
->
nodes
[
level
];
c
=
&
t
->
node
;
if
(
t
==
root
->
node
)
{
/* trying to split the root, lets make a new one */
ret
=
insert_new_root
(
root
,
path
,
level
+
1
);
if
(
ret
)
return
ret
;
}
/*
* bal_start tells us the first level in the tree that needed to
* be split. Go through the bal array inserting the new nodes
* as needed. The path is fixed as we go.
*/
while
(
bal_start
>
0
)
{
b_buffer
=
bal
[
bal_start
];
c
=
&
path
->
nodes
[
bal_start
]
->
node
;
__insert_ptr
(
root
,
path
,
b_buffer
->
node
.
keys
,
b_buffer
->
blocknr
,
path
->
slots
[
bal_start
+
1
]
+
1
,
bal_start
+
1
);
if
(
path
->
slots
[
bal_start
]
>=
c
->
header
.
nritems
)
{
path
->
slots
[
bal_start
]
-=
c
->
header
.
nritems
;
tree_block_release
(
root
,
path
->
nodes
[
bal_start
]);
path
->
nodes
[
bal_start
]
=
b_buffer
;
path
->
slots
[
bal_start
+
1
]
+=
1
;
}
else
{
tree_block_release
(
root
,
b_buffer
);
}
bal_start
--
;
if
(
!
bal
[
bal_start
])
break
;
split_buffer
=
alloc_free_block
(
root
);
split
=
&
split_buffer
->
node
;
split
->
header
.
flags
=
c
->
header
.
flags
;
split
->
header
.
blocknr
=
split_buffer
->
blocknr
;
split
->
header
.
parentid
=
root
->
node
->
node
.
header
.
parentid
;
mid
=
(
c
->
header
.
nritems
+
1
)
/
2
;
memcpy
(
split
->
keys
,
c
->
keys
+
mid
,
(
c
->
header
.
nritems
-
mid
)
*
sizeof
(
struct
key
));
memcpy
(
split
->
blockptrs
,
c
->
blockptrs
+
mid
,
(
c
->
header
.
nritems
-
mid
)
*
sizeof
(
u64
));
split
->
header
.
nritems
=
c
->
header
.
nritems
-
mid
;
c
->
header
.
nritems
=
mid
;
write_tree_block
(
root
,
t
);
write_tree_block
(
root
,
split_buffer
);
insert_ptr
(
root
,
path
,
split
->
keys
,
split_buffer
->
blocknr
,
path
->
slots
[
level
+
1
]
+
1
,
level
+
1
);
if
(
path
->
slots
[
level
]
>
mid
)
{
path
->
slots
[
level
]
-=
mid
;
tree_block_release
(
root
,
t
);
path
->
nodes
[
level
]
=
split_buffer
;
path
->
slots
[
level
+
1
]
+=
1
;
}
else
{
tree_block_release
(
root
,
split_buffer
);
}
/* Now that the tree has room, insert the requested pointer */
return
__insert_ptr
(
root
,
path
,
key
,
blocknr
,
path
->
slots
[
level
]
+
1
,
level
);
return
0
;
}
/*
...
...
@@ -623,6 +609,11 @@ int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size)
if
(
leaf_free_space
(
l
)
>=
sizeof
(
struct
item
)
+
data_size
)
return
0
;
}
if
(
!
path
->
nodes
[
1
])
{
ret
=
insert_new_root
(
root
,
path
,
1
);
if
(
ret
)
return
ret
;
}
slot
=
path
->
slots
[
0
];
nritems
=
l
->
header
.
nritems
;
mid
=
(
nritems
+
1
)
/
2
;
...
...
@@ -659,8 +650,7 @@ int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size)
l
->
header
.
nritems
=
mid
;
ret
=
insert_ptr
(
root
,
path
,
&
right
->
items
[
0
].
key
,
right_buffer
->
blocknr
,
1
);
right_buffer
->
blocknr
,
path
->
slots
[
1
]
+
1
,
1
);
write_tree_block
(
root
,
right_buffer
);
write_tree_block
(
root
,
l_buf
);
...
...
@@ -695,21 +685,10 @@ int insert_item(struct ctree_root *root, struct key *key,
refill_alloc_extent
(
root
);
/* create a root if there isn't one */
if
(
!
root
->
node
)
{
if
(
!
root
->
node
)
BUG
();
#if 0
struct tree_buffer *t;
t = alloc_free_block(root);
BUG_ON(!t);
t->node.header.nritems = 0;
t->node.header.flags = node_level(0);
t->node.header.blocknr = t->blocknr;
root->node = t;
write_tree_block(root, t);
#endif
}
init_path
(
&
path
);
ret
=
search_slot
(
root
,
key
,
&
path
);
ret
=
search_slot
(
root
,
key
,
&
path
,
data_size
);
if
(
ret
==
0
)
{
release_path
(
root
,
&
path
);
return
-
EEXIST
;
...
...
@@ -719,12 +698,6 @@ int insert_item(struct ctree_root *root, struct key *key,
leaf_buf
=
path
.
nodes
[
0
];
leaf
=
&
leaf_buf
->
leaf
;
/* make room if needed */
if
(
leaf_free_space
(
leaf
)
<
sizeof
(
struct
item
)
+
data_size
)
{
split_leaf
(
root
,
&
path
,
data_size
);
leaf_buf
=
path
.
nodes
[
0
];
leaf
=
&
path
.
nodes
[
0
]
->
leaf
;
}
nritems
=
leaf
->
header
.
nritems
;
data_end
=
leaf_data_end
(
leaf
);
...
...
@@ -950,7 +923,7 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start,
ins
->
offset
=
0
;
ins
->
flags
=
0
;
ret
=
search_slot
(
root
,
ins
,
&
path
);
ret
=
search_slot
(
root
,
ins
,
&
path
,
sizeof
(
struct
extent_item
)
);
while
(
1
)
{
l
=
&
path
.
nodes
[
0
]
->
leaf
;
slot
=
path
.
slots
[
0
];
...
...
@@ -1097,8 +1070,8 @@ void print_tree(struct ctree_root *root, struct tree_buffer *t)
/* for testing only */
int
next_key
(
int
i
,
int
max_key
)
{
return
rand
()
%
max_key
;
//
return i;
//
return rand() % max_key;
return
i
;
}
int
main
()
{
...
...
@@ -1154,7 +1127,7 @@ int main() {
num
=
next_key
(
i
,
max_key
);
ins
.
objectid
=
num
;
init_path
(
&
path
);
ret
=
search_slot
(
root
,
&
ins
,
&
path
);
ret
=
search_slot
(
root
,
&
ins
,
&
path
,
0
);
if
(
ret
)
{
print_tree
(
root
,
root
->
node
);
printf
(
"unable to find %d
\n
"
,
num
);
...
...
@@ -1176,7 +1149,7 @@ int main() {
num
=
next_key
(
i
,
max_key
);
ins
.
objectid
=
num
;
init_path
(
&
path
);
ret
=
search_slot
(
root
,
&
ins
,
&
path
);
ret
=
search_slot
(
root
,
&
ins
,
&
path
,
0
);
if
(
ret
)
continue
;
ret
=
del_item
(
root
,
&
path
);
...
...
@@ -1204,7 +1177,7 @@ int main() {
num
=
next_key
(
i
,
max_key
);
ins
.
objectid
=
num
;
init_path
(
&
path
);
ret
=
search_slot
(
root
,
&
ins
,
&
path
);
ret
=
search_slot
(
root
,
&
ins
,
&
path
,
0
);
if
(
ret
)
{
print_tree
(
root
,
root
->
node
);
printf
(
"unable to find %d
\n
"
,
num
);
...
...
@@ -1218,7 +1191,7 @@ int main() {
int
slot
;
ins
.
objectid
=
(
u64
)
-
1
;
init_path
(
&
path
);
ret
=
search_slot
(
root
,
&
ins
,
&
path
);
ret
=
search_slot
(
root
,
&
ins
,
&
path
,
0
);
if
(
ret
==
0
)
BUG
();
...
...
fs/btrfs/disk-io.c
浏览文件 @
5c680ed6
...
...
@@ -149,7 +149,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
}
ret
=
pread
(
fp
,
super
,
sizeof
(
struct
ctree_super_block
),
CTREE_SUPER_INFO_OFFSET
(
CTREE_BLOCKSIZE
));
if
(
ret
==
0
)
{
if
(
ret
==
0
||
super
->
root_info
.
tree_root
==
0
)
{
printf
(
"making new FS!
\n
"
);
ret
=
mkfs
(
fp
);
if
(
ret
)
return
NULL
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录