Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
db94535d
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
db94535d
编写于
10月 15, 2007
作者:
C
Chris Mason
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Btrfs: Allow tree blocks larger than the page size
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
1a5bc167
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
738 addition
and
497 deletion
+738
-497
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+229
-90
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+66
-46
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+58
-34
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+5
-4
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+147
-138
fs/btrfs/extent_map.c
fs/btrfs/extent_map.c
+66
-25
fs/btrfs/extent_map.h
fs/btrfs/extent_map.h
+5
-5
fs/btrfs/file-item.c
fs/btrfs/file-item.c
+5
-5
fs/btrfs/file.c
fs/btrfs/file.c
+60
-66
fs/btrfs/inode.c
fs/btrfs/inode.c
+44
-46
fs/btrfs/print-tree.c
fs/btrfs/print-tree.c
+13
-10
fs/btrfs/super.c
fs/btrfs/super.c
+4
-2
fs/btrfs/sysfs.c
fs/btrfs/sysfs.c
+3
-2
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+22
-17
fs/btrfs/tree-defrag.c
fs/btrfs/tree-defrag.c
+11
-7
未找到文件。
fs/btrfs/ctree.c
浏览文件 @
db94535d
...
...
@@ -83,16 +83,15 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans,
WARN_ON
(
root
->
ref_cows
&&
trans
->
transid
!=
root
->
last_trans
);
cow
=
btrfs_alloc_free_block
(
trans
,
root
,
search_start
,
empty_size
);
cow
=
btrfs_alloc_free_block
(
trans
,
root
,
buf
->
len
,
search_start
,
empty_size
);
if
(
IS_ERR
(
cow
))
return
PTR_ERR
(
cow
);
cow
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
if
(
buf
->
len
!=
root
->
sectorsize
||
cow
->
len
!=
root
->
sectorsize
)
WARN_ON
(
1
);
copy_extent_buffer
(
cow
,
buf
,
0
,
0
,
cow
->
len
);
btrfs_set_header_b
locknr
(
cow
,
extent_buffer_blocknr
(
cow
)
);
btrfs_set_header_b
ytenr
(
cow
,
cow
->
start
);
btrfs_set_header_generation
(
cow
,
trans
->
transid
);
btrfs_set_header_owner
(
cow
,
root
->
root_key
.
objectid
);
...
...
@@ -110,16 +109,16 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans,
root
->
node
=
cow
;
extent_buffer_get
(
cow
);
if
(
buf
!=
root
->
commit_root
)
{
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
buf
),
1
,
1
);
btrfs_free_extent
(
trans
,
root
,
buf
->
start
,
buf
->
len
,
1
);
}
free_extent_buffer
(
buf
);
}
else
{
btrfs_set_node_blockptr
(
parent
,
parent_slot
,
extent_buffer_blocknr
(
cow
)
);
cow
->
start
);
btrfs_mark_buffer_dirty
(
parent
);
WARN_ON
(
btrfs_header_generation
(
parent
)
!=
trans
->
transid
);
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
buf
),
1
,
1
);
btrfs_free_extent
(
trans
,
root
,
buf
->
start
,
buf
->
len
,
1
);
}
free_extent_buffer
(
buf
);
btrfs_mark_buffer_dirty
(
cow
);
...
...
@@ -149,13 +148,14 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
return
0
;
}
search_start
=
extent_buffer_blocknr
(
buf
)
&
~
((
u64
)
65535
);
search_start
=
buf
->
start
&
~
((
u64
)
BTRFS_BLOCK_GROUP_SIZE
-
1
);
ret
=
__btrfs_cow_block
(
trans
,
root
,
buf
,
parent
,
parent_slot
,
cow_ret
,
search_start
,
0
);
(
*
cow_ret
)
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
return
ret
;
}
#if 0
static int close_blocks(u64 blocknr, u64 other)
{
if (blocknr < other && other - blocknr < 8)
...
...
@@ -165,7 +165,6 @@ static int close_blocks(u64 blocknr, u64 other)
return 0;
}
#if 0
static int should_defrag_leaf(struct extent_buffer *eb)
{
return 0;
...
...
@@ -355,7 +354,7 @@ static int check_node(struct btrfs_root *root, struct btrfs_path *path,
BUG_ON
(
memcmp
(
&
parent_key
,
&
node_key
,
sizeof
(
struct
btrfs_disk_key
)));
BUG_ON
(
btrfs_node_blockptr
(
parent
,
parent_slot
)
!=
btrfs_header_b
lock
nr
(
node
));
btrfs_header_b
yte
nr
(
node
));
}
BUG_ON
(
nritems
>
BTRFS_NODEPTRS_PER_BLOCK
(
root
));
if
(
slot
!=
0
)
{
...
...
@@ -398,7 +397,7 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
BUG_ON
(
memcmp
(
&
parent_key
,
&
leaf_key
,
sizeof
(
struct
btrfs_disk_key
)));
BUG_ON
(
btrfs_node_blockptr
(
parent
,
parent_slot
)
!=
btrfs_header_b
lock
nr
(
leaf
));
btrfs_header_b
yte
nr
(
leaf
));
}
#if 0
for (i = 0; nritems > 1 && i < nritems - 2; i++) {
...
...
@@ -467,14 +466,16 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
static
int
check_block
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
)
{
#if 0
struct extent_buffer *buf = path->nodes[level];
if (memcmp_extent_buffer(buf, root->fs_info->fsid,
(unsigned long)btrfs_header_fsid(buf),
BTRFS_FSID_SIZE)) {
printk("warning bad block %Lu\n", buf->start);
BUG
()
;
return 1
;
}
#endif
if
(
level
==
0
)
return
check_leaf
(
root
,
path
,
level
);
return
check_node
(
root
,
path
,
level
);
...
...
@@ -585,7 +586,8 @@ static struct extent_buffer *read_node_slot(struct btrfs_root *root,
return
NULL
;
if
(
slot
>=
btrfs_header_nritems
(
parent
))
return
NULL
;
return
read_tree_block
(
root
,
btrfs_node_blockptr
(
parent
,
slot
));
return
read_tree_block
(
root
,
btrfs_node_blockptr
(
parent
,
slot
),
btrfs_level_size
(
root
,
btrfs_header_level
(
parent
)
-
1
));
}
static
int
balance_level
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
...
...
@@ -618,7 +620,6 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
*/
if
(
!
parent
)
{
struct
extent_buffer
*
child
;
u64
blocknr
=
extent_buffer_blocknr
(
mid
);
if
(
btrfs_header_nritems
(
mid
)
!=
1
)
return
0
;
...
...
@@ -632,9 +633,10 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
wait_on_tree_block_writeback
(
root
,
mid
);
/* once for the path */
free_extent_buffer
(
mid
);
ret
=
btrfs_free_extent
(
trans
,
root
,
mid
->
start
,
mid
->
len
,
1
);
/* once for the root ptr */
free_extent_buffer
(
mid
);
return
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
1
)
;
return
ret
;
}
if
(
btrfs_header_nritems
(
mid
)
>
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
/
4
)
...
...
@@ -680,7 +682,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
wret
<
0
&&
wret
!=
-
ENOSPC
)
ret
=
wret
;
if
(
btrfs_header_nritems
(
right
)
==
0
)
{
u64
blocknr
=
extent_buffer_blocknr
(
right
);
u64
bytenr
=
right
->
start
;
u32
blocksize
=
right
->
len
;
clean_tree_block
(
trans
,
root
,
right
);
wait_on_tree_block_writeback
(
root
,
right
);
free_extent_buffer
(
right
);
...
...
@@ -689,7 +693,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
1
);
if
(
wret
)
ret
=
wret
;
wret
=
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
1
);
wret
=
btrfs_free_extent
(
trans
,
root
,
bytenr
,
blocksize
,
1
);
if
(
wret
)
ret
=
wret
;
}
else
{
...
...
@@ -719,7 +724,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
}
if
(
btrfs_header_nritems
(
mid
)
==
0
)
{
/* we've managed to empty the middle node, drop it */
u64
blocknr
=
extent_buffer_blocknr
(
mid
);
u64
bytenr
=
mid
->
start
;
u32
blocksize
=
mid
->
len
;
clean_tree_block
(
trans
,
root
,
mid
);
wait_on_tree_block_writeback
(
root
,
mid
);
free_extent_buffer
(
mid
);
...
...
@@ -727,7 +733,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
wret
=
del_ptr
(
trans
,
root
,
path
,
level
+
1
,
pslot
);
if
(
wret
)
ret
=
wret
;
wret
=
btrfs_free_extent
(
trans
,
root
,
b
locknr
,
1
,
1
);
wret
=
btrfs_free_extent
(
trans
,
root
,
b
ytenr
,
blocksize
,
1
);
if
(
wret
)
ret
=
wret
;
}
else
{
...
...
@@ -830,7 +836,6 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
path
->
slots
[
level
]
=
orig_slot
;
free_extent_buffer
(
left
);
}
check_node
(
root
,
path
,
level
);
return
0
;
}
free_extent_buffer
(
left
);
...
...
@@ -874,12 +879,10 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
}
else
{
free_extent_buffer
(
right
);
}
check_node
(
root
,
path
,
level
);
return
0
;
}
free_extent_buffer
(
right
);
}
check_node
(
root
,
path
,
level
);
return
1
;
}
...
...
@@ -889,19 +892,23 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
static
void
reada_for_search
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
,
int
slot
)
{
return
;
#if 0
struct extent_buffer *node;
int i;
u32 nritems;
u64
b
lock
nr
;
u64 b
yte
nr;
u64 search;
u64 cluster_start;
int ret;
int nread = 0;
int direction = path->reada;
int level;
struct radix_tree_root found;
unsigned long gang[8];
struct extent_buffer *eb;
if (level == 0)
return;
...
...
@@ -918,8 +925,9 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
init_bit_radix(&found);
nritems = btrfs_header_nritems(node);
level = btrfs_header_level(node) - 1;
for (i = slot; i < nritems; i++) {
b
lock
nr
=
btrfs_node_blockptr
(
node
,
i
);
b
yte
nr = btrfs_node_blockptr(node, i);
set_radix_bit(&found, blocknr);
}
if (direction > 0) {
...
...
@@ -944,6 +952,7 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
}
}
}
#endif
}
/*
* look for key in the tree. path is filled in with nodes along the way
...
...
@@ -963,7 +972,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
ins_len
,
int
cow
)
{
struct
extent_buffer
*
b
;
u64
b
lock
nr
;
u64
b
yte
nr
;
int
slot
;
int
ret
;
int
level
;
...
...
@@ -1027,10 +1036,11 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
/* this is only true while dropping a snapshot */
if
(
level
==
lowest_level
)
break
;
b
lock
nr
=
btrfs_node_blockptr
(
b
,
slot
);
b
yte
nr
=
btrfs_node_blockptr
(
b
,
slot
);
if
(
should_reada
)
reada_for_search
(
root
,
p
,
level
,
slot
);
b
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
b
,
slot
));
b
=
read_tree_block
(
root
,
bytenr
,
btrfs_level_size
(
root
,
level
-
1
));
}
else
{
p
->
slots
[
level
]
=
slot
;
if
(
ins_len
>
0
&&
btrfs_leaf_free_space
(
root
,
b
)
<
...
...
@@ -1193,14 +1203,14 @@ static int insert_new_root(struct btrfs_trans_handle *trans,
BUG_ON
(
path
->
nodes
[
level
]);
BUG_ON
(
path
->
nodes
[
level
-
1
]
!=
root
->
node
);
c
=
btrfs_alloc_free_block
(
trans
,
root
,
extent_buffer_blocknr
(
root
->
node
)
,
0
);
c
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
nodesize
,
root
->
node
->
start
,
0
);
if
(
IS_ERR
(
c
))
return
PTR_ERR
(
c
);
memset_extent_buffer
(
c
,
0
,
0
,
root
->
nodesize
);
btrfs_set_header_nritems
(
c
,
1
);
btrfs_set_header_level
(
c
,
level
);
btrfs_set_header_b
locknr
(
c
,
extent_buffer_blocknr
(
c
)
);
btrfs_set_header_b
ytenr
(
c
,
c
->
start
);
btrfs_set_header_generation
(
c
,
trans
->
transid
);
btrfs_set_header_owner
(
c
,
root
->
root_key
.
objectid
);
lower
=
path
->
nodes
[
level
-
1
];
...
...
@@ -1213,7 +1223,7 @@ static int insert_new_root(struct btrfs_trans_handle *trans,
else
btrfs_node_key
(
lower
,
&
lower_key
,
0
);
btrfs_set_node_key
(
c
,
&
lower_key
,
0
);
btrfs_set_node_blockptr
(
c
,
0
,
extent_buffer_blocknr
(
lower
)
);
btrfs_set_node_blockptr
(
c
,
0
,
lower
->
start
);
btrfs_mark_buffer_dirty
(
c
);
...
...
@@ -1237,7 +1247,7 @@ static int insert_new_root(struct btrfs_trans_handle *trans,
*/
static
int
insert_ptr
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
btrfs_disk_key
*
key
,
u64
b
lock
nr
,
int
slot
,
int
level
)
*
key
,
u64
b
yte
nr
,
int
slot
,
int
level
)
{
struct
extent_buffer
*
lower
;
int
nritems
;
...
...
@@ -1256,10 +1266,9 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
(
nritems
-
slot
)
*
sizeof
(
struct
btrfs_key_ptr
));
}
btrfs_set_node_key
(
lower
,
key
,
slot
);
btrfs_set_node_blockptr
(
lower
,
slot
,
b
lock
nr
);
btrfs_set_node_blockptr
(
lower
,
slot
,
b
yte
nr
);
btrfs_set_header_nritems
(
lower
,
nritems
+
1
);
btrfs_mark_buffer_dirty
(
lower
);
check_node
(
root
,
path
,
level
);
return
0
;
}
...
...
@@ -1300,14 +1309,14 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
}
c_nritems
=
btrfs_header_nritems
(
c
);
split
=
btrfs_alloc_free_block
(
trans
,
root
,
extent_buffer_blocknr
(
c
)
,
0
);
split
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
nodesize
,
c
->
start
,
0
);
if
(
IS_ERR
(
split
))
return
PTR_ERR
(
split
);
btrfs_set_header_flags
(
split
,
btrfs_header_flags
(
c
));
btrfs_set_header_level
(
split
,
btrfs_header_level
(
c
));
btrfs_set_header_b
locknr
(
split
,
extent_buffer_blocknr
(
split
)
);
btrfs_set_header_b
ytenr
(
split
,
split
->
start
);
btrfs_set_header_generation
(
split
,
trans
->
transid
);
btrfs_set_header_owner
(
split
,
root
->
root_key
.
objectid
);
write_extent_buffer
(
split
,
root
->
fs_info
->
fsid
,
...
...
@@ -1328,8 +1337,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_mark_buffer_dirty
(
split
);
btrfs_node_key
(
split
,
&
disk_key
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
split
),
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
split
->
start
,
path
->
slots
[
level
+
1
]
+
1
,
level
+
1
);
if
(
wret
)
...
...
@@ -1407,6 +1415,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
u32
left_nritems
;
u32
right_nritems
;
u32
data_end
;
u32
this_item_size
;
int
ret
;
slot
=
path
->
slots
[
1
];
...
...
@@ -1417,7 +1426,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
slot
>=
btrfs_header_nritems
(
upper
)
-
1
)
return
1
;
right
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
upper
,
slot
+
1
));
right
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
upper
,
slot
+
1
),
root
->
leafsize
);
free_space
=
btrfs_leaf_free_space
(
root
,
right
);
if
(
free_space
<
data_size
+
sizeof
(
struct
btrfs_item
))
{
free_extent_buffer
(
right
);
...
...
@@ -1445,13 +1455,27 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
for
(
i
=
left_nritems
-
1
;
i
>=
1
;
i
--
)
{
item
=
btrfs_item_nr
(
left
,
i
);
if
(
path
->
slots
[
0
]
==
i
)
push_space
+=
data_size
+
sizeof
(
*
item
);
if
(
btrfs_item_size
(
left
,
item
)
+
sizeof
(
*
item
)
+
push_space
>
free_space
)
if
(
!
left
->
map_token
)
{
map_extent_buffer
(
left
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
left
->
map_token
,
&
left
->
kaddr
,
&
left
->
map_start
,
&
left
->
map_len
,
KM_USER1
);
}
this_item_size
=
btrfs_item_size
(
left
,
item
);
if
(
this_item_size
+
sizeof
(
*
item
)
+
push_space
>
free_space
)
break
;
push_items
++
;
push_space
+=
btrfs_item_size
(
left
,
item
)
+
sizeof
(
*
item
);
push_space
+=
this_item_size
+
sizeof
(
*
item
);
}
if
(
left
->
map_token
)
{
unmap_extent_buffer
(
left
,
left
->
map_token
,
KM_USER1
);
left
->
map_token
=
NULL
;
}
if
(
push_items
==
0
)
{
...
...
@@ -1493,11 +1517,23 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
right_nritems
+=
push_items
;
btrfs_set_header_nritems
(
right
,
right_nritems
);
push_space
=
BTRFS_LEAF_DATA_SIZE
(
root
);
for
(
i
=
0
;
i
<
right_nritems
;
i
++
)
{
item
=
btrfs_item_nr
(
right
,
i
);
btrfs_set_item_offset
(
right
,
item
,
push_space
-
btrfs_item_size
(
right
,
item
));
push_space
=
btrfs_item_offset
(
right
,
item
);
if
(
!
right
->
map_token
)
{
map_extent_buffer
(
right
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
right
->
map_token
,
&
right
->
kaddr
,
&
right
->
map_start
,
&
right
->
map_len
,
KM_USER1
);
}
push_space
-=
btrfs_item_size
(
right
,
item
);
btrfs_set_item_offset
(
right
,
item
,
push_space
);
}
if
(
right
->
map_token
)
{
unmap_extent_buffer
(
right
,
right
->
map_token
,
KM_USER1
);
right
->
map_token
=
NULL
;
}
left_nritems
-=
push_items
;
btrfs_set_header_nritems
(
left
,
left_nritems
);
...
...
@@ -1518,8 +1554,6 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
}
else
{
free_extent_buffer
(
right
);
}
if
(
path
->
nodes
[
1
])
check_node
(
root
,
path
,
1
);
return
0
;
}
/*
...
...
@@ -1542,6 +1576,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
u32
right_nritems
;
int
ret
=
0
;
int
wret
;
u32
this_item_size
;
u32
old_left_item_size
;
slot
=
path
->
slots
[
1
];
if
(
slot
==
0
)
...
...
@@ -1550,7 +1586,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
return
1
;
left
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
path
->
nodes
[
1
],
slot
-
1
)
);
slot
-
1
),
root
->
leafsize
);
free_space
=
btrfs_leaf_free_space
(
root
,
left
);
if
(
free_space
<
data_size
+
sizeof
(
struct
btrfs_item
))
{
free_extent_buffer
(
left
);
...
...
@@ -1579,14 +1615,30 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
for
(
i
=
0
;
i
<
right_nritems
-
1
;
i
++
)
{
item
=
btrfs_item_nr
(
right
,
i
);
if
(
!
right
->
map_token
)
{
map_extent_buffer
(
right
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
right
->
map_token
,
&
right
->
kaddr
,
&
right
->
map_start
,
&
right
->
map_len
,
KM_USER1
);
}
if
(
path
->
slots
[
0
]
==
i
)
push_space
+=
data_size
+
sizeof
(
*
item
);
if
(
btrfs_item_size
(
right
,
item
)
+
sizeof
(
*
item
)
+
push_space
>
free_space
)
this_item_size
=
btrfs_item_size
(
right
,
item
);
if
(
this_item_size
+
sizeof
(
*
item
)
+
push_space
>
free_space
)
break
;
push_items
++
;
push_space
+=
btrfs_item_size
(
right
,
item
)
+
sizeof
(
*
item
);
push_space
+=
this_item_size
+
sizeof
(
*
item
);
}
if
(
right
->
map_token
)
{
unmap_extent_buffer
(
right
,
right
->
map_token
,
KM_USER1
);
right
->
map_token
=
NULL
;
}
if
(
push_items
==
0
)
{
free_extent_buffer
(
left
);
return
1
;
...
...
@@ -1611,15 +1663,28 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
old_left_nritems
=
btrfs_header_nritems
(
left
);
BUG_ON
(
old_left_nritems
<
0
);
old_left_item_size
=
btrfs_item_offset_nr
(
left
,
old_left_nritems
-
1
);
for
(
i
=
old_left_nritems
;
i
<
old_left_nritems
+
push_items
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
left
,
i
);
if
(
!
left
->
map_token
)
{
map_extent_buffer
(
left
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
left
->
map_token
,
&
left
->
kaddr
,
&
left
->
map_start
,
&
left
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
left
,
item
);
btrfs_set_item_offset
(
left
,
item
,
ioff
-
(
BTRFS_LEAF_DATA_SIZE
(
root
)
-
btrfs_item_offset_nr
(
left
,
old_left_nritems
-
1
)));
ioff
-
(
BTRFS_LEAF_DATA_SIZE
(
root
)
-
old_left_item_size
));
}
btrfs_set_header_nritems
(
left
,
old_left_nritems
+
push_items
);
if
(
left
->
map_token
)
{
unmap_extent_buffer
(
left
,
left
->
map_token
,
KM_USER1
);
left
->
map_token
=
NULL
;
}
/* fixup right node */
push_space
=
btrfs_item_offset_nr
(
right
,
push_items
-
1
)
-
...
...
@@ -1640,9 +1705,21 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
for
(
i
=
0
;
i
<
right_nritems
;
i
++
)
{
item
=
btrfs_item_nr
(
right
,
i
);
btrfs_set_item_offset
(
right
,
item
,
push_space
-
btrfs_item_size
(
right
,
item
));
push_space
=
btrfs_item_offset
(
right
,
item
);
if
(
!
right
->
map_token
)
{
map_extent_buffer
(
right
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
right
->
map_token
,
&
right
->
kaddr
,
&
right
->
map_start
,
&
right
->
map_len
,
KM_USER1
);
}
push_space
=
push_space
-
btrfs_item_size
(
right
,
item
);
btrfs_set_item_offset
(
right
,
item
,
push_space
);
}
if
(
right
->
map_token
)
{
unmap_extent_buffer
(
right
,
right
->
map_token
,
KM_USER1
);
right
->
map_token
=
NULL
;
}
btrfs_mark_buffer_dirty
(
left
);
...
...
@@ -1664,8 +1741,6 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
path
->
slots
[
0
]
-=
push_items
;
}
BUG_ON
(
path
->
slots
[
0
]
<
0
);
if
(
path
->
nodes
[
1
])
check_node
(
root
,
path
,
1
);
return
ret
;
}
...
...
@@ -1718,13 +1793,13 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
nritems
=
btrfs_header_nritems
(
l
);
mid
=
(
nritems
+
1
)
/
2
;
right
=
btrfs_alloc_free_block
(
trans
,
root
,
extent_buffer_blocknr
(
l
)
,
0
);
right
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
leafsize
,
l
->
start
,
0
);
if
(
IS_ERR
(
right
))
return
PTR_ERR
(
right
);
memset_extent_buffer
(
right
,
0
,
0
,
sizeof
(
struct
btrfs_header
));
btrfs_set_header_b
locknr
(
right
,
extent_buffer_blocknr
(
right
)
);
btrfs_set_header_b
ytenr
(
right
,
right
->
start
);
btrfs_set_header_generation
(
right
,
trans
->
transid
);
btrfs_set_header_owner
(
right
,
root
->
root_key
.
objectid
);
btrfs_set_header_level
(
right
,
0
);
...
...
@@ -1740,8 +1815,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_cpu_key_to_disk
(
&
disk_key
,
ins_key
);
btrfs_set_header_nritems
(
right
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
right
),
&
disk_key
,
right
->
start
,
path
->
slots
[
1
]
+
1
,
1
);
if
(
wret
)
ret
=
wret
;
...
...
@@ -1762,7 +1836,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_header_nritems
(
right
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
right
)
,
right
->
start
,
path
->
slots
[
1
],
1
);
if
(
wret
)
ret
=
wret
;
...
...
@@ -1799,15 +1873,30 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
struct
btrfs_item
*
item
=
btrfs_item_nr
(
right
,
i
);
u32
ioff
=
btrfs_item_offset
(
right
,
item
);
u32
ioff
;
if
(
!
right
->
map_token
)
{
map_extent_buffer
(
right
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
right
->
map_token
,
&
right
->
kaddr
,
&
right
->
map_start
,
&
right
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
right
,
item
);
btrfs_set_item_offset
(
right
,
item
,
ioff
+
rt_data_off
);
}
if
(
right
->
map_token
)
{
unmap_extent_buffer
(
right
,
right
->
map_token
,
KM_USER1
);
right
->
map_token
=
NULL
;
}
btrfs_set_header_nritems
(
l
,
mid
);
ret
=
0
;
btrfs_item_key
(
right
,
&
disk_key
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
right
),
path
->
slots
[
1
]
+
1
,
1
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
right
->
start
,
path
->
slots
[
1
]
+
1
,
1
);
if
(
wret
)
ret
=
wret
;
...
...
@@ -1824,19 +1913,17 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
free_extent_buffer
(
right
);
BUG_ON
(
path
->
slots
[
0
]
<
0
);
check_node
(
root
,
path
,
1
);
check_leaf
(
root
,
path
,
0
);
if
(
!
double_split
)
return
ret
;
right
=
btrfs_alloc_free_block
(
trans
,
root
,
extent_buffer_blocknr
(
l
)
,
0
);
right
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
leafsize
,
l
->
start
,
0
);
if
(
IS_ERR
(
right
))
return
PTR_ERR
(
right
);
memset_extent_buffer
(
right
,
0
,
0
,
sizeof
(
struct
btrfs_header
));
btrfs_set_header_b
locknr
(
right
,
extent_buffer_blocknr
(
right
)
);
btrfs_set_header_b
ytenr
(
right
,
right
->
start
);
btrfs_set_header_generation
(
right
,
trans
->
transid
);
btrfs_set_header_owner
(
right
,
root
->
root_key
.
objectid
);
btrfs_set_header_level
(
right
,
0
);
...
...
@@ -1847,8 +1934,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_cpu_key_to_disk
(
&
disk_key
,
ins_key
);
btrfs_set_header_nritems
(
right
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
right
),
&
disk_key
,
right
->
start
,
path
->
slots
[
1
],
1
);
if
(
wret
)
ret
=
wret
;
...
...
@@ -1860,8 +1946,6 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
free_extent_buffer
(
path
->
nodes
[
0
]);
path
->
nodes
[
0
]
=
right
;
path
->
slots
[
0
]
=
0
;
check_node
(
root
,
path
,
1
);
check_leaf
(
root
,
path
,
0
);
return
ret
;
}
...
...
@@ -1904,9 +1988,24 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
for
(
i
=
slot
;
i
<
nritems
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
leaf
,
i
);
if
(
!
leaf
->
map_token
)
{
map_extent_buffer
(
leaf
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
leaf
->
map_token
,
&
leaf
->
kaddr
,
&
leaf
->
map_start
,
&
leaf
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
leaf
,
item
);
btrfs_set_item_offset
(
leaf
,
item
,
ioff
+
size_diff
);
}
if
(
leaf
->
map_token
)
{
unmap_extent_buffer
(
leaf
,
leaf
->
map_token
,
KM_USER1
);
leaf
->
map_token
=
NULL
;
}
/* shift the data */
memmove_extent_buffer
(
leaf
,
btrfs_leaf_data
(
leaf
)
+
data_end
+
size_diff
,
btrfs_leaf_data
(
leaf
)
+
...
...
@@ -1921,7 +2020,6 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
btrfs_print_leaf
(
root
,
leaf
);
BUG
();
}
check_leaf
(
root
,
path
,
0
);
return
ret
;
}
...
...
@@ -1963,10 +2061,23 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans,
for
(
i
=
slot
;
i
<
nritems
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
leaf
,
i
);
if
(
!
leaf
->
map_token
)
{
map_extent_buffer
(
leaf
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
leaf
->
map_token
,
&
leaf
->
kaddr
,
&
leaf
->
map_start
,
&
leaf
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
leaf
,
item
);
btrfs_set_item_offset
(
leaf
,
item
,
ioff
-
data_size
);
}
if
(
leaf
->
map_token
)
{
unmap_extent_buffer
(
leaf
,
leaf
->
map_token
,
KM_USER1
);
leaf
->
map_token
=
NULL
;
}
/* shift the data */
memmove_extent_buffer
(
leaf
,
btrfs_leaf_data
(
leaf
)
+
data_end
-
data_size
,
btrfs_leaf_data
(
leaf
)
+
...
...
@@ -1983,7 +2094,6 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans,
btrfs_print_leaf
(
root
,
leaf
);
BUG
();
}
check_leaf
(
root
,
path
,
0
);
return
ret
;
}
...
...
@@ -2046,12 +2156,26 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
* item0..itemN ... dataN.offset..dataN.size .. data0.size
*/
/* first correct the data pointers */
WARN_ON
(
leaf
->
map_token
);
for
(
i
=
slot
;
i
<
nritems
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
leaf
,
i
);
if
(
!
leaf
->
map_token
)
{
map_extent_buffer
(
leaf
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
leaf
->
map_token
,
&
leaf
->
kaddr
,
&
leaf
->
map_start
,
&
leaf
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
leaf
,
item
);
btrfs_set_item_offset
(
leaf
,
item
,
ioff
-
data_size
);
}
if
(
leaf
->
map_token
)
{
unmap_extent_buffer
(
leaf
,
leaf
->
map_token
,
KM_USER1
);
leaf
->
map_token
=
NULL
;
}
/* shift the items */
memmove_extent_buffer
(
leaf
,
btrfs_item_nr_offset
(
slot
+
1
),
...
...
@@ -2081,7 +2205,6 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
btrfs_print_leaf
(
root
,
leaf
);
BUG
();
}
check_leaf
(
root
,
path
,
0
);
out:
return
ret
;
}
...
...
@@ -2186,10 +2309,24 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
for
(
i
=
slot
+
1
;
i
<
nritems
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
leaf
,
i
);
if
(
!
leaf
->
map_token
)
{
map_extent_buffer
(
leaf
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
leaf
->
map_token
,
&
leaf
->
kaddr
,
&
leaf
->
map_start
,
&
leaf
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
leaf
,
item
);
btrfs_set_item_offset
(
leaf
,
item
,
ioff
+
dsize
);
}
if
(
leaf
->
map_token
)
{
unmap_extent_buffer
(
leaf
,
leaf
->
map_token
,
KM_USER1
);
leaf
->
map_token
=
NULL
;
}
memmove_extent_buffer
(
leaf
,
btrfs_item_nr_offset
(
slot
),
btrfs_item_nr_offset
(
slot
+
1
),
sizeof
(
struct
btrfs_item
)
*
...
...
@@ -2209,8 +2346,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
wret
)
ret
=
wret
;
wret
=
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
leaf
),
1
,
1
);
leaf
->
start
,
leaf
->
len
,
1
);
if
(
wret
)
ret
=
wret
;
}
...
...
@@ -2247,7 +2383,8 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
}
if
(
btrfs_header_nritems
(
leaf
)
==
0
)
{
u64
blocknr
=
extent_buffer_blocknr
(
leaf
);
u64
bytenr
=
leaf
->
start
;
u32
blocksize
=
leaf
->
len
;
clean_tree_block
(
trans
,
root
,
leaf
);
wait_on_tree_block_writeback
(
root
,
leaf
);
...
...
@@ -2257,8 +2394,8 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
ret
=
wret
;
free_extent_buffer
(
leaf
);
wret
=
btrfs_free_extent
(
trans
,
root
,
b
lock
nr
,
1
,
1
);
wret
=
btrfs_free_extent
(
trans
,
root
,
b
yte
nr
,
blocksize
,
1
);
if
(
wret
)
ret
=
wret
;
}
else
{
...
...
@@ -2281,7 +2418,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
{
int
slot
;
int
level
=
1
;
u64
b
lock
nr
;
u64
b
yte
nr
;
struct
extent_buffer
*
c
;
struct
extent_buffer
*
next
=
NULL
;
...
...
@@ -2296,14 +2433,15 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
continue
;
}
b
lock
nr
=
btrfs_node_blockptr
(
c
,
slot
);
b
yte
nr
=
btrfs_node_blockptr
(
c
,
slot
);
if
(
next
)
free_extent_buffer
(
next
);
if
(
path
->
reada
)
reada_for_search
(
root
,
path
,
level
,
slot
);
next
=
read_tree_block
(
root
,
blocknr
);
next
=
read_tree_block
(
root
,
bytenr
,
btrfs_level_size
(
root
,
level
-
1
));
break
;
}
path
->
slots
[
level
]
=
slot
;
...
...
@@ -2317,7 +2455,8 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
break
;
if
(
path
->
reada
)
reada_for_search
(
root
,
path
,
level
,
0
);
next
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
next
,
0
));
next
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
next
,
0
),
btrfs_level_size
(
root
,
level
-
1
));
}
return
0
;
}
fs/btrfs/ctree.h
浏览文件 @
db94535d
...
...
@@ -96,7 +96,7 @@ struct btrfs_key {
struct
btrfs_header
{
u8
csum
[
BTRFS_CSUM_SIZE
];
u8
fsid
[
BTRFS_FSID_SIZE
];
/* FS specific uuid */
__le64
b
lock
nr
;
/* which block this node is supposed to live in */
__le64
b
yte
nr
;
/* which block this node is supposed to live in */
__le64
generation
;
__le64
owner
;
__le32
nritems
;
...
...
@@ -122,16 +122,17 @@ struct btrfs_super_block {
u8
csum
[
BTRFS_CSUM_SIZE
];
/* the first 3 fields must match struct btrfs_header */
u8
fsid
[
16
];
/* FS specific uuid */
__le64
b
lock
nr
;
/* this block number */
__le64
b
yte
nr
;
/* this block number */
__le64
magic
;
__le64
generation
;
__le64
root
;
__le64
total_b
lock
s
;
__le64
b
lock
s_used
;
__le64
total_b
yte
s
;
__le64
b
yte
s_used
;
__le64
root_dir_objectid
;
__le32
sectorsize
;
__le32
nodesize
;
__le32
leafsize
;
u8
root_level
;
}
__attribute__
((
__packed__
));
/*
...
...
@@ -231,13 +232,14 @@ struct btrfs_dir_item {
struct
btrfs_root_item
{
struct
btrfs_inode_item
inode
;
__le64
root_dirid
;
__le64
b
lock
nr
;
__le64
b
lock
_limit
;
__le64
b
lock
s_used
;
__le64
b
yte
nr
;
__le64
b
yte
_limit
;
__le64
b
yte
s_used
;
__le32
flags
;
__le32
refs
;
struct
btrfs_disk_key
drop_progress
;
u8
drop_level
;
u8
level
;
}
__attribute__
((
__packed__
));
#define BTRFS_FILE_EXTENT_REG 0
...
...
@@ -250,8 +252,8 @@ struct btrfs_file_extent_item {
* disk space consumed by the extent, checksum blocks are included
* in these numbers
*/
__le64
disk_b
lock
nr
;
__le64
disk_num_b
lock
s
;
__le64
disk_b
yte
nr
;
__le64
disk_num_b
yte
s
;
/*
* the logical offset in file blocks (no csums)
* this extent record is for. This allows a file extent to point
...
...
@@ -263,7 +265,7 @@ struct btrfs_file_extent_item {
/*
* the logical number of file blocks (no csums included)
*/
__le64
num_b
lock
s
;
__le64
num_b
yte
s
;
}
__attribute__
((
__packed__
));
struct
btrfs_csum_item
{
...
...
@@ -429,6 +431,7 @@ static inline u##bits btrfs_##name(struct extent_buffer *eb, \
int err; \
char *map_token; \
char *kaddr; \
int unmap_on_exit = (eb->map_token == NULL); \
unsigned long map_start; \
unsigned long map_len; \
unsigned long offset = (unsigned long)s + \
...
...
@@ -436,12 +439,13 @@ static inline u##bits btrfs_##name(struct extent_buffer *eb, \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER
0
); \
&map_start, &map_len, KM_USER
1
); \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
u##bits res = le##bits##_to_cpu(*tmp); \
unmap_extent_buffer(eb, map_token, KM_USER0); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
return res; \
} else { \
__le##bits res; \
...
...
@@ -457,17 +461,19 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
char *kaddr; \
unsigned long map_start; \
unsigned long map_len; \
int unmap_on_exit = (eb->map_token == NULL); \
unsigned long offset = (unsigned long)s + \
offsetof(type, member); \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER
0
); \
&map_start, &map_len, KM_USER
1
); \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
*tmp = cpu_to_le##bits(val); \
unmap_extent_buffer(eb, map_token, KM_USER0); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
} else { \
val = cpu_to_le##bits(val); \
write_eb_member(eb, s, type, member, &val); \
...
...
@@ -483,15 +489,17 @@ static inline u##bits btrfs_##name(struct extent_buffer *eb) \
unsigned long map_start; \
unsigned long map_len; \
unsigned long offset = offsetof(type, member); \
int unmap_on_exit = (eb->map_token == NULL); \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER
0
); \
&map_start, &map_len, KM_USER
1
); \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
u##bits res = le##bits##_to_cpu(*tmp); \
unmap_extent_buffer(eb, map_token, KM_USER0); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
return res; \
} else { \
__le##bits res; \
...
...
@@ -508,15 +516,17 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
unsigned long map_start; \
unsigned long map_len; \
unsigned long offset = offsetof(type, member); \
int unmap_on_exit = (eb->map_token == NULL); \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER
0
); \
&map_start, &map_len, KM_USER
1
); \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
*tmp = cpu_to_le##bits(val); \
unmap_extent_buffer(eb, map_token, KM_USER0); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
} else { \
val = cpu_to_le##bits(val); \
write_eb_member(eb, NULL, type, member, &val); \
...
...
@@ -769,7 +779,7 @@ static inline void btrfs_set_key_type(struct btrfs_key *key, u8 val)
}
/* struct btrfs_header */
BTRFS_SETGET_HEADER_FUNCS
(
header_b
locknr
,
struct
btrfs_header
,
block
nr
,
64
);
BTRFS_SETGET_HEADER_FUNCS
(
header_b
ytenr
,
struct
btrfs_header
,
byte
nr
,
64
);
BTRFS_SETGET_HEADER_FUNCS
(
header_generation
,
struct
btrfs_header
,
generation
,
64
);
BTRFS_SETGET_HEADER_FUNCS
(
header_owner
,
struct
btrfs_header
,
owner
,
64
);
...
...
@@ -817,24 +827,28 @@ static inline int btrfs_is_leaf(struct extent_buffer *eb)
/* struct btrfs_root_item */
BTRFS_SETGET_FUNCS
(
disk_root_refs
,
struct
btrfs_root_item
,
refs
,
32
);
BTRFS_SETGET_FUNCS
(
disk_root_blocknr
,
struct
btrfs_root_item
,
blocknr
,
64
);
BTRFS_SETGET_FUNCS
(
disk_root_bytenr
,
struct
btrfs_root_item
,
bytenr
,
64
);
BTRFS_SETGET_FUNCS
(
disk_root_level
,
struct
btrfs_root_item
,
level
,
8
);
BTRFS_SETGET_STACK_FUNCS
(
root_blocknr
,
struct
btrfs_root_item
,
blocknr
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_bytenr
,
struct
btrfs_root_item
,
bytenr
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_level
,
struct
btrfs_root_item
,
level
,
8
);
BTRFS_SETGET_STACK_FUNCS
(
root_dirid
,
struct
btrfs_root_item
,
root_dirid
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_refs
,
struct
btrfs_root_item
,
refs
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
root_flags
,
struct
btrfs_root_item
,
flags
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
root_used
,
struct
btrfs_root_item
,
b
lock
s_used
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_limit
,
struct
btrfs_root_item
,
b
lock
_limit
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_used
,
struct
btrfs_root_item
,
b
yte
s_used
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_limit
,
struct
btrfs_root_item
,
b
yte
_limit
,
64
);
/* struct btrfs_super_block */
BTRFS_SETGET_STACK_FUNCS
(
super_b
locknr
,
struct
btrfs_super_block
,
block
nr
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_b
ytenr
,
struct
btrfs_super_block
,
byte
nr
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_generation
,
struct
btrfs_super_block
,
generation
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_root
,
struct
btrfs_super_block
,
root
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_total_blocks
,
struct
btrfs_super_block
,
total_blocks
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_blocks_used
,
struct
btrfs_super_block
,
blocks_used
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_root_level
,
struct
btrfs_super_block
,
root_level
,
8
);
BTRFS_SETGET_STACK_FUNCS
(
super_total_bytes
,
struct
btrfs_super_block
,
total_bytes
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_bytes_used
,
struct
btrfs_super_block
,
bytes_used
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_sectorsize
,
struct
btrfs_super_block
,
sectorsize
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
super_nodesize
,
struct
btrfs_super_block
,
...
...
@@ -856,33 +870,33 @@ static inline unsigned long btrfs_file_extent_inline_start(struct
btrfs_file_extent_item
*
e
)
{
unsigned
long
offset
=
(
unsigned
long
)
e
;
offset
+=
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
lock
nr
);
offset
+=
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
yte
nr
);
return
offset
;
}
static
inline
u32
btrfs_file_extent_calc_inline_size
(
u32
datasize
)
{
return
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
lock
nr
)
+
datasize
;
return
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
yte
nr
)
+
datasize
;
}
static
inline
u32
btrfs_file_extent_inline_len
(
struct
extent_buffer
*
eb
,
struct
btrfs_item
*
e
)
{
unsigned
long
offset
;
offset
=
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
lock
nr
);
offset
=
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
yte
nr
);
return
btrfs_item_size
(
eb
,
e
)
-
offset
;
}
BTRFS_SETGET_FUNCS
(
file_extent_disk_b
lock
nr
,
struct
btrfs_file_extent_item
,
disk_b
lock
nr
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_disk_b
yte
nr
,
struct
btrfs_file_extent_item
,
disk_b
yte
nr
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_generation
,
struct
btrfs_file_extent_item
,
generation
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_disk_num_b
lock
s
,
struct
btrfs_file_extent_item
,
disk_num_b
lock
s
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_disk_num_b
yte
s
,
struct
btrfs_file_extent_item
,
disk_num_b
yte
s
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_offset
,
struct
btrfs_file_extent_item
,
offset
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_num_b
lock
s
,
struct
btrfs_file_extent_item
,
num_b
lock
s
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_num_b
yte
s
,
struct
btrfs_file_extent_item
,
num_b
yte
s
,
64
);
static
inline
struct
btrfs_root
*
btrfs_sb
(
struct
super_block
*
sb
)
{
...
...
@@ -906,6 +920,12 @@ static inline int btrfs_set_root_name(struct btrfs_root *root,
return
0
;
}
static
inline
u32
btrfs_level_size
(
struct
btrfs_root
*
root
,
int
level
)
{
if
(
level
==
0
)
return
root
->
leafsize
;
return
root
->
nodesize
;
}
/* helper function to cast into the data area of the leaf. */
#define btrfs_item_ptr(leaf, slot, type) \
((type *)(btrfs_leaf_data(leaf) + \
...
...
@@ -927,7 +947,7 @@ int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
int
btrfs_copy_pinned
(
struct
btrfs_root
*
root
,
struct
extent_map_tree
*
copy
);
struct
btrfs_block_group_cache
*
btrfs_lookup_block_group
(
struct
btrfs_fs_info
*
info
,
u64
b
lock
nr
);
u64
b
yte
nr
);
struct
btrfs_block_group_cache
*
btrfs_find_block_group
(
struct
btrfs_root
*
root
,
struct
btrfs_block_group_cache
*
hint
,
u64
search_start
,
...
...
@@ -935,22 +955,22 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
int
btrfs_inc_root_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
struct
extent_buffer
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u
64
hint
,
u64
empty_size
);
struct
btrfs_root
*
root
,
u
32
size
,
u64
hint
,
u64
empty_size
);
int
btrfs_alloc_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
owner
,
u64
num_b
lock
s
,
u64
empty_size
,
u64
search_start
,
u64
num_b
yte
s
,
u64
empty_size
,
u64
search_start
,
u64
search_end
,
struct
btrfs_key
*
ins
,
int
data
);
int
btrfs_inc_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
);
int
btrfs_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
,
int
pin
);
*
root
,
u64
b
ytenr
,
u64
num_byte
s
,
int
pin
);
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_map_tree
*
unpin
);
int
btrfs_inc_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
);
u64
b
ytenr
,
u64
num_byte
s
);
int
btrfs_write_dirty_block_groups
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
int
btrfs_free_block_groups
(
struct
btrfs_fs_info
*
info
);
...
...
@@ -1040,12 +1060,12 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
int
btrfs_insert_file_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
objectid
,
u64
pos
,
u64
offset
,
u64
disk_num_b
lock
s
,
u64
num_b
lock
s
);
u64
disk_num_b
yte
s
,
u64
num_b
yte
s
);
int
btrfs_lookup_file_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
objectid
,
u64
b
lock
nr
,
int
mod
);
u64
b
yte
nr
,
int
mod
);
int
btrfs_csum_file_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
objectid
,
u64
offset
,
...
...
fs/btrfs/disk-io.c
浏览文件 @
db94535d
...
...
@@ -28,6 +28,7 @@
#include "disk-io.h"
#include "transaction.h"
#include "btrfs_inode.h"
#include "print-tree.h"
#if 0
static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
...
...
@@ -43,26 +44,25 @@ static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
#endif
struct
extent_buffer
*
btrfs_find_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
)
u64
b
ytenr
,
u32
blocksize
)
{
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
extent_buffer
*
eb
;
eb
=
find_extent_buffer
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
blocknr
*
root
->
sectorsize
,
root
->
sectorsize
,
GFP_NOFS
);
bytenr
,
blocksize
,
GFP_NOFS
);
if
(
eb
)
eb
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
return
eb
;
}
struct
extent_buffer
*
btrfs_find_create_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
)
u64
b
ytenr
,
u32
blocksize
)
{
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
extent_buffer
*
eb
;
eb
=
alloc_extent_buffer
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
blocknr
*
root
->
sectorsize
,
root
->
sectorsize
,
GFP_NOFS
);
bytenr
,
blocksize
,
GFP_NOFS
);
eb
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
return
eb
;
}
...
...
@@ -208,13 +208,13 @@ static struct address_space_operations btree_aops = {
.
sync_page
=
block_sync_page
,
};
int
readahead_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
)
int
readahead_tree_block
(
struct
btrfs_root
*
root
,
u64
b
ytenr
,
u32
blocksize
)
{
struct
extent_buffer
*
buf
=
NULL
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
int
ret
=
0
;
buf
=
btrfs_find_create_tree_block
(
root
,
b
locknr
);
buf
=
btrfs_find_create_tree_block
(
root
,
b
ytenr
,
blocksize
);
if
(
!
buf
)
return
0
;
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
...
...
@@ -223,12 +223,13 @@ int readahead_tree_block(struct btrfs_root *root, u64 blocknr)
return
ret
;
}
struct
extent_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
struct
extent_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
)
{
struct
extent_buffer
*
buf
=
NULL
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
buf
=
btrfs_find_create_tree_block
(
root
,
b
locknr
);
buf
=
btrfs_find_create_tree_block
(
root
,
b
ytenr
,
blocksize
);
if
(
!
buf
)
return
NULL
;
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
...
...
@@ -261,7 +262,7 @@ int set_tree_block_dirty(struct btrfs_root *root, struct extent_buffer *buf)
return
0
;
}
static
int
__setup_root
(
int
block
size
,
static
int
__setup_root
(
u32
nodesize
,
u32
leafsize
,
u32
sector
size
,
struct
btrfs_root
*
root
,
struct
btrfs_fs_info
*
fs_info
,
u64
objectid
)
...
...
@@ -269,9 +270,9 @@ static int __setup_root(int blocksize,
root
->
node
=
NULL
;
root
->
inode
=
NULL
;
root
->
commit_root
=
NULL
;
root
->
sectorsize
=
block
size
;
root
->
nodesize
=
block
size
;
root
->
leafsize
=
block
size
;
root
->
sectorsize
=
sector
size
;
root
->
nodesize
=
node
size
;
root
->
leafsize
=
leaf
size
;
root
->
ref_cows
=
0
;
root
->
fs_info
=
fs_info
;
root
->
objectid
=
objectid
;
...
...
@@ -291,21 +292,23 @@ static int __setup_root(int blocksize,
return
0
;
}
static
int
find_and_setup_root
(
int
blocksize
,
struct
btrfs_root
*
tree_root
,
static
int
find_and_setup_root
(
struct
btrfs_root
*
tree_root
,
struct
btrfs_fs_info
*
fs_info
,
u64
objectid
,
struct
btrfs_root
*
root
)
{
int
ret
;
u32
blocksize
;
__setup_root
(
blocksize
,
root
,
fs_info
,
objectid
);
__setup_root
(
tree_root
->
nodesize
,
tree_root
->
leafsize
,
tree_root
->
sectorsize
,
root
,
fs_info
,
objectid
);
ret
=
btrfs_find_last_root
(
tree_root
,
objectid
,
&
root
->
root_item
,
&
root
->
root_key
);
BUG_ON
(
ret
);
root
->
node
=
read_tree_block
(
root
,
btrfs_root_blocknr
(
&
root
->
root_item
));
blocksize
=
btrfs_level_size
(
root
,
btrfs_root_level
(
&
root
->
root_item
));
root
->
node
=
read_tree_block
(
root
,
btrfs_root_bytenr
(
&
root
->
root_item
),
blocksize
);
BUG_ON
(
!
root
->
node
);
return
0
;
}
...
...
@@ -318,14 +321,14 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
struct
btrfs_path
*
path
;
struct
extent_buffer
*
l
;
u64
highest_inode
;
u32
blocksize
;
int
ret
=
0
;
root
=
kzalloc
(
sizeof
(
*
root
),
GFP_NOFS
);
if
(
!
root
)
return
ERR_PTR
(
-
ENOMEM
);
if
(
location
->
offset
==
(
u64
)
-
1
)
{
ret
=
find_and_setup_root
(
fs_info
->
sb
->
s_blocksize
,
fs_info
->
tree_root
,
fs_info
,
ret
=
find_and_setup_root
(
tree_root
,
fs_info
,
location
->
objectid
,
root
);
if
(
ret
)
{
kfree
(
root
);
...
...
@@ -334,7 +337,8 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
goto
insert
;
}
__setup_root
(
fs_info
->
sb
->
s_blocksize
,
root
,
fs_info
,
__setup_root
(
tree_root
->
nodesize
,
tree_root
->
leafsize
,
tree_root
->
sectorsize
,
root
,
fs_info
,
location
->
objectid
);
path
=
btrfs_alloc_path
();
...
...
@@ -357,8 +361,9 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
kfree
(
root
);
return
ERR_PTR
(
ret
);
}
root
->
node
=
read_tree_block
(
root
,
btrfs_root_blocknr
(
&
root
->
root_item
));
blocksize
=
btrfs_level_size
(
root
,
btrfs_root_level
(
&
root
->
root_item
));
root
->
node
=
read_tree_block
(
root
,
btrfs_root_bytenr
(
&
root
->
root_item
),
blocksize
);
BUG_ON
(
!
root
->
node
);
insert:
root
->
ref_cows
=
1
;
...
...
@@ -418,6 +423,10 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
)
{
u32
sectorsize
;
u32
nodesize
;
u32
leafsize
;
u32
blocksize
;
struct
btrfs_root
*
extent_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
GFP_NOFS
);
struct
btrfs_root
*
tree_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
...
...
@@ -474,12 +483,12 @@ struct btrfs_root *open_ctree(struct super_block *sb)
mutex_init
(
&
fs_info
->
trans_mutex
);
mutex_init
(
&
fs_info
->
fs_mutex
);
__setup_root
(
sb
->
s_blocksize
,
tree_root
,
__setup_root
(
512
,
512
,
512
,
tree_root
,
fs_info
,
BTRFS_ROOT_TREE_OBJECTID
);
fs_info
->
sb_buffer
=
read_tree_block
(
tree_root
,
BTRFS_SUPER_INFO_OFFSET
/
sb
->
s_blocksize
);
BTRFS_SUPER_INFO_OFFSET
,
512
);
if
(
!
fs_info
->
sb_buffer
)
goto
fail_iput
;
...
...
@@ -494,9 +503,15 @@ struct btrfs_root *open_ctree(struct super_block *sb)
if
(
!
btrfs_super_root
(
disk_super
))
goto
fail_sb_buffer
;
nodesize
=
btrfs_super_nodesize
(
disk_super
);
leafsize
=
btrfs_super_leafsize
(
disk_super
);
sectorsize
=
btrfs_super_sectorsize
(
disk_super
);
tree_root
->
nodesize
=
nodesize
;
tree_root
->
leafsize
=
leafsize
;
tree_root
->
sectorsize
=
sectorsize
;
i_size_write
(
fs_info
->
btree_inode
,
btrfs_super_total_blocks
(
disk_super
)
<<
fs_info
->
btree_inode
->
i_blkbits
);
btrfs_super_total_bytes
(
disk_super
));
if
(
strncmp
((
char
*
)(
&
disk_super
->
magic
),
BTRFS_MAGIC
,
...
...
@@ -504,13 +519,22 @@ struct btrfs_root *open_ctree(struct super_block *sb)
printk
(
"btrfs: valid FS not found on %s
\n
"
,
sb
->
s_id
);
goto
fail_sb_buffer
;
}
blocksize
=
btrfs_level_size
(
tree_root
,
btrfs_super_root_level
(
disk_super
));
tree_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_root
(
disk_super
));
btrfs_super_root
(
disk_super
),
blocksize
);
if
(
!
tree_root
->
node
)
goto
fail_sb_buffer
;
#if 0
btrfs_print_leaf(tree_root, tree_root->node);
err = -EIO;
goto fail_tree_root;
#endif
mutex_lock
(
&
fs_info
->
fs_mutex
);
ret
=
find_and_setup_root
(
sb
->
s_blocksize
,
tree_root
,
fs_info
,
ret
=
find_and_setup_root
(
tree_root
,
fs_info
,
BTRFS_EXTENT_TREE_OBJECTID
,
extent_root
);
if
(
ret
)
{
mutex_unlock
(
&
fs_info
->
fs_mutex
);
...
...
@@ -611,11 +635,11 @@ int close_ctree(struct btrfs_root *root)
free_extent_buffer
(
fs_info
->
tree_root
->
node
);
free_extent_buffer
(
fs_info
->
sb_buffer
);
truncate_inode_pages
(
fs_info
->
btree_inode
->
i_mapping
,
0
);
iput
(
fs_info
->
btree_inode
);
btrfs_free_block_groups
(
root
->
fs_info
);
del_fs_roots
(
fs_info
);
truncate_inode_pages
(
fs_info
->
btree_inode
->
i_mapping
,
0
);
iput
(
fs_info
->
btree_inode
);
kfree
(
fs_info
->
extent_root
);
kfree
(
fs_info
->
tree_root
);
return
0
;
...
...
@@ -642,7 +666,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
if
(
transid
!=
root
->
fs_info
->
generation
)
{
printk
(
KERN_CRIT
"transid mismatch buffer %llu, found %Lu running %Lu
\n
"
,
(
unsigned
long
long
)
extent_buffer_blocknr
(
buf
)
,
(
unsigned
long
long
)
buf
->
start
,
transid
,
root
->
fs_info
->
generation
);
WARN_ON
(
1
);
}
...
...
fs/btrfs/disk-io.h
浏览文件 @
db94535d
...
...
@@ -21,10 +21,11 @@
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
struct
extent_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
int
readahead_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
struct
extent_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
);
int
readahead_tree_block
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
);
struct
extent_buffer
*
btrfs_find_create_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
);
u64
b
ytenr
,
u32
blocksize
);
int
clean_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
);
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
);
...
...
@@ -32,7 +33,7 @@ int close_ctree(struct btrfs_root *root);
int
write_ctree_super
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
struct
extent_buffer
*
btrfs_find_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
);
u64
b
ytenr
,
u32
blocksize
);
struct
btrfs_root
*
btrfs_read_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_key
*
location
,
const
char
*
name
,
int
namelen
);
...
...
fs/btrfs/extent-tree.c
浏览文件 @
db94535d
...
...
@@ -129,7 +129,7 @@ static int cache_block_group(struct btrfs_root *root,
struct
btrfs_block_group_cache
*
btrfs_lookup_block_group
(
struct
btrfs_fs_info
*
info
,
u64
b
lock
nr
)
u64
b
yte
nr
)
{
struct
extent_map_tree
*
block_group_cache
;
struct
btrfs_block_group_cache
*
block_group
=
NULL
;
...
...
@@ -140,7 +140,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
block_group_cache
=
&
info
->
block_group_cache
;
ret
=
find_first_extent_bit
(
block_group_cache
,
b
lock
nr
,
&
start
,
&
end
,
b
yte
nr
,
&
start
,
&
end
,
BLOCK_GROUP_DATA
|
BLOCK_GROUP_METADATA
);
if
(
ret
)
{
return
NULL
;
...
...
@@ -152,7 +152,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
block_group
=
(
struct
btrfs_block_group_cache
*
)
ptr
;
if
(
block_group
->
key
.
objectid
<=
b
locknr
&&
block
nr
<=
if
(
block_group
->
key
.
objectid
<=
b
ytenr
&&
byte
nr
<=
block_group
->
key
.
objectid
+
block_group
->
key
.
offset
)
return
block_group
;
...
...
@@ -315,7 +315,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
int
btrfs_inc_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
)
u64
b
ytenr
,
u64
num_byte
s
)
{
struct
btrfs_path
*
path
;
int
ret
;
...
...
@@ -324,13 +324,14 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
struct
btrfs_extent_item
*
item
;
u32
refs
;
WARN_ON
(
num_bytes
<
root
->
sectorsize
);
path
=
btrfs_alloc_path
();
if
(
!
path
)
return
-
ENOMEM
;
key
.
objectid
=
b
lock
nr
;
key
.
objectid
=
b
yte
nr
;
btrfs_set_key_type
(
&
key
,
BTRFS_EXTENT_ITEM_KEY
);
key
.
offset
=
num_b
lock
s
;
key
.
offset
=
num_b
yte
s
;
ret
=
btrfs_search_slot
(
trans
,
root
->
fs_info
->
extent_root
,
&
key
,
path
,
0
,
1
);
if
(
ret
<
0
)
...
...
@@ -361,8 +362,8 @@ int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
}
static
int
lookup_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
lock
nr
,
u64
num_b
lock
s
,
u32
*
refs
)
struct
btrfs_root
*
root
,
u64
b
yte
nr
,
u64
num_b
yte
s
,
u32
*
refs
)
{
struct
btrfs_path
*
path
;
int
ret
;
...
...
@@ -370,9 +371,10 @@ static int lookup_extent_ref(struct btrfs_trans_handle *trans,
struct
extent_buffer
*
l
;
struct
btrfs_extent_item
*
item
;
WARN_ON
(
num_bytes
<
root
->
sectorsize
);
path
=
btrfs_alloc_path
();
key
.
objectid
=
b
lock
nr
;
key
.
offset
=
num_b
lock
s
;
key
.
objectid
=
b
yte
nr
;
key
.
offset
=
num_b
yte
s
;
btrfs_set_key_type
(
&
key
,
BTRFS_EXTENT_ITEM_KEY
);
ret
=
btrfs_search_slot
(
trans
,
root
->
fs_info
->
extent_root
,
&
key
,
path
,
0
,
0
);
...
...
@@ -380,7 +382,7 @@ static int lookup_extent_ref(struct btrfs_trans_handle *trans,
goto
out
;
if
(
ret
!=
0
)
{
btrfs_print_leaf
(
root
,
path
->
nodes
[
0
]);
printk
(
"failed to find block number %Lu
\n
"
,
b
lock
nr
);
printk
(
"failed to find block number %Lu
\n
"
,
b
yte
nr
);
BUG
();
}
l
=
path
->
nodes
[
0
];
...
...
@@ -394,19 +396,19 @@ static int lookup_extent_ref(struct btrfs_trans_handle *trans,
int
btrfs_inc_root_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
return
btrfs_inc_extent_ref
(
trans
,
root
,
extent_buffer_blocknr
(
root
->
node
),
1
);
return
btrfs_inc_extent_ref
(
trans
,
root
,
root
->
node
->
start
,
root
->
node
->
len
);
}
int
btrfs_inc_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
)
{
u64
b
lock
nr
;
u64
b
yte
nr
;
u32
nritems
;
struct
btrfs_key
key
;
struct
btrfs_file_extent_item
*
fi
;
int
i
;
int
le
af
;
int
le
vel
;
int
ret
;
int
faili
;
int
err
;
...
...
@@ -414,11 +416,11 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
!
root
->
ref_cows
)
return
0
;
le
af
=
btrfs_is_leaf
(
buf
);
le
vel
=
btrfs_header_level
(
buf
);
nritems
=
btrfs_header_nritems
(
buf
);
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
if
(
le
af
)
{
u64
disk_b
lock
nr
;
if
(
le
vel
==
0
)
{
u64
disk_b
yte
nr
;
btrfs_item_key_to_cpu
(
buf
,
&
key
,
i
);
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_EXTENT_DATA_KEY
)
continue
;
...
...
@@ -427,18 +429,19 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
btrfs_file_extent_type
(
buf
,
fi
)
==
BTRFS_FILE_EXTENT_INLINE
)
continue
;
disk_b
locknr
=
btrfs_file_extent_disk_block
nr
(
buf
,
fi
);
if
(
disk_b
lock
nr
==
0
)
disk_b
ytenr
=
btrfs_file_extent_disk_byte
nr
(
buf
,
fi
);
if
(
disk_b
yte
nr
==
0
)
continue
;
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
disk_b
lock
nr
,
btrfs_file_extent_disk_num_b
lock
s
(
buf
,
fi
));
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
disk_b
yte
nr
,
btrfs_file_extent_disk_num_b
yte
s
(
buf
,
fi
));
if
(
ret
)
{
faili
=
i
;
goto
fail
;
}
}
else
{
blocknr
=
btrfs_node_blockptr
(
buf
,
i
);
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
blocknr
,
1
);
bytenr
=
btrfs_node_blockptr
(
buf
,
i
);
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
bytenr
,
btrfs_level_size
(
root
,
level
-
1
));
if
(
ret
)
{
faili
=
i
;
goto
fail
;
...
...
@@ -449,8 +452,8 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
fail:
WARN_ON
(
1
);
for
(
i
=
0
;
i
<
faili
;
i
++
)
{
if
(
le
af
)
{
u64
disk_b
lock
nr
;
if
(
le
vel
==
0
)
{
u64
disk_b
yte
nr
;
btrfs_item_key_to_cpu
(
buf
,
&
key
,
i
);
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_EXTENT_DATA_KEY
)
continue
;
...
...
@@ -459,16 +462,17 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
btrfs_file_extent_type
(
buf
,
fi
)
==
BTRFS_FILE_EXTENT_INLINE
)
continue
;
disk_b
locknr
=
btrfs_file_extent_disk_block
nr
(
buf
,
fi
);
if
(
disk_b
lock
nr
==
0
)
disk_b
ytenr
=
btrfs_file_extent_disk_byte
nr
(
buf
,
fi
);
if
(
disk_b
yte
nr
==
0
)
continue
;
err
=
btrfs_free_extent
(
trans
,
root
,
disk_b
lock
nr
,
btrfs_file_extent_disk_num_b
lock
s
(
buf
,
err
=
btrfs_free_extent
(
trans
,
root
,
disk_b
yte
nr
,
btrfs_file_extent_disk_num_b
yte
s
(
buf
,
fi
),
0
);
BUG_ON
(
err
);
}
else
{
blocknr
=
btrfs_node_blockptr
(
buf
,
i
);
err
=
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
0
);
bytenr
=
btrfs_node_blockptr
(
buf
,
i
);
err
=
btrfs_free_extent
(
trans
,
root
,
bytenr
,
btrfs_level_size
(
root
,
level
-
1
),
0
);
BUG_ON
(
err
);
}
}
...
...
@@ -558,31 +562,31 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
static
int
update_block_group
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num
,
int
alloc
,
int
mark_free
,
int
data
)
u64
b
ytenr
,
u64
num_bytes
,
int
alloc
,
int
mark_free
,
int
data
)
{
struct
btrfs_block_group_cache
*
cache
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
u64
total
=
num
;
u64
total
=
num
_bytes
;
u64
old_val
;
u64
b
lock
_in_group
;
u64
b
yte
_in_group
;
u64
start
;
u64
end
;
while
(
total
)
{
cache
=
btrfs_lookup_block_group
(
info
,
b
lock
nr
);
cache
=
btrfs_lookup_block_group
(
info
,
b
yte
nr
);
if
(
!
cache
)
{
return
-
1
;
}
b
lock_in_group
=
block
nr
-
cache
->
key
.
objectid
;
WARN_ON
(
b
lock
_in_group
>
cache
->
key
.
offset
);
b
yte_in_group
=
byte
nr
-
cache
->
key
.
objectid
;
WARN_ON
(
b
yte
_in_group
>
cache
->
key
.
offset
);
start
=
cache
->
key
.
objectid
;
end
=
start
+
cache
->
key
.
offset
-
1
;
set_extent_bits
(
&
info
->
block_group_cache
,
start
,
end
,
BLOCK_GROUP_DIRTY
,
GFP_NOFS
);
old_val
=
btrfs_block_group_used
(
&
cache
->
item
);
num
=
min
(
total
,
cache
->
key
.
offset
-
block
_in_group
);
num
_bytes
=
min
(
total
,
cache
->
key
.
offset
-
byte
_in_group
);
if
(
alloc
)
{
if
(
cache
->
data
!=
data
&&
old_val
<
(
cache
->
key
.
offset
>>
1
))
{
...
...
@@ -608,18 +612,18 @@ static int update_block_group(struct btrfs_trans_handle *trans,
start
,
end
,
bit_to_set
,
GFP_NOFS
);
}
old_val
+=
num
;
old_val
+=
num
_bytes
;
}
else
{
old_val
-=
num
;
old_val
-=
num
_bytes
;
if
(
mark_free
)
{
set_extent_dirty
(
&
info
->
free_space_cache
,
b
locknr
,
blocknr
+
num
-
1
,
b
ytenr
,
bytenr
+
num_bytes
-
1
,
GFP_NOFS
);
}
}
btrfs_set_block_group_used
(
&
cache
->
item
,
old_val
);
total
-=
num
;
b
locknr
+=
num
;
total
-=
num
_bytes
;
b
ytenr
+=
num_bytes
;
}
return
0
;
}
...
...
@@ -701,13 +705,14 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
return
0
;
}
static
int
pin_down_block
(
struct
btrfs_root
*
root
,
u64
blocknr
,
int
pending
)
static
int
pin_down_bytes
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
num_bytes
,
int
pending
)
{
int
err
=
0
;
struct
extent_buffer
*
buf
;
if
(
!
pending
)
{
buf
=
btrfs_find_tree_block
(
root
,
b
locknr
);
buf
=
btrfs_find_tree_block
(
root
,
b
ytenr
,
num_bytes
);
if
(
buf
)
{
if
(
btrfs_buffer_uptodate
(
buf
))
{
u64
transid
=
...
...
@@ -720,10 +725,11 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
free_extent_buffer
(
buf
);
}
set_extent_dirty
(
&
root
->
fs_info
->
pinned_extents
,
b
locknr
,
blocknr
,
GFP_NOFS
);
b
ytenr
,
bytenr
+
num_bytes
-
1
,
GFP_NOFS
);
}
else
{
set_extent_bits
(
&
root
->
fs_info
->
pending_del
,
blocknr
,
blocknr
,
EXTENT_LOCKED
,
GFP_NOFS
);
bytenr
,
bytenr
+
num_bytes
-
1
,
EXTENT_LOCKED
,
GFP_NOFS
);
}
BUG_ON
(
err
<
0
);
return
0
;
...
...
@@ -733,7 +739,7 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
* remove an extent from the root, returns 0 on success
*/
static
int
__free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
,
int
pin
,
*
root
,
u64
b
ytenr
,
u64
num_byte
s
,
int
pin
,
int
mark_free
)
{
struct
btrfs_path
*
path
;
...
...
@@ -745,9 +751,9 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
struct
btrfs_extent_item
*
ei
;
u32
refs
;
key
.
objectid
=
b
lock
nr
;
key
.
objectid
=
b
yte
nr
;
btrfs_set_key_type
(
&
key
,
BTRFS_EXTENT_ITEM_KEY
);
key
.
offset
=
num_b
lock
s
;
key
.
offset
=
num_b
yte
s
;
path
=
btrfs_alloc_path
();
if
(
!
path
)
...
...
@@ -768,28 +774,29 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_mark_buffer_dirty
(
leaf
);
if
(
refs
==
0
)
{
u64
super_blocks_used
,
root_blocks_used
;
u64
super_used
;
u64
root_used
;
if
(
pin
)
{
ret
=
pin_down_b
lock
(
root
,
blocknr
,
0
);
ret
=
pin_down_b
ytes
(
root
,
bytenr
,
num_bytes
,
0
);
BUG_ON
(
ret
);
}
/* block accounting for super block */
super_
blocks_used
=
btrfs_super_block
s_used
(
&
info
->
super_copy
);
btrfs_set_super_b
lock
s_used
(
&
info
->
super_copy
,
super_blocks_used
-
num_block
s
);
super_
used
=
btrfs_super_byte
s_used
(
&
info
->
super_copy
);
btrfs_set_super_b
yte
s_used
(
&
info
->
super_copy
,
super_used
-
num_byte
s
);
/* block accounting for root item */
root_
blocks_
used
=
btrfs_root_used
(
&
root
->
root_item
);
root_used
=
btrfs_root_used
(
&
root
->
root_item
);
btrfs_set_root_used
(
&
root
->
root_item
,
root_
blocks_used
-
num_block
s
);
root_
used
-
num_byte
s
);
ret
=
btrfs_del_item
(
trans
,
extent_root
,
path
);
if
(
ret
)
{
return
ret
;
}
ret
=
update_block_group
(
trans
,
root
,
b
locknr
,
num_block
s
,
0
,
ret
=
update_block_group
(
trans
,
root
,
b
ytenr
,
num_byte
s
,
0
,
mark_free
,
0
);
BUG_ON
(
ret
);
}
...
...
@@ -836,17 +843,18 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
* remove an extent from the root, returns 0 on success
*/
int
btrfs_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
,
int
pin
)
*
root
,
u64
b
ytenr
,
u64
num_byte
s
,
int
pin
)
{
struct
btrfs_root
*
extent_root
=
root
->
fs_info
->
extent_root
;
int
pending_ret
;
int
ret
;
WARN_ON
(
num_bytes
<
root
->
sectorsize
);
if
(
root
==
extent_root
)
{
pin_down_b
lock
(
root
,
blocknr
,
1
);
pin_down_b
ytes
(
root
,
bytenr
,
num_bytes
,
1
);
return
0
;
}
ret
=
__free_extent
(
trans
,
root
,
b
locknr
,
num_block
s
,
pin
,
pin
==
0
);
ret
=
__free_extent
(
trans
,
root
,
b
ytenr
,
num_byte
s
,
pin
,
pin
==
0
);
pending_ret
=
del_pending_extents
(
trans
,
root
->
fs_info
->
extent_root
);
return
ret
?
ret
:
pending_ret
;
}
...
...
@@ -860,8 +868,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
* Any available blocks before search_start are skipped.
*/
static
int
find_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
orig_root
,
u64
num_b
lock
s
,
u64
empty_size
,
u64
search_start
,
u64
search_end
,
u64
hint_b
lock
,
*
orig_root
,
u64
num_b
yte
s
,
u64
empty_size
,
u64
search_start
,
u64
search_end
,
u64
hint_b
yte
,
struct
btrfs_key
*
ins
,
u64
exclude_start
,
u64
exclude_nr
,
int
data
)
{
...
...
@@ -870,30 +878,29 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
int
ret
;
u64
hole_size
=
0
;
int
slot
=
0
;
u64
last_b
lock
=
0
;
u64
last_b
yte
=
0
;
u64
orig_search_start
=
search_start
;
int
start_found
;
struct
extent_buffer
*
l
;
struct
btrfs_root
*
root
=
orig_root
->
fs_info
->
extent_root
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
int
total_needed
=
num_block
s
;
u64
total_needed
=
num_byte
s
;
int
level
;
struct
btrfs_block_group_cache
*
block_group
;
int
full_scan
=
0
;
int
wrapped
=
0
;
u64
cached_search_start
=
0
;
WARN_ON
(
num_b
locks
<
1
);
WARN_ON
(
num_b
ytes
<
root
->
sectorsize
);
btrfs_set_key_type
(
ins
,
BTRFS_EXTENT_ITEM_KEY
);
level
=
btrfs_header_level
(
root
->
node
);
if
(
search_end
==
(
u64
)
-
1
)
search_end
=
btrfs_super_total_b
lock
s
(
&
info
->
super_copy
);
if
(
hint_b
lock
)
{
block_group
=
btrfs_lookup_block_group
(
info
,
hint_b
lock
);
search_end
=
btrfs_super_total_b
yte
s
(
&
info
->
super_copy
);
if
(
hint_b
yte
)
{
block_group
=
btrfs_lookup_block_group
(
info
,
hint_b
yte
);
block_group
=
btrfs_find_block_group
(
root
,
block_group
,
hint_b
lock
,
data
,
1
);
hint_b
yte
,
data
,
1
);
}
else
{
block_group
=
btrfs_find_block_group
(
root
,
trans
->
block_group
,
0
,
...
...
@@ -906,7 +913,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
check_failed:
search_start
=
find_search_start
(
root
,
&
block_group
,
search_start
,
total_needed
,
data
);
cached_search_start
=
search_start
;
btrfs_init_path
(
path
);
ins
->
objectid
=
search_start
;
...
...
@@ -958,27 +964,27 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
start_found
=
1
;
goto
check_pending
;
}
ins
->
objectid
=
last_b
lock
>
search_start
?
last_b
lock
:
search_start
;
ins
->
objectid
=
last_b
yte
>
search_start
?
last_b
yte
:
search_start
;
ins
->
offset
=
search_end
-
ins
->
objectid
;
goto
check_pending
;
}
btrfs_item_key_to_cpu
(
l
,
&
key
,
slot
);
if
(
key
.
objectid
>=
search_start
&&
key
.
objectid
>
last_b
lock
&&
if
(
key
.
objectid
>=
search_start
&&
key
.
objectid
>
last_b
yte
&&
start_found
)
{
if
(
last_b
lock
<
search_start
)
last_b
lock
=
search_start
;
hole_size
=
key
.
objectid
-
last_b
lock
;
if
(
hole_size
>=
num_b
lock
s
)
{
ins
->
objectid
=
last_b
lock
;
if
(
last_b
yte
<
search_start
)
last_b
yte
=
search_start
;
hole_size
=
key
.
objectid
-
last_b
yte
;
if
(
hole_size
>=
num_b
yte
s
)
{
ins
->
objectid
=
last_b
yte
;
ins
->
offset
=
hole_size
;
goto
check_pending
;
}
}
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_EXTENT_ITEM_KEY
)
{
if
(
!
start_found
)
{
last_b
lock
=
key
.
objectid
;
last_b
yte
=
key
.
objectid
;
start_found
=
1
;
}
goto
next
;
...
...
@@ -986,9 +992,9 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
start_found
=
1
;
last_b
lock
=
key
.
objectid
+
key
.
offset
;
last_b
yte
=
key
.
objectid
+
key
.
offset
;
if
(
!
full_scan
&&
last_b
lock
>=
block_group
->
key
.
objectid
+
if
(
!
full_scan
&&
last_b
yte
>=
block_group
->
key
.
objectid
+
block_group
->
key
.
offset
)
{
btrfs_release_path
(
root
,
path
);
search_start
=
block_group
->
key
.
objectid
+
...
...
@@ -1006,20 +1012,20 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_release_path
(
root
,
path
);
BUG_ON
(
ins
->
objectid
<
search_start
);
if
(
ins
->
objectid
+
num_b
lock
s
>=
search_end
)
if
(
ins
->
objectid
+
num_b
yte
s
>=
search_end
)
goto
enospc
;
if
(
test_range_bit
(
&
info
->
extent_ins
,
ins
->
objectid
,
ins
->
objectid
+
num_b
lock
s
-
1
,
EXTENT_LOCKED
,
0
))
{
search_start
=
ins
->
objectid
+
num_b
lock
s
;
ins
->
objectid
+
num_b
yte
s
-
1
,
EXTENT_LOCKED
,
0
))
{
search_start
=
ins
->
objectid
+
num_b
yte
s
;
goto
new_group
;
}
if
(
test_range_bit
(
&
info
->
pinned_extents
,
ins
->
objectid
,
ins
->
objectid
+
num_b
lock
s
-
1
,
EXTENT_DIRTY
,
0
))
{
search_start
=
ins
->
objectid
+
num_b
lock
s
;
ins
->
objectid
+
num_b
yte
s
-
1
,
EXTENT_DIRTY
,
0
))
{
search_start
=
ins
->
objectid
+
num_b
yte
s
;
goto
new_group
;
}
if
(
exclude_nr
>
0
&&
(
ins
->
objectid
+
num_b
lock
s
>
exclude_start
&&
if
(
exclude_nr
>
0
&&
(
ins
->
objectid
+
num_b
yte
s
>
exclude_start
&&
ins
->
objectid
<
exclude_start
+
exclude_nr
))
{
search_start
=
exclude_start
+
exclude_nr
;
goto
new_group
;
...
...
@@ -1029,12 +1035,12 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
block_group
)
trans
->
block_group
=
block_group
;
}
ins
->
offset
=
num_b
lock
s
;
ins
->
offset
=
num_b
yte
s
;
btrfs_free_path
(
path
);
return
0
;
new_group:
if
(
search_start
+
num_b
lock
s
>=
search_end
)
{
if
(
search_start
+
num_b
yte
s
>=
search_end
)
{
enospc:
search_start
=
orig_search_start
;
if
(
full_scan
)
{
...
...
@@ -1069,12 +1075,12 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*/
int
btrfs_alloc_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
owner
,
u64
num_b
locks
,
u64
empty_size
,
u64
hint_block
,
u64
num_b
ytes
,
u64
empty_size
,
u64
hint_byte
,
u64
search_end
,
struct
btrfs_key
*
ins
,
int
data
)
{
int
ret
;
int
pending_ret
;
u64
super_
blocks_used
,
root_blocks
_used
;
u64
super_
used
,
root
_used
;
u64
search_start
=
0
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
struct
btrfs_root
*
extent_root
=
info
->
extent_root
;
...
...
@@ -1083,9 +1089,9 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
btrfs_set_stack_extent_refs
(
&
extent_item
,
1
);
btrfs_set_stack_extent_owner
(
&
extent_item
,
owner
);
WARN_ON
(
num_b
locks
<
1
);
ret
=
find_free_extent
(
trans
,
root
,
num_b
lock
s
,
empty_size
,
search_start
,
search_end
,
hint_b
lock
,
ins
,
WARN_ON
(
num_b
ytes
<
root
->
sectorsize
);
ret
=
find_free_extent
(
trans
,
root
,
num_b
yte
s
,
empty_size
,
search_start
,
search_end
,
hint_b
yte
,
ins
,
trans
->
alloc_exclude_start
,
trans
->
alloc_exclude_nr
,
data
);
BUG_ON
(
ret
);
...
...
@@ -1093,21 +1099,18 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
return
ret
;
/* block accounting for super block */
super_blocks_used
=
btrfs_super_blocks_used
(
&
info
->
super_copy
);
btrfs_set_super_blocks_used
(
&
info
->
super_copy
,
super_blocks_used
+
num_blocks
);
super_used
=
btrfs_super_bytes_used
(
&
info
->
super_copy
);
btrfs_set_super_bytes_used
(
&
info
->
super_copy
,
super_used
+
num_bytes
);
/* block accounting for root item */
root_blocks_used
=
btrfs_root_used
(
&
root
->
root_item
);
btrfs_set_root_used
(
&
root
->
root_item
,
root_blocks_used
+
num_blocks
);
root_used
=
btrfs_root_used
(
&
root
->
root_item
);
btrfs_set_root_used
(
&
root
->
root_item
,
root_used
+
num_bytes
);
clear_extent_dirty
(
&
root
->
fs_info
->
free_space_cache
,
ins
->
objectid
,
ins
->
objectid
+
ins
->
offset
-
1
,
GFP_NOFS
);
if
(
root
==
extent_root
)
{
BUG_ON
(
num_blocks
!=
1
);
set_extent_bits
(
&
root
->
fs_info
->
extent_ins
,
ins
->
objectid
,
ins
->
objectid
+
ins
->
offset
-
1
,
EXTENT_LOCKED
,
GFP_NOFS
);
...
...
@@ -1146,7 +1149,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
* returns the tree buffer or NULL.
*/
struct
extent_buffer
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
hint
,
struct
btrfs_root
*
root
,
u32
blocksize
,
u64
hint
,
u64
empty_size
)
{
struct
btrfs_key
ins
;
...
...
@@ -1154,14 +1158,15 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
struct
extent_buffer
*
buf
;
ret
=
btrfs_alloc_extent
(
trans
,
root
,
root
->
root_key
.
objectid
,
1
,
empty_size
,
hint
,
(
u64
)
-
1
,
&
ins
,
0
);
blocksize
,
empty_size
,
hint
,
(
u64
)
-
1
,
&
ins
,
0
);
if
(
ret
)
{
BUG_ON
(
ret
>
0
);
return
ERR_PTR
(
ret
);
}
buf
=
btrfs_find_create_tree_block
(
root
,
ins
.
objectid
);
buf
=
btrfs_find_create_tree_block
(
root
,
ins
.
objectid
,
blocksize
);
if
(
!
buf
)
{
btrfs_free_extent
(
trans
,
root
,
ins
.
objectid
,
1
,
0
);
btrfs_free_extent
(
trans
,
root
,
ins
.
objectid
,
blocksize
,
0
);
return
ERR_PTR
(
-
ENOMEM
);
}
btrfs_set_buffer_uptodate
(
buf
);
...
...
@@ -1191,7 +1196,7 @@ static int drop_leaf_ref(struct btrfs_trans_handle *trans,
BUG_ON
(
!
btrfs_is_leaf
(
leaf
));
nritems
=
btrfs_header_nritems
(
leaf
);
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
u64
disk_b
lock
nr
;
u64
disk_b
yte
nr
;
btrfs_item_key_to_cpu
(
leaf
,
&
key
,
i
);
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_EXTENT_DATA_KEY
)
...
...
@@ -1204,11 +1209,11 @@ static int drop_leaf_ref(struct btrfs_trans_handle *trans,
* FIXME make sure to insert a trans record that
* repeats the snapshot del on crash
*/
disk_b
locknr
=
btrfs_file_extent_disk_block
nr
(
leaf
,
fi
);
if
(
disk_b
lock
nr
==
0
)
disk_b
ytenr
=
btrfs_file_extent_disk_byte
nr
(
leaf
,
fi
);
if
(
disk_b
yte
nr
==
0
)
continue
;
ret
=
btrfs_free_extent
(
trans
,
root
,
disk_b
lock
nr
,
btrfs_file_extent_disk_num_b
lock
s
(
leaf
,
fi
),
0
);
ret
=
btrfs_free_extent
(
trans
,
root
,
disk_b
yte
nr
,
btrfs_file_extent_disk_num_b
yte
s
(
leaf
,
fi
),
0
);
BUG_ON
(
ret
);
}
return
0
;
...
...
@@ -1219,19 +1224,23 @@ static void reada_walk_down(struct btrfs_root *root,
{
int
i
;
u32
nritems
;
u64
b
lock
nr
;
u64
b
yte
nr
;
int
ret
;
u32
refs
;
int
level
;
u32
blocksize
;
nritems
=
btrfs_header_nritems
(
node
);
level
=
btrfs_header_level
(
node
);
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
blocknr
=
btrfs_node_blockptr
(
node
,
i
);
ret
=
lookup_extent_ref
(
NULL
,
root
,
blocknr
,
1
,
&
refs
);
bytenr
=
btrfs_node_blockptr
(
node
,
i
);
blocksize
=
btrfs_level_size
(
root
,
level
-
1
);
ret
=
lookup_extent_ref
(
NULL
,
root
,
bytenr
,
blocksize
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
!=
1
)
continue
;
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
ret
=
readahead_tree_block
(
root
,
b
locknr
);
ret
=
readahead_tree_block
(
root
,
b
ytenr
,
blocksize
);
cond_resched
();
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
if
(
ret
)
...
...
@@ -1248,15 +1257,16 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
{
struct
extent_buffer
*
next
;
struct
extent_buffer
*
cur
;
u64
blocknr
;
u64
bytenr
;
u32
blocksize
;
int
ret
;
u32
refs
;
WARN_ON
(
*
level
<
0
);
WARN_ON
(
*
level
>=
BTRFS_MAX_LEVEL
);
ret
=
lookup_extent_ref
(
trans
,
root
,
extent_buffer_blocknr
(
path
->
nodes
[
*
level
])
,
1
,
&
refs
);
path
->
nodes
[
*
level
]
->
start
,
path
->
nodes
[
*
level
]
->
len
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
>
1
)
goto
out
;
...
...
@@ -1283,30 +1293,33 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
BUG_ON
(
ret
);
break
;
}
blocknr
=
btrfs_node_blockptr
(
cur
,
path
->
slots
[
*
level
]);
ret
=
lookup_extent_ref
(
trans
,
root
,
blocknr
,
1
,
&
refs
);
bytenr
=
btrfs_node_blockptr
(
cur
,
path
->
slots
[
*
level
]);
blocksize
=
btrfs_level_size
(
root
,
*
level
-
1
);
ret
=
lookup_extent_ref
(
trans
,
root
,
bytenr
,
blocksize
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
!=
1
)
{
path
->
slots
[
*
level
]
++
;
ret
=
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
1
);
ret
=
btrfs_free_extent
(
trans
,
root
,
bytenr
,
blocksize
,
1
);
BUG_ON
(
ret
);
continue
;
}
next
=
btrfs_find_tree_block
(
root
,
b
locknr
);
next
=
btrfs_find_tree_block
(
root
,
b
ytenr
,
blocksize
);
if
(
!
next
||
!
btrfs_buffer_uptodate
(
next
))
{
free_extent_buffer
(
next
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
next
=
read_tree_block
(
root
,
b
locknr
);
next
=
read_tree_block
(
root
,
b
ytenr
,
blocksize
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
/* we dropped the lock, check one more time */
ret
=
lookup_extent_ref
(
trans
,
root
,
blocknr
,
1
,
&
refs
);
ret
=
lookup_extent_ref
(
trans
,
root
,
bytenr
,
blocksize
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
!=
1
)
{
path
->
slots
[
*
level
]
++
;
free_extent_buffer
(
next
);
ret
=
btrfs_free_extent
(
trans
,
root
,
b
locknr
,
1
,
1
);
b
ytenr
,
blocksize
,
1
);
BUG_ON
(
ret
);
continue
;
}
...
...
@@ -1321,8 +1334,8 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
out:
WARN_ON
(
*
level
<
0
);
WARN_ON
(
*
level
>=
BTRFS_MAX_LEVEL
);
ret
=
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
path
->
nodes
[
*
level
]),
1
,
1
);
ret
=
btrfs_free_extent
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
start
,
path
->
nodes
[
*
level
]
->
len
,
1
);
free_extent_buffer
(
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
*
level
+=
1
;
...
...
@@ -1359,8 +1372,8 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
return
0
;
}
else
{
ret
=
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
path
->
nodes
[
*
level
])
,
1
,
1
);
path
->
nodes
[
*
level
]
->
start
,
path
->
nodes
[
*
level
]
->
len
,
1
);
BUG_ON
(
ret
);
free_extent_buffer
(
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
...
...
@@ -1476,16 +1489,12 @@ int btrfs_read_block_groups(struct btrfs_root *root)
struct
btrfs_key
key
;
struct
btrfs_key
found_key
;
struct
extent_buffer
*
leaf
;
u64
group_size_blocks
;
block_group_cache
=
&
info
->
block_group_cache
;
group_size_blocks
=
BTRFS_BLOCK_GROUP_SIZE
>>
info
->
sb
->
s_blocksize_bits
;
root
=
info
->
extent_root
;
key
.
objectid
=
0
;
key
.
offset
=
group_size_blocks
;
key
.
offset
=
BTRFS_BLOCK_GROUP_SIZE
;
btrfs_set_key_type
(
&
key
,
BTRFS_BLOCK_GROUP_ITEM_KEY
);
path
=
btrfs_alloc_path
();
...
...
@@ -1532,7 +1541,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
(
u64
)
cache
);
if
(
key
.
objectid
>=
btrfs_super_total_b
lock
s
(
&
info
->
super_copy
))
btrfs_super_total_b
yte
s
(
&
info
->
super_copy
))
break
;
}
...
...
fs/btrfs/extent_map.c
浏览文件 @
db94535d
...
...
@@ -1963,18 +1963,27 @@ static inline struct page *extent_buffer_page(struct extent_buffer *eb, int i)
struct
page
*
p
;
if
(
i
==
0
)
return
eb
->
first_page
;
i
+=
eb
->
start
>>
PAGE_CACHE_SHIFT
;
if
(
eb
->
last_page
&&
eb
->
last_page
->
index
==
i
)
return
eb
->
last_page
;
p
=
find_get_page
(
eb
->
first_page
->
mapping
,
i
);
page_cache_release
(
p
);
eb
->
last_page
=
p
;
return
p
;
}
static
inline
unsigned
long
num_extent_pages
(
u64
start
,
u64
len
)
{
return
((
start
+
len
+
PAGE_CACHE_SIZE
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
start
>>
PAGE_CACHE_SHIFT
);
}
struct
extent_buffer
*
alloc_extent_buffer
(
struct
extent_map_tree
*
tree
,
u64
start
,
unsigned
long
len
,
gfp_t
mask
)
{
unsigned
long
num_pages
=
((
start
+
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
unsigned
long
num_pages
=
num_extent_pages
(
start
,
len
);
unsigned
long
i
;
unsigned
long
index
=
start
>>
PAGE_CACHE_SHIFT
;
struct
extent_buffer
*
eb
;
...
...
@@ -1986,7 +1995,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
if
(
!
eb
||
IS_ERR
(
eb
))
return
NULL
;
eb
->
alloc_addr
=
__builtin_return_address
(
0
);
eb
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
eb
->
start
=
start
;
eb
->
len
=
len
;
atomic_set
(
&
eb
->
refs
,
1
);
...
...
@@ -1994,6 +2003,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
for
(
i
=
0
;
i
<
num_pages
;
i
++
,
index
++
)
{
p
=
find_or_create_page
(
mapping
,
index
,
mask
|
__GFP_HIGHMEM
);
if
(
!
p
)
{
WARN_ON
(
1
);
/* make sure the free only frees the pages we've
* grabbed a reference on
*/
...
...
@@ -2021,8 +2031,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
u64
start
,
unsigned
long
len
,
gfp_t
mask
)
{
unsigned
long
num_pages
=
((
start
+
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
unsigned
long
num_pages
=
num_extent_pages
(
start
,
len
);
unsigned
long
i
;
unsigned
long
index
=
start
>>
PAGE_CACHE_SHIFT
;
struct
extent_buffer
*
eb
;
...
...
@@ -2033,7 +2042,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
if
(
!
eb
||
IS_ERR
(
eb
))
return
NULL
;
eb
->
alloc_addr
=
__builtin_return_address
(
0
);
eb
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
eb
->
start
=
start
;
eb
->
len
=
len
;
atomic_set
(
&
eb
->
refs
,
1
);
...
...
@@ -2070,8 +2079,7 @@ void free_extent_buffer(struct extent_buffer *eb)
if
(
!
atomic_dec_and_test
(
&
eb
->
refs
))
return
;
num_pages
=
((
eb
->
start
+
eb
->
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
eb
->
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
if
(
eb
->
first_page
)
page_cache_release
(
eb
->
first_page
);
...
...
@@ -2094,8 +2102,7 @@ int clear_extent_buffer_dirty(struct extent_map_tree *tree,
u64
end
=
start
+
eb
->
len
-
1
;
set
=
clear_extent_dirty
(
tree
,
start
,
end
,
GFP_NOFS
);
num_pages
=
((
eb
->
start
+
eb
->
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
eb
->
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
page
=
extent_buffer_page
(
eb
,
i
);
...
...
@@ -2145,8 +2152,7 @@ int set_extent_buffer_uptodate(struct extent_map_tree *tree,
struct
page
*
page
;
unsigned
long
num_pages
;
num_pages
=
((
eb
->
start
+
eb
->
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
eb
->
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
set_extent_uptodate
(
tree
,
eb
->
start
,
eb
->
start
+
eb
->
len
-
1
,
GFP_NOFS
);
...
...
@@ -2191,8 +2197,7 @@ int read_extent_buffer_pages(struct extent_map_tree *tree,
return
0
;
}
num_pages
=
((
eb
->
start
+
eb
->
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
eb
->
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
page
=
extent_buffer_page
(
eb
,
i
);
if
(
PageUptodate
(
page
))
{
...
...
@@ -2267,14 +2272,14 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
}
EXPORT_SYMBOL
(
read_extent_buffer
);
int
map_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
*
map_start
,
unsigned
long
*
map_len
,
int
km
)
static
int
__map_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
*
map_start
,
unsigned
long
*
map_len
,
int
km
)
{
size_t
offset
=
start
&
(
PAGE_CACHE_SIZE
-
1
);
char
*
kaddr
;
struct
page
*
p
;
size_t
start_offset
=
eb
->
start
&
((
u64
)
PAGE_CACHE_SIZE
-
1
);
unsigned
long
i
=
(
start_offset
+
start
)
>>
PAGE_CACHE_SHIFT
;
unsigned
long
end_i
=
(
start_offset
+
start
+
min_len
)
>>
...
...
@@ -2283,21 +2288,59 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
if
(
i
!=
end_i
)
return
-
EINVAL
;
WARN_ON
(
start
>
eb
->
len
);
if
(
start
>=
eb
->
len
)
{
printk
(
"bad start in map eb start %Lu len %lu caller start %lu min %lu
\n
"
,
eb
->
start
,
eb
->
len
,
start
,
min_len
);
WARN_ON
(
1
);
}
if
(
i
==
0
)
{
offset
=
start_offset
;
*
map_start
=
0
;
}
else
{
offset
=
0
;
*
map_start
=
(
i
<<
PAGE_CACHE_SHIFT
)
-
start_offset
;
}
kaddr
=
kmap_atomic
(
extent_buffer_page
(
eb
,
i
),
km
);
p
=
extent_buffer_page
(
eb
,
i
);
WARN_ON
(
!
PageUptodate
(
p
));
kaddr
=
kmap_atomic
(
p
,
km
);
*
token
=
kaddr
;
*
map
=
kaddr
+
offset
;
*
map_len
=
PAGE_CACHE_SIZE
-
offset
;
return
0
;
}
int
map_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
*
map_start
,
unsigned
long
*
map_len
,
int
km
)
{
int
err
;
int
save
=
0
;
if
(
eb
->
map_token
)
{
if
(
start
>=
eb
->
map_start
&&
start
+
min_len
<=
eb
->
map_start
+
eb
->
map_len
)
{
*
token
=
eb
->
map_token
;
*
map
=
eb
->
kaddr
;
*
map_start
=
eb
->
map_start
;
*
map_len
=
eb
->
map_len
;
return
0
;
}
unmap_extent_buffer
(
eb
,
eb
->
map_token
,
km
);
eb
->
map_token
=
NULL
;
save
=
1
;
}
err
=
__map_extent_buffer
(
eb
,
start
,
min_len
,
token
,
map
,
map_start
,
map_len
,
km
);
if
(
!
err
&&
save
)
{
eb
->
map_token
=
*
token
;
eb
->
kaddr
=
*
map
;
eb
->
map_start
=
*
map_start
;
eb
->
map_len
=
*
map_len
;
}
return
err
;
}
EXPORT_SYMBOL
(
map_extent_buffer
);
void
unmap_extent_buffer
(
struct
extent_buffer
*
eb
,
char
*
token
,
int
km
)
...
...
@@ -2574,7 +2617,6 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
((
unsigned
long
)
PAGE_CACHE_SIZE
-
1
);
src_off_in_page
=
src_end
&
((
unsigned
long
)
PAGE_CACHE_SIZE
-
1
);
if
(
src_i
==
0
)
src_off_in_page
+=
start_offset
;
if
(
dst_i
==
0
)
...
...
@@ -2582,14 +2624,13 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
cur
=
min
(
len
,
src_off_in_page
+
1
);
cur
=
min
(
cur
,
dst_off_in_page
+
1
);
move_pages
(
extent_buffer_page
(
dst
,
dst_i
),
extent_buffer_page
(
dst
,
src_i
),
dst_off_in_page
-
cur
+
1
,
src_off_in_page
-
cur
+
1
,
cur
);
dst_end
-=
cur
-
1
;
src_end
-=
cur
-
1
;
dst_end
-=
cur
;
src_end
-=
cur
;
len
-=
cur
;
}
}
...
...
fs/btrfs/extent_map.h
浏览文件 @
db94535d
...
...
@@ -70,7 +70,12 @@ struct extent_buffer {
struct
list_head
list
;
struct
list_head
leak_list
;
struct
page
*
first_page
;
struct
page
*
last_page
;
unsigned
long
alloc_addr
;
char
*
map_token
;
char
*
kaddr
;
unsigned
long
map_start
;
unsigned
long
map_len
;
};
typedef
struct
extent_map
*
(
get_extent_t
)(
struct
inode
*
inode
,
...
...
@@ -147,11 +152,6 @@ static inline void extent_buffer_get(struct extent_buffer *eb)
atomic_inc
(
&
eb
->
refs
);
}
static
inline
u64
extent_buffer_blocknr
(
struct
extent_buffer
*
eb
)
{
return
eb
->
start
/
4096
;
}
int
memcmp_extent_buffer
(
struct
extent_buffer
*
eb
,
const
void
*
ptrv
,
unsigned
long
start
,
unsigned
long
len
);
...
...
fs/btrfs/file-item.c
浏览文件 @
db94535d
...
...
@@ -27,8 +27,8 @@
int
btrfs_insert_file_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
objectid
,
u64
pos
,
u64
offset
,
u64
disk_num_b
lock
s
,
u64
num_b
lock
s
)
u64
offset
,
u64
disk_num_b
yte
s
,
u64
num_b
yte
s
)
{
int
ret
=
0
;
struct
btrfs_file_extent_item
*
item
;
...
...
@@ -50,10 +50,10 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
leaf
=
path
->
nodes
[
0
];
item
=
btrfs_item_ptr
(
leaf
,
path
->
slots
[
0
],
struct
btrfs_file_extent_item
);
btrfs_set_file_extent_disk_b
lock
nr
(
leaf
,
item
,
offset
);
btrfs_set_file_extent_disk_num_b
locks
(
leaf
,
item
,
disk_num_block
s
);
btrfs_set_file_extent_disk_b
yte
nr
(
leaf
,
item
,
offset
);
btrfs_set_file_extent_disk_num_b
ytes
(
leaf
,
item
,
disk_num_byte
s
);
btrfs_set_file_extent_offset
(
leaf
,
item
,
0
);
btrfs_set_file_extent_num_b
locks
(
leaf
,
item
,
num_block
s
);
btrfs_set_file_extent_num_b
ytes
(
leaf
,
item
,
num_byte
s
);
btrfs_set_file_extent_generation
(
leaf
,
item
,
trans
->
transid
);
btrfs_set_file_extent_type
(
leaf
,
item
,
BTRFS_FILE_EXTENT_REG
);
btrfs_mark_buffer_dirty
(
leaf
);
...
...
fs/btrfs/file.c
浏览文件 @
db94535d
...
...
@@ -120,9 +120,9 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
btrfs_set_file_extent_type
(
leaf
,
ei
,
BTRFS_FILE_EXTENT_INLINE
);
ptr
=
btrfs_file_extent_inline_start
(
ei
);
kaddr
=
kmap_atomic
(
page
,
KM_USER
0
);
kaddr
=
kmap_atomic
(
page
,
KM_USER
1
);
write_extent_buffer
(
leaf
,
kaddr
+
page_offset
,
ptr
,
size
);
kunmap_atomic
(
kaddr
,
KM_USER
0
);
kunmap_atomic
(
kaddr
,
KM_USER
1
);
btrfs_mark_buffer_dirty
(
leaf
);
fail:
btrfs_free_path
(
path
);
...
...
@@ -142,11 +142,12 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
struct
extent_map
*
em
;
struct
extent_map_tree
*
em_tree
=
&
BTRFS_I
(
inode
)
->
extent_tree
;
u64
hint_b
lock
;
u64
num_b
lock
s
;
u64
hint_b
yte
;
u64
num_b
yte
s
;
u64
start_pos
;
u64
end_of_last_block
;
u64
end_pos
=
pos
+
write_bytes
;
u32
inline_size
;
loff_t
isize
=
i_size_read
(
inode
);
em
=
alloc_extent_map
(
GFP_NOFS
);
...
...
@@ -156,11 +157,12 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
em
->
bdev
=
inode
->
i_sb
->
s_bdev
;
start_pos
=
pos
&
~
((
u64
)
root
->
sectorsize
-
1
);
num_b
locks
=
(
write_bytes
+
pos
-
start_pos
+
root
->
sectorsize
-
1
)
>>
inode
->
i_blkbits
;
num_b
ytes
=
(
write_bytes
+
pos
-
start_pos
+
root
->
sectorsize
-
1
)
&
~
((
u64
)
root
->
sectorsize
-
1
)
;
down_read
(
&
BTRFS_I
(
inode
)
->
root
->
snap_sem
);
end_of_last_block
=
start_pos
+
(
num_blocks
<<
inode
->
i_blkbits
)
-
1
;
end_of_last_block
=
start_pos
+
num_bytes
-
1
;
lock_extent
(
em_tree
,
start_pos
,
end_of_last_block
,
GFP_NOFS
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
...
...
@@ -169,8 +171,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
goto
out_unlock
;
}
btrfs_set_trans_block_group
(
trans
,
inode
);
inode
->
i_blocks
+=
num_b
locks
<<
3
;
hint_b
lock
=
0
;
inode
->
i_blocks
+=
num_b
ytes
>>
9
;
hint_b
yte
=
0
;
if
((
end_of_last_block
&
4095
)
==
0
)
{
printk
(
"strange end of last %Lu %zu %Lu
\n
"
,
start_pos
,
write_bytes
,
end_of_last_block
);
...
...
@@ -191,11 +193,10 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
err
=
btrfs_drop_extents
(
trans
,
root
,
inode
,
last_pos_in_file
,
last_pos_in_file
+
hole_size
,
&
hint_b
lock
);
&
hint_b
yte
);
if
(
err
)
goto
failed
;
hole_size
>>=
inode
->
i_blkbits
;
err
=
btrfs_insert_file_extent
(
trans
,
root
,
inode
->
i_ino
,
last_pos_in_file
,
...
...
@@ -209,8 +210,10 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
* either allocate an extent for the new bytes or setup the key
* to show we are doing inline data in the extent
*/
inline_size
=
end_pos
-
start_pos
;
if
(
isize
>=
PAGE_CACHE_SIZE
||
pos
+
write_bytes
<
inode
->
i_size
||
pos
+
write_bytes
-
start_pos
>
BTRFS_MAX_INLINE_DATA_SIZE
(
root
))
{
inline_size
>=
BTRFS_MAX_INLINE_DATA_SIZE
(
root
)
||
inline_size
>=
PAGE_CACHE_SIZE
)
{
u64
last_end
;
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
struct
page
*
p
=
pages
[
i
];
...
...
@@ -224,10 +227,9 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
}
else
{
struct
page
*
p
=
pages
[
0
];
/* step one, delete the existing extents in this range */
/* FIXME blocksize != pagesize */
err
=
btrfs_drop_extents
(
trans
,
root
,
inode
,
start_pos
,
(
pos
+
write_bytes
+
root
->
sectorsize
-
1
)
&
~
((
u64
)
root
->
sectorsize
-
1
),
&
hint_b
lock
);
~
((
u64
)
root
->
sectorsize
-
1
),
&
hint_b
yte
);
if
(
err
)
goto
failed
;
...
...
@@ -283,7 +285,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
*/
int
btrfs_drop_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
inode
*
inode
,
u64
start
,
u64
end
,
u64
*
hint_b
lock
)
u64
start
,
u64
end
,
u64
*
hint_b
yte
)
{
int
ret
;
struct
btrfs_key
key
;
...
...
@@ -346,8 +348,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
found_type
=
btrfs_file_extent_type
(
leaf
,
extent
);
if
(
found_type
==
BTRFS_FILE_EXTENT_REG
)
{
extent_end
=
key
.
offset
+
(
btrfs_file_extent_num_blocks
(
leaf
,
extent
)
<<
inode
->
i_blkbits
);
btrfs_file_extent_num_bytes
(
leaf
,
extent
);
found_extent
=
1
;
}
else
if
(
found_type
==
BTRFS_FILE_EXTENT_INLINE
)
{
struct
btrfs_item
*
item
;
...
...
@@ -386,17 +387,17 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
if
(
end
<
extent_end
&&
end
>=
key
.
offset
)
{
if
(
found_extent
)
{
u64
disk_b
lock
nr
=
btrfs_file_extent_disk_b
locknr
(
leaf
,
extent
);
u64
disk_num_b
lock
s
=
btrfs_file_extent_disk_num_b
lock
s
(
leaf
,
u64
disk_b
yte
nr
=
btrfs_file_extent_disk_b
ytenr
(
leaf
,
extent
);
u64
disk_num_b
yte
s
=
btrfs_file_extent_disk_num_b
yte
s
(
leaf
,
extent
);
read_extent_buffer
(
leaf
,
&
old
,
(
unsigned
long
)
extent
,
sizeof
(
old
));
if
(
disk_b
lock
nr
!=
0
)
{
if
(
disk_b
yte
nr
!=
0
)
{
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
disk_b
locknr
,
disk_num_block
s
);
disk_b
ytenr
,
disk_num_byte
s
);
BUG_ON
(
ret
);
}
}
...
...
@@ -410,21 +411,19 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
keep
=
1
;
WARN_ON
(
start
&
(
root
->
sectorsize
-
1
));
if
(
found_extent
)
{
new_num
=
(
start
-
key
.
offset
)
>>
inode
->
i_blkbits
;
old_num
=
btrfs_file_extent_num_blocks
(
leaf
,
extent
);
*
hint_block
=
btrfs_file_extent_disk_blocknr
(
leaf
,
extent
);
if
(
btrfs_file_extent_disk_blocknr
(
leaf
,
extent
))
{
new_num
=
start
-
key
.
offset
;
old_num
=
btrfs_file_extent_num_bytes
(
leaf
,
extent
);
*
hint_byte
=
btrfs_file_extent_disk_bytenr
(
leaf
,
extent
);
if
(
btrfs_file_extent_disk_bytenr
(
leaf
,
extent
))
{
inode
->
i_blocks
-=
(
old_num
-
new_num
)
<<
3
;
(
old_num
-
new_num
)
>>
9
;
}
btrfs_set_file_extent_num_blocks
(
leaf
,
extent
,
new_num
);
btrfs_set_file_extent_num_bytes
(
leaf
,
extent
,
new_num
);
btrfs_mark_buffer_dirty
(
leaf
);
}
else
{
WARN_ON
(
1
);
...
...
@@ -432,33 +431,32 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
}
/* delete the entire extent */
if
(
!
keep
)
{
u64
disk_b
lock
nr
=
0
;
u64
disk_num_b
lock
s
=
0
;
u64
extent_num_b
lock
s
=
0
;
u64
disk_b
yte
nr
=
0
;
u64
disk_num_b
yte
s
=
0
;
u64
extent_num_b
yte
s
=
0
;
if
(
found_extent
)
{
disk_b
lock
nr
=
btrfs_file_extent_disk_b
lock
nr
(
leaf
,
disk_b
yte
nr
=
btrfs_file_extent_disk_b
yte
nr
(
leaf
,
extent
);
disk_num_blocks
=
btrfs_file_extent_disk_num_blocks
(
leaf
,
extent
);
extent_num_blocks
=
btrfs_file_extent_num_blocks
(
leaf
,
extent
);
*
hint_block
=
btrfs_file_extent_disk_blocknr
(
leaf
,
disk_num_bytes
=
btrfs_file_extent_disk_num_bytes
(
leaf
,
extent
);
extent_num_bytes
=
btrfs_file_extent_num_bytes
(
leaf
,
extent
);
*
hint_byte
=
btrfs_file_extent_disk_bytenr
(
leaf
,
extent
);
}
ret
=
btrfs_del_item
(
trans
,
root
,
path
);
/* TODO update progress marker and return */
BUG_ON
(
ret
);
btrfs_release_path
(
root
,
path
);
extent
=
NULL
;
if
(
found_extent
&&
disk_b
lock
nr
!=
0
)
{
inode
->
i_blocks
-=
extent_num_b
locks
<<
3
;
if
(
found_extent
&&
disk_b
yte
nr
!=
0
)
{
inode
->
i_blocks
-=
extent_num_b
ytes
>>
9
;
ret
=
btrfs_free_extent
(
trans
,
root
,
disk_b
lock
nr
,
disk_num_b
lock
s
,
0
);
disk_b
yte
nr
,
disk_num_b
yte
s
,
0
);
}
BUG_ON
(
ret
);
...
...
@@ -491,20 +489,19 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
(
unsigned
long
)
extent
,
sizeof
(
old
));
btrfs_set_file_extent_offset
(
leaf
,
extent
,
le64_to_cpu
(
old
.
offset
)
+
((
end
-
key
.
offset
)
>>
inode
->
i_blkbits
));
WARN_ON
(
le64_to_cpu
(
old
.
num_blocks
)
<
(
extent_end
-
end
)
>>
inode
->
i_blkbits
);
btrfs_set_file_extent_num_blocks
(
leaf
,
extent
,
(
extent_end
-
end
)
>>
inode
->
i_blkbits
);
le64_to_cpu
(
old
.
offset
)
+
end
-
key
.
offset
);
WARN_ON
(
le64_to_cpu
(
old
.
num_bytes
)
<
(
extent_end
-
end
));
btrfs_set_file_extent_num_bytes
(
leaf
,
extent
,
extent_end
-
end
);
btrfs_set_file_extent_type
(
leaf
,
extent
,
BTRFS_FILE_EXTENT_REG
);
btrfs_mark_buffer_dirty
(
path
->
nodes
[
0
]);
if
(
le64_to_cpu
(
old
.
disk_b
lock
nr
)
!=
0
)
{
if
(
le64_to_cpu
(
old
.
disk_b
yte
nr
)
!=
0
)
{
inode
->
i_blocks
+=
btrfs_file_extent_num_b
lock
s
(
leaf
,
extent
)
<<
3
;
btrfs_file_extent_num_b
yte
s
(
leaf
,
extent
)
>>
9
;
}
ret
=
0
;
goto
out
;
...
...
@@ -531,12 +528,9 @@ static int prepare_pages(struct btrfs_root *root,
unsigned
long
index
=
pos
>>
PAGE_CACHE_SHIFT
;
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
int
err
=
0
;
u64
num_blocks
;
u64
start_pos
;
start_pos
=
pos
&
~
((
u64
)
root
->
sectorsize
-
1
);
num_blocks
=
(
write_bytes
+
pos
-
start_pos
+
root
->
sectorsize
-
1
)
>>
inode
->
i_blkbits
;
memset
(
pages
,
0
,
num_pages
*
sizeof
(
struct
page
*
));
...
...
fs/btrfs/inode.c
浏览文件 @
db94535d
...
...
@@ -77,19 +77,19 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end)
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_key
ins
;
u64
alloc_hint
=
0
;
u64
num_b
lock
s
;
u64
num_b
yte
s
;
int
ret
;
u64
blocksize
=
1
<<
inode
->
i_blkbits
;
u64
blocksize
=
root
->
sectorsize
;
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
btrfs_set_trans_block_group
(
trans
,
inode
);
BUG_ON
(
!
trans
);
num_b
lock
s
=
(
end
-
start
+
blocksize
)
&
~
(
blocksize
-
1
);
num_b
yte
s
=
(
end
-
start
+
blocksize
)
&
~
(
blocksize
-
1
);
ret
=
btrfs_drop_extents
(
trans
,
root
,
inode
,
start
,
start
+
num_b
lock
s
,
&
alloc_hint
);
num_blocks
=
num_blocks
>>
inode
->
i_blkbits
;
ret
=
btrfs_alloc_extent
(
trans
,
root
,
inode
->
i_ino
,
num_b
lock
s
,
0
,
start
,
start
+
num_b
yte
s
,
&
alloc_hint
);
ret
=
btrfs_alloc_extent
(
trans
,
root
,
inode
->
i_ino
,
num_b
yte
s
,
0
,
alloc_hint
,
(
u64
)
-
1
,
&
ins
,
1
);
if
(
ret
)
{
WARN_ON
(
1
);
...
...
@@ -186,7 +186,8 @@ int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end)
zeroit:
printk
(
"btrfs csum failed ino %lu off %llu
\n
"
,
page
->
mapping
->
host
->
i_ino
,
(
unsigned
long
long
)
start
);
memset
(
kaddr
+
offset
,
1
,
end
-
start
+
1
);
flush_dcache_page
(
page
);
memset
(
kaddr
+
offset
,
1
,
end
-
start
+
1
);
flush_dcache_page
(
page
);
kunmap_atomic
(
kaddr
,
KM_IRQ0
);
return
0
;
}
...
...
@@ -547,7 +548,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
struct
extent_buffer
*
leaf
;
struct
btrfs_file_extent_item
*
fi
;
u64
extent_start
=
0
;
u64
extent_num_b
lock
s
=
0
;
u64
extent_num_b
yte
s
=
0
;
u64
item_end
=
0
;
int
found_extent
;
int
del_item
;
...
...
@@ -593,8 +594,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
if
(
btrfs_file_extent_type
(
leaf
,
fi
)
!=
BTRFS_FILE_EXTENT_INLINE
)
{
item_end
+=
btrfs_file_extent_num_blocks
(
leaf
,
fi
)
<<
inode
->
i_blkbits
;
btrfs_file_extent_num_bytes
(
leaf
,
fi
);
}
}
if
(
found_type
==
BTRFS_CSUM_ITEM_KEY
)
{
...
...
@@ -626,28 +626,27 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
btrfs_file_extent_type
(
leaf
,
fi
)
!=
BTRFS_FILE_EXTENT_INLINE
)
{
u64
num_dec
;
extent_start
=
btrfs_file_extent_disk_b
lock
nr
(
leaf
,
fi
);
extent_start
=
btrfs_file_extent_disk_b
yte
nr
(
leaf
,
fi
);
if
(
!
del_item
)
{
u64
orig_num_b
lock
s
=
btrfs_file_extent_num_b
lock
s
(
leaf
,
fi
);
extent_num_b
lock
s
=
inode
->
i_size
-
u64
orig_num_b
yte
s
=
btrfs_file_extent_num_b
yte
s
(
leaf
,
fi
);
extent_num_b
yte
s
=
inode
->
i_size
-
found_key
.
offset
+
root
->
sectorsize
-
1
;
extent_num_blocks
>>=
inode
->
i_blkbits
;
btrfs_set_file_extent_num_blocks
(
leaf
,
fi
,
extent_num_blocks
);
num_dec
=
(
orig_num_blocks
-
extent_num_blocks
)
<<
3
;
btrfs_set_file_extent_num_bytes
(
leaf
,
fi
,
extent_num_bytes
);
num_dec
=
(
orig_num_bytes
-
extent_num_bytes
)
>>
9
;
if
(
extent_start
!=
0
)
{
inode
->
i_blocks
-=
num_dec
;
}
btrfs_mark_buffer_dirty
(
leaf
);
}
else
{
extent_num_b
lock
s
=
btrfs_file_extent_disk_num_b
lock
s
(
leaf
,
fi
);
extent_num_b
yte
s
=
btrfs_file_extent_disk_num_b
yte
s
(
leaf
,
fi
);
/* FIXME blocksize != 4096 */
num_dec
=
btrfs_file_extent_num_b
lock
s
(
leaf
,
fi
)
<<
3
;
num_dec
=
btrfs_file_extent_num_b
yte
s
(
leaf
,
fi
)
>>
9
;
if
(
extent_start
!=
0
)
{
found_extent
=
1
;
inode
->
i_blocks
-=
num_dec
;
...
...
@@ -664,7 +663,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
btrfs_release_path
(
root
,
path
);
if
(
found_extent
)
{
ret
=
btrfs_free_extent
(
trans
,
root
,
extent_start
,
extent_num_b
lock
s
,
0
);
extent_num_b
yte
s
,
0
);
BUG_ON
(
ret
);
}
}
...
...
@@ -709,7 +708,8 @@ static int btrfs_cow_one_page(struct inode *inode, struct page *page,
static
int
btrfs_truncate_page
(
struct
address_space
*
mapping
,
loff_t
from
)
{
struct
inode
*
inode
=
mapping
->
host
;
unsigned
blocksize
=
1
<<
inode
->
i_blkbits
;
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
u32
blocksize
=
root
->
sectorsize
;
pgoff_t
index
=
from
>>
PAGE_CACHE_SHIFT
;
unsigned
offset
=
from
&
(
PAGE_CACHE_SIZE
-
1
);
struct
page
*
page
;
...
...
@@ -719,7 +719,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
if
((
offset
&
(
blocksize
-
1
))
==
0
)
goto
out
;
down_read
(
&
BTRFS_I
(
inode
)
->
root
->
snap_sem
);
down_read
(
&
root
->
snap_sem
);
ret
=
-
ENOMEM
;
page
=
grab_cache_page
(
mapping
,
index
);
if
(
!
page
)
...
...
@@ -778,8 +778,6 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
err
=
btrfs_drop_extents
(
trans
,
root
,
inode
,
pos
,
pos
+
hole_size
,
&
alloc_hint
);
hole_size
>>=
inode
->
i_blkbits
;
err
=
btrfs_insert_file_extent
(
trans
,
root
,
inode
->
i_ino
,
pos
,
0
,
0
,
hole_size
);
btrfs_end_transaction
(
trans
,
root
);
...
...
@@ -1490,7 +1488,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
{
int
ret
;
int
err
=
0
;
u64
b
lock
nr
;
u64
b
yte
nr
;
u64
extent_start
=
0
;
u64
extent_end
=
0
;
u64
objectid
=
inode
->
i_ino
;
...
...
@@ -1540,10 +1538,6 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
leaf
=
path
->
nodes
[
0
];
item
=
btrfs_item_ptr
(
leaf
,
path
->
slots
[
0
],
struct
btrfs_file_extent_item
);
blocknr
=
btrfs_file_extent_disk_blocknr
(
leaf
,
item
);
blocknr
+=
btrfs_file_extent_offset
(
leaf
,
item
);
/* are we inside the extent that was found? */
btrfs_item_key_to_cpu
(
leaf
,
&
found_key
,
path
->
slots
[
0
]);
found_type
=
btrfs_key_type
(
&
found_key
);
...
...
@@ -1556,8 +1550,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
extent_start
=
found_key
.
offset
;
if
(
found_type
==
BTRFS_FILE_EXTENT_REG
)
{
extent_end
=
extent_start
+
(
btrfs_file_extent_num_blocks
(
leaf
,
item
)
<<
inode
->
i_blkbits
);
btrfs_file_extent_num_bytes
(
leaf
,
item
);
err
=
0
;
if
(
start
<
extent_start
||
start
>=
extent_end
)
{
em
->
start
=
start
;
...
...
@@ -1570,17 +1563,18 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
}
goto
not_found_em
;
}
if
(
btrfs_file_extent_disk_blocknr
(
leaf
,
item
)
==
0
)
{
bytenr
=
btrfs_file_extent_disk_bytenr
(
leaf
,
item
);
if
(
bytenr
==
0
)
{
em
->
start
=
extent_start
;
em
->
end
=
extent_end
-
1
;
em
->
block_start
=
EXTENT_MAP_HOLE
;
em
->
block_end
=
EXTENT_MAP_HOLE
;
goto
insert
;
}
em
->
block_start
=
blocknr
<<
inode
->
i_blkbits
;
bytenr
+=
btrfs_file_extent_offset
(
leaf
,
item
);
em
->
block_start
=
bytenr
;
em
->
block_end
=
em
->
block_start
+
(
btrfs_file_extent_num_blocks
(
leaf
,
item
)
<<
inode
->
i_blkbits
)
-
1
;
btrfs_file_extent_num_bytes
(
leaf
,
item
)
-
1
;
em
->
start
=
extent_start
;
em
->
end
=
extent_end
-
1
;
goto
insert
;
...
...
@@ -1592,7 +1586,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
size
=
btrfs_file_extent_inline_len
(
leaf
,
btrfs_item_nr
(
leaf
,
path
->
slots
[
0
]));
extent_end
=
extent_start
|
((
u64
)
root
->
sectorsize
-
1
);
extent_end
=
(
extent_start
+
size
)
|
((
u64
)
root
->
sectorsize
-
1
);
if
(
start
<
extent_start
||
start
>=
extent_end
)
{
em
->
start
=
start
;
if
(
start
<
extent_start
)
{
...
...
@@ -1617,8 +1612,10 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
ptr
=
btrfs_file_extent_inline_start
(
item
);
map
=
kmap
(
page
);
read_extent_buffer
(
leaf
,
map
+
page_offset
,
ptr
,
size
);
/*
memset(map + page_offset + size, 0,
root->sectorsize - (page_offset + size));
*/
flush_dcache_page
(
page
);
kunmap
(
page
);
set_extent_uptodate
(
em_tree
,
extent_start
,
...
...
@@ -1836,13 +1833,13 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
trans
=
btrfs_start_transaction
(
root
,
1
);
BUG_ON
(
!
trans
);
leaf
=
btrfs_alloc_free_block
(
trans
,
root
,
0
,
0
);
leaf
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
leafsize
,
0
,
0
);
if
(
IS_ERR
(
leaf
))
return
PTR_ERR
(
leaf
);
btrfs_set_header_nritems
(
leaf
,
0
);
btrfs_set_header_level
(
leaf
,
0
);
btrfs_set_header_b
locknr
(
leaf
,
extent_buffer_blocknr
(
leaf
)
);
btrfs_set_header_b
ytenr
(
leaf
,
leaf
->
start
);
btrfs_set_header_generation
(
leaf
,
trans
->
transid
);
btrfs_set_header_owner
(
leaf
,
root
->
root_key
.
objectid
);
write_extent_buffer
(
leaf
,
root
->
fs_info
->
fsid
,
...
...
@@ -1858,7 +1855,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
inode_item
->
nblocks
=
cpu_to_le64
(
1
);
inode_item
->
mode
=
cpu_to_le32
(
S_IFDIR
|
0755
);
btrfs_set_root_blocknr
(
&
root_item
,
extent_buffer_blocknr
(
leaf
));
btrfs_set_root_bytenr
(
&
root_item
,
leaf
->
start
);
btrfs_set_root_level
(
&
root_item
,
0
);
btrfs_set_root_refs
(
&
root_item
,
1
);
btrfs_set_root_used
(
&
root_item
,
0
);
...
...
@@ -1971,8 +1969,8 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
btrfs_set_key_type
(
&
key
,
BTRFS_ROOT_ITEM_KEY
);
btrfs_cow_block
(
trans
,
root
,
root
->
node
,
NULL
,
0
,
&
tmp
);
btrfs_set_root_b
locknr
(
&
new_root_item
,
extent_buffer_blocknr
(
root
->
node
));
btrfs_set_root_b
ytenr
(
&
new_root_item
,
root
->
node
->
start
);
btrfs_set_root_level
(
&
new_root_item
,
btrfs_header_level
(
root
->
node
));
ret
=
btrfs_insert_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
key
,
&
new_root_item
);
...
...
fs/btrfs/print-tree.c
浏览文件 @
db94535d
...
...
@@ -36,7 +36,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
u32
type
;
printk
(
"leaf %llu total ptrs %d free space %d
\n
"
,
(
unsigned
long
long
)
btrfs_header_b
lock
nr
(
l
),
nr
,
(
unsigned
long
long
)
btrfs_header_b
yte
nr
(
l
),
nr
,
btrfs_leaf_free_space
(
root
,
l
));
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
item
=
btrfs_item_nr
(
l
,
i
);
...
...
@@ -65,8 +65,8 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
break
;
case
BTRFS_ROOT_ITEM_KEY
:
ri
=
btrfs_item_ptr
(
l
,
i
,
struct
btrfs_root_item
);
printk
(
"
\t\t
root data b
lock
nr %llu refs %u
\n
"
,
(
unsigned
long
long
)
btrfs_disk_root_b
lock
nr
(
l
,
ri
),
printk
(
"
\t\t
root data b
yte
nr %llu refs %u
\n
"
,
(
unsigned
long
long
)
btrfs_disk_root_b
yte
nr
(
l
,
ri
),
btrfs_disk_root_refs
(
l
,
ri
));
break
;
case
BTRFS_EXTENT_ITEM_KEY
:
...
...
@@ -84,12 +84,12 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
btrfs_file_extent_inline_len
(
l
,
item
));
break
;
}
printk
(
"
\t\t
extent data disk b
lock
%llu nr %llu
\n
"
,
(
unsigned
long
long
)
btrfs_file_extent_disk_b
lock
nr
(
l
,
fi
),
(
unsigned
long
long
)
btrfs_file_extent_disk_num_b
lock
s
(
l
,
fi
));
printk
(
"
\t\t
extent data disk b
ytenr
%llu nr %llu
\n
"
,
(
unsigned
long
long
)
btrfs_file_extent_disk_b
yte
nr
(
l
,
fi
),
(
unsigned
long
long
)
btrfs_file_extent_disk_num_b
yte
s
(
l
,
fi
));
printk
(
"
\t\t
extent data offset %llu nr %llu
\n
"
,
(
unsigned
long
long
)
btrfs_file_extent_offset
(
l
,
fi
),
(
unsigned
long
long
)
btrfs_file_extent_num_b
lock
s
(
l
,
fi
));
(
unsigned
long
long
)
btrfs_file_extent_num_b
yte
s
(
l
,
fi
));
break
;
case
BTRFS_BLOCK_GROUP_ITEM_KEY
:
bi
=
btrfs_item_ptr
(
l
,
i
,
...
...
@@ -106,16 +106,18 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
int
i
;
u32
nr
;
struct
btrfs_key
key
;
int
level
;
if
(
!
c
)
return
;
nr
=
btrfs_header_nritems
(
c
);
if
(
btrfs_is_leaf
(
c
))
{
level
=
btrfs_header_level
(
c
);
if
(
level
==
0
)
{
btrfs_print_leaf
(
root
,
c
);
return
;
}
printk
(
"node %llu level %d total ptrs %d free spc %u
\n
"
,
(
unsigned
long
long
)
btrfs_header_b
lock
nr
(
c
),
(
unsigned
long
long
)
btrfs_header_b
yte
nr
(
c
),
btrfs_header_level
(
c
),
nr
,
(
u32
)
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
-
nr
);
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
...
...
@@ -129,7 +131,8 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
}
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
struct
extent_buffer
*
next
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
c
,
i
));
btrfs_node_blockptr
(
c
,
i
),
btrfs_level_size
(
root
,
level
-
1
));
if
(
btrfs_is_leaf
(
next
)
&&
btrfs_header_level
(
c
)
!=
1
)
BUG
();
...
...
fs/btrfs/super.c
浏览文件 @
db94535d
...
...
@@ -303,10 +303,12 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct
btrfs_root
*
root
=
btrfs_sb
(
dentry
->
d_sb
);
struct
btrfs_super_block
*
disk_super
=
&
root
->
fs_info
->
super_copy
;
int
bits
=
dentry
->
d_sb
->
s_blocksize_bits
;
buf
->
f_namelen
=
BTRFS_NAME_LEN
;
buf
->
f_blocks
=
btrfs_super_total_blocks
(
disk_super
);
buf
->
f_bfree
=
buf
->
f_blocks
-
btrfs_super_blocks_used
(
disk_super
);
buf
->
f_blocks
=
btrfs_super_total_bytes
(
disk_super
)
>>
bits
;
buf
->
f_bfree
=
buf
->
f_blocks
-
(
btrfs_super_bytes_used
(
disk_super
)
>>
bits
);
buf
->
f_bavail
=
buf
->
f_bfree
;
buf
->
f_bsize
=
dentry
->
d_sb
->
s_blocksize
;
buf
->
f_type
=
BTRFS_SUPER_MAGIC
;
...
...
fs/btrfs/sysfs.c
浏览文件 @
db94535d
...
...
@@ -42,14 +42,15 @@ static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf)
static
ssize_t
super_blocks_used_show
(
struct
btrfs_fs_info
*
fs
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%llu
\n
"
,
(
unsigned
long
long
)
btrfs_super_b
lock
s_used
(
&
fs
->
super_copy
));
(
unsigned
long
long
)
btrfs_super_b
yte
s_used
(
&
fs
->
super_copy
));
}
static
ssize_t
super_total_blocks_show
(
struct
btrfs_fs_info
*
fs
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%llu
\n
"
,
(
unsigned
long
long
)
btrfs_super_total_b
lock
s
(
&
fs
->
super_copy
));
(
unsigned
long
long
)
btrfs_super_total_b
yte
s
(
&
fs
->
super_copy
));
}
static
ssize_t
super_blocksize_show
(
struct
btrfs_fs_info
*
fs
,
char
*
buf
)
...
...
fs/btrfs/transaction.c
浏览文件 @
db94535d
...
...
@@ -205,12 +205,13 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
btrfs_write_dirty_block_groups
(
trans
,
extent_root
);
while
(
1
)
{
old_extent_block
=
btrfs_root_blocknr
(
&
extent_root
->
root_item
);
if
(
old_extent_block
==
extent_buffer_blocknr
(
extent_root
->
node
))
old_extent_block
=
btrfs_root_bytenr
(
&
extent_root
->
root_item
);
if
(
old_extent_block
==
extent_root
->
node
->
start
)
break
;
btrfs_set_root_blocknr
(
&
extent_root
->
root_item
,
extent_buffer_blocknr
(
extent_root
->
node
));
btrfs_set_root_bytenr
(
&
extent_root
->
root_item
,
extent_root
->
node
->
start
);
btrfs_set_root_level
(
&
extent_root
->
root_item
,
btrfs_header_level
(
extent_root
->
node
));
ret
=
btrfs_update_root
(
trans
,
tree_root
,
&
extent_root
->
root_key
,
&
extent_root
->
root_item
);
...
...
@@ -284,8 +285,8 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
(
unsigned
long
)
root
->
root_key
.
objectid
,
BTRFS_ROOT_TRANS_TAG
);
if
(
root
->
commit_root
==
root
->
node
)
{
WARN_ON
(
extent_buffer_blocknr
(
root
->
node
)
!=
btrfs_root_b
lock
nr
(
&
root
->
root_item
));
WARN_ON
(
root
->
node
->
start
!=
btrfs_root_b
yte
nr
(
&
root
->
root_item
));
free_extent_buffer
(
root
->
commit_root
);
root
->
commit_root
=
NULL
;
...
...
@@ -314,8 +315,10 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
root
->
commit_root
=
NULL
;
root
->
root_key
.
offset
=
root
->
fs_info
->
generation
;
btrfs_set_root_blocknr
(
&
root
->
root_item
,
extent_buffer_blocknr
(
root
->
node
));
btrfs_set_root_bytenr
(
&
root
->
root_item
,
root
->
node
->
start
);
btrfs_set_root_level
(
&
root
->
root_item
,
btrfs_header_level
(
root
->
node
));
err
=
btrfs_insert_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
root
->
root_key
,
&
root
->
root_item
);
...
...
@@ -407,8 +410,8 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
struct
dirty_root
*
dirty
;
struct
btrfs_trans_handle
*
trans
;
unsigned
long
nr
;
u64
num_b
lock
s
;
u64
b
lock
s_used
;
u64
num_b
yte
s
;
u64
b
yte
s_used
;
int
ret
=
0
;
int
err
;
...
...
@@ -419,7 +422,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
dirty
=
list_entry
(
list
->
next
,
struct
dirty_root
,
list
);
list_del_init
(
&
dirty
->
list
);
num_b
lock
s
=
btrfs_root_used
(
&
dirty
->
root
->
root_item
);
num_b
yte
s
=
btrfs_root_used
(
&
dirty
->
root
->
root_item
);
root
=
dirty
->
latest_root
;
while
(
1
)
{
...
...
@@ -446,12 +449,12 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
}
BUG_ON
(
ret
);
num_b
lock
s
-=
btrfs_root_used
(
&
dirty
->
root
->
root_item
);
b
lock
s_used
=
btrfs_root_used
(
&
root
->
root_item
);
if
(
num_b
lock
s
)
{
num_b
yte
s
-=
btrfs_root_used
(
&
dirty
->
root
->
root_item
);
b
yte
s_used
=
btrfs_root_used
(
&
root
->
root_item
);
if
(
num_b
yte
s
)
{
record_root_in_trans
(
root
);
btrfs_set_root_used
(
&
root
->
root_item
,
blocks_used
-
num_block
s
);
bytes_used
-
num_byte
s
);
}
ret
=
btrfs_del_root
(
trans
,
tree_root
,
&
dirty
->
root
->
root_key
);
if
(
ret
)
{
...
...
@@ -560,7 +563,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
btrfs_set_super_generation
(
&
root
->
fs_info
->
super_copy
,
cur_trans
->
transid
);
btrfs_set_super_root
(
&
root
->
fs_info
->
super_copy
,
extent_buffer_blocknr
(
root
->
fs_info
->
tree_root
->
node
));
root
->
fs_info
->
tree_root
->
node
->
start
);
btrfs_set_super_root_level
(
&
root
->
fs_info
->
super_copy
,
btrfs_header_level
(
root
->
fs_info
->
tree_root
->
node
));
write_extent_buffer
(
root
->
fs_info
->
sb_buffer
,
&
root
->
fs_info
->
super_copy
,
0
,
...
...
fs/btrfs/tree-defrag.c
浏览文件 @
db94535d
...
...
@@ -27,13 +27,15 @@ static void reada_defrag(struct btrfs_root *root,
{
int
i
;
u32
nritems
;
u64
blocknr
;
u64
bytenr
;
u32
blocksize
;
int
ret
;
blocksize
=
btrfs_level_size
(
root
,
btrfs_header_level
(
node
)
-
1
);
nritems
=
btrfs_header_nritems
(
node
);
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
b
lock
nr
=
btrfs_node_blockptr
(
node
,
i
);
ret
=
readahead_tree_block
(
root
,
b
locknr
);
b
yte
nr
=
btrfs_node_blockptr
(
node
,
i
);
ret
=
readahead_tree_block
(
root
,
b
ytenr
,
blocksize
);
if
(
ret
)
break
;
}
...
...
@@ -46,7 +48,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
{
struct
extent_buffer
*
next
;
struct
extent_buffer
*
cur
;
u64
b
lock
nr
;
u64
b
yte
nr
;
int
ret
=
0
;
int
is_extent
=
0
;
...
...
@@ -80,10 +82,11 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
break
;
}
b
lock
nr
=
btrfs_node_blockptr
(
cur
,
path
->
slots
[
*
level
]);
b
yte
nr
=
btrfs_node_blockptr
(
cur
,
path
->
slots
[
*
level
]);
if
(
cache_only
)
{
next
=
btrfs_find_tree_block
(
root
,
blocknr
);
next
=
btrfs_find_tree_block
(
root
,
bytenr
,
btrfs_level_size
(
root
,
*
level
-
1
));
/* FIXME, test for defrag */
if
(
!
next
||
!
btrfs_buffer_uptodate
(
next
))
{
free_extent_buffer
(
next
);
...
...
@@ -91,7 +94,8 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
continue
;
}
}
else
{
next
=
read_tree_block
(
root
,
blocknr
);
next
=
read_tree_block
(
root
,
bytenr
,
btrfs_level_size
(
root
,
*
level
-
1
));
}
ret
=
btrfs_cow_block
(
trans
,
root
,
next
,
path
->
nodes
[
*
level
],
path
->
slots
[
*
level
],
&
next
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录