Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xiphi1978
linux
提交
e9d0b13b
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,发现更多精彩内容 >>
提交
e9d0b13b
编写于
8月 10, 2007
作者:
C
Chris Mason
提交者:
David Woodhouse
8月 10, 2007
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Btrfs: Btree defrag on the extent-mapping tree as well
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
409eb95d
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
125 addition
and
79 deletion
+125
-79
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+11
-7
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+3
-1
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+27
-1
fs/btrfs/inode.c
fs/btrfs/inode.c
+2
-21
fs/btrfs/super.c
fs/btrfs/super.c
+2
-0
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+49
-42
fs/btrfs/transaction.h
fs/btrfs/transaction.h
+2
-0
fs/btrfs/tree-defrag.c
fs/btrfs/tree-defrag.c
+29
-7
未找到文件。
fs/btrfs/ctree.c
浏览文件 @
e9d0b13b
...
...
@@ -99,7 +99,6 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
ret
)
return
ret
;
}
else
{
WARN_ON
(
!
root
->
ref_cows
);
clean_tree_block
(
trans
,
root
,
buf
);
}
...
...
@@ -162,13 +161,14 @@ static int close_blocks(u64 blocknr, u64 other)
int
btrfs_realloc_node
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
buffer_head
*
parent
,
int
cache_only
)
int
cache_only
,
u64
*
last_ret
)
{
struct
btrfs_node
*
parent_node
;
struct
buffer_head
*
cur_bh
;
struct
buffer_head
*
tmp_bh
;
u64
blocknr
;
u64
search_start
=
0
;
u64
search_start
=
*
last_ret
;
u64
last_block
=
0
;
u64
other
;
u32
parent_nritems
;
int
start_slot
;
...
...
@@ -198,6 +198,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
for
(
i
=
start_slot
;
i
<
end_slot
;
i
++
)
{
int
close
=
1
;
blocknr
=
btrfs_node_blockptr
(
parent_node
,
i
);
if
(
last_block
==
0
)
last_block
=
blocknr
;
if
(
i
>
0
)
{
other
=
btrfs_node_blockptr
(
parent_node
,
i
-
1
);
close
=
close_blocks
(
blocknr
,
other
);
...
...
@@ -206,8 +208,10 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
other
=
btrfs_node_blockptr
(
parent_node
,
i
+
1
);
close
=
close_blocks
(
blocknr
,
other
);
}
if
(
close
)
if
(
close
)
{
last_block
=
blocknr
;
continue
;
}
cur_bh
=
btrfs_find_tree_block
(
root
,
blocknr
);
if
(
!
cur_bh
||
!
buffer_uptodate
(
cur_bh
)
||
...
...
@@ -219,9 +223,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
brelse
(
cur_bh
);
cur_bh
=
read_tree_block
(
root
,
blocknr
);
}
if
(
search_start
==
0
)
{
search_start
=
bh_blocknr
(
cur_bh
)
&
~
((
u64
)
65535
);
}
if
(
search_start
==
0
)
search_start
=
last_block
&
~
((
u64
)
65535
);
err
=
__btrfs_cow_block
(
trans
,
root
,
cur_bh
,
parent
,
i
,
&
tmp_bh
,
search_start
,
min
(
8
,
end_slot
-
i
));
...
...
fs/btrfs/ctree.h
浏览文件 @
e9d0b13b
...
...
@@ -1019,6 +1019,8 @@ static inline void btrfs_memmove(struct btrfs_root *root,
btrfs_item_offset((leaf)->items + (slot))))
/* extent-tree.c */
int
btrfs_extent_post_op
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
int
btrfs_copy_pinned
(
struct
btrfs_root
*
root
,
struct
radix_tree_root
*
copy
);
struct
btrfs_block_group_cache
*
btrfs_lookup_block_group
(
struct
btrfs_fs_info
*
info
,
...
...
@@ -1066,7 +1068,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
ins_len
,
int
cow
);
int
btrfs_realloc_node
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
buffer_head
*
parent
,
int
cache_only
);
int
cache_only
,
u64
*
last_ret
);
void
btrfs_release_path
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
p
);
struct
btrfs_path
*
btrfs_alloc_path
(
void
);
void
btrfs_free_path
(
struct
btrfs_path
*
p
);
...
...
fs/btrfs/extent-tree.c
浏览文件 @
e9d0b13b
...
...
@@ -396,6 +396,14 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
return
0
;
}
int
btrfs_extent_post_op
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
finish_current_insert
(
trans
,
root
->
fs_info
->
extent_root
);
del_pending_extents
(
trans
,
root
->
fs_info
->
extent_root
);
return
0
;
}
static
int
lookup_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
u32
*
refs
)
...
...
@@ -1374,7 +1382,25 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
BUG_ON
(
ret
);
continue
;
}
next
=
read_tree_block
(
root
,
blocknr
);
next
=
btrfs_find_tree_block
(
root
,
blocknr
);
if
(
!
next
||
!
buffer_uptodate
(
next
))
{
brelse
(
next
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
next
=
read_tree_block
(
root
,
blocknr
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
/* we dropped the lock, check one more time */
ret
=
lookup_extent_ref
(
trans
,
root
,
blocknr
,
1
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
!=
1
)
{
path
->
slots
[
*
level
]
++
;
brelse
(
next
);
ret
=
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
1
);
BUG_ON
(
ret
);
continue
;
}
}
WARN_ON
(
*
level
<=
0
);
if
(
path
->
nodes
[
*
level
-
1
])
btrfs_block_release
(
root
,
path
->
nodes
[
*
level
-
1
]);
...
...
fs/btrfs/inode.c
浏览文件 @
e9d0b13b
...
...
@@ -2159,9 +2159,7 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
{
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
struct
btrfs_ioctl_vol_args
vol_args
;
struct
btrfs_trans_handle
*
trans
;
int
ret
=
0
;
int
err
;
struct
btrfs_dir_item
*
di
;
int
namelen
;
struct
btrfs_path
*
path
;
...
...
@@ -2201,25 +2199,8 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
case
BTRFS_IOC_DEFRAG
:
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
memset
(
&
root
->
defrag_progress
,
0
,
sizeof
(
root
->
defrag_progress
));
while
(
1
)
{
root
->
defrag_running
=
1
;
err
=
btrfs_defrag_leaves
(
trans
,
root
,
0
);
btrfs_end_transaction
(
trans
,
root
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
btrfs_btree_balance_dirty
(
root
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
if
(
err
!=
-
EAGAIN
)
break
;
}
root
->
defrag_running
=
0
;
btrfs_end_transaction
(
trans
,
root
);
btrfs_defrag_root
(
root
,
0
);
btrfs_defrag_root
(
root
->
fs_info
->
extent_root
,
0
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
ret
=
0
;
break
;
...
...
fs/btrfs/super.c
浏览文件 @
e9d0b13b
...
...
@@ -121,7 +121,9 @@ static int btrfs_sync_fs(struct super_block *sb, int wait)
filemap_flush
(
root
->
fs_info
->
btree_inode
->
i_mapping
);
return
0
;
}
btrfs_clean_old_snapshots
(
root
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
btrfs_defrag_dirty_roots
(
root
->
fs_info
);
trans
=
btrfs_start_transaction
(
root
,
1
);
ret
=
btrfs_commit_transaction
(
trans
,
root
);
sb
->
s_dirt
=
0
;
...
...
fs/btrfs/transaction.c
浏览文件 @
e9d0b13b
...
...
@@ -317,18 +317,47 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
return
err
;
}
int
btrfs_defrag_root
(
struct
btrfs_root
*
root
,
int
cacheonly
)
{
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
int
ret
;
struct
btrfs_trans_handle
*
trans
;
if
(
root
->
defrag_running
)
return
0
;
trans
=
btrfs_start_transaction
(
root
,
1
);
while
(
1
)
{
root
->
defrag_running
=
1
;
ret
=
btrfs_defrag_leaves
(
trans
,
root
,
cacheonly
);
btrfs_end_transaction
(
trans
,
root
);
mutex_unlock
(
&
info
->
fs_mutex
);
btrfs_btree_balance_dirty
(
root
);
cond_resched
();
mutex_lock
(
&
info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
if
(
ret
!=
-
EAGAIN
)
break
;
}
root
->
defrag_running
=
0
;
radix_tree_tag_clear
(
&
info
->
fs_roots_radix
,
(
unsigned
long
)
root
->
root_key
.
objectid
,
BTRFS_ROOT_DEFRAG_TAG
);
btrfs_end_transaction
(
trans
,
root
);
return
0
;
}
int
btrfs_defrag_dirty_roots
(
struct
btrfs_fs_info
*
info
)
{
struct
btrfs_root
*
gang
[
1
];
struct
btrfs_root
*
root
;
struct
btrfs_root
*
tree_root
=
info
->
tree_root
;
struct
btrfs_trans_handle
*
trans
;
int
i
;
int
ret
;
int
err
=
0
;
u64
last
=
0
;
trans
=
btrfs_start_transaction
(
tree_root
,
1
);
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
info
->
fs_roots_radix
,
(
void
**
)
gang
,
last
,
...
...
@@ -339,37 +368,10 @@ int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info)
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
root
=
gang
[
i
];
last
=
root
->
root_key
.
objectid
+
1
;
radix_tree_tag_clear
(
&
info
->
fs_roots_radix
,
(
unsigned
long
)
root
->
root_key
.
objectid
,
BTRFS_ROOT_DEFRAG_TAG
);
if
(
root
->
defrag_running
)
continue
;
while
(
1
)
{
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
record_root_in_trans
(
root
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
root
->
defrag_running
=
1
;
err
=
btrfs_defrag_leaves
(
trans
,
root
,
1
);
btrfs_end_transaction
(
trans
,
tree_root
);
mutex_unlock
(
&
info
->
fs_mutex
);
btrfs_btree_balance_dirty
(
root
);
cond_resched
();
mutex_lock
(
&
info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
tree_root
,
1
);
if
(
err
!=
-
EAGAIN
)
break
;
}
root
->
defrag_running
=
0
;
radix_tree_tag_clear
(
&
info
->
fs_roots_radix
,
(
unsigned
long
)
root
->
root_key
.
objectid
,
BTRFS_ROOT_DEFRAG_TAG
);
btrfs_defrag_root
(
root
,
1
);
}
}
btrfs_
end_transaction
(
trans
,
tree_root
);
btrfs_
defrag_root
(
info
->
extent_root
,
1
);
return
err
;
}
...
...
@@ -527,6 +529,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
return
ret
;
}
int
btrfs_clean_old_snapshots
(
struct
btrfs_root
*
root
)
{
struct
list_head
dirty_roots
;
INIT_LIST_HEAD
(
&
dirty_roots
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
list_splice_init
(
&
root
->
fs_info
->
dead_roots
,
&
dirty_roots
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
if
(
!
list_empty
(
&
dirty_roots
))
{
drop_dirty_roots
(
root
,
&
dirty_roots
);
}
return
0
;
}
void
btrfs_transaction_cleaner
(
struct
work_struct
*
work
)
{
struct
btrfs_fs_info
*
fs_info
=
container_of
(
work
,
...
...
@@ -536,12 +552,10 @@ void btrfs_transaction_cleaner(struct work_struct *work)
struct
btrfs_root
*
root
=
fs_info
->
tree_root
;
struct
btrfs_transaction
*
cur
;
struct
btrfs_trans_handle
*
trans
;
struct
list_head
dirty_roots
;
unsigned
long
now
;
unsigned
long
delay
=
HZ
*
30
;
int
ret
;
INIT_LIST_HEAD
(
&
dirty_roots
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
cur
=
root
->
fs_info
->
running_transaction
;
...
...
@@ -561,14 +575,7 @@ void btrfs_transaction_cleaner(struct work_struct *work)
ret
=
btrfs_commit_transaction
(
trans
,
root
);
out:
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
list_splice_init
(
&
root
->
fs_info
->
dead_roots
,
&
dirty_roots
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
if
(
!
list_empty
(
&
dirty_roots
))
{
drop_dirty_roots
(
root
,
&
dirty_roots
);
}
btrfs_clean_old_snapshots
(
root
);
btrfs_transaction_queue_work
(
root
,
delay
);
}
...
...
fs/btrfs/transaction.h
浏览文件 @
e9d0b13b
...
...
@@ -73,5 +73,7 @@ void btrfs_init_transaction_sys(void);
void
btrfs_exit_transaction_sys
(
void
);
int
btrfs_add_dead_root
(
struct
btrfs_root
*
root
,
struct
list_head
*
dead_list
);
int
btrfs_defrag_dirty_roots
(
struct
btrfs_fs_info
*
info
);
int
btrfs_defrag_root
(
struct
btrfs_root
*
root
,
int
cacheonly
);
int
btrfs_clean_old_snapshots
(
struct
btrfs_root
*
root
);
#endif
fs/btrfs/tree-defrag.c
浏览文件 @
e9d0b13b
...
...
@@ -42,16 +42,20 @@ static void reada_defrag(struct btrfs_root *root,
static
int
defrag_walk_down
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
*
level
,
int
cache_only
)
int
cache_only
,
u64
*
last_ret
)
{
struct
buffer_head
*
next
;
struct
buffer_head
*
cur
;
u64
blocknr
;
int
ret
=
0
;
int
is_extent
=
0
;
WARN_ON
(
*
level
<
0
);
WARN_ON
(
*
level
>=
BTRFS_MAX_LEVEL
);
if
(
root
->
fs_info
->
extent_root
==
root
)
is_extent
=
1
;
while
(
*
level
>
0
)
{
WARN_ON
(
*
level
<
0
);
WARN_ON
(
*
level
>=
BTRFS_MAX_LEVEL
);
...
...
@@ -70,7 +74,10 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
if
(
*
level
==
1
)
{
ret
=
btrfs_realloc_node
(
trans
,
root
,
path
->
nodes
[
*
level
],
cache_only
);
cache_only
,
last_ret
);
if
(
is_extent
)
btrfs_extent_post_op
(
trans
,
root
);
break
;
}
blocknr
=
btrfs_node_blockptr
(
btrfs_buffer_node
(
cur
),
...
...
@@ -90,8 +97,13 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
ret
=
btrfs_cow_block
(
trans
,
root
,
next
,
path
->
nodes
[
*
level
],
path
->
slots
[
*
level
],
&
next
);
BUG_ON
(
ret
);
ret
=
btrfs_realloc_node
(
trans
,
root
,
next
,
cache_only
);
ret
=
btrfs_realloc_node
(
trans
,
root
,
next
,
cache_only
,
last_ret
);
BUG_ON
(
ret
);
if
(
is_extent
)
btrfs_extent_post_op
(
trans
,
root
);
WARN_ON
(
*
level
<=
0
);
if
(
path
->
nodes
[
*
level
-
1
])
btrfs_block_release
(
root
,
path
->
nodes
[
*
level
-
1
]);
...
...
@@ -148,10 +160,14 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
int
level
;
int
orig_level
;
int
i
;
int
is_extent
=
0
;
u64
last_ret
=
0
;
if
(
root
->
fs_info
->
extent_root
==
root
)
is_extent
=
1
;
if
(
root
->
ref_cows
==
0
)
{
if
(
root
->
ref_cows
==
0
&&
!
is_extent
)
goto
out
;
}
path
=
btrfs_alloc_path
();
if
(
!
path
)
return
-
ENOMEM
;
...
...
@@ -165,16 +181,21 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
get_bh
(
root
->
node
);
ret
=
btrfs_cow_block
(
trans
,
root
,
root
->
node
,
NULL
,
0
,
&
tmp
);
BUG_ON
(
ret
);
ret
=
btrfs_realloc_node
(
trans
,
root
,
root
->
node
,
cache_only
);
ret
=
btrfs_realloc_node
(
trans
,
root
,
root
->
node
,
cache_only
,
&
last_ret
);
BUG_ON
(
ret
);
path
->
nodes
[
level
]
=
root
->
node
;
path
->
slots
[
level
]
=
0
;
if
(
is_extent
)
btrfs_extent_post_op
(
trans
,
root
);
}
else
{
level
=
root
->
defrag_level
;
path
->
lowest_level
=
level
;
wret
=
btrfs_search_slot
(
trans
,
root
,
&
root
->
defrag_progress
,
path
,
0
,
1
);
if
(
is_extent
)
btrfs_extent_post_op
(
trans
,
root
);
if
(
wret
<
0
)
{
ret
=
wret
;
goto
out
;
...
...
@@ -188,7 +209,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
}
while
(
1
)
{
wret
=
defrag_walk_down
(
trans
,
root
,
path
,
&
level
,
cache_only
);
wret
=
defrag_walk_down
(
trans
,
root
,
path
,
&
level
,
cache_only
,
&
last_ret
);
if
(
wret
>
0
)
break
;
if
(
wret
<
0
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录