Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xiphi1978
linux
提交
0f7d52f4
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,发现更多精彩内容 >>
提交
0f7d52f4
编写于
4月 09, 2007
作者:
C
Chris Mason
提交者:
David Woodhouse
4月 09, 2007
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Btrfs: groundwork for subvolume and snapshot roots
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
d6e4a428
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
282 addition
and
99 deletion
+282
-99
fs/btrfs/bit-radix.c
fs/btrfs/bit-radix.c
+1
-1
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+17
-3
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+137
-41
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+2
-0
fs/btrfs/super.c
fs/btrfs/super.c
+22
-17
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+103
-37
未找到文件。
fs/btrfs/bit-radix.c
浏览文件 @
0f7d52f4
...
...
@@ -86,7 +86,7 @@ int find_first_radix_bit(struct radix_tree_root *radix, unsigned long *retbits,
int
i
;
int
total_found
=
0
;
ret
=
radix_tree_gang_lookup
(
radix
,
(
void
*
)
&
gang
,
0
,
ARRAY_SIZE
(
gang
));
ret
=
radix_tree_gang_lookup
(
radix
,
(
void
*
*
)
gang
,
0
,
ARRAY_SIZE
(
gang
));
for
(
i
=
0
;
i
<
ret
&&
nr
>
0
;
i
++
)
{
found
=
0
;
bits
=
gang
[
i
];
...
...
fs/btrfs/ctree.h
浏览文件 @
0f7d52f4
...
...
@@ -232,12 +232,12 @@ struct btrfs_inode_map_item {
struct
crypto_hash
;
struct
btrfs_fs_info
{
struct
btrfs_root
*
fs_root
;
struct
btrfs_root
*
extent_root
;
struct
btrfs_root
*
tree_root
;
struct
btrfs_root
*
inode_root
;
struct
btrfs_key
current_insert
;
struct
btrfs_key
last_insert
;
struct
radix_tree_root
fs_roots_radix
;
struct
radix_tree_root
pending_del_radix
;
struct
radix_tree_root
pinned_radix
;
u64
last_inode_alloc
;
...
...
@@ -266,6 +266,9 @@ struct btrfs_root {
struct
btrfs_root_item
root_item
;
struct
btrfs_key
root_key
;
struct
btrfs_fs_info
*
fs_info
;
struct
inode
*
inode
;
u64
objectid
;
u64
last_trans
;
u32
blocksize
;
int
ref_cows
;
u32
type
;
...
...
@@ -595,7 +598,7 @@ static inline u32 btrfs_key_overflow(struct btrfs_key *key)
static
inline
void
btrfs_set_key_overflow
(
struct
btrfs_key
*
key
,
u32
over
)
{
BUG_ON
(
over
>
BTRFS_KEY_OVERFLOW_MAX
);
BUG_ON
(
over
>
=
BTRFS_KEY_OVERFLOW_MAX
);
over
=
over
<<
BTRFS_KEY_OVERFLOW_SHIFT
;
key
->
flags
=
(
key
->
flags
&
~
((
u64
)
BTRFS_KEY_OVERFLOW_MASK
))
|
over
;
}
...
...
@@ -634,7 +637,7 @@ static inline void btrfs_set_disK_key_overflow(struct btrfs_disk_key *key,
u32
over
)
{
u32
flags
=
btrfs_disk_key_flags
(
key
);
BUG_ON
(
over
>
BTRFS_KEY_OVERFLOW_MAX
);
BUG_ON
(
over
>
=
BTRFS_KEY_OVERFLOW_MAX
);
over
=
over
<<
BTRFS_KEY_OVERFLOW_SHIFT
;
flags
=
(
flags
&
~
((
u64
)
BTRFS_KEY_OVERFLOW_MASK
))
|
over
;
btrfs_set_disk_key_flags
(
key
,
flags
);
...
...
@@ -748,6 +751,17 @@ static inline void btrfs_set_super_blocknr(struct btrfs_super_block *s, u64 val)
s
->
blocknr
=
cpu_to_le64
(
val
);
}
static
inline
u64
btrfs_super_generation
(
struct
btrfs_super_block
*
s
)
{
return
le64_to_cpu
(
s
->
generation
);
}
static
inline
void
btrfs_set_super_generation
(
struct
btrfs_super_block
*
s
,
u64
val
)
{
s
->
generation
=
cpu_to_le64
(
val
);
}
static
inline
u64
btrfs_super_root
(
struct
btrfs_super_block
*
s
)
{
return
le64_to_cpu
(
s
->
root
);
...
...
fs/btrfs/disk-io.c
浏览文件 @
0f7d52f4
...
...
@@ -4,9 +4,11 @@
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/swap.h>
#include <linux/radix-tree.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
#include "btrfs_inode.h"
static
int
check_tree_block
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
buf
)
{
...
...
@@ -180,7 +182,7 @@ static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh,
static
int
btree_writepage
(
struct
page
*
page
,
struct
writeback_control
*
wbc
)
{
struct
buffer_head
*
bh
;
struct
btrfs_root
*
root
=
btrfs_sb
(
page
->
mapping
->
host
->
i_sb
)
;
struct
btrfs_root
*
root
=
BTRFS_I
(
page
->
mapping
->
host
)
->
root
;
struct
buffer_head
*
head
;
if
(
!
page_has_buffers
(
page
))
{
create_empty_buffers
(
page
,
root
->
fs_info
->
sb
->
s_blocksize
,
...
...
@@ -259,10 +261,13 @@ static int __setup_root(int blocksize,
u64
objectid
)
{
root
->
node
=
NULL
;
root
->
inode
=
NULL
;
root
->
commit_root
=
NULL
;
root
->
blocksize
=
blocksize
;
root
->
ref_cows
=
0
;
root
->
fs_info
=
fs_info
;
root
->
objectid
=
objectid
;
root
->
last_trans
=
0
;
memset
(
&
root
->
root_key
,
0
,
sizeof
(
root
->
root_key
));
memset
(
&
root
->
root_item
,
0
,
sizeof
(
root
->
root_item
));
return
0
;
...
...
@@ -287,10 +292,78 @@ static int find_and_setup_root(int blocksize,
return
0
;
}
struct
btrfs_root
*
btrfs_read_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_key
*
location
)
{
struct
btrfs_root
*
root
;
struct
btrfs_root
*
tree_root
=
fs_info
->
tree_root
;
struct
btrfs_path
*
path
;
struct
btrfs_leaf
*
l
;
int
ret
=
0
;
printk
(
"read_fs_root looking for %Lu %Lu %u
\n
"
,
location
->
objectid
,
location
->
offset
,
location
->
flags
);
root
=
kmalloc
(
sizeof
(
*
root
),
GFP_NOFS
);
if
(
!
root
)
{
printk
(
"failed1
\n
"
);
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
,
location
->
objectid
,
root
);
if
(
ret
)
{
printk
(
"failed2
\n
"
);
kfree
(
root
);
return
ERR_PTR
(
ret
);
}
goto
insert
;
}
__setup_root
(
fs_info
->
sb
->
s_blocksize
,
root
,
fs_info
,
location
->
objectid
);
path
=
btrfs_alloc_path
();
BUG_ON
(
!
path
);
ret
=
btrfs_search_slot
(
NULL
,
tree_root
,
location
,
path
,
0
,
0
);
if
(
ret
!=
0
)
{
printk
(
"internal search_slot gives us %d
\n
"
,
ret
);
if
(
ret
>
0
)
ret
=
-
ENOENT
;
goto
out
;
}
l
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
memcpy
(
&
root
->
root_item
,
btrfs_item_ptr
(
l
,
path
->
slots
[
0
],
struct
btrfs_root_item
),
sizeof
(
root
->
root_item
));
memcpy
(
&
root
->
root_key
,
location
,
sizeof
(
*
location
));
ret
=
0
;
out:
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
if
(
ret
)
{
kfree
(
root
);
return
ERR_PTR
(
ret
);
}
root
->
node
=
read_tree_block
(
root
,
btrfs_root_blocknr
(
&
root
->
root_item
));
BUG_ON
(
!
root
->
node
);
insert:
printk
(
"inserting %p
\n
"
,
root
);
root
->
ref_cows
=
1
;
ret
=
radix_tree_insert
(
&
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
root
,
root
);
if
(
ret
)
{
printk
(
"radix_tree_insert gives us %d
\n
"
,
ret
);
brelse
(
root
->
node
);
kfree
(
root
);
return
ERR_PTR
(
ret
);
}
printk
(
"all worked
\n
"
);
return
root
;
}
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
)
{
struct
btrfs_root
*
root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
GFP_NOFS
);
struct
btrfs_root
*
extent_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
GFP_NOFS
);
struct
btrfs_root
*
tree_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
...
...
@@ -304,9 +377,9 @@ struct btrfs_root *open_ctree(struct super_block *sb)
init_bit_radix
(
&
fs_info
->
pinned_radix
);
init_bit_radix
(
&
fs_info
->
pending_del_radix
);
INIT_RADIX_TREE
(
&
fs_info
->
fs_roots_radix
,
GFP_NOFS
);
sb_set_blocksize
(
sb
,
4096
);
fs_info
->
running_transaction
=
NULL
;
fs_info
->
fs_root
=
root
;
fs_info
->
tree_root
=
tree_root
;
fs_info
->
extent_root
=
extent_root
;
fs_info
->
inode_root
=
inode_root
;
...
...
@@ -318,6 +391,9 @@ struct btrfs_root *open_ctree(struct super_block *sb)
fs_info
->
btree_inode
->
i_nlink
=
1
;
fs_info
->
btree_inode
->
i_size
=
sb
->
s_bdev
->
bd_inode
->
i_size
;
fs_info
->
btree_inode
->
i_mapping
->
a_ops
=
&
btree_aops
;
BTRFS_I
(
fs_info
->
btree_inode
)
->
root
=
tree_root
;
memset
(
&
BTRFS_I
(
fs_info
->
btree_inode
)
->
location
,
0
,
sizeof
(
struct
btrfs_key
));
insert_inode_hash
(
fs_info
->
btree_inode
);
mapping_set_gfp_mask
(
fs_info
->
btree_inode
->
i_mapping
,
GFP_NOFS
);
fs_info
->
hash_tfm
=
crypto_alloc_hash
(
"sha256"
,
0
,
CRYPTO_ALG_ASYNC
);
...
...
@@ -337,13 +413,12 @@ struct btrfs_root *open_ctree(struct super_block *sb)
BTRFS_SUPER_INFO_OFFSET
/
sb
->
s_blocksize
);
if
(
!
fs_info
->
sb_buffer
)
{
if
(
!
fs_info
->
sb_buffer
)
return
NULL
;
}
disk_super
=
(
struct
btrfs_super_block
*
)
fs_info
->
sb_buffer
->
b_data
;
if
(
!
btrfs_super_root
(
disk_super
))
{
if
(
!
btrfs_super_root
(
disk_super
))
return
NULL
;
}
fs_info
->
disk_super
=
disk_super
;
tree_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_root
(
disk_super
));
...
...
@@ -358,14 +433,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
BTRFS_INODE_MAP_OBJECTID
,
inode_root
);
BUG_ON
(
ret
);
ret
=
find_and_setup_root
(
sb
->
s_blocksize
,
tree_root
,
fs_info
,
BTRFS_FS_TREE_OBJECTID
,
root
);
BUG_ON
(
ret
);
root
->
commit_root
=
root
->
node
;
get_bh
(
root
->
node
);
root
->
ref_cows
=
1
;
root
->
fs_info
->
generation
=
root
->
root_key
.
offset
+
1
;
ret
=
btrfs_find_highest_inode
(
root
,
&
root
->
fs_info
->
last_inode_alloc
);
fs_info
->
generation
=
btrfs_super_generation
(
disk_super
)
+
1
;
ret
=
btrfs_find_highest_inode
(
tree_root
,
&
fs_info
->
last_inode_alloc
);
if
(
ret
==
0
)
fs_info
->
highest_inode
=
fs_info
->
last_inode_alloc
;
memset
(
&
fs_info
->
kobj
,
0
,
sizeof
(
fs_info
->
kobj
));
...
...
@@ -373,7 +442,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
kobject_set_name
(
&
fs_info
->
kobj
,
"%s"
,
sb
->
s_id
);
kobject_register
(
&
fs_info
->
kobj
);
mutex_unlock
(
&
fs_info
->
fs_mutex
);
return
root
;
return
tree_
root
;
}
int
write_ctree_super
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
...
...
@@ -398,12 +467,42 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
return
0
;
}
int
del_fs_roots
(
struct
btrfs_fs_info
*
fs_info
)
{
int
ret
;
struct
btrfs_root
*
gang
[
8
];
int
i
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup
(
&
fs_info
->
fs_roots_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
));
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
radix_tree_delete
(
&
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
gang
[
i
]);
if
(
gang
[
i
]
->
inode
)
iput
(
gang
[
i
]
->
inode
);
else
printk
(
"no inode for root %p
\n
"
,
gang
[
i
]);
if
(
gang
[
i
]
->
node
)
brelse
(
gang
[
i
]
->
node
);
if
(
gang
[
i
]
->
commit_root
)
brelse
(
gang
[
i
]
->
commit_root
);
kfree
(
gang
[
i
]);
}
}
return
0
;
}
int
close_ctree
(
struct
btrfs_root
*
root
)
{
int
ret
;
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_fs_info
*
fs_info
=
root
->
fs_info
;
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_lock
(
&
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
btrfs_commit_transaction
(
trans
,
root
);
/* run commit again to drop the original snapshot */
...
...
@@ -412,29 +511,26 @@ int close_ctree(struct btrfs_root *root)
ret
=
btrfs_write_and_wait_transaction
(
NULL
,
root
);
BUG_ON
(
ret
);
write_ctree_super
(
NULL
,
root
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
if
(
root
->
node
)
btrfs_block_release
(
root
,
root
->
node
);
if
(
root
->
fs_info
->
extent_root
->
node
)
btrfs_block_release
(
root
->
fs_info
->
extent_root
,
root
->
fs_info
->
extent_root
->
node
);
if
(
root
->
fs_info
->
inode_root
->
node
)
btrfs_block_release
(
root
->
fs_info
->
inode_root
,
root
->
fs_info
->
inode_root
->
node
);
if
(
root
->
fs_info
->
tree_root
->
node
)
btrfs_block_release
(
root
->
fs_info
->
tree_root
,
root
->
fs_info
->
tree_root
->
node
);
btrfs_block_release
(
root
,
root
->
commit_root
);
btrfs_block_release
(
root
,
root
->
fs_info
->
sb_buffer
);
crypto_free_hash
(
root
->
fs_info
->
hash_tfm
);
truncate_inode_pages
(
root
->
fs_info
->
btree_inode
->
i_mapping
,
0
);
iput
(
root
->
fs_info
->
btree_inode
);
kfree
(
root
->
fs_info
->
extent_root
);
kfree
(
root
->
fs_info
->
inode_root
);
kfree
(
root
->
fs_info
->
tree_root
);
kobject_unregister
(
&
root
->
fs_info
->
kobj
);
kfree
(
root
);
mutex_unlock
(
&
fs_info
->
fs_mutex
);
if
(
fs_info
->
extent_root
->
node
)
btrfs_block_release
(
fs_info
->
extent_root
,
fs_info
->
extent_root
->
node
);
if
(
fs_info
->
inode_root
->
node
)
btrfs_block_release
(
fs_info
->
inode_root
,
fs_info
->
inode_root
->
node
);
if
(
fs_info
->
tree_root
->
node
)
btrfs_block_release
(
fs_info
->
tree_root
,
fs_info
->
tree_root
->
node
);
btrfs_block_release
(
root
,
fs_info
->
sb_buffer
);
crypto_free_hash
(
fs_info
->
hash_tfm
);
truncate_inode_pages
(
fs_info
->
btree_inode
->
i_mapping
,
0
);
iput
(
fs_info
->
btree_inode
);
del_fs_roots
(
fs_info
);
kfree
(
fs_info
->
extent_root
);
kfree
(
fs_info
->
inode_root
);
kfree
(
fs_info
->
tree_root
);
kobject_unregister
(
&
fs_info
->
kobj
);
return
0
;
}
...
...
fs/btrfs/disk-io.h
浏览文件 @
0f7d52f4
...
...
@@ -39,4 +39,6 @@ int write_ctree_super(struct btrfs_trans_handle *trans,
struct
buffer_head
*
btrfs_find_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
int
btrfs_csum_data
(
struct
btrfs_root
*
root
,
char
*
data
,
size_t
len
,
char
*
result
);
struct
btrfs_root
*
btrfs_read_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_key
*
location
);
#endif
fs/btrfs/super.c
浏览文件 @
0f7d52f4
...
...
@@ -436,7 +436,6 @@ int fixup_tree_root_location(struct btrfs_root *root,
{
struct
btrfs_path
*
path
;
struct
btrfs_root_item
*
ri
;
int
ret
;
if
(
btrfs_key_type
(
location
)
!=
BTRFS_ROOT_ITEM_KEY
)
return
0
;
...
...
@@ -447,22 +446,19 @@ int fixup_tree_root_location(struct btrfs_root *root,
BUG_ON
(
!
path
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
ret
=
btrfs_lookup_inode
(
NULL
,
root
,
path
,
location
,
0
);
if
(
ret
)
goto
out
;
ri
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_root_item
);
*
sub_root
=
btrfs_read_fs_root
(
root
->
fs_info
,
location
);
if
(
IS_ERR
(
*
sub_root
))
return
PTR_ERR
(
*
sub_root
);
ri
=
&
(
*
sub_root
)
->
root_item
;
location
->
objectid
=
btrfs_root_dirid
(
ri
);
location
->
flags
=
0
;
btrfs_set_key_type
(
location
,
BTRFS_INODE_ITEM_KEY
);
location
->
offset
=
0
;
/* FIXME properly select the root */
*
sub_root
=
root
->
fs_info
->
fs_root
;
out:
btrfs_free_path
(
path
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
return
ret
;
return
0
;
}
...
...
@@ -494,6 +490,15 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
if
(
!
inode
)
return
ERR_PTR
(
-
EACCES
);
if
(
inode
->
i_state
&
I_NEW
)
{
if
(
sub_root
!=
root
)
{
ret
=
radix_tree_insert
(
&
root
->
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
sub_root
,
sub_root
);
printk
(
"adding new root for inode %lu
\n
"
,
inode
->
i_ino
);
igrab
(
inode
);
sub_root
->
inode
=
inode
;
}
BTRFS_I
(
inode
)
->
root
=
sub_root
;
memcpy
(
&
BTRFS_I
(
inode
)
->
location
,
&
location
,
sizeof
(
location
));
...
...
@@ -605,7 +610,7 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
struct
inode
*
inode
;
struct
dentry
*
root_dentry
;
struct
btrfs_super_block
*
disk_super
;
struct
btrfs_root
*
root
;
struct
btrfs_root
*
tree_
root
;
struct
btrfs_inode
*
bi
;
sb
->
s_maxbytes
=
MAX_LFS_FILESIZE
;
...
...
@@ -613,14 +618,14 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
sb
->
s_op
=
&
btrfs_super_ops
;
sb
->
s_time_gran
=
1
;
root
=
open_ctree
(
sb
);
tree_
root
=
open_ctree
(
sb
);
if
(
!
root
)
{
if
(
!
tree_
root
)
{
printk
(
"btrfs: open_ctree failed
\n
"
);
return
-
EIO
;
}
sb
->
s_fs_info
=
root
;
disk_super
=
root
->
fs_info
->
disk_super
;
sb
->
s_fs_info
=
tree_
root
;
disk_super
=
tree_
root
->
fs_info
->
disk_super
;
printk
(
"read in super total blocks %Lu root %Lu
\n
"
,
btrfs_super_total_blocks
(
disk_super
),
btrfs_super_root_dir
(
disk_super
));
...
...
@@ -630,7 +635,7 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
bi
->
location
.
objectid
=
inode
->
i_ino
;
bi
->
location
.
offset
=
0
;
bi
->
location
.
flags
=
0
;
bi
->
root
=
root
->
fs_info
->
tree_root
;
bi
->
root
=
tree_root
;
btrfs_set_key_type
(
&
bi
->
location
,
BTRFS_INODE_ITEM_KEY
);
if
(
!
inode
)
...
...
fs/btrfs/transaction.c
浏览文件 @
0f7d52f4
...
...
@@ -8,6 +8,8 @@ static int total_trans = 0;
extern
struct
kmem_cache
*
btrfs_trans_handle_cachep
;
extern
struct
kmem_cache
*
btrfs_transaction_cachep
;
#define BTRFS_ROOT_TRANS_TAG 0
#define TRANS_MAGIC 0xE1E10E
static
void
put_transaction
(
struct
btrfs_transaction
*
transaction
)
{
...
...
@@ -31,9 +33,10 @@ static int join_transaction(struct btrfs_root *root)
GFP_NOFS
);
total_trans
++
;
BUG_ON
(
!
cur_trans
);
root
->
fs_info
->
generation
++
;
root
->
fs_info
->
running_transaction
=
cur_trans
;
cur_trans
->
num_writers
=
0
;
cur_trans
->
transid
=
root
->
root_key
.
offset
+
1
;
cur_trans
->
transid
=
root
->
fs_info
->
generation
;
init_waitqueue_head
(
&
cur_trans
->
writer_wait
);
init_waitqueue_head
(
&
cur_trans
->
commit_wait
);
cur_trans
->
magic
=
TRANS_MAGIC
;
...
...
@@ -51,13 +54,22 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
struct
btrfs_trans_handle
*
h
=
kmem_cache_alloc
(
btrfs_trans_handle_cachep
,
GFP_NOFS
);
int
ret
;
u64
running_trans_id
;
/* FIXME, use the right root */
root
=
root
->
fs_info
->
fs_root
;
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
ret
=
join_transaction
(
root
);
BUG_ON
(
ret
);
h
->
transid
=
root
->
fs_info
->
running_transaction
->
transid
;
running_trans_id
=
root
->
fs_info
->
running_transaction
->
transid
;
if
(
root
!=
root
->
fs_info
->
tree_root
&&
root
->
last_trans
<
running_trans_id
)
{
radix_tree_tag_set
(
&
root
->
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
root
,
BTRFS_ROOT_TRANS_TAG
);
root
->
commit_root
=
root
->
node
;
get_bh
(
root
->
node
);
}
root
->
last_trans
=
running_trans_id
;
h
->
transid
=
running_trans_id
;
h
->
transaction
=
root
->
fs_info
->
running_transaction
;
h
->
blocks_reserved
=
num_blocks
;
h
->
blocks_used
=
0
;
...
...
@@ -72,9 +84,6 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
{
struct
btrfs_transaction
*
cur_trans
;
/* FIXME, use the right root */
root
=
root
->
fs_info
->
fs_root
;
WARN_ON
(
trans
->
magic
!=
TRANS_MAGIC
);
WARN_ON
(
trans
->
magic2
!=
TRANS_MAGIC
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
...
...
@@ -145,17 +154,96 @@ static int wait_for_commit(struct btrfs_root *root,
return
0
;
}
struct
dirty_root
{
struct
list_head
list
;
struct
btrfs_key
snap_key
;
struct
buffer_head
*
commit_root
;
struct
btrfs_root
*
root
;
};
int
add_dirty_roots
(
struct
btrfs_trans_handle
*
trans
,
struct
radix_tree_root
*
radix
,
struct
list_head
*
list
)
{
struct
dirty_root
*
dirty
;
struct
btrfs_root
*
gang
[
8
];
struct
btrfs_root
*
root
;
int
i
;
int
ret
;
int
err
;
printk
(
"add dirty
\n
"
);
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
),
BTRFS_ROOT_TRANS_TAG
);
if
(
ret
==
0
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
root
=
gang
[
i
];
radix_tree_tag_clear
(
radix
,
(
unsigned
long
)
root
,
BTRFS_ROOT_TRANS_TAG
);
if
(
root
->
commit_root
==
root
->
node
)
{
WARN_ON
(
root
->
node
->
b_blocknr
!=
btrfs_root_blocknr
(
&
root
->
root_item
));
brelse
(
root
->
commit_root
);
root
->
commit_root
=
NULL
;
continue
;
}
dirty
=
kmalloc
(
sizeof
(
*
dirty
),
GFP_NOFS
);
BUG_ON
(
!
dirty
);
memcpy
(
&
dirty
->
snap_key
,
&
root
->
root_key
,
sizeof
(
root
->
root_key
));
dirty
->
commit_root
=
root
->
commit_root
;
root
->
commit_root
=
NULL
;
dirty
->
root
=
root
;
printk
(
"adding dirty root %Lu gen %Lu blocknr %Lu
\n
"
,
root
->
root_key
.
objectid
,
root
->
root_key
.
offset
,
dirty
->
commit_root
->
b_blocknr
);
root
->
root_key
.
offset
=
root
->
fs_info
->
generation
;
btrfs_set_root_blocknr
(
&
root
->
root_item
,
root
->
node
->
b_blocknr
);
err
=
btrfs_insert_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
root
->
root_key
,
&
root
->
root_item
);
BUG_ON
(
err
);
list_add
(
&
dirty
->
list
,
list
);
}
}
printk
(
"add dirty done
\n
"
);
return
0
;
}
int
drop_dirty_roots
(
struct
btrfs_root
*
tree_root
,
struct
list_head
*
list
)
{
struct
dirty_root
*
dirty
;
struct
btrfs_trans_handle
*
trans
;
int
ret
;
while
(
!
list_empty
(
list
))
{
dirty
=
list_entry
(
list
->
next
,
struct
dirty_root
,
list
);
list_del_init
(
&
dirty
->
list
);
trans
=
btrfs_start_transaction
(
tree_root
,
1
);
printk
(
"drop snapshot root %p, commit_root blocknr %Lu generation %Lu
\n
"
,
dirty
->
root
,
dirty
->
commit_root
->
b_blocknr
,
dirty
->
snap_key
.
offset
);
ret
=
btrfs_drop_snapshot
(
trans
,
dirty
->
root
,
dirty
->
commit_root
);
BUG_ON
(
ret
);
printk
(
"del root objectid %Lu, offset %Lu
\n
"
,
dirty
->
snap_key
.
objectid
,
dirty
->
snap_key
.
offset
);
ret
=
btrfs_del_root
(
trans
,
tree_root
,
&
dirty
->
snap_key
);
BUG_ON
(
ret
);
ret
=
btrfs_end_transaction
(
trans
,
tree_root
);
BUG_ON
(
ret
);
kfree
(
dirty
);
}
return
0
;
}
int
btrfs_commit_transaction
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
int
ret
=
0
;
struct
buffer_head
*
snap
;
struct
btrfs_key
snap_key
;
struct
btrfs_transaction
*
cur_trans
;
struct
list_head
dirty_fs_roots
;
DEFINE_WAIT
(
wait
);
/* FIXME, use the right root */
root
=
root
->
fs_info
->
fs_root
;
INIT_LIST_HEAD
(
&
dirty_fs_roots
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
if
(
trans
->
transaction
->
in_commit
)
{
...
...
@@ -184,22 +272,13 @@ printk("already in commit!, waiting\n");
}
finish_wait
(
&
trans
->
transaction
->
writer_wait
,
&
wait
);
WARN_ON
(
cur_trans
!=
trans
->
transaction
);
if
(
root
->
node
!=
root
->
commit_root
)
{
memcpy
(
&
snap_key
,
&
root
->
root_key
,
sizeof
(
snap_key
));
root
->
root_key
.
offset
++
;
}
if
(
btrfs_root_blocknr
(
&
root
->
root_item
)
!=
root
->
node
->
b_blocknr
)
{
btrfs_set_root_blocknr
(
&
root
->
root_item
,
root
->
node
->
b_blocknr
);
ret
=
btrfs_insert_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
root
->
root_key
,
&
root
->
root_item
);
BUG_ON
(
ret
);
}
add_dirty_roots
(
trans
,
&
root
->
fs_info
->
fs_roots_radix
,
&
dirty_fs_roots
);
ret
=
btrfs_commit_tree_roots
(
trans
,
root
);
BUG_ON
(
ret
);
cur_trans
=
root
->
fs_info
->
running_transaction
;
root
->
fs_info
->
running_transaction
=
NULL
;
btrfs_set_super_generation
(
root
->
fs_info
->
disk_super
,
root
->
fs_info
->
generation
+
1
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
ret
=
btrfs_write_and_wait_transaction
(
trans
,
root
);
BUG_ON
(
ret
);
...
...
@@ -213,21 +292,8 @@ printk("already in commit!, waiting\n");
put_transaction
(
cur_trans
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
kmem_cache_free
(
btrfs_trans_handle_cachep
,
trans
);
if
(
root
->
node
!=
root
->
commit_root
)
{
trans
=
btrfs_start_transaction
(
root
,
1
);
snap
=
root
->
commit_root
;
root
->
commit_root
=
root
->
node
;
get_bh
(
root
->
node
);
ret
=
btrfs_drop_snapshot
(
trans
,
root
,
snap
);
BUG_ON
(
ret
);
ret
=
btrfs_del_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
snap_key
);
BUG_ON
(
ret
);
root
->
fs_info
->
generation
=
root
->
root_key
.
offset
+
1
;
ret
=
btrfs_end_transaction
(
trans
,
root
);
BUG_ON
(
ret
);
}
drop_dirty_roots
(
root
->
fs_info
->
tree_root
,
&
dirty_fs_roots
);
return
ret
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录