Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
FengXiao2002
Linux Imx
提交
a28ec197
L
Linux Imx
项目概览
FengXiao2002
/
Linux Imx
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
Linux Imx
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a28ec197
编写于
3月 06, 2007
作者:
C
Chris Mason
提交者:
David Woodhouse
3月 06, 2007
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Btrfs: Fixup reference counting on cows
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
02217ed2
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
267 addition
and
127 deletion
+267
-127
fs/btrfs/Makefile
fs/btrfs/Makefile
+1
-1
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+4
-5
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+4
-0
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+26
-5
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+2
-2
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+204
-87
fs/btrfs/print-tree.c
fs/btrfs/print-tree.c
+4
-2
fs/btrfs/quick-test.c
fs/btrfs/quick-test.c
+15
-11
fs/btrfs/random-test.c
fs/btrfs/random-test.c
+7
-14
未找到文件。
fs/btrfs/Makefile
浏览文件 @
a28ec197
CC
=
gcc
CFLAGS
=
-g
-Wall
headers
=
radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h
headers
=
radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h
list.h
objects
=
ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o
# if you don't have sparse installed, use ls instead
...
...
fs/btrfs/ctree.c
浏览文件 @
a28ec197
...
...
@@ -50,16 +50,17 @@ int btrfs_cow_block(struct ctree_root *root,
memcpy
(
&
cow
->
node
,
&
buf
->
node
,
sizeof
(
buf
->
node
));
cow
->
node
.
header
.
blocknr
=
cow
->
blocknr
;
*
cow_ret
=
cow
;
btrfs_inc_ref
(
root
,
buf
);
if
(
buf
==
root
->
node
)
{
root
->
node
=
cow
;
cow
->
count
++
;
if
(
buf
!=
root
->
commit_root
)
free_extent
(
root
,
buf
->
blocknr
,
1
);
tree_block_release
(
root
,
buf
);
}
else
{
parent
->
node
.
blockptrs
[
parent_slot
]
=
cow
->
blocknr
;
BUG_ON
(
list_empty
(
&
parent
->
dirty
));
}
if
(
0
&&
root
!=
root
->
extent_root
&&
!
is_leaf
(
cow
->
node
.
header
.
flags
))
{
btrfs_inc_ref
(
root
,
cow
);
free_extent
(
root
,
buf
->
blocknr
,
1
);
}
tree_block_release
(
root
,
buf
);
return
0
;
...
...
@@ -1018,7 +1019,6 @@ static int split_leaf(struct ctree_root *root, struct ctree_path *path,
slot
=
path
->
slots
[
0
];
nritems
=
l
->
header
.
nritems
;
mid
=
(
nritems
+
1
)
/
2
;
right_buffer
=
alloc_free_block
(
root
);
BUG_ON
(
!
right_buffer
);
BUG_ON
(
mid
==
nritems
);
...
...
@@ -1170,7 +1170,6 @@ static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level,
node
=
&
parent
->
node
;
nritems
=
node
->
header
.
nritems
;
if
(
slot
!=
nritems
-
1
)
{
memmove
(
node
->
keys
+
slot
,
node
->
keys
+
slot
+
1
,
sizeof
(
struct
key
)
*
(
nritems
-
slot
-
1
));
...
...
fs/btrfs/ctree.h
浏览文件 @
a28ec197
...
...
@@ -51,10 +51,12 @@ struct tree_buffer;
*/
struct
ctree_root
{
struct
tree_buffer
*
node
;
struct
tree_buffer
*
commit_root
;
struct
ctree_root
*
extent_root
;
struct
key
current_insert
;
int
fp
;
struct
radix_tree_root
cache_radix
;
struct
radix_tree_root
pinned_radix
;
struct
list_head
trans
;
struct
list_head
cache
;
int
cache_size
;
...
...
@@ -151,4 +153,6 @@ int del_item(struct ctree_root *root, struct ctree_path *path);
int
insert_item
(
struct
ctree_root
*
root
,
struct
key
*
key
,
void
*
data
,
int
data_size
);
int
next_leaf
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
);
int
leaf_free_space
(
struct
leaf
*
leaf
);
int
btrfs_drop_snapshot
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
snap
);
int
btrfs_finish_extent_commit
(
struct
ctree_root
*
root
);
#endif
fs/btrfs/disk-io.c
浏览文件 @
a28ec197
...
...
@@ -153,13 +153,24 @@ static int __commit_transaction(struct ctree_root *root)
return
ret
;
}
int
commit_transaction
(
struct
ctree_root
*
root
)
int
commit_transaction
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
)
{
int
ret
;
int
ret
=
0
;
ret
=
__commit_transaction
(
root
);
if
(
!
ret
&&
root
!=
root
->
extent_root
)
ret
=
__commit_transaction
(
root
->
extent_root
);
BUG_ON
(
ret
);
if
(
root
->
commit_root
!=
root
->
node
)
{
struct
tree_buffer
*
snap
=
root
->
commit_root
;
root
->
commit_root
=
root
->
node
;
root
->
node
->
count
++
;
ret
=
btrfs_drop_snapshot
(
root
,
snap
);
BUG_ON
(
ret
);
tree_block_release
(
root
,
snap
);
}
write_ctree_super
(
root
,
s
);
btrfs_finish_extent_commit
(
root
);
return
ret
;
}
...
...
@@ -168,10 +179,13 @@ static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
{
INIT_LIST_HEAD
(
&
root
->
trans
);
INIT_LIST_HEAD
(
&
root
->
cache
);
root
->
cache_size
=
0
;
root
->
fp
=
fp
;
root
->
node
=
NULL
;
root
->
node
=
read_tree_block
(
root
,
info
->
tree_root
);
root
->
extent_root
=
extent_root
;
root
->
commit_root
=
NULL
;
root
->
node
=
read_tree_block
(
root
,
info
->
tree_root
);
memset
(
&
root
->
current_insert
,
0
,
sizeof
(
root
->
current_insert
));
return
0
;
}
...
...
@@ -188,6 +202,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
return
NULL
;
}
INIT_RADIX_TREE
(
&
root
->
cache_radix
,
GFP_KERNEL
);
INIT_RADIX_TREE
(
&
root
->
pinned_radix
,
GFP_KERNEL
);
INIT_RADIX_TREE
(
&
extent_root
->
pinned_radix
,
GFP_KERNEL
);
INIT_RADIX_TREE
(
&
extent_root
->
cache_radix
,
GFP_KERNEL
);
ret
=
pread
(
fp
,
super
,
sizeof
(
struct
ctree_super_block
),
CTREE_SUPER_INFO_OFFSET
(
CTREE_BLOCKSIZE
));
...
...
@@ -204,6 +220,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
BUG_ON
(
ret
<
0
);
__setup_root
(
root
,
extent_root
,
&
super
->
root_info
,
fp
);
__setup_root
(
extent_root
,
extent_root
,
&
super
->
extent_info
,
fp
);
root
->
commit_root
=
root
->
node
;
root
->
node
->
count
++
;
return
root
;
}
...
...
@@ -236,9 +254,11 @@ static int drop_cache(struct ctree_root *root)
}
return
0
;
}
int
close_ctree
(
struct
ctree_root
*
root
)
int
close_ctree
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
)
{
commit_transaction
(
root
);
commit_transaction
(
root
,
s
);
__commit_transaction
(
root
->
extent_root
);
write_ctree_super
(
root
,
s
);
drop_cache
(
root
->
extent_root
);
drop_cache
(
root
);
BUG_ON
(
!
list_empty
(
&
root
->
trans
));
...
...
@@ -249,6 +269,7 @@ int close_ctree(struct ctree_root *root)
tree_block_release
(
root
,
root
->
node
);
if
(
root
->
extent_root
->
node
)
tree_block_release
(
root
->
extent_root
,
root
->
extent_root
->
node
);
tree_block_release
(
root
,
root
->
commit_root
);
free
(
root
);
printf
(
"on close %d blocks are allocated
\n
"
,
allocated_blocks
);
return
0
;
...
...
fs/btrfs/disk-io.h
浏览文件 @
a28ec197
...
...
@@ -18,9 +18,9 @@ struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr);
int
write_tree_block
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
);
int
dirty_tree_block
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
);
int
clean_tree_block
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
);
int
commit_transaction
(
struct
ctree_root
*
root
);
int
commit_transaction
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
);
struct
ctree_root
*
open_ctree
(
char
*
filename
,
struct
ctree_super_block
*
s
);
int
close_ctree
(
struct
ctree_root
*
root
);
int
close_ctree
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
);
void
tree_block_release
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
);
int
write_ctree_super
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
);
int
mkfs
(
int
fd
);
...
...
fs/btrfs/extent-tree.c
浏览文件 @
a28ec197
...
...
@@ -13,7 +13,8 @@
* other allocations are done. The pending tag is also used in the same
* manner for deletes.
*/
#define CTREE_EXTENT_PENDING 0
#define CTREE_EXTENT_PENDING_ADD 0
#define CTREE_EXTENT_PENDING_DEL 1
static
int
inc_block_ref
(
struct
ctree_root
*
root
,
u64
blocknr
)
{
...
...
@@ -27,20 +28,51 @@ static int inc_block_ref(struct ctree_root *root, u64 blocknr)
key
.
flags
=
0
;
key
.
offset
=
1
;
ret
=
search_slot
(
root
->
extent_root
,
&
key
,
&
path
,
0
,
1
);
if
(
ret
!=
0
)
BUG
();
BUG_ON
(
ret
!=
0
);
l
=
&
path
.
nodes
[
0
]
->
leaf
;
item
=
(
struct
extent_item
*
)(
l
->
data
+
l
->
items
[
path
.
slots
[
0
]].
offset
);
item
->
refs
++
;
BUG_ON
(
list_empty
(
&
path
.
nodes
[
0
]
->
dirty
));
release_path
(
root
->
extent_root
,
&
path
);
return
0
;
}
static
int
lookup_block_ref
(
struct
ctree_root
*
root
,
u64
blocknr
,
int
*
refs
)
{
struct
ctree_path
path
;
int
ret
;
struct
key
key
;
struct
leaf
*
l
;
struct
extent_item
*
item
;
init_path
(
&
path
);
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
1
;
ret
=
search_slot
(
root
->
extent_root
,
&
key
,
&
path
,
0
,
0
);
if
(
ret
!=
0
)
BUG
();
l
=
&
path
.
nodes
[
0
]
->
leaf
;
item
=
(
struct
extent_item
*
)(
l
->
data
+
l
->
items
[
path
.
slots
[
0
]].
offset
);
*
refs
=
item
->
refs
;
release_path
(
root
->
extent_root
,
&
path
);
return
0
;
}
int
btrfs_inc_ref
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
)
{
u64
blocknr
;
int
i
;
if
(
root
==
root
->
extent_root
)
return
0
;
if
(
is_leaf
(
buf
->
node
.
header
.
flags
))
return
0
;
for
(
i
=
0
;
i
<
buf
->
node
.
header
.
nritems
;
i
++
)
{
blocknr
=
buf
->
node
.
blockptrs
[
i
];
inc_block_ref
(
root
,
blocknr
);
...
...
@@ -48,85 +80,187 @@ int btrfs_inc_ref(struct ctree_root *root, struct tree_buffer *buf)
return
0
;
}
int
btrfs_finish_extent_commit
(
struct
ctree_root
*
root
)
{
struct
ctree_root
*
extent_root
=
root
->
extent_root
;
unsigned
long
gang
[
8
];
int
ret
;
int
i
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup
(
&
extent_root
->
pinned_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
));
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
radix_tree_delete
(
&
extent_root
->
pinned_radix
,
gang
[
i
]);
}
return
0
;
}
/*
* find all the blocks marked as pending in the radix tree and remove
* them from the extent map
* remove an extent from the root, returns 0 on success
*/
static
int
del_pending_extents
(
struct
ctree_root
*
extent_root
)
int
__free_extent
(
struct
ctree_root
*
root
,
u64
blocknr
,
u64
num_blocks
)
{
struct
ctree_path
path
;
struct
key
key
;
struct
ctree_root
*
extent_root
=
root
->
extent_root
;
int
ret
;
struct
item
*
item
;
struct
extent_item
*
ei
;
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
num_blocks
;
init_path
(
&
path
);
ret
=
search_slot
(
extent_root
,
&
key
,
&
path
,
-
1
,
1
);
if
(
ret
)
{
printf
(
"failed to find %Lu
\n
"
,
key
.
objectid
);
print_tree
(
extent_root
,
extent_root
->
node
);
printf
(
"failed to find %Lu
\n
"
,
key
.
objectid
);
BUG
();
}
item
=
path
.
nodes
[
0
]
->
leaf
.
items
+
path
.
slots
[
0
];
ei
=
(
struct
extent_item
*
)(
path
.
nodes
[
0
]
->
leaf
.
data
+
item
->
offset
);
BUG_ON
(
ei
->
refs
==
0
);
ei
->
refs
--
;
if
(
ei
->
refs
==
0
)
{
if
(
root
==
extent_root
)
{
int
err
;
radix_tree_preload
(
GFP_KERNEL
);
err
=
radix_tree_insert
(
&
extent_root
->
pinned_radix
,
blocknr
,
(
void
*
)
blocknr
);
BUG_ON
(
err
);
radix_tree_preload_end
();
}
ret
=
del_item
(
extent_root
,
&
path
);
if
(
ret
)
BUG
();
}
release_path
(
extent_root
,
&
path
);
return
ret
;
}
/*
* insert all of the pending extents reserved during the original
* allocation. (CTREE_EXTENT_PENDING). Returns zero if it all worked out
*/
static
int
insert_pending_extents
(
struct
ctree_root
*
extent_root
)
{
int
ret
;
struct
key
key
;
struct
extent_item
item
;
struct
tree_buffer
*
gang
[
4
];
int
i
;
struct
ctree_path
path
;
// FIXME -ENOSPC
item
.
owner
=
extent_root
->
node
->
node
.
header
.
parentid
;
item
.
refs
=
1
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
extent_root
->
cache_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PENDING
);
CTREE_EXTENT_PENDING
_ADD
);
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
key
.
objectid
=
gang
[
i
]
->
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
1
;
init_path
(
&
path
);
ret
=
search_slot
(
extent_root
,
&
key
,
&
path
,
-
1
,
1
);
ret
=
insert_item
(
extent_root
,
&
key
,
&
item
,
sizeof
(
item
)
);
if
(
ret
)
{
printf
(
"%Lu already in tree
\n
"
,
key
.
objectid
);
print_tree
(
extent_root
,
extent_root
->
node
);
printf
(
"unable to find %Lu
\n
"
,
key
.
objectid
);
BUG
();
// FIXME undo it and return sane
return
ret
;
}
ret
=
del_item
(
extent_root
,
&
path
);
if
(
ret
)
{
BUG
();
return
ret
;
}
release_path
(
extent_root
,
&
path
);
radix_tree_tag_clear
(
&
extent_root
->
cache_radix
,
gang
[
i
]
->
blocknr
,
CTREE_EXTENT_PENDING_ADD
);
tree_block_release
(
extent_root
,
gang
[
i
]);
}
}
return
0
;
}
/*
* find all the blocks marked as pending in the radix tree and remove
* them from the extent map
*/
static
int
del_pending_extents
(
struct
ctree_root
*
extent_root
)
{
int
ret
;
struct
tree_buffer
*
gang
[
4
];
int
i
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
extent_root
->
cache_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PENDING_DEL
);
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
ret
=
__free_extent
(
extent_root
,
gang
[
i
]
->
blocknr
,
1
);
radix_tree_tag_clear
(
&
extent_root
->
cache_radix
,
gang
[
i
]
->
blocknr
,
CTREE_EXTENT_PENDING
);
CTREE_EXTENT_PENDING
_DEL
);
tree_block_release
(
extent_root
,
gang
[
i
]);
}
}
return
0
;
}
static
int
run_pending
(
struct
ctree_root
*
extent_root
)
{
while
(
radix_tree_tagged
(
&
extent_root
->
cache_radix
,
CTREE_EXTENT_PENDING_DEL
)
||
radix_tree_tagged
(
&
extent_root
->
cache_radix
,
CTREE_EXTENT_PENDING_ADD
))
{
insert_pending_extents
(
extent_root
);
del_pending_extents
(
extent_root
);
}
return
0
;
}
/*
* remove an extent from the root, returns 0 on success
*/
int
free_extent
(
struct
ctree_root
*
root
,
u64
blocknr
,
u64
num_blocks
)
{
struct
ctree_path
path
;
struct
key
key
;
struct
ctree_root
*
extent_root
=
root
->
extent_root
;
struct
tree_buffer
*
t
;
int
pending_ret
;
int
ret
;
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
num_blocks
;
if
(
root
==
extent_root
)
{
t
=
read_tree_block
(
root
,
key
.
objectid
);
radix_tree_tag_set
(
&
root
->
cache_radix
,
key
.
objectid
,
CTREE_EXTENT_PENDING
);
t
=
find_tree_block
(
root
,
blocknr
);
if
(
radix_tree_tag_get
(
&
root
->
cache_radix
,
blocknr
,
CTREE_EXTENT_PENDING_ADD
))
{
radix_tree_tag_clear
(
&
root
->
cache_radix
,
blocknr
,
CTREE_EXTENT_PENDING_ADD
);
/* once for us */
tree_block_release
(
root
,
t
);
/* once for the pending add */
tree_block_release
(
root
,
t
);
}
else
{
radix_tree_tag_set
(
&
root
->
cache_radix
,
blocknr
,
CTREE_EXTENT_PENDING_DEL
);
}
return
0
;
}
init_path
(
&
path
);
ret
=
search_slot
(
extent_root
,
&
key
,
&
path
,
-
1
,
1
);
if
(
ret
)
{
print_tree
(
extent_root
,
extent_root
->
node
);
printf
(
"failed to find %Lu
\n
"
,
key
.
objectid
);
BUG
();
}
ret
=
del_item
(
extent_root
,
&
path
);
if
(
ret
)
BUG
();
release_path
(
extent_root
,
&
path
);
pending_ret
=
del_pending_extents
(
root
->
extent_root
);
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
num_blocks
;
ret
=
__free_extent
(
root
,
blocknr
,
num_blocks
);
pending_ret
=
run_pending
(
root
->
extent_root
);
return
ret
?
ret
:
pending_ret
;
}
...
...
@@ -203,7 +337,7 @@ check_pending:
*/
release_path
(
root
,
&
path
);
BUG_ON
(
ins
->
objectid
<
search_start
);
if
(
orig_root
->
extent_root
==
orig_root
)
{
if
(
1
||
orig_root
->
extent_root
==
orig_root
)
{
BUG_ON
(
num_blocks
!=
1
);
if
((
root
->
current_insert
.
objectid
<=
ins
->
objectid
&&
root
->
current_insert
.
objectid
+
...
...
@@ -211,8 +345,9 @@ check_pending:
(
root
->
current_insert
.
objectid
>
ins
->
objectid
&&
root
->
current_insert
.
objectid
<=
ins
->
objectid
+
ins
->
offset
)
||
radix_tree_lookup
(
&
root
->
pinned_radix
,
ins
->
objectid
)
||
radix_tree_tag_get
(
&
root
->
cache_radix
,
ins
->
objectid
,
CTREE_EXTENT_PENDING
))
{
CTREE_EXTENT_PENDING
_ADD
))
{
search_start
=
ins
->
objectid
+
1
;
goto
check_failed
;
}
...
...
@@ -225,51 +360,6 @@ error:
return
ret
;
}
/*
* insert all of the pending extents reserved during the original
* allocation. (CTREE_EXTENT_PENDING). Returns zero if it all worked out
*/
static
int
insert_pending_extents
(
struct
ctree_root
*
extent_root
)
{
int
ret
;
struct
key
key
;
struct
extent_item
item
;
struct
tree_buffer
*
gang
[
4
];
int
i
;
// FIXME -ENOSPC
item
.
refs
=
1
;
item
.
owner
=
extent_root
->
node
->
node
.
header
.
parentid
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
extent_root
->
cache_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PENDING
);
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
key
.
objectid
=
gang
[
i
]
->
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
1
;
ret
=
insert_item
(
extent_root
,
&
key
,
&
item
,
sizeof
(
item
));
if
(
ret
)
{
printf
(
"%Lu already in tree
\n
"
,
key
.
objectid
);
print_tree
(
extent_root
,
extent_root
->
node
);
BUG
();
// FIXME undo it and return sane
return
ret
;
}
radix_tree_tag_clear
(
&
extent_root
->
cache_radix
,
gang
[
i
]
->
blocknr
,
CTREE_EXTENT_PENDING
);
printf
(
"%Lu is not pending
\n
"
,
gang
[
i
]
->
blocknr
);
tree_block_release
(
extent_root
,
gang
[
i
]);
}
}
return
0
;
}
/*
* finds a free extent and does all the dirty work required for allocation
* returns the key for the extent through ins, and a tree buffer for
...
...
@@ -296,7 +386,7 @@ int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start,
sizeof
(
extent_item
));
memset
(
&
root
->
extent_root
->
current_insert
,
0
,
sizeof
(
struct
key
));
pending_ret
=
insert_pending_extents
(
root
->
extent_root
);
pending_ret
=
run_pending
(
root
->
extent_root
);
if
(
ret
)
return
ret
;
if
(
pending_ret
)
...
...
@@ -309,9 +399,8 @@ int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start,
BUG_ON
(
ins
->
offset
!=
1
);
*
buf
=
find_tree_block
(
root
,
ins
->
objectid
);
BUG_ON
(
!*
buf
);
printf
(
"%Lu is pending
\n
"
,
ins
->
objectid
);
radix_tree_tag_set
(
&
root
->
cache_radix
,
ins
->
objectid
,
CTREE_EXTENT_PENDING
);
CTREE_EXTENT_PENDING
_ADD
);
(
*
buf
)
->
count
++
;
dirty_tree_block
(
root
,
*
buf
);
return
0
;
...
...
@@ -331,13 +420,41 @@ struct tree_buffer *alloc_free_block(struct ctree_root *root)
ret
=
alloc_extent
(
root
,
1
,
0
,
(
unsigned
long
)
-
1
,
root
->
node
->
node
.
header
.
parentid
,
&
ins
,
&
buf
);
if
(
ret
)
{
BUG
();
return
NULL
;
}
if
(
root
!=
root
->
extent_root
)
BUG_ON
(
radix_tree_tag_get
(
&
root
->
extent_root
->
cache_radix
,
buf
->
blocknr
,
CTREE_EXTENT_PENDING
));
buf
->
blocknr
,
CTREE_EXTENT_PENDING_ADD
));
return
buf
;
}
int
btrfs_drop_snapshot
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
snap
)
{
int
ret
;
int
level
;
int
refs
;
u64
blocknr
=
snap
->
blocknr
;
level
=
node_level
(
snap
->
node
.
header
.
flags
);
ret
=
lookup_block_ref
(
root
,
snap
->
blocknr
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
==
1
&&
level
!=
0
)
{
struct
node
*
n
=
&
snap
->
node
;
struct
tree_buffer
*
b
;
int
i
;
for
(
i
=
0
;
i
<
n
->
header
.
nritems
;
i
++
)
{
b
=
read_tree_block
(
root
,
n
->
blockptrs
[
i
]);
/* FIXME, don't recurse here */
ret
=
btrfs_drop_snapshot
(
root
,
b
);
BUG_ON
(
ret
);
tree_block_release
(
root
,
b
);
}
}
ret
=
free_extent
(
root
,
blocknr
,
1
);
BUG_ON
(
ret
);
return
0
;
}
fs/btrfs/print-tree.c
浏览文件 @
a28ec197
...
...
@@ -21,9 +21,11 @@ void print_leaf(struct leaf *l)
item
->
key
.
objectid
,
item
->
key
.
flags
,
item
->
key
.
offset
,
item
->
offset
,
item
->
size
);
fflush
(
stdout
);
printf
(
"
\t\t
item data %.*s
\n
"
,
item
->
size
,
l
->
data
+
item
->
offset
);
printf
(
"
\t\t
item data %.*s
\n
"
,
item
->
size
,
l
->
data
+
item
->
offset
);
ei
=
(
struct
extent_item
*
)(
l
->
data
+
item
->
offset
);
printf
(
"
\t\t
extent data %u %Lu
\n
"
,
ei
->
refs
,
ei
->
owner
);
printf
(
"
\t\t
extent data refs %u owner %Lu
\n
"
,
ei
->
refs
,
ei
->
owner
);
fflush
(
stdout
);
}
}
...
...
fs/btrfs/quick-test.c
浏览文件 @
a28ec197
...
...
@@ -19,7 +19,7 @@ int main(int ac, char **av) {
int
i
;
int
num
;
int
ret
;
int
run_size
=
10
24
;
int
run_size
=
10
0000
;
int
max_key
=
100000000
;
int
tree_size
=
0
;
struct
ctree_path
path
;
...
...
@@ -44,9 +44,9 @@ int main(int ac, char **av) {
if
(
!
ret
)
tree_size
++
;
free
(
buf
);
}
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
printf
(
"starting search
\n
"
);
...
...
@@ -65,8 +65,7 @@ int main(int ac, char **av) {
}
release_path
(
root
,
&
path
);
}
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
printf
(
"node %p level %d total ptrs %d free spc %lu
\n
"
,
root
->
node
,
node_level
(
root
->
node
->
node
.
header
.
flags
),
...
...
@@ -90,8 +89,7 @@ int main(int ac, char **av) {
}
release_path
(
root
,
&
path
);
}
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
srand
(
128
);
for
(
i
=
0
;
i
<
run_size
;
i
++
)
{
...
...
@@ -106,8 +104,7 @@ int main(int ac, char **av) {
tree_size
++
;
free
(
buf
);
}
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
srand
(
128
);
printf
(
"starting search2
\n
"
);
...
...
@@ -156,10 +153,17 @@ int main(int ac, char **av) {
}
release_path
(
root
,
&
path
);
}
/*
printf("previous tree:\n");
print_tree(root, root->commit_root);
printf("map before commit\n");
print_tree(root->extent_root, root->extent_root->node);
*/
commit_transaction
(
root
,
&
super
);
printf
(
"tree size is now %d
\n
"
,
tree_size
);
printf
(
"root %p commit root %p
\n
"
,
root
->
node
,
root
->
commit_root
);
printf
(
"map tree
\n
"
);
print_tree
(
root
->
extent_root
,
root
->
extent_root
->
node
);
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
return
0
;
}
fs/btrfs/random-test.c
浏览文件 @
a28ec197
...
...
@@ -8,6 +8,7 @@
#include "print-tree.h"
int
keep_running
=
1
;
struct
ctree_super_block
super
;
static
int
setup_key
(
struct
radix_tree_root
*
root
,
struct
key
*
key
,
int
exists
)
{
...
...
@@ -59,11 +60,6 @@ error:
return
-
1
;
}
static
int
run_commit
(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
{
return
commit_transaction
(
root
);
}
static
int
insert_dup
(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
{
struct
ctree_path
path
;
...
...
@@ -210,7 +206,7 @@ static int fill_tree(struct ctree_root *root, struct radix_tree_root *radix,
goto
out
;
}
if
(
i
%
1000
==
0
)
{
ret
=
commit_transaction
(
root
);
ret
=
commit_transaction
(
root
,
&
super
);
if
(
ret
)
{
fprintf
(
stderr
,
"fill commit failed
\n
"
);
return
ret
;
...
...
@@ -229,7 +225,7 @@ out:
static
int
bulk_op
(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
{
int
ret
;
int
nr
=
rand
()
%
20
000
;
int
nr
=
rand
()
%
5
000
;
static
int
run_nr
=
0
;
/* do the bulk op much less frequently */
...
...
@@ -247,7 +243,7 @@ static int bulk_op(struct ctree_root *root, struct radix_tree_root *radix)
int
(
*
ops
[])(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
=
{
ins_one
,
insert_dup
,
del_one
,
lookup_item
,
lookup_enoent
,
bulk_op
,
run_commit
};
lookup_enoent
,
bulk_op
};
static
int
fill_radix
(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
{
...
...
@@ -314,7 +310,6 @@ int print_usage(void)
int
main
(
int
ac
,
char
**
av
)
{
RADIX_TREE
(
radix
,
GFP_KERNEL
);
struct
ctree_super_block
super
;
struct
ctree_root
*
root
;
int
i
;
int
ret
;
...
...
@@ -365,8 +360,7 @@ int main(int ac, char **av)
printf
(
"open & close, root level %d nritems %d
\n
"
,
node_level
(
root
->
node
->
node
.
header
.
flags
),
root
->
node
->
node
.
header
.
nritems
);
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
}
while
(
count
--
)
{
...
...
@@ -380,7 +374,7 @@ int main(int ac, char **av)
err
=
ret
;
goto
out
;
}
if
(
ops
[
op
]
==
bulk_op
||
ops
[
op
]
==
run_commit
)
if
(
ops
[
op
]
==
bulk_op
)
break
;
if
(
keep_running
==
0
)
{
err
=
0
;
...
...
@@ -389,8 +383,7 @@ int main(int ac, char **av)
}
}
out:
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
return
err
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录