Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
e20d96d6
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
e20d96d6
编写于
3月 22, 2007
作者:
C
Chris Mason
提交者:
David Woodhouse
3月 22, 2007
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Mountable btrfs, with readdir
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
2e635a27
变更
14
展开全部
隐藏空白更改
内联
并排
Showing
14 changed file
with
651 addition
and
490 deletion
+651
-490
fs/btrfs/Makefile
fs/btrfs/Makefile
+3
-2
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+140
-133
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+48
-14
fs/btrfs/dir-item.c
fs/btrfs/dir-item.c
+7
-10
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+83
-198
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+28
-23
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+74
-70
fs/btrfs/hash.c
fs/btrfs/hash.c
+9
-0
fs/btrfs/inode-map.c
fs/btrfs/inode-map.c
+4
-4
fs/btrfs/print-tree.c
fs/btrfs/print-tree.c
+9
-11
fs/btrfs/print-tree.h
fs/btrfs/print-tree.h
+1
-1
fs/btrfs/root-tree.c
fs/btrfs/root-tree.c
+2
-2
fs/btrfs/super.c
fs/btrfs/super.c
+241
-20
fs/btrfs/transaction.h
fs/btrfs/transaction.h
+2
-2
未找到文件。
fs/btrfs/Makefile
浏览文件 @
e20d96d6
...
...
@@ -2,7 +2,8 @@ ifneq ($(KERNELRELEASE),)
# kbuild part of makefile
obj-m
:=
btrfs.o
btrfs-y
:=
super.o
btrfs-y
:=
super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o
\
hash.o file-item.o inode-item.o inode-map.o disk-io.o
#btrfs-y := ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
# root-tree.o dir-item.o hash.o file-item.o inode-item.o \
...
...
@@ -14,7 +15,7 @@ else
KERNELDIR
:=
/lib/modules/
`
uname
-r
`
/build
all
::
$(MAKE)
-C
$(KERNELDIR)
M
=
`
pwd
`
modules
$(MAKE)
C
=
1
-C
$(KERNELDIR)
M
=
`
pwd
`
modules
clean
::
rm
*
.o btrfs.ko
endif
fs/btrfs/ctree.c
浏览文件 @
e20d96d6
此差异已折叠。
点击以展开。
fs/btrfs/ctree.h
浏览文件 @
e20d96d6
#ifndef __BTRFS__
#define __BTRFS__
#include <linux/radix-tree.h>
#include <linux/fs.h>
struct
btrfs_trans_handle
;
#define BTRFS_MAGIC "_BtRfS_M"
...
...
@@ -10,6 +13,12 @@ struct btrfs_trans_handle;
#define BTRFS_INODE_MAP_OBJECTID 3
#define BTRFS_FS_TREE_OBJECTID 4
/*
* we can actually store much bigger names, but lets not confuse the rest
* of linux
*/
#define BTRFS_NAME_LEN 255
/*
* the key defines the order in the tree, and so it also defines (optimal)
* block layout. objectid corresonds to the inode number. The flags
...
...
@@ -57,7 +66,7 @@ struct btrfs_header {
#define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->blocksize))
struct
b
trfs_buffer
;
struct
b
uffer_head
;
/*
* the super block basically lists the main trees of the FS
* it currently lacks any block count etc etc
...
...
@@ -120,7 +129,7 @@ struct btrfs_node {
* used while walking the tree.
*/
struct
btrfs_path
{
struct
b
trfs_buffer
*
nodes
[
BTRFS_MAX_LEVEL
];
struct
b
uffer_head
*
nodes
[
BTRFS_MAX_LEVEL
];
int
slots
[
BTRFS_MAX_LEVEL
];
};
...
...
@@ -211,17 +220,14 @@ struct btrfs_fs_info {
struct
btrfs_root
*
inode_root
;
struct
btrfs_key
current_insert
;
struct
btrfs_key
last_insert
;
struct
radix_tree_root
cache_radix
;
struct
radix_tree_root
pinned_radix
;
struct
list_head
trans
;
struct
list_head
cache
;
u64
last_inode_alloc
;
u64
last_inode_alloc_dirid
;
u64
generation
;
int
cache_size
;
int
fp
;
struct
btrfs_trans_handle
*
running_transaction
;
struct
btrfs_super_block
*
disk_super
;
struct
buffer_head
*
sb_buffer
;
struct
super_block
*
sb
;
};
/*
...
...
@@ -230,8 +236,8 @@ struct btrfs_fs_info {
* only for the extent tree.
*/
struct
btrfs_root
{
struct
b
trfs_buffer
*
node
;
struct
b
trfs_buffer
*
commit_root
;
struct
b
uffer_head
*
node
;
struct
b
uffer_head
*
commit_root
;
struct
btrfs_root_item
root_item
;
struct
btrfs_key
root_key
;
struct
btrfs_fs_info
*
fs_info
;
...
...
@@ -389,6 +395,29 @@ static inline void btrfs_set_inode_compat_flags(struct btrfs_inode_item *i,
i
->
compat_flags
=
cpu_to_le16
(
val
);
}
static
inline
u32
btrfs_timespec_sec
(
struct
btrfs_inode_timespec
*
ts
)
{
return
le32_to_cpu
(
ts
->
sec
);
}
static
inline
void
btrfs_set_timespec_sec
(
struct
btrfs_inode_timespec
*
ts
,
u32
val
)
{
ts
->
sec
=
cpu_to_le32
(
val
);
}
static
inline
u32
btrfs_timespec_nsec
(
struct
btrfs_inode_timespec
*
ts
)
{
return
le32_to_cpu
(
ts
->
nsec
);
}
static
inline
void
btrfs_set_timespec_nsec
(
struct
btrfs_inode_timespec
*
ts
,
u32
val
)
{
ts
->
nsec
=
cpu_to_le32
(
val
);
}
static
inline
u64
btrfs_extent_owner
(
struct
btrfs_extent_item
*
ei
)
{
...
...
@@ -757,15 +786,20 @@ static inline void btrfs_set_file_extent_num_blocks(struct
e
->
num_blocks
=
cpu_to_le64
(
val
);
}
static
inline
struct
btrfs_root
*
btrfs_sb
(
struct
super_block
*
sb
)
{
return
sb
->
s_fs_info
;
}
/* helper function to cast into the data area of the leaf. */
#define btrfs_item_ptr(leaf, slot, type) \
((type *)(btrfs_leaf_data(leaf) + \
btrfs_item_offset((leaf)->items + (slot))))
struct
b
trfs_buffer
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
b
uffer_head
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
int
btrfs_inc_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
);
struct
b
uffer_head
*
buf
);
int
btrfs_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
int
pin
);
int
btrfs_search_slot
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
...
...
@@ -783,7 +817,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
int
btrfs_next_leaf
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
);
int
btrfs_leaf_free_space
(
struct
btrfs_root
*
root
,
struct
btrfs_leaf
*
leaf
);
int
btrfs_drop_snapshot
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
snap
);
*
root
,
struct
b
uffer_head
*
snap
);
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
int
btrfs_del_root
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
...
...
@@ -800,8 +834,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*
root
,
char
*
name
,
int
name_len
,
u64
dir
,
u64
objectid
,
u8
type
);
int
btrfs_lookup_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
char
*
name
,
int
name_len
,
int
mod
);
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
const
char
*
name
,
int
name_len
,
int
mod
);
int
btrfs_match_dir_item_name
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
char
*
name
,
int
name_len
);
int
btrfs_find_free_objectid
(
struct
btrfs_trans_handle
*
trans
,
...
...
fs/btrfs/dir-item.c
浏览文件 @
e20d96d6
...
...
@@ -18,12 +18,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
key
.
objectid
=
dir
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_DIR_ITEM_KEY
);
if
(
name_len
==
1
&&
*
name
==
'.'
)
key
.
offset
=
1
;
else
if
(
name_len
==
2
&&
name
[
0
]
==
'.'
&&
name
[
1
]
==
'.'
)
key
.
offset
=
2
;
else
ret
=
btrfs_name_hash
(
name
,
name_len
,
&
key
.
offset
);
ret
=
btrfs_name_hash
(
name
,
name_len
,
&
key
.
offset
);
BUG_ON
(
ret
);
btrfs_init_path
(
&
path
);
data_size
=
sizeof
(
*
dir_item
)
+
name_len
;
...
...
@@ -31,7 +26,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
ret
)
goto
out
;
dir_item
=
btrfs_item_ptr
(
&
path
.
nodes
[
0
]
->
leaf
,
path
.
slots
[
0
],
dir_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
]),
path
.
slots
[
0
],
struct
btrfs_dir_item
);
btrfs_set_dir_objectid
(
dir_item
,
objectid
);
btrfs_set_dir_type
(
dir_item
,
type
);
...
...
@@ -45,8 +41,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
}
int
btrfs_lookup_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
char
*
name
,
int
name_len
,
int
mod
)
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
const
char
*
name
,
int
name_len
,
int
mod
)
{
int
ret
;
struct
btrfs_key
key
;
...
...
@@ -69,7 +65,8 @@ int btrfs_match_dir_item_name(struct btrfs_root *root,
struct
btrfs_dir_item
*
dir_item
;
char
*
name_ptr
;
dir_item
=
btrfs_item_ptr
(
&
path
->
nodes
[
0
]
->
leaf
,
path
->
slots
[
0
],
dir_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_dir_item
);
if
(
btrfs_dir_name_len
(
dir_item
)
!=
name_len
)
return
0
;
...
...
fs/btrfs/disk-io.c
浏览文件 @
e20d96d6
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "kerncompat.h"
#include "radix-tree.h"
#include <linux/module.h>
#include <linux/fs.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
static
int
allocated_blocks
=
0
;
int
cache_max
=
10000
;
static
int
check_tree_block
(
struct
btrfs_root
*
root
,
struct
btrfs_buffer
*
buf
)
static
int
check_tree_block
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
buf
)
{
if
(
buf
->
blocknr
!=
btrfs_header_blocknr
(
&
buf
->
node
.
header
))
struct
btrfs_node
*
node
=
btrfs_buffer_node
(
buf
);
if
(
buf
->
b_blocknr
!=
btrfs_header_blocknr
(
&
node
->
header
))
BUG
();
if
(
root
->
node
&&
btrfs_header_parentid
(
&
buf
->
node
.
header
)
!=
btrfs_header_parentid
(
&
root
->
node
->
node
.
header
))
if
(
root
->
node
&&
btrfs_header_parentid
(
&
node
->
header
)
!=
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)
))
BUG
();
return
0
;
}
st
atic
int
free_some_buffers
(
struct
btrfs_root
*
root
)
st
ruct
buffer_head
*
alloc_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
{
struct
list_head
*
node
,
*
next
;
struct
btrfs_buffer
*
b
;
if
(
root
->
fs_info
->
cache_size
<
cache_max
)
return
0
;
list_for_each_safe
(
node
,
next
,
&
root
->
fs_info
->
cache
)
{
b
=
list_entry
(
node
,
struct
btrfs_buffer
,
cache
);
if
(
b
->
count
==
1
)
{
BUG_ON
(
!
list_empty
(
&
b
->
dirty
));
list_del_init
(
&
b
->
cache
);
btrfs_block_release
(
root
,
b
);
if
(
root
->
fs_info
->
cache_size
<
cache_max
)
break
;
}
}
return
0
;
return
sb_getblk
(
root
->
fs_info
->
sb
,
blocknr
);
}
struct
b
trfs_buffer
*
alloc
_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
struct
b
uffer_head
*
find
_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
{
struct
btrfs_buffer
*
buf
;
int
ret
;
buf
=
malloc
(
sizeof
(
struct
btrfs_buffer
)
+
root
->
blocksize
);
if
(
!
buf
)
return
buf
;
allocated_blocks
++
;
buf
->
blocknr
=
blocknr
;
buf
->
count
=
2
;
INIT_LIST_HEAD
(
&
buf
->
dirty
);
free_some_buffers
(
root
);
radix_tree_preload
(
GFP_KERNEL
);
ret
=
radix_tree_insert
(
&
root
->
fs_info
->
cache_radix
,
blocknr
,
buf
);
radix_tree_preload_end
();
list_add_tail
(
&
buf
->
cache
,
&
root
->
fs_info
->
cache
);
root
->
fs_info
->
cache_size
++
;
if
(
ret
)
{
free
(
buf
);
return
NULL
;
}
return
buf
;
return
sb_getblk
(
root
->
fs_info
->
sb
,
blocknr
);
}
struct
b
trfs_buffer
*
fin
d_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
struct
b
uffer_head
*
rea
d_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
{
struct
btrfs_buffer
*
buf
;
buf
=
radix_tree_lookup
(
&
root
->
fs_info
->
cache_radix
,
blocknr
);
if
(
buf
)
{
buf
->
count
++
;
}
else
{
buf
=
alloc_tree_block
(
root
,
blocknr
);
if
(
!
buf
)
{
BUG
();
return
NULL
;
}
}
return
buf
;
}
struct
btrfs_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
{
loff_t
offset
=
blocknr
*
root
->
blocksize
;
struct
btrfs_buffer
*
buf
;
int
ret
;
struct
buffer_head
*
buf
=
sb_bread
(
root
->
fs_info
->
sb
,
blocknr
);
buf
=
radix_tree_lookup
(
&
root
->
fs_info
->
cache_radix
,
blocknr
);
if
(
buf
)
{
buf
->
count
++
;
}
else
{
buf
=
alloc_tree_block
(
root
,
blocknr
);
if
(
!
buf
)
return
NULL
;
ret
=
pread
(
root
->
fs_info
->
fp
,
&
buf
->
node
,
root
->
blocksize
,
offset
);
if
(
ret
!=
root
->
blocksize
)
{
free
(
buf
);
return
NULL
;
}
}
if
(
!
buf
)
return
buf
;
if
(
check_tree_block
(
root
,
buf
))
BUG
();
return
buf
;
}
int
dirty_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
struct
b
uffer_head
*
buf
)
{
if
(
!
list_empty
(
&
buf
->
dirty
))
return
0
;
list_add_tail
(
&
buf
->
dirty
,
&
root
->
fs_info
->
trans
);
buf
->
count
++
;
mark_buffer_dirty
(
buf
);
return
0
;
}
int
clean_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
struct
b
uffer_head
*
buf
)
{
if
(
!
list_empty
(
&
buf
->
dirty
))
{
list_del_init
(
&
buf
->
dirty
);
btrfs_block_release
(
root
,
buf
);
}
clear_buffer_dirty
(
buf
);
return
0
;
}
int
write_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
struct
b
uffer_head
*
buf
)
{
u64
blocknr
=
buf
->
blocknr
;
loff_t
offset
=
blocknr
*
root
->
blocksize
;
int
ret
;
if
(
buf
->
blocknr
!=
btrfs_header_blocknr
(
&
buf
->
node
.
header
))
BUG
();
ret
=
pwrite
(
root
->
fs_info
->
fp
,
&
buf
->
node
,
root
->
blocksize
,
offset
);
if
(
ret
!=
root
->
blocksize
)
return
ret
;
mark_buffer_dirty
(
buf
);
return
0
;
}
static
int
__commit_transaction
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
struct
btrfs_buffer
*
b
;
int
ret
=
0
;
int
wret
;
while
(
!
list_empty
(
&
root
->
fs_info
->
trans
))
{
b
=
list_entry
(
root
->
fs_info
->
trans
.
next
,
struct
btrfs_buffer
,
dirty
);
list_del_init
(
&
b
->
dirty
);
wret
=
write_tree_block
(
trans
,
root
,
b
);
if
(
wret
)
ret
=
wret
;
btrfs_block_release
(
root
,
b
);
}
return
ret
;
filemap_write_and_wait
(
root
->
fs_info
->
sb
->
s_bdev
->
bd_inode
->
i_mapping
);
return
0
;
}
static
int
commit_tree_roots
(
struct
btrfs_trans_handle
*
trans
,
...
...
@@ -172,17 +74,17 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans,
struct
btrfs_root
*
inode_root
=
fs_info
->
inode_root
;
btrfs_set_root_blocknr
(
&
inode_root
->
root_item
,
inode_root
->
node
->
blocknr
);
inode_root
->
node
->
b
_b
locknr
);
ret
=
btrfs_update_root
(
trans
,
tree_root
,
&
inode_root
->
root_key
,
&
inode_root
->
root_item
);
BUG_ON
(
ret
);
while
(
1
)
{
old_extent_block
=
btrfs_root_blocknr
(
&
extent_root
->
root_item
);
if
(
old_extent_block
==
extent_root
->
node
->
blocknr
)
if
(
old_extent_block
==
extent_root
->
node
->
b
_b
locknr
)
break
;
btrfs_set_root_blocknr
(
&
extent_root
->
root_item
,
extent_root
->
node
->
blocknr
);
extent_root
->
node
->
b
_b
locknr
);
ret
=
btrfs_update_root
(
trans
,
tree_root
,
&
extent_root
->
root_key
,
&
extent_root
->
root_item
);
...
...
@@ -195,7 +97,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
)
{
int
ret
=
0
;
struct
b
trfs_buffer
*
snap
=
root
->
commit_root
;
struct
b
uffer_head
*
snap
=
root
->
commit_root
;
struct
btrfs_key
snap_key
;
if
(
root
->
commit_root
==
root
->
node
)
...
...
@@ -204,7 +106,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
memcpy
(
&
snap_key
,
&
root
->
root_key
,
sizeof
(
snap_key
));
root
->
root_key
.
offset
++
;
btrfs_set_root_blocknr
(
&
root
->
root_item
,
root
->
node
->
blocknr
);
btrfs_set_root_blocknr
(
&
root
->
root_item
,
root
->
node
->
b
_b
locknr
);
ret
=
btrfs_insert_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
root
->
root_key
,
&
root
->
root_item
);
BUG_ON
(
ret
);
...
...
@@ -220,7 +122,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
btrfs_finish_extent_commit
(
trans
,
root
->
fs_info
->
tree_root
);
root
->
commit_root
=
root
->
node
;
root
->
node
->
count
++
;
get_bh
(
root
->
node
)
;
ret
=
btrfs_drop_snapshot
(
trans
,
root
,
snap
);
BUG_ON
(
ret
);
...
...
@@ -234,7 +136,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
static
int
__setup_root
(
struct
btrfs_super_block
*
super
,
struct
btrfs_root
*
root
,
struct
btrfs_fs_info
*
fs_info
,
u64
objectid
,
int
fp
)
u64
objectid
)
{
root
->
node
=
NULL
;
root
->
commit_root
=
NULL
;
...
...
@@ -250,11 +152,11 @@ static int find_and_setup_root(struct btrfs_super_block *super,
struct
btrfs_root
*
tree_root
,
struct
btrfs_fs_info
*
fs_info
,
u64
objectid
,
struct
btrfs_root
*
root
,
int
fp
)
struct
btrfs_root
*
root
)
{
int
ret
;
__setup_root
(
super
,
root
,
fs_info
,
objectid
,
fp
);
__setup_root
(
super
,
root
,
fs_info
,
objectid
);
ret
=
btrfs_find_last_root
(
tree_root
,
objectid
,
&
root
->
root_item
,
&
root
->
root_key
);
BUG_ON
(
ret
);
...
...
@@ -265,32 +167,26 @@ static int find_and_setup_root(struct btrfs_super_block *super,
return
0
;
}
struct
btrfs_root
*
open_ctree
(
char
*
filename
,
struct
btrfs_super_block
*
super
)
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
,
struct
buffer_head
*
sb_buffer
,
struct
btrfs_super_block
*
disk_super
)
{
int
fp
;
fp
=
open
(
filename
,
O_CREAT
|
O_RDWR
,
0600
);
if
(
fp
<
0
)
{
return
NULL
;
}
return
open_ctree_fd
(
fp
,
super
);
}
struct
btrfs_root
*
open_ctree_fd
(
int
fp
,
struct
btrfs_super_block
*
super
)
{
struct
btrfs_root
*
root
=
malloc
(
sizeof
(
struct
btrfs_root
));
struct
btrfs_root
*
extent_root
=
malloc
(
sizeof
(
struct
btrfs_root
));
struct
btrfs_root
*
tree_root
=
malloc
(
sizeof
(
struct
btrfs_root
));
struct
btrfs_root
*
inode_root
=
malloc
(
sizeof
(
struct
btrfs_root
));
struct
btrfs_fs_info
*
fs_info
=
malloc
(
sizeof
(
*
fs_info
));
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
),
GFP_NOFS
);
struct
btrfs_root
*
inode_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
GFP_NOFS
);
struct
btrfs_fs_info
*
fs_info
=
kmalloc
(
sizeof
(
*
fs_info
),
GFP_NOFS
);
int
ret
;
INIT_RADIX_TREE
(
&
fs_info
->
cache_radix
,
GFP_KERNEL
);
/* FIXME: don't be stupid */
if
(
!
btrfs_super_root
(
disk_super
))
return
NULL
;
INIT_RADIX_TREE
(
&
fs_info
->
pinned_radix
,
GFP_KERNEL
);
INIT_LIST_HEAD
(
&
fs_info
->
trans
);
INIT_LIST_HEAD
(
&
fs_info
->
cache
);
fs_info
->
cache_size
=
0
;
fs_info
->
fp
=
fp
;
fs_info
->
running_transaction
=
NULL
;
fs_info
->
fs_root
=
root
;
fs_info
->
tree_root
=
tree_root
;
...
...
@@ -298,36 +194,31 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super)
fs_info
->
inode_root
=
inode_root
;
fs_info
->
last_inode_alloc
=
0
;
fs_info
->
last_inode_alloc_dirid
=
0
;
fs_info
->
disk_super
=
super
;
fs_info
->
disk_super
=
disk_super
;
fs_info
->
sb_buffer
=
sb_buffer
;
fs_info
->
sb
=
sb
;
memset
(
&
fs_info
->
current_insert
,
0
,
sizeof
(
fs_info
->
current_insert
));
memset
(
&
fs_info
->
last_insert
,
0
,
sizeof
(
fs_info
->
last_insert
));
ret
=
pread
(
fp
,
super
,
sizeof
(
struct
btrfs_super_block
),
BTRFS_SUPER_INFO_OFFSET
);
if
(
ret
==
0
||
btrfs_super_root
(
super
)
==
0
)
{
BUG
();
return
NULL
;
}
BUG_ON
(
ret
<
0
);
__setup_root
(
super
,
tree_root
,
fs_info
,
BTRFS_ROOT_TREE_OBJECTID
,
fp
);
tree_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_root
(
super
));
__setup_root
(
disk_super
,
tree_root
,
fs_info
,
BTRFS_ROOT_TREE_OBJECTID
);
tree_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_root
(
disk_super
));
BUG_ON
(
!
tree_root
->
node
);
ret
=
find_and_setup_root
(
super
,
tree_root
,
fs_info
,
BTRFS_EXTENT_TREE_OBJECTID
,
extent_root
,
fp
);
ret
=
find_and_setup_root
(
disk_
super
,
tree_root
,
fs_info
,
BTRFS_EXTENT_TREE_OBJECTID
,
extent_root
);
BUG_ON
(
ret
);
ret
=
find_and_setup_root
(
super
,
tree_root
,
fs_info
,
BTRFS_INODE_MAP_OBJECTID
,
inode_root
,
fp
);
ret
=
find_and_setup_root
(
disk_
super
,
tree_root
,
fs_info
,
BTRFS_INODE_MAP_OBJECTID
,
inode_root
);
BUG_ON
(
ret
);
ret
=
find_and_setup_root
(
super
,
tree_root
,
fs_info
,
BTRFS_FS_TREE_OBJECTID
,
root
,
fp
);
ret
=
find_and_setup_root
(
disk_
super
,
tree_root
,
fs_info
,
BTRFS_FS_TREE_OBJECTID
,
root
);
BUG_ON
(
ret
);
root
->
commit_root
=
root
->
node
;
root
->
node
->
count
++
;
get_bh
(
root
->
node
)
;
root
->
ref_cows
=
1
;
root
->
fs_info
->
generation
=
root
->
root_key
.
offset
+
1
;
return
root
;
...
...
@@ -336,8 +227,11 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super)
int
write_ctree_super
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
)
{
return
0
;
#if 0
int ret;
btrfs_set_super_root
(
s
,
root
->
fs_info
->
tree_root
->
node
->
blocknr
);
btrfs_set_super_root(s, root->fs_info->tree_root->node->b_blocknr);
ret = pwrite(root->fs_info->fp, s, sizeof(*s),
BTRFS_SUPER_INFO_OFFSET);
if (ret != sizeof(*s)) {
...
...
@@ -345,35 +239,38 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
return ret;
}
return 0;
#endif
}
static
int
drop_cache
(
struct
btrfs_root
*
root
)
{
return
0
;
#if 0
while(!list_empty(&root->fs_info->cache)) {
struct
b
trfs_buffer
*
b
=
list_entry
(
root
->
fs_info
->
cache
.
next
,
struct
b
trfs_buffer
,
struct b
uffer_head
*b = list_entry(root->fs_info->cache.next,
struct b
uffer_head
,
cache);
list_del_init(&b->cache);
btrfs_block_release(root, b);
}
return 0;
#endif
}
int
close_ctree
(
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
)
int
close_ctree
(
struct
btrfs_root
*
root
)
{
int
ret
;
struct
btrfs_trans_handle
*
trans
;
trans
=
root
->
fs_info
->
running_transaction
;
btrfs_commit_transaction
(
trans
,
root
,
s
);
btrfs_commit_transaction
(
trans
,
root
,
root
->
fs_info
->
disk_super
);
ret
=
commit_tree_roots
(
trans
,
root
->
fs_info
);
BUG_ON
(
ret
);
ret
=
__commit_transaction
(
trans
,
root
);
BUG_ON
(
ret
);
write_ctree_super
(
trans
,
root
,
s
);
write_ctree_super
(
trans
,
root
,
root
->
fs_info
->
disk_super
);
drop_cache
(
root
);
BUG_ON
(
!
list_empty
(
&
root
->
fs_info
->
trans
));
close
(
root
->
fs_info
->
fp
);
if
(
root
->
node
)
btrfs_block_release
(
root
,
root
->
node
);
if
(
root
->
fs_info
->
extent_root
->
node
)
...
...
@@ -386,29 +283,17 @@ int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s)
btrfs_block_release
(
root
->
fs_info
->
tree_root
,
root
->
fs_info
->
tree_root
->
node
);
btrfs_block_release
(
root
,
root
->
commit_root
);
free
(
root
);
printf
(
"on close %d blocks are allocated
\n
"
,
allocated_blocks
);
btrfs_block_release
(
root
,
root
->
fs_info
->
sb_buffer
);
kfree
(
root
->
fs_info
->
extent_root
);
kfree
(
root
->
fs_info
->
inode_root
);
kfree
(
root
->
fs_info
->
tree_root
);
kfree
(
root
->
fs_info
);
kfree
(
root
);
return
0
;
}
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
b
uffer_head
*
buf
)
{
buf
->
count
--
;
if
(
buf
->
count
<
0
)
BUG
();
if
(
buf
->
count
==
0
)
{
BUG_ON
(
!
list_empty
(
&
buf
->
cache
));
BUG_ON
(
!
list_empty
(
&
buf
->
dirty
));
if
(
!
radix_tree_lookup
(
&
root
->
fs_info
->
cache_radix
,
buf
->
blocknr
))
BUG
();
radix_tree_delete
(
&
root
->
fs_info
->
cache_radix
,
buf
->
blocknr
);
memset
(
buf
,
0
,
sizeof
(
*
buf
));
free
(
buf
);
BUG_ON
(
allocated_blocks
==
0
);
allocated_blocks
--
;
BUG_ON
(
root
->
fs_info
->
cache_size
==
0
);
root
->
fs_info
->
cache_size
--
;
}
brelse
(
buf
);
}
fs/btrfs/disk-io.h
浏览文件 @
e20d96d6
#ifndef __DISKIO__
#define __DISKIO__
#include "list.h"
struct
btrfs_buffer
{
u64
blocknr
;
int
count
;
struct
list_head
dirty
;
struct
list_head
cache
;
union
{
struct
btrfs_node
node
;
struct
btrfs_leaf
leaf
;
};
};
#include <linux/buffer_head.h>
struct
btrfs_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
struct
btrfs_buffer
*
find_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
static
inline
struct
btrfs_node
*
btrfs_buffer_node
(
struct
buffer_head
*
bh
)
{
return
(
struct
btrfs_node
*
)
bh
->
b_data
;
}
static
inline
struct
btrfs_leaf
*
btrfs_buffer_leaf
(
struct
buffer_head
*
bh
)
{
return
(
struct
btrfs_leaf
*
)
bh
->
b_data
;
}
static
inline
struct
btrfs_header
*
btrfs_buffer_header
(
struct
buffer_head
*
bh
)
{
return
&
((
struct
btrfs_node
*
)
bh
->
b_data
)
->
header
;
}
struct
buffer_head
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
struct
buffer_head
*
find_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
int
write_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
);
struct
b
uffer_head
*
buf
);
int
dirty_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
);
struct
b
uffer_head
*
buf
);
int
clean_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
);
struct
btrfs_root
*
root
,
struct
b
uffer_head
*
buf
);
int
btrfs_commit_transaction
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
);
struct
btrfs_root
*
open_ctree
(
char
*
filename
,
struct
btrfs_super_block
*
s
);
struct
btrfs_root
*
open_ctree_fd
(
int
fp
,
struct
btrfs_super_block
*
super
);
int
close_ctree
(
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
);
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
btrfs_buffer
*
buf
);
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
,
struct
buffer_head
*
sb_buffer
,
struct
btrfs_super_block
*
disk_super
);
int
close_ctree
(
struct
btrfs_root
*
root
);
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
buf
);
int
write_ctree_super
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
);
int
mkfs
(
int
fd
,
u64
num_blocks
,
u32
blocksize
);
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
#endif
fs/btrfs/extent-tree.c
浏览文件 @
e20d96d6
...
...
@@ -10,9 +10,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
search_end
,
struct
btrfs_key
*
ins
);
static
int
finish_current_insert
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
);
static
int
run_pending
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
);
static
int
del_pending_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
);
/*
* pending extents are blocks that we're trying to allocate in the extent
* map while trying to grow the map because of other allocations. To avoid
...
...
@@ -21,6 +20,7 @@ static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root
* manner for deletes.
*/
#define CTREE_EXTENT_PENDING_DEL 0
#define CTREE_EXTENT_PINNED 1
static
int
inc_block_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
)
...
...
@@ -45,15 +45,14 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
ret
!=
0
)
BUG
();
BUG_ON
(
ret
!=
0
);
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
item
=
btrfs_item_ptr
(
l
,
path
.
slots
[
0
],
struct
btrfs_extent_item
);
refs
=
btrfs_extent_refs
(
item
);
btrfs_set_extent_refs
(
item
,
refs
+
1
);
BUG_ON
(
list_empty
(
&
path
.
nodes
[
0
]
->
dirty
));
btrfs_release_path
(
root
->
fs_info
->
extent_root
,
&
path
);
finish_current_insert
(
trans
,
root
->
fs_info
->
extent_root
);
run_pending
(
trans
,
root
->
fs_info
->
extent_root
);
del_pending_extents
(
trans
,
root
->
fs_info
->
extent_root
);
return
0
;
}
...
...
@@ -74,7 +73,7 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
0
,
0
);
if
(
ret
!=
0
)
BUG
();
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
item
=
btrfs_item_ptr
(
l
,
path
.
slots
[
0
],
struct
btrfs_extent_item
);
*
refs
=
btrfs_extent_refs
(
item
);
btrfs_release_path
(
root
->
fs_info
->
extent_root
,
&
path
);
...
...
@@ -82,18 +81,20 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
}
int
btrfs_inc_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
struct
b
uffer_head
*
buf
)
{
u64
blocknr
;
struct
btrfs_node
*
buf_node
;
int
i
;
if
(
!
root
->
ref_cows
)
return
0
;
if
(
btrfs_is_leaf
(
&
buf
->
node
))
buf_node
=
btrfs_buffer_node
(
buf
);
if
(
btrfs_is_leaf
(
buf_node
))
return
0
;
for
(
i
=
0
;
i
<
btrfs_header_nritems
(
&
buf
->
node
.
header
);
i
++
)
{
blocknr
=
btrfs_node_blockptr
(
&
buf
->
node
,
i
);
for
(
i
=
0
;
i
<
btrfs_header_nritems
(
&
buf
_node
->
header
);
i
++
)
{
blocknr
=
btrfs_node_blockptr
(
buf_
node
,
i
);
inc_block_ref
(
trans
,
root
,
blocknr
);
}
return
0
;
...
...
@@ -108,9 +109,10 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
int
i
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup
(
&
root
->
fs_info
->
pinned_radix
,
ret
=
radix_tree_gang_lookup
_tag
(
&
root
->
fs_info
->
pinned_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
));
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PINNED
);
if
(
!
ret
)
break
;
if
(
!
first
)
...
...
@@ -137,7 +139,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
btrfs_set_extent_refs
(
&
extent_item
,
1
);
btrfs_set_extent_owner
(
&
extent_item
,
btrfs_header_parentid
(
&
extent_root
->
node
->
node
.
header
));
btrfs_header_parentid
(
btrfs_buffer_header
(
extent_root
->
node
)
));
ins
.
offset
=
1
;
ins
.
flags
=
0
;
btrfs_set_key_type
(
&
ins
,
BTRFS_EXTENT_ITEM_KEY
);
...
...
@@ -156,11 +158,24 @@ 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
tag
)
{
int
err
;
err
=
radix_tree_insert
(
&
root
->
fs_info
->
pinned_radix
,
blocknr
,
(
void
*
)
blocknr
);
BUG_ON
(
err
);
if
(
err
)
return
err
;
radix_tree_tag_set
(
&
root
->
fs_info
->
pinned_radix
,
blocknr
,
tag
);
return
0
;
}
/*
* remove an extent from the root, returns 0 on success
*/
static
int
__free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
int
pin
)
*
root
,
u64
blocknr
,
u64
num_blocks
)
{
struct
btrfs_path
path
;
struct
btrfs_key
key
;
...
...
@@ -171,7 +186,6 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
struct
btrfs_key
ins
;
u32
refs
;
BUG_ON
(
pin
&&
num_blocks
!=
1
);
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_EXTENT_ITEM_KEY
);
...
...
@@ -186,26 +200,18 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
printk
(
"failed to find %Lu
\n
"
,
key
.
objectid
);
BUG
();
}
ei
=
btrfs_item_ptr
(
&
path
.
nodes
[
0
]
->
leaf
,
path
.
slots
[
0
],
ei
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
,
path
.
slots
[
0
],
struct
btrfs_extent_item
);
BUG_ON
(
ei
->
refs
==
0
);
refs
=
btrfs_extent_refs
(
ei
)
-
1
;
btrfs_set_extent_refs
(
ei
,
refs
);
if
(
refs
==
0
)
{
u64
super_blocks_used
;
if
(
pin
)
{
int
err
;
radix_tree_preload
(
GFP_KERNEL
);
err
=
radix_tree_insert
(
&
info
->
pinned_radix
,
blocknr
,
(
void
*
)
blocknr
);
BUG_ON
(
err
);
radix_tree_preload_end
();
}
super_blocks_used
=
btrfs_super_blocks_used
(
info
->
disk_super
);
btrfs_set_super_blocks_used
(
info
->
disk_super
,
super_blocks_used
-
num_blocks
);
ret
=
btrfs_del_item
(
trans
,
extent_root
,
&
path
);
if
(
!
pin
&&
extent_root
->
fs_info
->
last_insert
.
objectid
>
if
(
extent_root
->
fs_info
->
last_insert
.
objectid
>
blocknr
)
extent_root
->
fs_info
->
last_insert
.
objectid
=
blocknr
;
if
(
ret
)
...
...
@@ -224,39 +230,32 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
btrfs_root
*
extent_root
)
{
int
ret
;
struct
btrfs_buffer
*
gang
[
4
];
int
wret
;
int
err
=
0
;
unsigned
long
gang
[
4
];
int
i
;
struct
radix_tree_root
*
radix
=
&
extent_root
->
fs_info
->
pinned_radix
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
extent_root
->
fs_info
->
cache
_radix
,
&
extent_root
->
fs_info
->
pinned
_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PENDING_DEL
);
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
ret
=
__free_extent
(
trans
,
extent_root
,
gang
[
i
]
->
blocknr
,
1
,
1
);
radix_tree_tag_clear
(
&
extent_root
->
fs_info
->
cache_radix
,
gang
[
i
]
->
blocknr
,
radix_tree_tag_set
(
radix
,
gang
[
i
],
CTREE_EXTENT_PINNED
);
radix_tree_tag_clear
(
radix
,
gang
[
i
],
CTREE_EXTENT_PENDING_DEL
);
btrfs_block_release
(
extent_root
,
gang
[
i
]);
wret
=
__free_extent
(
trans
,
extent_root
,
gang
[
i
],
1
);
if
(
wret
)
err
=
wret
;
}
}
return
0
;
return
err
;
}
static
int
run_pending
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
)
{
while
(
radix_tree_tagged
(
&
extent_root
->
fs_info
->
cache_radix
,
CTREE_EXTENT_PENDING_DEL
))
del_pending_extents
(
trans
,
extent_root
);
return
0
;
}
/*
* remove an extent from the root, returns 0 on success
*/
...
...
@@ -264,18 +263,21 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
int
pin
)
{
struct
btrfs_root
*
extent_root
=
root
->
fs_info
->
extent_root
;
struct
b
trfs_buffer
*
t
;
struct
b
uffer_head
*
t
;
int
pending_ret
;
int
ret
;
if
(
root
==
extent_root
)
{
t
=
find_tree_block
(
root
,
blocknr
);
radix_tree_tag_set
(
&
root
->
fs_info
->
cache_radix
,
blocknr
,
CTREE_EXTENT_PENDING_DEL
);
pin_down_block
(
root
,
blocknr
,
CTREE_EXTENT_PENDING_DEL
);
return
0
;
}
ret
=
__free_extent
(
trans
,
root
,
blocknr
,
num_blocks
,
pin
);
pending_ret
=
run_pending
(
trans
,
root
->
fs_info
->
extent_root
);
if
(
pin
)
{
ret
=
pin_down_block
(
root
,
blocknr
,
CTREE_EXTENT_PINNED
);
BUG_ON
(
ret
);
}
ret
=
__free_extent
(
trans
,
root
,
blocknr
,
num_blocks
);
pending_ret
=
del_pending_extents
(
trans
,
root
->
fs_info
->
extent_root
);
return
ret
?
ret
:
pending_ret
;
}
...
...
@@ -296,14 +298,16 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
int
ret
;
u64
hole_size
=
0
;
int
slot
=
0
;
u64
last_block
;
u64
last_block
=
0
;
u64
test_block
;
int
start_found
;
struct
btrfs_leaf
*
l
;
struct
btrfs_root
*
root
=
orig_root
->
fs_info
->
extent_root
;
int
total_needed
=
num_blocks
;
int
level
;
total_needed
+=
(
btrfs_header_level
(
&
root
->
node
->
node
.
header
)
+
1
)
*
3
;
level
=
btrfs_header_level
(
btrfs_buffer_header
(
root
->
node
));
total_needed
+=
(
level
+
1
)
*
3
;
if
(
root
->
fs_info
->
last_insert
.
objectid
>
search_start
)
search_start
=
root
->
fs_info
->
last_insert
.
objectid
;
...
...
@@ -323,7 +327,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
path
.
slots
[
0
]
--
;
while
(
1
)
{
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
slot
=
path
.
slots
[
0
];
if
(
slot
>=
btrfs_header_nritems
(
&
l
->
header
))
{
ret
=
btrfs_next_leaf
(
root
,
&
path
);
...
...
@@ -429,7 +433,7 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
sizeof
(
extent_item
));
finish_current_insert
(
trans
,
extent_root
);
pending_ret
=
run_pending
(
trans
,
extent_root
);
pending_ret
=
del_pending_extents
(
trans
,
extent_root
);
if
(
ret
)
return
ret
;
if
(
pending_ret
)
...
...
@@ -441,16 +445,15 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
* helper function to allocate a block for a given tree
* returns the tree buffer or NULL.
*/
struct
b
trfs_buffer
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
b
uffer_head
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
struct
btrfs_key
ins
;
int
ret
;
struct
b
trfs_buffer
*
buf
;
struct
b
uffer_head
*
buf
;
ret
=
alloc_extent
(
trans
,
root
,
1
,
0
,
(
unsigned
long
)
-
1
,
btrfs_header_parentid
(
&
root
->
node
->
node
.
header
),
&
ins
);
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)),
&
ins
);
if
(
ret
)
{
BUG
();
return
NULL
;
...
...
@@ -467,13 +470,13 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
static
int
walk_down_tree
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
*
level
)
{
struct
b
trfs_buffer
*
next
;
struct
b
trfs_buffer
*
cur
;
struct
b
uffer_head
*
next
;
struct
b
uffer_head
*
cur
;
u64
blocknr
;
int
ret
;
u32
refs
;
ret
=
lookup_block_ref
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
blocknr
,
ret
=
lookup_block_ref
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
b
_b
locknr
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
>
1
)
...
...
@@ -484,9 +487,10 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
while
(
*
level
>
0
)
{
cur
=
path
->
nodes
[
*
level
];
if
(
path
->
slots
[
*
level
]
>=
btrfs_header_nritems
(
&
cur
->
node
.
header
))
btrfs_header_nritems
(
btrfs_buffer_header
(
cur
)
))
break
;
blocknr
=
btrfs_node_blockptr
(
&
cur
->
node
,
path
->
slots
[
*
level
]);
blocknr
=
btrfs_node_blockptr
(
btrfs_buffer_node
(
cur
),
path
->
slots
[
*
level
]);
ret
=
lookup_block_ref
(
trans
,
root
,
blocknr
,
&
refs
);
if
(
refs
!=
1
||
*
level
==
1
)
{
path
->
slots
[
*
level
]
++
;
...
...
@@ -499,12 +503,12 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
path
->
nodes
[
*
level
-
1
])
btrfs_block_release
(
root
,
path
->
nodes
[
*
level
-
1
]);
path
->
nodes
[
*
level
-
1
]
=
next
;
*
level
=
btrfs_header_level
(
&
next
->
node
.
header
);
*
level
=
btrfs_header_level
(
btrfs_buffer_header
(
next
)
);
path
->
slots
[
*
level
]
=
0
;
}
out:
ret
=
btrfs_free_extent
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
b
locknr
,
1
,
1
);
ret
=
btrfs_free_extent
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
b
_blocknr
,
1
,
1
);
btrfs_block_release
(
root
,
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
*
level
+=
1
;
...
...
@@ -525,14 +529,14 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
int
ret
;
for
(
i
=
*
level
;
i
<
BTRFS_MAX_LEVEL
-
1
&&
path
->
nodes
[
i
];
i
++
)
{
slot
=
path
->
slots
[
i
];
if
(
slot
<
btrfs_
header_nritems
(
&
path
->
nodes
[
i
]
->
node
.
header
)
-
1
)
{
if
(
slot
<
btrfs_header_nritems
(
btrfs_
buffer_header
(
path
->
nodes
[
i
]))
-
1
)
{
path
->
slots
[
i
]
++
;
*
level
=
i
;
return
0
;
}
else
{
ret
=
btrfs_free_extent
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
blocknr
,
path
->
nodes
[
*
level
]
->
b
_b
locknr
,
1
,
1
);
btrfs_block_release
(
root
,
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
...
...
@@ -549,7 +553,7 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
* decremented.
*/
int
btrfs_drop_snapshot
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
snap
)
*
root
,
struct
b
uffer_head
*
snap
)
{
int
ret
=
0
;
int
wret
;
...
...
@@ -560,7 +564,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_init_path
(
&
path
);
level
=
btrfs_header_level
(
&
snap
->
node
.
header
);
level
=
btrfs_header_level
(
btrfs_buffer_header
(
snap
)
);
orig_level
=
level
;
path
.
nodes
[
level
]
=
snap
;
path
.
slots
[
level
]
=
0
;
...
...
fs/btrfs/hash.c
浏览文件 @
e20d96d6
...
...
@@ -10,6 +10,7 @@
* License.
*/
#include <linux/types.h>
#define DELTA 0x9E3779B9
static
void
TEA_transform
(
__u32
buf
[
2
],
__u32
const
in
[])
...
...
@@ -63,6 +64,14 @@ int btrfs_name_hash(const char *name, int len, u64 *hash_result)
const
char
*
p
;
__u32
in
[
8
],
buf
[
2
];
if
(
len
==
1
&&
*
name
==
'.'
)
{
*
hash_result
=
1
;
return
0
;
}
else
if
(
len
==
2
&&
name
[
0
]
==
'.'
&&
name
[
1
]
==
'.'
)
{
*
hash_result
=
2
;
return
0
;
}
/* Initialize the default seed for the hash checksum functions */
buf
[
0
]
=
0x67452301
;
buf
[
1
]
=
0xefcdab89
;
...
...
fs/btrfs/inode-map.c
浏览文件 @
e20d96d6
...
...
@@ -15,7 +15,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
int
ret
;
u64
hole_size
=
0
;
int
slot
=
0
;
u64
last_ino
;
u64
last_ino
=
0
;
int
start_found
;
struct
btrfs_leaf
*
l
;
struct
btrfs_root
*
root
=
fs_root
->
fs_info
->
inode_root
;
...
...
@@ -40,7 +40,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
path
.
slots
[
0
]
--
;
while
(
1
)
{
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
slot
=
path
.
slots
[
0
];
if
(
slot
>=
btrfs_header_nritems
(
&
l
->
header
))
{
ret
=
btrfs_next_leaf
(
root
,
&
path
);
...
...
@@ -105,8 +105,8 @@ int btrfs_insert_inode_map(struct btrfs_trans_handle *trans,
if
(
ret
)
goto
out
;
inode_item
=
btrfs_item_ptr
(
&
path
.
nodes
[
0
]
->
leaf
,
path
.
slots
[
0
]
,
struct
btrfs_inode_map_item
);
inode_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
,
path
.
slots
[
0
],
struct
btrfs_inode_map_item
);
btrfs_cpu_key_to_disk
(
&
inode_item
->
key
,
location
);
out:
btrfs_release_path
(
inode_root
,
&
path
);
...
...
fs/btrfs/print-tree.c
浏览文件 @
e20d96d6
...
...
@@ -17,7 +17,6 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
printk
(
"leaf %Lu total ptrs %d free space %d
\n
"
,
btrfs_header_blocknr
(
&
l
->
header
),
nr
,
btrfs_leaf_free_space
(
root
,
l
));
fflush
(
stdout
);
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
item
=
l
->
items
+
i
;
type
=
btrfs_disk_key_type
(
&
item
->
key
);
...
...
@@ -67,10 +66,10 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
btrfs_leaf_data
(
l
)
+
btrfs_item_offset
(
item
));
break
;
};
fflush
(
stdout
);
}
}
void
btrfs_print_tree
(
struct
btrfs_root
*
root
,
struct
btrfs_buffer
*
t
)
void
btrfs_print_tree
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
t
)
{
int
i
;
u32
nr
;
...
...
@@ -78,16 +77,16 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t)
if
(
!
t
)
return
;
c
=
&
t
->
node
;
c
=
btrfs_buffer_node
(
t
)
;
nr
=
btrfs_header_nritems
(
&
c
->
header
);
if
(
btrfs_is_leaf
(
c
))
{
btrfs_print_leaf
(
root
,
(
struct
btrfs_leaf
*
)
c
);
return
;
}
printk
(
"node %Lu level %d total ptrs %d free spc %u
\n
"
,
t
->
blocknr
,
btrfs_header_level
(
&
c
->
header
),
nr
,
(
u32
)
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
-
nr
);
fflush
(
stdout
);
printk
(
"node %Lu level %d total ptrs %d free spc %u
\n
"
,
btrfs_header_blocknr
(
&
c
->
header
)
,
btrfs_header_level
(
&
c
->
header
),
nr
,
(
u32
)
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
-
nr
);
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
printk
(
"
\t
key %d (%Lu %u %Lu) block %Lu
\n
"
,
i
,
...
...
@@ -95,12 +94,11 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t)
c
->
ptrs
[
i
].
key
.
flags
,
c
->
ptrs
[
i
].
key
.
offset
,
btrfs_node_blockptr
(
c
,
i
));
fflush
(
stdout
);
}
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
struct
b
trfs_buffer
*
next_buf
=
read_tree_block
(
root
,
struct
b
uffer_head
*
next_buf
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
c
,
i
));
struct
btrfs_node
*
next
=
&
next_buf
->
node
;
struct
btrfs_node
*
next
=
btrfs_buffer_node
(
next_buf
)
;
if
(
btrfs_is_leaf
(
next
)
&&
btrfs_header_level
(
&
c
->
header
)
!=
1
)
BUG
();
...
...
fs/btrfs/print-tree.h
浏览文件 @
e20d96d6
#ifndef __PRINT_TREE_
#define __PRINT_TREE_
void
btrfs_print_leaf
(
struct
btrfs_root
*
root
,
struct
btrfs_leaf
*
l
);
void
btrfs_print_tree
(
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
t
);
void
btrfs_print_tree
(
struct
btrfs_root
*
root
,
struct
b
uffer_head
*
t
);
#endif
fs/btrfs/root-tree.c
浏览文件 @
e20d96d6
...
...
@@ -21,7 +21,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
if
(
ret
<
0
)
goto
out
;
BUG_ON
(
ret
==
0
);
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
BUG_ON
(
path
.
slots
[
0
]
==
0
);
slot
=
path
.
slots
[
0
]
-
1
;
if
(
btrfs_disk_key_objectid
(
&
l
->
items
[
slot
].
key
)
!=
objectid
)
{
...
...
@@ -51,7 +51,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
ret
<
0
)
goto
out
;
BUG_ON
(
ret
!=
0
);
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
slot
=
path
.
slots
[
0
];
memcpy
(
btrfs_item_ptr
(
l
,
slot
,
struct
btrfs_root_item
),
item
,
sizeof
(
*
item
));
...
...
fs/btrfs/super.c
浏览文件 @
e20d96d6
#include <linux/module.h>
#include <linux/buffer_head.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
...
...
@@ -8,13 +9,18 @@
#include <linux/smp_lock.h>
#include <linux/backing-dev.h>
#include "ctree.h"
#include "disk-io.h"
#define BTRFS_SUPER_MAGIC 0x9123682E
static
struct
inode_operations
btrfs_dir_inode_operations
;
static
struct
super_operations
btrfs_super_ops
;
static
struct
file_operations
btrfs_dir_file_operations
;
#if 0
/* some random number */
static struct super_operations ramfs_ops;
static struct inode_operations ramfs_dir_inode_operations;
static struct backing_dev_info ramfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
...
...
@@ -129,46 +135,243 @@ static struct inode_operations ramfs_dir_inode_operations = {
};
#endif
st
ruct
inode
*
btrfs_get_inode
(
struct
super_block
*
sb
,
int
mode
,
dev_t
dev
)
st
atic
void
btrfs_read_locked_inode
(
struct
inode
*
inode
)
{
struct
inode
*
inode
=
new_inode
(
sb
);
struct
btrfs_path
path
;
struct
btrfs_inode_item
*
inode_item
;
struct
btrfs_root
*
root
=
btrfs_sb
(
inode
->
i_sb
);
int
ret
;
printk
(
"read locked inode %lu
\n
"
,
inode
->
i_ino
);
btrfs_init_path
(
&
path
);
ret
=
btrfs_lookup_inode
(
NULL
,
root
,
&
path
,
inode
->
i_ino
,
0
);
if
(
ret
)
{
make_bad_inode
(
inode
);
return
;
}
inode_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
]),
path
.
slots
[
0
],
struct
btrfs_inode_item
);
if
(
inode
)
{
inode
->
i_mode
=
mode
;
inode
->
i_uid
=
current
->
fsuid
;
inode
->
i_gid
=
current
->
fsgid
;
inode
->
i_blocks
=
0
;
inode
->
i_atime
=
inode
->
i_mtime
=
inode
->
i_ctime
=
CURRENT_TIME
;
printk
(
"found locked inode %lu
\n
"
,
inode
->
i_ino
);
inode
->
i_mode
=
btrfs_inode_mode
(
inode_item
);
inode
->
i_nlink
=
btrfs_inode_nlink
(
inode_item
);
inode
->
i_uid
=
btrfs_inode_uid
(
inode_item
);
inode
->
i_gid
=
btrfs_inode_gid
(
inode_item
);
inode
->
i_size
=
btrfs_inode_size
(
inode_item
);
inode
->
i_atime
.
tv_sec
=
btrfs_timespec_sec
(
&
inode_item
->
atime
);
inode
->
i_atime
.
tv_nsec
=
btrfs_timespec_nsec
(
&
inode_item
->
atime
);
inode
->
i_mtime
.
tv_sec
=
btrfs_timespec_sec
(
&
inode_item
->
mtime
);
inode
->
i_mtime
.
tv_nsec
=
btrfs_timespec_nsec
(
&
inode_item
->
mtime
);
inode
->
i_ctime
.
tv_sec
=
btrfs_timespec_sec
(
&
inode_item
->
ctime
);
inode
->
i_ctime
.
tv_nsec
=
btrfs_timespec_nsec
(
&
inode_item
->
ctime
);
inode
->
i_blocks
=
btrfs_inode_nblocks
(
inode_item
);
inode
->
i_generation
=
btrfs_inode_generation
(
inode_item
);
printk
(
"about to release
\n
"
);
btrfs_release_path
(
root
,
&
path
);
switch
(
inode
->
i_mode
&
S_IFMT
)
{
#if 0
default:
init_special_inode(inode, inode->i_mode,
btrfs_inode_rdev(inode_item));
break;
#endif
case
S_IFREG
:
printk
(
"inode %lu now a file
\n
"
,
inode
->
i_ino
);
break
;
case
S_IFDIR
:
printk
(
"inode %lu now a directory
\n
"
,
inode
->
i_ino
);
inode
->
i_op
=
&
btrfs_dir_inode_operations
;
inode
->
i_fop
=
&
btrfs_dir_file_operations
;
break
;
case
S_IFLNK
:
printk
(
"inode %lu now a link
\n
"
,
inode
->
i_ino
);
// inode->i_op = &page_symlink_inode_operations;
break
;
}
return
inode
;
printk
(
"returning!
\n
"
);
return
;
}
static
struct
super_operations
btrfs_ops
=
{
.
statfs
=
simple_statfs
,
.
drop_inode
=
generic_delete_inode
,
};
static
int
btrfs_inode_by_name
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
ino_t
*
ino
)
{
const
char
*
name
=
dentry
->
d_name
.
name
;
int
namelen
=
dentry
->
d_name
.
len
;
struct
btrfs_dir_item
*
di
;
struct
btrfs_path
path
;
struct
btrfs_root
*
root
=
btrfs_sb
(
dir
->
i_sb
);
int
ret
;
btrfs_init_path
(
&
path
);
ret
=
btrfs_lookup_dir_item
(
NULL
,
root
,
&
path
,
dir
->
i_ino
,
name
,
namelen
,
0
);
if
(
ret
)
{
*
ino
=
0
;
goto
out
;
}
di
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
]),
path
.
slots
[
0
],
struct
btrfs_dir_item
);
*
ino
=
btrfs_dir_objectid
(
di
);
out:
btrfs_release_path
(
root
,
&
path
);
return
ret
;
}
static
struct
dentry
*
btrfs_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
struct
inode
*
inode
;
ino_t
ino
;
int
ret
;
if
(
dentry
->
d_name
.
len
>
BTRFS_NAME_LEN
)
return
ERR_PTR
(
-
ENAMETOOLONG
);
ret
=
btrfs_inode_by_name
(
dir
,
dentry
,
&
ino
);
if
(
ret
<
0
)
return
ERR_PTR
(
ret
);
inode
=
NULL
;
if
(
ino
)
{
printk
(
"lookup on %.*s returns %lu
\n
"
,
dentry
->
d_name
.
len
,
dentry
->
d_name
.
name
,
ino
);
inode
=
iget
(
dir
->
i_sb
,
ino
);
if
(
!
inode
)
return
ERR_PTR
(
-
EACCES
);
}
return
d_splice_alias
(
inode
,
dentry
);
}
static
int
btrfs_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
{
struct
inode
*
inode
=
filp
->
f_path
.
dentry
->
d_inode
;
struct
btrfs_root
*
root
=
btrfs_sb
(
inode
->
i_sb
);
struct
btrfs_item
*
item
;
struct
btrfs_dir_item
*
di
;
struct
btrfs_key
key
;
struct
btrfs_path
path
;
int
ret
;
u32
nritems
;
struct
btrfs_leaf
*
leaf
;
int
slot
;
int
advance
;
unsigned
char
d_type
=
DT_UNKNOWN
;
int
over
;
key
.
objectid
=
inode
->
i_ino
;
printk
(
"readdir on dir %Lu pos %Lu
\n
"
,
key
.
objectid
,
filp
->
f_pos
);
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_DIR_ITEM_KEY
);
key
.
offset
=
filp
->
f_pos
;
btrfs_init_path
(
&
path
);
ret
=
btrfs_search_slot
(
NULL
,
root
,
&
key
,
&
path
,
0
,
0
);
if
(
ret
<
0
)
{
goto
err
;
}
printk
(
"first ret %d
\n
"
,
ret
);
advance
=
filp
->
f_pos
>
0
&&
ret
!=
0
;
while
(
1
)
{
leaf
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
]);
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
slot
=
path
.
slots
[
0
];
printk
(
"leaf %Lu nritems %lu slot %d
\n
"
,
path
.
nodes
[
0
]
->
b_blocknr
,
nritems
,
slot
);
if
(
advance
)
{
printk
(
"advancing!
\n
"
);
if
(
slot
==
nritems
-
1
)
{
ret
=
btrfs_next_leaf
(
root
,
&
path
);
if
(
ret
)
break
;
leaf
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
]);
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
slot
=
path
.
slots
[
0
];
printk
(
"2leaf %Lu nritems %lu slot %d
\n
"
,
path
.
nodes
[
0
]
->
b_blocknr
,
nritems
,
slot
);
}
else
{
slot
++
;
path
.
slots
[
0
]
++
;
}
}
advance
=
1
;
item
=
leaf
->
items
+
slot
;
printk
(
"item key %Lu %u %Lu
\n
"
,
btrfs_disk_key_objectid
(
&
item
->
key
),
btrfs_disk_key_flags
(
&
item
->
key
),
btrfs_disk_key_offset
(
&
item
->
key
));
if
(
btrfs_disk_key_objectid
(
&
item
->
key
)
!=
key
.
objectid
)
break
;
if
(
btrfs_disk_key_type
(
&
item
->
key
)
!=
BTRFS_DIR_ITEM_KEY
)
continue
;
di
=
btrfs_item_ptr
(
leaf
,
slot
,
struct
btrfs_dir_item
);
printk
(
"filldir name %.*s, objectid %Lu
\n
"
,
btrfs_dir_name_len
(
di
),
(
const
char
*
)(
di
+
1
),
btrfs_dir_objectid
(
di
));
over
=
filldir
(
dirent
,
(
const
char
*
)(
di
+
1
),
btrfs_dir_name_len
(
di
),
btrfs_disk_key_offset
(
&
item
->
key
),
btrfs_dir_objectid
(
di
),
d_type
);
if
(
over
)
break
;
filp
->
f_pos
=
btrfs_disk_key_offset
(
&
item
->
key
)
+
1
;
}
printk
(
"filldir all done
\n
"
);
ret
=
0
;
err:
btrfs_release_path
(
root
,
&
path
);
return
ret
;
}
static
void
btrfs_put_super
(
struct
super_block
*
sb
)
{
struct
btrfs_root
*
root
=
btrfs_sb
(
sb
);
int
ret
;
ret
=
close_ctree
(
root
);
if
(
ret
)
{
printk
(
"close ctree returns %d
\n
"
,
ret
);
}
sb
->
s_fs_info
=
NULL
;
}
static
int
btrfs_fill_super
(
struct
super_block
*
sb
,
void
*
data
,
int
silent
)
{
struct
inode
*
inode
;
struct
dentry
*
root
;
struct
dentry
*
root_dentry
;
struct
btrfs_super_block
*
disk_super
;
struct
buffer_head
*
bh
;
struct
btrfs_root
*
root
;
sb
->
s_maxbytes
=
MAX_LFS_FILESIZE
;
sb
->
s_blocksize
=
PAGE_CACHE_SIZE
;
sb
->
s_blocksize_bits
=
PAGE_CACHE_SHIFT
;
sb
->
s_magic
=
BTRFS_SUPER_MAGIC
;
sb
->
s_op
=
&
btrfs_ops
;
sb
->
s_op
=
&
btrfs_
super_
ops
;
sb
->
s_time_gran
=
1
;
inode
=
btrfs_get_inode
(
sb
,
S_IFDIR
|
0755
,
0
);
bh
=
sb_bread
(
sb
,
BTRFS_SUPER_INFO_OFFSET
/
sb
->
s_blocksize
);
if
(
!
bh
)
{
printk
(
"btrfs: unable to read on disk super
\n
"
);
return
-
EIO
;
}
disk_super
=
(
struct
btrfs_super_block
*
)
bh
->
b_data
;
root
=
open_ctree
(
sb
,
bh
,
disk_super
);
sb
->
s_fs_info
=
root
;
if
(
!
root
)
{
printk
(
"btrfs: open_ctree failed
\n
"
);
return
-
EIO
;
}
printk
(
"read in super total blocks %Lu root %Lu
\n
"
,
btrfs_super_total_blocks
(
disk_super
),
btrfs_super_root_dir
(
disk_super
));
inode
=
iget_locked
(
sb
,
btrfs_super_root_dir
(
disk_super
));
if
(
!
inode
)
return
-
ENOMEM
;
if
(
inode
->
i_state
&
I_NEW
)
{
btrfs_read_locked_inode
(
inode
);
unlock_new_inode
(
inode
);
}
root
=
d_alloc_root
(
inode
);
if
(
!
root
)
{
root
_dentry
=
d_alloc_root
(
inode
);
if
(
!
root
_dentry
)
{
iput
(
inode
);
return
-
ENOMEM
;
}
sb
->
s_root
=
root
;
sb
->
s_root
=
root_dentry
;
return
0
;
}
...
...
@@ -187,6 +390,24 @@ static struct file_system_type btrfs_fs_type = {
.
fs_flags
=
FS_REQUIRES_DEV
,
};
static
struct
super_operations
btrfs_super_ops
=
{
.
statfs
=
simple_statfs
,
.
drop_inode
=
generic_delete_inode
,
.
put_super
=
btrfs_put_super
,
.
read_inode
=
btrfs_read_locked_inode
,
};
static
struct
inode_operations
btrfs_dir_inode_operations
=
{
.
lookup
=
btrfs_lookup
,
};
static
struct
file_operations
btrfs_dir_file_operations
=
{
.
llseek
=
generic_file_llseek
,
.
read
=
generic_read_dir
,
.
readdir
=
btrfs_readdir
,
};
static
int
__init
init_btrfs_fs
(
void
)
{
printk
(
"btrfs loaded!
\n
"
);
...
...
fs/btrfs/transaction.h
浏览文件 @
e20d96d6
...
...
@@ -10,7 +10,7 @@ struct btrfs_trans_handle {
static
inline
struct
btrfs_trans_handle
*
btrfs_start_transaction
(
struct
btrfs_root
*
root
,
int
num_blocks
)
{
struct
btrfs_trans_handle
*
h
=
malloc
(
sizeof
(
*
h
)
);
struct
btrfs_trans_handle
*
h
=
kmalloc
(
sizeof
(
*
h
),
GFP_NOFS
);
h
->
transid
=
root
->
root_key
.
offset
;
h
->
blocks_reserved
=
num_blocks
;
h
->
blocks_used
=
0
;
...
...
@@ -21,7 +21,7 @@ static inline void btrfs_free_transaction(struct btrfs_root *root,
struct
btrfs_trans_handle
*
handle
)
{
memset
(
handle
,
0
,
sizeof
(
*
handle
));
free
(
handle
);
k
free
(
handle
);
}
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录