Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xiphi1978
linux
提交
be744175
L
linux
项目概览
xiphi1978
/
linux
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
be744175
编写于
5月 06, 2007
作者:
C
Chris Mason
提交者:
David Woodhouse
5月 06, 2007
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Btrfs: more allocator enhancements
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
be08c1b9
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
249 addition
and
85 deletion
+249
-85
fs/btrfs/bit-radix.c
fs/btrfs/bit-radix.c
+4
-2
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+5
-2
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+1
-1
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+238
-79
fs/btrfs/super.c
fs/btrfs/super.c
+1
-1
未找到文件。
fs/btrfs/bit-radix.c
浏览文件 @
be744175
...
@@ -26,8 +26,10 @@ int set_radix_bit(struct radix_tree_root *radix, unsigned long bit)
...
@@ -26,8 +26,10 @@ int set_radix_bit(struct radix_tree_root *radix, unsigned long bit)
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
}
}
set_bit
(
bit_slot
,
bits
+
1
);
ret
=
test_and_set_bit
(
bit_slot
,
bits
+
1
);
return
0
;
if
(
ret
<
0
)
ret
=
1
;
return
ret
;
}
}
int
test_radix_bit
(
struct
radix_tree_root
*
radix
,
unsigned
long
bit
)
int
test_radix_bit
(
struct
radix_tree_root
*
radix
,
unsigned
long
bit
)
...
...
fs/btrfs/ctree.h
浏览文件 @
be744175
...
@@ -257,6 +257,8 @@ struct btrfs_block_group_cache {
...
@@ -257,6 +257,8 @@ struct btrfs_block_group_cache {
struct
btrfs_block_group_item
item
;
struct
btrfs_block_group_item
item
;
u64
first_free
;
u64
first_free
;
u64
last_alloc
;
u64
last_alloc
;
u64
pinned
;
int
data
;
};
};
struct
crypto_hash
;
struct
crypto_hash
;
...
@@ -264,12 +266,12 @@ struct btrfs_fs_info {
...
@@ -264,12 +266,12 @@ struct btrfs_fs_info {
struct
btrfs_root
*
extent_root
;
struct
btrfs_root
*
extent_root
;
struct
btrfs_root
*
tree_root
;
struct
btrfs_root
*
tree_root
;
struct
btrfs_root
*
dev_root
;
struct
btrfs_root
*
dev_root
;
struct
btrfs_block_group_cache
*
block_group_cache
;
struct
radix_tree_root
fs_roots_radix
;
struct
radix_tree_root
fs_roots_radix
;
struct
radix_tree_root
pending_del_radix
;
struct
radix_tree_root
pending_del_radix
;
struct
radix_tree_root
pinned_radix
;
struct
radix_tree_root
pinned_radix
;
struct
radix_tree_root
dev_radix
;
struct
radix_tree_root
dev_radix
;
struct
radix_tree_root
block_group_radix
;
struct
radix_tree_root
block_group_radix
;
struct
radix_tree_root
block_group_data_radix
;
u64
extent_tree_insert
[
BTRFS_MAX_LEVEL
*
3
];
u64
extent_tree_insert
[
BTRFS_MAX_LEVEL
*
3
];
int
extent_tree_insert_nr
;
int
extent_tree_insert_nr
;
...
@@ -1072,7 +1074,8 @@ static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh)
...
@@ -1072,7 +1074,8 @@ static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh)
/* extent-tree.c */
/* extent-tree.c */
struct
btrfs_block_group_cache
*
btrfs_find_block_group
(
struct
btrfs_root
*
root
,
struct
btrfs_block_group_cache
*
btrfs_find_block_group
(
struct
btrfs_root
*
root
,
struct
btrfs_block_group_cache
struct
btrfs_block_group_cache
*
hint
,
int
data
);
*
hint
,
u64
search_start
,
int
data
);
int
btrfs_inc_root_ref
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_inc_root_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
struct
btrfs_root
*
root
);
struct
buffer_head
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
buffer_head
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
...
...
fs/btrfs/disk-io.c
浏览文件 @
be744175
...
@@ -554,6 +554,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
...
@@ -554,6 +554,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
INIT_RADIX_TREE
(
&
fs_info
->
fs_roots_radix
,
GFP_NOFS
);
INIT_RADIX_TREE
(
&
fs_info
->
fs_roots_radix
,
GFP_NOFS
);
INIT_RADIX_TREE
(
&
fs_info
->
dev_radix
,
GFP_NOFS
);
INIT_RADIX_TREE
(
&
fs_info
->
dev_radix
,
GFP_NOFS
);
INIT_RADIX_TREE
(
&
fs_info
->
block_group_radix
,
GFP_KERNEL
);
INIT_RADIX_TREE
(
&
fs_info
->
block_group_radix
,
GFP_KERNEL
);
INIT_RADIX_TREE
(
&
fs_info
->
block_group_data_radix
,
GFP_KERNEL
);
INIT_LIST_HEAD
(
&
fs_info
->
trans_list
);
INIT_LIST_HEAD
(
&
fs_info
->
trans_list
);
sb_set_blocksize
(
sb
,
4096
);
sb_set_blocksize
(
sb
,
4096
);
fs_info
->
running_transaction
=
NULL
;
fs_info
->
running_transaction
=
NULL
;
...
@@ -582,7 +583,6 @@ struct btrfs_root *open_ctree(struct super_block *sb)
...
@@ -582,7 +583,6 @@ struct btrfs_root *open_ctree(struct super_block *sb)
}
}
mutex_init
(
&
fs_info
->
trans_mutex
);
mutex_init
(
&
fs_info
->
trans_mutex
);
mutex_init
(
&
fs_info
->
fs_mutex
);
mutex_init
(
&
fs_info
->
fs_mutex
);
fs_info
->
block_group_cache
=
NULL
;
__setup_root
(
sb
->
s_blocksize
,
dev_root
,
__setup_root
(
sb
->
s_blocksize
,
dev_root
,
fs_info
,
BTRFS_DEV_TREE_OBJECTID
);
fs_info
,
BTRFS_DEV_TREE_OBJECTID
);
...
...
fs/btrfs/extent-tree.c
浏览文件 @
be744175
...
@@ -12,36 +12,88 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
...
@@ -12,36 +12,88 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
static
int
del_pending_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
static
int
del_pending_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
);
btrfs_root
*
extent_root
);
static
struct
btrfs_block_group_cache
*
lookup_block_group
(
struct
btrfs_fs_info
*
info
,
u64
blocknr
)
{
struct
btrfs_block_group_cache
*
block_group
;
int
ret
;
ret
=
radix_tree_gang_lookup
(
&
info
->
block_group_radix
,
(
void
**
)
&
block_group
,
blocknr
,
1
);
if
(
ret
)
{
if
(
block_group
->
key
.
objectid
<=
blocknr
&&
blocknr
<
block_group
->
key
.
objectid
+
block_group
->
key
.
offset
)
return
block_group
;
}
ret
=
radix_tree_gang_lookup
(
&
info
->
block_group_data_radix
,
(
void
**
)
&
block_group
,
blocknr
,
1
);
if
(
ret
)
{
if
(
block_group
->
key
.
objectid
<=
blocknr
&&
blocknr
<
block_group
->
key
.
objectid
+
block_group
->
key
.
offset
)
return
block_group
;
}
printk
(
"lookup_block_group fails for blocknr %Lu
\n
"
,
blocknr
);
return
NULL
;
}
struct
btrfs_block_group_cache
*
btrfs_find_block_group
(
struct
btrfs_root
*
root
,
struct
btrfs_block_group_cache
*
btrfs_find_block_group
(
struct
btrfs_root
*
root
,
struct
btrfs_block_group_cache
struct
btrfs_block_group_cache
*
hint
,
int
data
)
*
hint
,
u64
search_start
,
int
data
)
{
{
struct
btrfs_block_group_cache
*
cache
[
8
];
struct
btrfs_block_group_cache
*
cache
[
8
];
struct
btrfs_block_group_cache
*
found_group
=
NULL
;
struct
btrfs_block_group_cache
*
found_group
=
NULL
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
struct
radix_tree_root
*
radix
;
u64
used
;
u64
used
;
u64
last
=
0
;
u64
last
=
0
;
u64
hint_last
;
u64
hint_last
;
int
i
;
int
i
;
int
ret
;
int
ret
;
int
full_search
=
0
;
int
full_search
=
0
;
if
(
!
data
&&
hint
)
{
if
(
data
)
radix
=
&
info
->
block_group_data_radix
;
else
radix
=
&
info
->
block_group_radix
;
if
(
search_start
)
{
struct
btrfs_block_group_cache
*
shint
;
shint
=
lookup_block_group
(
info
,
search_start
);
if
(
shint
->
data
==
data
)
{
used
=
btrfs_block_group_used
(
&
shint
->
item
);
if
(
used
+
shint
->
pinned
<
(
shint
->
key
.
offset
*
8
)
/
10
)
{
return
shint
;
}
}
}
if
(
hint
&&
hint
->
data
==
data
)
{
used
=
btrfs_block_group_used
(
&
hint
->
item
);
used
=
btrfs_block_group_used
(
&
hint
->
item
);
if
(
used
<
(
hint
->
key
.
offset
*
2
)
/
3
)
{
if
(
used
+
hint
->
pinned
<
(
hint
->
key
.
offset
*
8
)
/
10
)
{
return
hint
;
return
hint
;
}
}
radix_tree_tag_clear
(
&
info
->
block_group_radix
,
if
(
used
>=
(
hint
->
key
.
offset
*
8
)
/
10
)
{
hint
->
key
.
objectid
+
hint
->
key
.
offset
-
1
,
radix_tree_tag_clear
(
radix
,
BTRFS_BLOCK_GROUP_AVAIL
);
hint
->
key
.
objectid
+
last
=
hint
->
key
.
objectid
+
hint
->
key
.
offset
;
hint
->
key
.
offset
-
1
,
BTRFS_BLOCK_GROUP_AVAIL
);
}
last
=
hint
->
key
.
offset
*
2
;
if
(
hint
->
key
.
objectid
>=
last
)
last
=
max
(
search_start
,
hint
->
key
.
objectid
-
last
);
else
last
=
hint
->
key
.
objectid
+
hint
->
key
.
offset
;
hint_last
=
last
;
hint_last
=
last
;
}
else
{
}
else
{
hint_last
=
0
;
hint_last
=
search_start
;
last
=
0
;
last
=
search_start
;
}
}
while
(
1
)
{
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
info
->
block_group_radix
,
ret
=
radix_tree_gang_lookup_tag
(
radix
,
(
void
**
)
cache
,
(
void
**
)
cache
,
last
,
ARRAY_SIZE
(
cache
),
last
,
ARRAY_SIZE
(
cache
),
BTRFS_BLOCK_GROUP_AVAIL
);
BTRFS_BLOCK_GROUP_AVAIL
);
if
(
!
ret
)
if
(
!
ret
)
...
@@ -49,65 +101,54 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
...
@@ -49,65 +101,54 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
last
=
cache
[
i
]
->
key
.
objectid
+
last
=
cache
[
i
]
->
key
.
objectid
+
cache
[
i
]
->
key
.
offset
;
cache
[
i
]
->
key
.
offset
;
if
(
!
full_search
&&
!
data
&&
(
cache
[
i
]
->
key
.
objectid
&
cache
[
i
]
->
key
.
offset
))
continue
;
if
(
!
full_search
&&
data
&&
(
cache
[
i
]
->
key
.
objectid
&
cache
[
i
]
->
key
.
offset
)
==
0
)
continue
;
used
=
btrfs_block_group_used
(
&
cache
[
i
]
->
item
);
used
=
btrfs_block_group_used
(
&
cache
[
i
]
->
item
);
if
(
used
<
(
cache
[
i
]
->
key
.
offset
*
2
)
/
3
)
{
if
(
used
+
cache
[
i
]
->
pinned
<
info
->
block_group_cache
=
cache
[
i
];
(
cache
[
i
]
->
key
.
offset
*
8
)
/
10
)
{
found_group
=
cache
[
i
];
found_group
=
cache
[
i
];
goto
found
;
goto
found
;
}
}
radix_tree_tag_clear
(
&
info
->
block_group_radix
,
if
(
used
>=
(
cache
[
i
]
->
key
.
offset
*
8
)
/
10
)
{
cache
[
i
]
->
key
.
objectid
+
radix_tree_tag_clear
(
radix
,
cache
[
i
]
->
key
.
offset
-
1
,
cache
[
i
]
->
key
.
objectid
+
BTRFS_BLOCK_GROUP_AVAIL
);
cache
[
i
]
->
key
.
offset
-
1
,
BTRFS_BLOCK_GROUP_AVAIL
);
}
}
}
}
}
last
=
hint_last
;
last
=
hint_last
;
again:
again:
while
(
1
)
{
while
(
1
)
{
ret
=
radix_tree_gang_lookup
(
&
info
->
block_group_radix
,
ret
=
radix_tree_gang_lookup
(
radix
,
(
void
**
)
cache
,
(
void
**
)
cache
,
last
,
ARRAY_SIZE
(
cache
));
last
,
ARRAY_SIZE
(
cache
));
if
(
!
ret
)
if
(
!
ret
)
break
;
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
last
=
cache
[
i
]
->
key
.
objectid
+
last
=
cache
[
i
]
->
key
.
objectid
+
cache
[
i
]
->
key
.
offset
;
cache
[
i
]
->
key
.
offset
;
if
(
!
full_search
&&
!
data
&&
(
cache
[
i
]
->
key
.
objectid
&
cache
[
i
]
->
key
.
offset
))
continue
;
if
(
!
full_search
&&
data
&&
(
cache
[
i
]
->
key
.
objectid
&
cache
[
i
]
->
key
.
offset
)
==
0
)
continue
;
used
=
btrfs_block_group_used
(
&
cache
[
i
]
->
item
);
used
=
btrfs_block_group_used
(
&
cache
[
i
]
->
item
);
if
(
used
<
cache
[
i
]
->
key
.
offset
)
{
if
(
used
+
cache
[
i
]
->
pinned
<
cache
[
i
]
->
key
.
offset
)
{
info
->
block_group_cache
=
cache
[
i
];
found_group
=
cache
[
i
];
found_group
=
cache
[
i
];
goto
found
;
goto
found
;
}
}
radix_tree_tag_clear
(
&
info
->
block_group_radix
,
if
(
used
>=
cache
[
i
]
->
key
.
offset
)
{
cache
[
i
]
->
key
.
objectid
+
radix_tree_tag_clear
(
radix
,
cache
[
i
]
->
key
.
offset
-
1
,
cache
[
i
]
->
key
.
objectid
+
BTRFS_BLOCK_GROUP_AVAIL
);
cache
[
i
]
->
key
.
offset
-
1
,
BTRFS_BLOCK_GROUP_AVAIL
);
}
}
}
}
}
info
->
block_group_cache
=
NULL
;
if
(
!
full_search
)
{
if
(
!
full_search
)
{
last
=
0
;
last
=
search_start
;
full_search
=
1
;
full_search
=
1
;
goto
again
;
goto
again
;
}
}
found:
if
(
!
found_group
)
{
if
(
!
found_group
)
{
ret
=
radix_tree_gang_lookup
(
&
info
->
block_group_
radix
,
ret
=
radix_tree_gang_lookup
(
radix
,
(
void
**
)
&
found_group
,
0
,
1
);
(
void
**
)
&
found_group
,
0
,
1
);
BUG_ON
(
ret
!=
1
);
BUG_ON
(
ret
!=
1
);
}
}
found:
return
found_group
;
return
found_group
;
}
}
...
@@ -252,18 +293,20 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
...
@@ -252,18 +293,20 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
return
ret
;
return
ret
;
if
(
pending_ret
)
if
(
pending_ret
)
return
pending_ret
;
return
pending_ret
;
if
(
cache
->
data
)
cache
->
last_alloc
=
cache
->
first_free
;
return
0
;
return
0
;
}
}
int
btrfs_write_dirty_block_groups
(
struct
btrfs_trans_handle
*
trans
,
static
int
write_dirty_block_radix
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
struct
btrfs_root
*
root
,
struct
radix_tree_root
*
radix
)
{
{
struct
btrfs_block_group_cache
*
cache
[
8
];
struct
btrfs_block_group_cache
*
cache
[
8
];
int
ret
;
int
ret
;
int
err
=
0
;
int
err
=
0
;
int
werr
=
0
;
int
werr
=
0
;
struct
radix_tree_root
*
radix
=
&
root
->
fs_info
->
block_group_radix
;
int
i
;
int
i
;
struct
btrfs_path
*
path
;
struct
btrfs_path
*
path
;
...
@@ -285,35 +328,74 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
...
@@ -285,35 +328,74 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
path
,
cache
[
i
]);
path
,
cache
[
i
]);
if
(
err
)
if
(
err
)
werr
=
err
;
werr
=
err
;
cache
[
i
]
->
last_alloc
=
cache
[
i
]
->
first_free
;
}
}
}
}
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
return
werr
;
return
werr
;
}
}
int
btrfs_write_dirty_block_groups
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
int
ret
;
int
ret2
;
ret
=
write_dirty_block_radix
(
trans
,
root
,
&
root
->
fs_info
->
block_group_radix
);
ret2
=
write_dirty_block_radix
(
trans
,
root
,
&
root
->
fs_info
->
block_group_data_radix
);
if
(
ret
)
return
ret
;
if
(
ret2
)
return
ret2
;
return
0
;
}
static
int
update_block_group
(
struct
btrfs_trans_handle
*
trans
,
static
int
update_block_group
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num
,
int
alloc
)
u64
blocknr
,
u64
num
,
int
alloc
)
{
{
struct
btrfs_block_group_cache
*
cache
;
struct
btrfs_block_group_cache
*
cache
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
struct
radix_tree_root
*
radix
;
u64
total
=
num
;
u64
total
=
num
;
u64
old_val
;
u64
old_val
;
u64
block_in_group
;
u64
block_in_group
;
int
ret
;
int
ret
;
if
(
num
!=
1
)
radix
=
&
info
->
block_group_data_radix
;
else
radix
=
&
info
->
block_group_radix
;
while
(
total
)
{
while
(
total
)
{
ret
=
radix_tree_gang_lookup
(
&
info
->
block_group_radix
,
ret
=
radix_tree_gang_lookup
(
radix
,
(
void
**
)
&
cache
,
(
void
**
)
&
cache
,
blocknr
,
1
);
blocknr
,
1
);
if
(
!
ret
)
{
if
(
!
ret
)
{
printk
(
KERN_CRIT
"blocknr %Lu lookup failed
\n
"
,
printk
(
KERN_CRIT
"blocknr %Lu lookup failed
\n
"
,
blocknr
);
blocknr
);
return
-
1
;
return
-
1
;
}
}
block_in_group
=
blocknr
-
cache
->
key
.
objectid
;
block_in_group
=
blocknr
-
cache
->
key
.
objectid
;
if
(
block_in_group
>
cache
->
key
.
offset
||
cache
->
key
.
objectid
>
blocknr
)
{
if
(
radix
==
&
info
->
block_group_data_radix
)
radix
=
&
info
->
block_group_radix
;
else
radix
=
&
info
->
block_group_data_radix
;
ret
=
radix_tree_gang_lookup
(
radix
,
(
void
**
)
&
cache
,
blocknr
,
1
);
if
(
!
ret
)
{
printk
(
KERN_CRIT
"blocknr %Lu lookup failed
\n
"
,
blocknr
);
return
-
1
;
}
block_in_group
=
blocknr
-
cache
->
key
.
objectid
;
if
(
block_in_group
>
cache
->
key
.
offset
||
cache
->
key
.
objectid
>
blocknr
)
{
BUG
();
}
}
WARN_ON
(
block_in_group
>
cache
->
key
.
offset
);
WARN_ON
(
block_in_group
>
cache
->
key
.
offset
);
radix_tree_tag_set
(
&
info
->
block_group_radix
,
radix_tree_tag_set
(
radix
,
cache
->
key
.
objectid
+
cache
->
key
.
o
bjectid
+
cache
->
key
.
o
ffset
-
1
,
cache
->
key
.
offset
-
1
,
BTRFS_BLOCK_GROUP_DIRTY
);
BTRFS_BLOCK_GROUP_DIRTY
);
old_val
=
btrfs_block_group_used
(
&
cache
->
item
);
old_val
=
btrfs_block_group_used
(
&
cache
->
item
);
...
@@ -346,6 +428,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
...
@@ -346,6 +428,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
{
{
unsigned
long
gang
[
8
];
unsigned
long
gang
[
8
];
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
btrfs_block_group_cache
*
block_group
;
u64
first
=
0
;
u64
first
=
0
;
int
ret
;
int
ret
;
int
i
;
int
i
;
...
@@ -360,6 +443,14 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
...
@@ -360,6 +443,14 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
first
=
gang
[
0
];
first
=
gang
[
0
];
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
clear_radix_bit
(
pinned_radix
,
gang
[
i
]);
clear_radix_bit
(
pinned_radix
,
gang
[
i
]);
block_group
=
lookup_block_group
(
root
->
fs_info
,
gang
[
i
]);
if
(
block_group
)
{
WARN_ON
(
block_group
->
pinned
==
0
);
block_group
->
pinned
--
;
if
(
gang
[
i
]
<
block_group
->
last_alloc
)
block_group
->
last_alloc
=
gang
[
i
];
}
try_remove_page
(
btree_inode
->
i_mapping
,
try_remove_page
(
btree_inode
->
i_mapping
,
gang
[
i
]
<<
(
PAGE_CACHE_SHIFT
-
gang
[
i
]
<<
(
PAGE_CACHE_SHIFT
-
btree_inode
->
i_blkbits
));
btree_inode
->
i_blkbits
));
...
@@ -420,10 +511,16 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
...
@@ -420,10 +511,16 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
btrfs_block_release
(
root
,
bh
);
btrfs_block_release
(
root
,
bh
);
}
}
err
=
set_radix_bit
(
&
root
->
fs_info
->
pinned_radix
,
blocknr
);
err
=
set_radix_bit
(
&
root
->
fs_info
->
pinned_radix
,
blocknr
);
if
(
!
err
)
{
struct
btrfs_block_group_cache
*
cache
;
cache
=
lookup_block_group
(
root
->
fs_info
,
blocknr
);
if
(
cache
)
cache
->
pinned
++
;
}
}
else
{
}
else
{
err
=
set_radix_bit
(
&
root
->
fs_info
->
pending_del_radix
,
blocknr
);
err
=
set_radix_bit
(
&
root
->
fs_info
->
pending_del_radix
,
blocknr
);
}
}
BUG_ON
(
err
);
BUG_ON
(
err
<
0
);
return
0
;
return
0
;
}
}
...
@@ -502,6 +599,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
...
@@ -502,6 +599,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
int
i
;
int
i
;
struct
radix_tree_root
*
pending_radix
;
struct
radix_tree_root
*
pending_radix
;
struct
radix_tree_root
*
pinned_radix
;
struct
radix_tree_root
*
pinned_radix
;
struct
btrfs_block_group_cache
*
cache
;
pending_radix
=
&
extent_root
->
fs_info
->
pending_del_radix
;
pending_radix
=
&
extent_root
->
fs_info
->
pending_del_radix
;
pinned_radix
=
&
extent_root
->
fs_info
->
pinned_radix
;
pinned_radix
=
&
extent_root
->
fs_info
->
pinned_radix
;
...
@@ -513,7 +611,17 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
...
@@ -513,7 +611,17 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
break
;
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
wret
=
set_radix_bit
(
pinned_radix
,
gang
[
i
]);
wret
=
set_radix_bit
(
pinned_radix
,
gang
[
i
]);
BUG_ON
(
wret
);
if
(
wret
==
0
)
{
cache
=
lookup_block_group
(
extent_root
->
fs_info
,
gang
[
i
]);
if
(
cache
)
cache
->
pinned
++
;
}
if
(
wret
<
0
)
{
printk
(
KERN_CRIT
"set_radix_bit, err %d
\n
"
,
wret
);
BUG_ON
(
wret
<
0
);
}
wret
=
clear_radix_bit
(
pending_radix
,
gang
[
i
]);
wret
=
clear_radix_bit
(
pending_radix
,
gang
[
i
]);
BUG_ON
(
wret
);
BUG_ON
(
wret
);
wret
=
__free_extent
(
trans
,
extent_root
,
wret
=
__free_extent
(
trans
,
extent_root
,
...
@@ -563,6 +671,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -563,6 +671,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
int
slot
=
0
;
int
slot
=
0
;
u64
last_block
=
0
;
u64
last_block
=
0
;
u64
test_block
;
u64
test_block
;
u64
orig_search_start
=
search_start
;
int
start_found
;
int
start_found
;
struct
btrfs_leaf
*
l
;
struct
btrfs_leaf
*
l
;
struct
btrfs_root
*
root
=
orig_root
->
fs_info
->
extent_root
;
struct
btrfs_root
*
root
=
orig_root
->
fs_info
->
extent_root
;
...
@@ -572,6 +681,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -572,6 +681,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
int
fill_prealloc
=
0
;
int
fill_prealloc
=
0
;
int
level
;
int
level
;
struct
btrfs_block_group_cache
*
block_group
;
struct
btrfs_block_group_cache
*
block_group
;
int
full_scan
=
0
;
path
=
btrfs_alloc_path
();
path
=
btrfs_alloc_path
();
ins
->
flags
=
0
;
ins
->
flags
=
0
;
...
@@ -583,10 +693,21 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -583,10 +693,21 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
num_blocks
=
1
;
num_blocks
=
1
;
total_needed
=
(
min
(
level
+
1
,
BTRFS_MAX_LEVEL
)
+
2
)
*
3
;
total_needed
=
(
min
(
level
+
1
,
BTRFS_MAX_LEVEL
)
+
2
)
*
3
;
}
}
block_group
=
btrfs_find_block_group
(
root
,
trans
->
block_group
,
data
);
if
(
search_start
)
{
block_group
=
lookup_block_group
(
info
,
search_start
);
block_group
=
btrfs_find_block_group
(
root
,
block_group
,
search_start
,
data
);
}
else
{
block_group
=
btrfs_find_block_group
(
root
,
trans
->
block_group
,
0
,
data
);
}
check_failed:
if
(
block_group
->
data
!=
data
)
WARN_ON
(
1
);
if
(
block_group
->
last_alloc
>
search_start
)
if
(
block_group
->
last_alloc
>
search_start
)
search_start
=
block_group
->
last_alloc
;
search_start
=
block_group
->
last_alloc
;
check_failed:
btrfs_init_path
(
path
);
btrfs_init_path
(
path
);
ins
->
objectid
=
search_start
;
ins
->
objectid
=
search_start
;
ins
->
offset
=
0
;
ins
->
offset
=
0
;
...
@@ -639,6 +760,13 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -639,6 +760,13 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
}
}
start_found
=
1
;
start_found
=
1
;
last_block
=
key
.
objectid
+
key
.
offset
;
last_block
=
key
.
objectid
+
key
.
offset
;
if
(
last_block
>=
block_group
->
key
.
objectid
+
block_group
->
key
.
offset
)
{
btrfs_release_path
(
root
,
path
);
search_start
=
block_group
->
key
.
objectid
+
block_group
->
key
.
offset
*
2
;
goto
new_group
;
}
next:
next:
path
->
slots
[
0
]
++
;
path
->
slots
[
0
]
++
;
}
}
...
@@ -650,16 +778,17 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -650,16 +778,17 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_release_path
(
root
,
path
);
btrfs_release_path
(
root
,
path
);
BUG_ON
(
ins
->
objectid
<
search_start
);
BUG_ON
(
ins
->
objectid
<
search_start
);
if
(
ins
->
objectid
>=
btrfs_super_total_blocks
(
info
->
disk_super
))
{
if
(
ins
->
objectid
>=
btrfs_super_total_blocks
(
info
->
disk_super
))
{
if
(
search_start
==
0
)
if
(
full_scan
)
return
-
ENOSPC
;
return
-
ENOSPC
;
search_start
=
0
;
search_start
=
orig_search_start
;
goto
check_failed
;
full_scan
=
1
;
goto
new_group
;
}
}
for
(
test_block
=
ins
->
objectid
;
for
(
test_block
=
ins
->
objectid
;
test_block
<
ins
->
objectid
+
num_blocks
;
test_block
++
)
{
test_block
<
ins
->
objectid
+
num_blocks
;
test_block
++
)
{
if
(
test_radix_bit
(
&
info
->
pinned_radix
,
test_block
))
{
if
(
test_radix_bit
(
&
info
->
pinned_radix
,
test_block
))
{
search_start
=
test_block
+
1
;
search_start
=
test_block
+
1
;
goto
check_failed
;
goto
new_group
;
}
}
}
}
if
(
!
fill_prealloc
&&
info
->
extent_tree_insert_nr
)
{
if
(
!
fill_prealloc
&&
info
->
extent_tree_insert_nr
)
{
...
@@ -670,7 +799,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -670,7 +799,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
ins
->
objectid
<=
last
)
{
ins
->
objectid
<=
last
)
{
search_start
=
last
+
1
;
search_start
=
last
+
1
;
WARN_ON
(
1
);
WARN_ON
(
1
);
goto
check_failed
;
goto
new_group
;
}
}
}
}
if
(
!
fill_prealloc
&&
info
->
extent_tree_prealloc_nr
)
{
if
(
!
fill_prealloc
&&
info
->
extent_tree_prealloc_nr
)
{
...
@@ -680,7 +809,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -680,7 +809,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
ins
->
objectid
<=
info
->
extent_tree_prealloc
[
0
])
{
ins
->
objectid
<=
info
->
extent_tree_prealloc
[
0
])
{
search_start
=
info
->
extent_tree_prealloc
[
0
]
+
1
;
search_start
=
info
->
extent_tree_prealloc
[
0
]
+
1
;
WARN_ON
(
1
);
WARN_ON
(
1
);
goto
check_failed
;
goto
new_group
;
}
}
}
}
if
(
fill_prealloc
)
{
if
(
fill_prealloc
)
{
...
@@ -696,14 +825,12 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -696,14 +825,12 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
}
}
if
(
total_found
<
total_needed
)
{
if
(
total_found
<
total_needed
)
{
search_start
=
test_block
;
search_start
=
test_block
;
goto
check_failed
;
goto
new_group
;
}
}
info
->
extent_tree_prealloc_nr
=
total_found
;
info
->
extent_tree_prealloc_nr
=
total_found
;
}
}
ret
=
radix_tree_gang_lookup
(
&
info
->
block_group_radix
,
block_group
=
lookup_block_group
(
info
,
ins
->
objectid
);
(
void
**
)
&
block_group
,
if
(
block_group
)
{
ins
->
objectid
,
1
);
if
(
ret
)
{
block_group
->
last_alloc
=
ins
->
objectid
;
block_group
->
last_alloc
=
ins
->
objectid
;
if
(
!
data
)
if
(
!
data
)
trans
->
block_group
=
block_group
;
trans
->
block_group
=
block_group
;
...
@@ -711,6 +838,18 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -711,6 +838,18 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
ins
->
offset
=
num_blocks
;
ins
->
offset
=
num_blocks
;
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
return
0
;
return
0
;
new_group:
if
(
search_start
>=
btrfs_super_total_blocks
(
info
->
disk_super
))
{
search_start
=
orig_search_start
;
full_scan
=
1
;
}
block_group
=
lookup_block_group
(
info
,
search_start
);
if
(
!
full_scan
)
block_group
=
btrfs_find_block_group
(
root
,
block_group
,
search_start
,
data
);
goto
check_failed
;
error:
error:
btrfs_release_path
(
root
,
path
);
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
...
@@ -794,7 +933,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
...
@@ -794,7 +933,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
struct
buffer_head
*
buf
;
struct
buffer_head
*
buf
;
ret
=
btrfs_alloc_extent
(
trans
,
root
,
root
->
root_key
.
objectid
,
ret
=
btrfs_alloc_extent
(
trans
,
root
,
root
->
root_key
.
objectid
,
1
,
0
,
(
unsigned
long
)
-
1
,
&
ins
,
0
);
1
,
hint
,
(
unsigned
long
)
-
1
,
&
ins
,
0
);
if
(
ret
)
{
if
(
ret
)
{
BUG
();
BUG
();
return
NULL
;
return
NULL
;
...
@@ -984,21 +1123,19 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -984,21 +1123,19 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
return
ret
;
return
ret
;
}
}
int
btrfs_free_block_groups
(
struct
btrfs_fs_info
*
info
)
static
int
free_block_group_radix
(
struct
radix_tree_root
*
radix
)
{
{
int
ret
;
int
ret
;
struct
btrfs_block_group_cache
*
cache
[
8
];
struct
btrfs_block_group_cache
*
cache
[
8
];
int
i
;
int
i
;
while
(
1
)
{
while
(
1
)
{
ret
=
radix_tree_gang_lookup
(
&
info
->
block_group_radix
,
ret
=
radix_tree_gang_lookup
(
radix
,
(
void
**
)
cache
,
0
,
(
void
**
)
cache
,
0
,
ARRAY_SIZE
(
cache
));
ARRAY_SIZE
(
cache
));
if
(
!
ret
)
if
(
!
ret
)
break
;
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
radix_tree_delete
(
&
info
->
block_group_radix
,
radix_tree_delete
(
radix
,
cache
[
i
]
->
key
.
objectid
+
cache
[
i
]
->
key
.
objectid
+
cache
[
i
]
->
key
.
offset
-
1
);
cache
[
i
]
->
key
.
offset
-
1
);
kfree
(
cache
[
i
]);
kfree
(
cache
[
i
]);
}
}
...
@@ -1006,6 +1143,20 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
...
@@ -1006,6 +1143,20 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
return
0
;
return
0
;
}
}
int
btrfs_free_block_groups
(
struct
btrfs_fs_info
*
info
)
{
int
ret
;
int
ret2
;
ret
=
free_block_group_radix
(
&
info
->
block_group_radix
);
ret2
=
free_block_group_radix
(
&
info
->
block_group_data_radix
);
if
(
ret
)
return
ret
;
if
(
ret2
)
return
ret2
;
return
0
;
}
int
btrfs_read_block_groups
(
struct
btrfs_root
*
root
)
int
btrfs_read_block_groups
(
struct
btrfs_root
*
root
)
{
{
struct
btrfs_path
*
path
;
struct
btrfs_path
*
path
;
...
@@ -1013,13 +1164,16 @@ int btrfs_read_block_groups(struct btrfs_root *root)
...
@@ -1013,13 +1164,16 @@ int btrfs_read_block_groups(struct btrfs_root *root)
int
err
=
0
;
int
err
=
0
;
struct
btrfs_block_group_item
*
bi
;
struct
btrfs_block_group_item
*
bi
;
struct
btrfs_block_group_cache
*
cache
;
struct
btrfs_block_group_cache
*
cache
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
struct
radix_tree_root
*
radix
;
struct
btrfs_key
key
;
struct
btrfs_key
key
;
struct
btrfs_key
found_key
;
struct
btrfs_key
found_key
;
struct
btrfs_leaf
*
leaf
;
struct
btrfs_leaf
*
leaf
;
u64
group_size_blocks
=
BTRFS_BLOCK_GROUP_SIZE
/
root
->
blocksize
;
u64
group_size_blocks
=
BTRFS_BLOCK_GROUP_SIZE
/
root
->
blocksize
;
u64
used
;
u64
used
;
u64
nr
=
0
;
root
=
root
->
fs_
info
->
extent_root
;
root
=
info
->
extent_root
;
key
.
objectid
=
0
;
key
.
objectid
=
0
;
key
.
offset
=
group_size_blocks
;
key
.
offset
=
group_size_blocks
;
key
.
flags
=
0
;
key
.
flags
=
0
;
...
@@ -1030,7 +1184,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
...
@@ -1030,7 +1184,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
return
-
ENOMEM
;
return
-
ENOMEM
;
while
(
1
)
{
while
(
1
)
{
ret
=
btrfs_search_slot
(
NULL
,
root
->
fs_
info
->
extent_root
,
ret
=
btrfs_search_slot
(
NULL
,
info
->
extent_root
,
&
key
,
path
,
0
,
0
);
&
key
,
path
,
0
,
0
);
if
(
ret
!=
0
)
{
if
(
ret
!=
0
)
{
err
=
ret
;
err
=
ret
;
...
@@ -1050,23 +1204,28 @@ int btrfs_read_block_groups(struct btrfs_root *root)
...
@@ -1050,23 +1204,28 @@ int btrfs_read_block_groups(struct btrfs_root *root)
memcpy
(
&
cache
->
key
,
&
found_key
,
sizeof
(
found_key
));
memcpy
(
&
cache
->
key
,
&
found_key
,
sizeof
(
found_key
));
cache
->
last_alloc
=
cache
->
key
.
objectid
;
cache
->
last_alloc
=
cache
->
key
.
objectid
;
cache
->
first_free
=
cache
->
key
.
objectid
;
cache
->
first_free
=
cache
->
key
.
objectid
;
cache
->
pinned
=
0
;
cache
->
data
=
(
nr
&
1
);
key
.
objectid
=
found_key
.
objectid
+
found_key
.
offset
;
key
.
objectid
=
found_key
.
objectid
+
found_key
.
offset
;
btrfs_release_path
(
root
,
path
);
btrfs_release_path
(
root
,
path
);
ret
=
radix_tree_insert
(
&
root
->
fs_info
->
block_group_radix
,
if
(
nr
&
1
)
found_key
.
objectid
+
radix
=
&
info
->
block_group_data_radix
;
else
radix
=
&
info
->
block_group_radix
;
ret
=
radix_tree_insert
(
radix
,
found_key
.
objectid
+
found_key
.
offset
-
1
,
found_key
.
offset
-
1
,
(
void
*
)
cache
);
(
void
*
)
cache
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
used
=
btrfs_block_group_used
(
bi
);
used
=
btrfs_block_group_used
(
bi
);
if
(
used
<
(
key
.
offset
*
2
)
/
3
)
{
if
(
used
<
(
key
.
offset
*
8
)
/
10
)
{
radix_tree_tag_set
(
&
root
->
fs_info
->
block_group_radix
,
radix_tree_tag_set
(
radix
,
found_key
.
objectid
+
found_key
.
objectid
+
found_key
.
offset
-
1
,
found_key
.
offset
-
1
,
BTRFS_BLOCK_GROUP_AVAIL
);
BTRFS_BLOCK_GROUP_AVAIL
);
}
}
if
(
key
.
objectid
>=
if
(
key
.
objectid
>=
btrfs_super_total_blocks
(
root
->
fs_
info
->
disk_super
))
btrfs_super_total_blocks
(
info
->
disk_super
))
break
;
break
;
nr
++
;
}
}
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
...
...
fs/btrfs/super.c
浏览文件 @
be744175
...
@@ -811,7 +811,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
...
@@ -811,7 +811,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
return
ERR_PTR
(
-
ENOMEM
);
return
ERR_PTR
(
-
ENOMEM
);
BTRFS_I
(
inode
)
->
root
=
root
;
BTRFS_I
(
inode
)
->
root
=
root
;
group
=
btrfs_find_block_group
(
root
,
group
,
0
);
group
=
btrfs_find_block_group
(
root
,
group
,
0
,
0
);
BTRFS_I
(
inode
)
->
block_group
=
group
;
BTRFS_I
(
inode
)
->
block_group
=
group
;
inode
->
i_uid
=
current
->
fsuid
;
inode
->
i_uid
=
current
->
fsuid
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录