Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Linux-御风守护者
linux
提交
b18c6685
L
linux
项目概览
Linux-御风守护者
/
linux
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
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,发现更多精彩内容 >>
提交
b18c6685
编写于
4月 17, 2007
作者:
C
Chris Mason
提交者:
David Woodhouse
4月 17, 2007
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Btrfs: progress on file_write
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
6567e837
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
394 addition
and
49 deletion
+394
-49
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+57
-0
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+16
-5
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+11
-9
fs/btrfs/file-item.c
fs/btrfs/file-item.c
+41
-20
fs/btrfs/super.c
fs/btrfs/super.c
+269
-15
未找到文件。
fs/btrfs/ctree.c
浏览文件 @
b18c6685
...
...
@@ -1249,6 +1249,63 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
return
ret
;
}
int
btrfs_truncate_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u32
new_size
)
{
int
ret
=
0
;
int
slot
;
int
slot_orig
;
struct
btrfs_leaf
*
leaf
;
struct
buffer_head
*
leaf_buf
;
u32
nritems
;
unsigned
int
data_end
;
unsigned
int
old_data_start
;
unsigned
int
old_size
;
unsigned
int
size_diff
;
int
i
;
slot_orig
=
path
->
slots
[
0
];
leaf_buf
=
path
->
nodes
[
0
];
leaf
=
btrfs_buffer_leaf
(
leaf_buf
);
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
data_end
=
leaf_data_end
(
root
,
leaf
);
slot
=
path
->
slots
[
0
];
old_data_start
=
btrfs_item_offset
(
leaf
->
items
+
slot
);
old_size
=
btrfs_item_size
(
leaf
->
items
+
slot
);
BUG_ON
(
old_size
<=
new_size
);
size_diff
=
old_size
-
new_size
;
BUG_ON
(
slot
<
0
);
BUG_ON
(
slot
>=
nritems
);
/*
* item0..itemN ... dataN.offset..dataN.size .. data0.size
*/
/* first correct the data pointers */
for
(
i
=
slot
;
i
<
nritems
;
i
++
)
{
u32
ioff
=
btrfs_item_offset
(
leaf
->
items
+
i
);
btrfs_set_item_offset
(
leaf
->
items
+
i
,
ioff
+
size_diff
);
}
/* shift the data */
printk
(
"truncate item, new_size %u old_size %u, diff %u, bufp %p, dst, %p, num %u, old_data_start %u, data_end %u
\n
"
,
new_size
,
old_size
,
size_diff
,
leaf
,
btrfs_leaf_data
(
leaf
)
+
data_end
+
size_diff
,
old_data_start
-
data_end
,
old_data_start
,
data_end
);
btrfs_memmove
(
root
,
leaf
,
btrfs_leaf_data
(
leaf
)
+
data_end
+
size_diff
,
btrfs_leaf_data
(
leaf
)
+
data_end
,
old_data_start
+
new_size
-
data_end
);
btrfs_set_item_size
(
leaf
->
items
+
slot
,
new_size
);
btrfs_mark_buffer_dirty
(
leaf_buf
);
ret
=
0
;
if
(
btrfs_leaf_free_space
(
root
,
leaf
)
<
0
)
BUG
();
check_leaf
(
root
,
path
,
0
);
return
ret
;
}
int
btrfs_extend_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u32
data_size
)
{
...
...
fs/btrfs/ctree.h
浏览文件 @
b18c6685
...
...
@@ -999,7 +999,7 @@ static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh)
((type *)(btrfs_leaf_data(leaf) + \
btrfs_item_offset((leaf)->items + (slot))))
/* extent-
item
.c */
/* extent-
tree
.c */
int
btrfs_inc_root_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
struct
buffer_head
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
...
...
@@ -1013,9 +1013,16 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
int
pin
);
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
int
btrfs_inc_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
);
/* ctree.c */
int
btrfs_extend_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u32
data_size
);
int
btrfs_truncate_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u32
new_size
);
int
btrfs_search_slot
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_key
*
key
,
struct
btrfs_path
*
p
,
int
ins_len
,
int
cow
);
...
...
@@ -1073,11 +1080,10 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
struct
btrfs_key
*
location
,
int
mod
);
/* file-item.c */
int
btrfs_
alloc
_file_extent
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_
insert
_file_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
objectid
,
u64
offset
,
u64
num_blocks
,
u64
hint_block
,
u64
*
result
);
u64
objectid
,
u64
pos
,
u64
offset
,
u64
num_blocks
);
int
btrfs_lookup_file_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
objectid
,
...
...
@@ -1090,6 +1096,11 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
int
btrfs_csum_verify_file_block
(
struct
btrfs_root
*
root
,
u64
objectid
,
u64
offset
,
char
*
data
,
size_t
len
);
struct
btrfs_csum_item
*
btrfs_lookup_csum
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
objectid
,
u64
offset
,
int
cow
);
/* super.c */
extern
struct
subsystem
btrfs_subsys
;
...
...
fs/btrfs/extent-tree.c
浏览文件 @
b18c6685
...
...
@@ -12,8 +12,9 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
static
int
del_pending_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
);
static
int
inc_block_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
)
int
btrfs_inc_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
)
{
struct
btrfs_path
*
path
;
int
ret
;
...
...
@@ -50,8 +51,9 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
return
0
;
}
static
int
lookup_block_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
u32
*
refs
)
static
int
lookup_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
u32
*
refs
)
{
struct
btrfs_path
*
path
;
int
ret
;
...
...
@@ -80,7 +82,7 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
int
btrfs_inc_root_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
return
inc_block
_ref
(
trans
,
root
,
bh_blocknr
(
root
->
node
),
1
);
return
btrfs_inc_extent
_ref
(
trans
,
root
,
bh_blocknr
(
root
->
node
),
1
);
}
int
btrfs_inc_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
...
...
@@ -107,13 +109,13 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
continue
;
fi
=
btrfs_item_ptr
(
buf_leaf
,
i
,
struct
btrfs_file_extent_item
);
ret
=
inc_block
_ref
(
trans
,
root
,
ret
=
btrfs_inc_extent
_ref
(
trans
,
root
,
btrfs_file_extent_disk_blocknr
(
fi
),
btrfs_file_extent_disk_num_blocks
(
fi
));
BUG_ON
(
ret
);
}
else
{
blocknr
=
btrfs_node_blockptr
(
buf_node
,
i
);
ret
=
inc_block
_ref
(
trans
,
root
,
blocknr
,
1
);
ret
=
btrfs_inc_extent
_ref
(
trans
,
root
,
blocknr
,
1
);
BUG_ON
(
ret
);
}
}
...
...
@@ -563,7 +565,7 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
WARN_ON
(
*
level
<
0
);
WARN_ON
(
*
level
>=
BTRFS_MAX_LEVEL
);
ret
=
lookup_
block
_ref
(
trans
,
root
,
bh_blocknr
(
path
->
nodes
[
*
level
]),
ret
=
lookup_
extent
_ref
(
trans
,
root
,
bh_blocknr
(
path
->
nodes
[
*
level
]),
1
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
>
1
)
...
...
@@ -587,7 +589,7 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
}
blocknr
=
btrfs_node_blockptr
(
btrfs_buffer_node
(
cur
),
path
->
slots
[
*
level
]);
ret
=
lookup_
block
_ref
(
trans
,
root
,
blocknr
,
1
,
&
refs
);
ret
=
lookup_
extent
_ref
(
trans
,
root
,
blocknr
,
1
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
!=
1
)
{
path
->
slots
[
*
level
]
++
;
...
...
fs/btrfs/file-item.c
浏览文件 @
b18c6685
...
...
@@ -6,13 +6,11 @@
#define MAX_CSUM_ITEMS(r) ((((BTRFS_LEAF_DATA_SIZE(r) - \
sizeof(struct btrfs_item)) / \
sizeof(struct btrfs_csum_item)) - 1))
int
btrfs_
alloc
_file_extent
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_
insert
_file_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
objectid
,
u64
offset
,
u64
num_blocks
,
u64
hint_block
,
u64
*
result
)
u64
objectid
,
u64
pos
,
u64
offset
,
u64
num_blocks
)
{
struct
btrfs_key
ins
;
int
ret
=
0
;
struct
btrfs_file_extent_item
*
item
;
struct
btrfs_key
file_key
;
...
...
@@ -21,11 +19,13 @@ int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans,
path
=
btrfs_alloc_path
();
BUG_ON
(
!
path
);
btrfs_init_path
(
path
);
/*
ret = btrfs_alloc_extent(trans, root, num_blocks, hint_block,
(u64)-1, &ins);
*/
BUG_ON
(
ret
);
file_key
.
objectid
=
objectid
;
file_key
.
offset
=
offset
;
file_key
.
offset
=
pos
;
file_key
.
flags
=
0
;
btrfs_set_key_type
(
&
file_key
,
BTRFS_EXTENT_DATA_KEY
);
...
...
@@ -34,21 +34,22 @@ int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans,
BUG_ON
(
ret
);
item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_file_extent_item
);
btrfs_set_file_extent_disk_blocknr
(
item
,
ins
.
objectid
);
btrfs_set_file_extent_disk_num_blocks
(
item
,
ins
.
offset
);
btrfs_set_file_extent_disk_blocknr
(
item
,
offset
);
btrfs_set_file_extent_disk_num_blocks
(
item
,
num_blocks
);
btrfs_set_file_extent_offset
(
item
,
0
);
btrfs_set_file_extent_num_blocks
(
item
,
ins
.
offset
);
btrfs_set_file_extent_num_blocks
(
item
,
num_blocks
);
btrfs_set_file_extent_generation
(
item
,
trans
->
transid
);
btrfs_mark_buffer_dirty
(
path
->
nodes
[
0
]);
*
result
=
ins
.
objectid
;
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
return
0
;
}
static
struct
btrfs_csum_item
*
__lookup_csum_item
(
struct
btrfs_root
*
root
,
struct
btrfs_csum_item
*
btrfs_lookup_csum
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
objectid
,
u64
offset
)
u64
objectid
,
u64
offset
,
int
cow
)
{
int
ret
;
struct
btrfs_key
file_key
;
...
...
@@ -61,19 +62,23 @@ static struct btrfs_csum_item *__lookup_csum_item(struct btrfs_root *root,
file_key
.
offset
=
offset
;
file_key
.
flags
=
0
;
btrfs_set_key_type
(
&
file_key
,
BTRFS_CSUM_ITEM_KEY
);
ret
=
btrfs_search_slot
(
NULL
,
root
,
&
file_key
,
path
,
0
,
0
);
printk
(
"__lookup for %Lu
\n
"
,
offset
);
ret
=
btrfs_search_slot
(
trans
,
root
,
&
file_key
,
path
,
0
,
cow
);
if
(
ret
<
0
)
goto
fail
;
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
if
(
ret
>
0
)
{
ret
=
1
;
if
(
path
->
slots
[
0
]
==
0
)
if
(
path
->
slots
[
0
]
==
0
)
{
printk
(
"fail1
\n
"
);
goto
fail
;
}
path
->
slots
[
0
]
--
;
btrfs_disk_key_to_cpu
(
&
found_key
,
&
leaf
->
items
[
path
->
slots
[
0
]].
key
);
if
(
btrfs_key_type
(
&
found_key
)
!=
BTRFS_CSUM_ITEM_KEY
||
found_key
.
objectid
!=
objectid
)
{
printk
(
"fail2 type %u %Lu %Lu
\n
"
,
btrfs_key_type
(
&
found_key
),
found_key
.
objectid
,
objectid
);
goto
fail
;
}
csum_offset
=
(
offset
-
found_key
.
offset
)
>>
...
...
@@ -81,6 +86,7 @@ static struct btrfs_csum_item *__lookup_csum_item(struct btrfs_root *root,
if
(
csum_offset
>=
btrfs_item_size
(
leaf
->
items
+
path
->
slots
[
0
])
/
sizeof
(
struct
btrfs_csum_item
))
{
printk
(
"fail3, csum offset %lu size %u
\n
"
,
csum_offset
,
btrfs_item_size
(
leaf
->
items
+
path
->
slots
[
0
])
/
sizeof
(
struct
btrfs_csum_item
));
goto
fail
;
}
}
...
...
@@ -89,7 +95,7 @@ static struct btrfs_csum_item *__lookup_csum_item(struct btrfs_root *root,
return
item
;
fail:
if
(
ret
>
0
)
ret
=
-
E
IO
;
ret
=
-
E
NOENT
;
return
ERR_PTR
(
ret
);
}
...
...
@@ -105,7 +111,7 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
int
cow
=
mod
!=
0
;
struct
btrfs_csum_item
*
csum_item
;
csum_item
=
__lookup_csum_item
(
root
,
path
,
objectid
,
offset
);
csum_item
=
btrfs_lookup_csum
(
trans
,
root
,
path
,
objectid
,
offset
,
0
);
if
(
IS_ERR
(
csum_item
))
return
PTR_ERR
(
csum_item
);
file_key
.
objectid
=
objectid
;
...
...
@@ -113,7 +119,9 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
file_key
.
flags
=
0
;
btrfs_set_key_type
(
&
file_key
,
BTRFS_EXTENT_DATA_KEY
);
btrfs_release_path
(
root
,
path
);
printk
(
"lookup file extent searches for %Lu
\n
"
,
file_key
.
offset
);
ret
=
btrfs_search_slot
(
trans
,
root
,
&
file_key
,
path
,
ins_len
,
cow
);
printk
(
"ret is %d
\n
"
,
ret
);
return
ret
;
}
...
...
@@ -134,17 +142,23 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
path
=
btrfs_alloc_path
();
BUG_ON
(
!
path
);
btrfs_init_path
(
path
);
item
=
btrfs_lookup_csum
(
trans
,
root
,
path
,
objectid
,
offset
,
0
);
if
(
!
IS_ERR
(
item
))
goto
found
;
btrfs_release_path
(
root
,
path
);
file_key
.
objectid
=
objectid
;
file_key
.
offset
=
offset
;
file_key
.
flags
=
0
;
btrfs_set_key_type
(
&
file_key
,
BTRFS_CSUM_ITEM_KEY
);
printk
(
"searching for csum %Lu %Lu
\n
"
,
objectid
,
offset
);
ret
=
btrfs_search_slot
(
trans
,
root
,
&
file_key
,
path
,
sizeof
(
struct
btrfs_csum_item
),
1
);
printk
(
"ret %d
\n
"
,
ret
);
if
(
ret
<
0
)
goto
fail
;
if
(
ret
==
0
)
{
csum_offset
=
0
;
goto
csum
;
BUG
();
}
if
(
path
->
slots
[
0
]
==
0
)
{
btrfs_release_path
(
root
,
path
);
...
...
@@ -153,12 +167,15 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
path
->
slots
[
0
]
--
;
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
btrfs_disk_key_to_cpu
(
&
found_key
,
&
leaf
->
items
[
path
->
slots
[
0
]].
key
);
printk
(
"found key %Lu %Lu %u
\n
"
,
found_key
.
objectid
,
found_key
.
offset
,
found_key
.
flags
);
csum_offset
=
(
offset
-
found_key
.
offset
)
>>
root
->
fs_info
->
sb
->
s_blocksize_bits
;
printk
(
"csum_offset %Lu
\n
"
,
csum_offset
);
if
(
btrfs_key_type
(
&
found_key
)
!=
BTRFS_CSUM_ITEM_KEY
||
found_key
.
objectid
!=
objectid
||
csum_offset
>=
MAX_CSUM_ITEMS
(
root
))
{
btrfs_release_path
(
root
,
path
);
printk
(
"insert1
\n
"
);
goto
insert
;
}
if
(
csum_offset
>=
btrfs_item_size
(
leaf
->
items
+
path
->
slots
[
0
])
/
...
...
@@ -166,11 +183,13 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
ret
=
btrfs_extend_item
(
trans
,
root
,
path
,
sizeof
(
struct
btrfs_csum_item
));
BUG_ON
(
ret
);
printk
(
"item extended
\n
"
);
goto
csum
;
}
insert:
csum_offset
=
0
;
printk
(
"inserting item %Lu %Lu %u
\n
"
,
file_key
.
objectid
,
file_key
.
offset
,
file_key
.
flags
);
ret
=
btrfs_insert_empty_item
(
trans
,
root
,
path
,
&
file_key
,
sizeof
(
struct
btrfs_csum_item
));
if
(
ret
!=
0
&&
ret
!=
-
EEXIST
)
...
...
@@ -180,12 +199,14 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
struct
btrfs_csum_item
);
ret
=
0
;
item
+=
csum_offset
;
found:
ret
=
btrfs_csum_data
(
root
,
data
,
len
,
item
->
csum
);
btrfs_set_csum_extent_offset
(
item
,
extent_offset
);
btrfs_mark_buffer_dirty
(
path
->
nodes
[
0
]);
fail:
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
printk
(
"return ret %d
\n
"
,
ret
);
return
ret
;
}
...
...
@@ -208,7 +229,7 @@ int btrfs_csum_verify_file_block(struct btrfs_root *root,
btrfs_set_key_type
(
&
file_key
,
BTRFS_CSUM_ITEM_KEY
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
item
=
__lookup_csum_item
(
root
,
path
,
objectid
,
offset
);
item
=
btrfs_lookup_csum
(
NULL
,
root
,
path
,
objectid
,
offset
,
0
);
if
(
IS_ERR
(
item
))
{
ret
=
PTR_ERR
(
item
);
goto
fail
;
...
...
fs/btrfs/super.c
浏览文件 @
b18c6685
...
...
@@ -1089,7 +1089,6 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
extent_start
=
btrfs_disk_key_offset
(
&
leaf
->
items
[
path
->
slots
[
0
]].
key
);
extent_start
=
extent_start
>>
inode
->
i_blkbits
;
extent_start
+=
btrfs_file_extent_offset
(
item
);
extent_end
=
extent_start
+
btrfs_file_extent_num_blocks
(
item
);
if
(
iblock
>=
extent_start
&&
iblock
<
extent_end
)
{
err
=
0
;
...
...
@@ -1103,6 +1102,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
err
=
0
;
goto
out
;
}
#if 0
ret = btrfs_alloc_file_extent(trans, root, objectid,
iblock << inode->i_blkbits,
1, extent_end, &blocknr);
...
...
@@ -1115,9 +1115,11 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
map_bh(result, inode->i_sb, blocknr);
btrfs_map_bh_to_logical(root, result, blocknr);
#endif
out:
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
printk
(
"mapping iblock %lu to %lu
\n
"
,
iblock
,
result
->
b_blocknr
);
if
(
trans
)
btrfs_end_transaction
(
trans
,
root
);
return
err
;
...
...
@@ -1273,8 +1275,244 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
return
err
;
}
static
int
prepare_pages
(
struct
btrfs_trans_handle
*
trans
,
static
int
drop_csums
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
inode
*
inode
,
u64
start
,
u64
end
)
{
struct
btrfs_path
*
path
;
struct
btrfs_leaf
*
leaf
;
struct
btrfs_key
key
;
int
slot
;
struct
btrfs_csum_item
*
item
;
char
*
old_block
=
NULL
;
u64
cur
=
start
;
u64
found_end
;
u64
num_csums
;
u64
item_size
;
int
ret
;
path
=
btrfs_alloc_path
();
if
(
!
path
)
return
-
ENOMEM
;
while
(
cur
<
end
)
{
item
=
btrfs_lookup_csum
(
trans
,
root
,
path
,
inode
->
i_ino
,
cur
,
1
);
if
(
IS_ERR
(
item
))
{
cur
+=
root
->
blocksize
;
continue
;
}
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
slot
=
path
->
slots
[
0
];
btrfs_disk_key_to_cpu
(
&
key
,
&
leaf
->
items
[
slot
].
key
);
item_size
=
btrfs_item_size
(
leaf
->
items
+
slot
);
num_csums
=
item_size
/
sizeof
(
struct
btrfs_csum_item
);
found_end
=
key
.
offset
+
(
num_csums
<<
inode
->
i_blkbits
);
cur
=
found_end
;
if
(
found_end
>
end
)
{
char
*
src
;
old_block
=
kmalloc
(
root
->
blocksize
,
GFP_NOFS
);
src
=
btrfs_item_ptr
(
leaf
,
slot
,
char
);
memcpy
(
old_block
,
src
,
item_size
);
}
if
(
key
.
offset
<
start
)
{
u64
new_size
=
(
start
-
key
.
offset
)
>>
inode
->
i_blkbits
;
new_size
*=
sizeof
(
struct
btrfs_csum_item
);
ret
=
btrfs_truncate_item
(
trans
,
root
,
path
,
new_size
);
BUG_ON
(
ret
);
}
else
{
btrfs_del_item
(
trans
,
root
,
path
);
}
btrfs_release_path
(
root
,
path
);
if
(
found_end
>
end
)
{
char
*
dst
;
int
i
;
int
new_size
;
num_csums
=
(
found_end
-
end
)
>>
inode
->
i_blkbits
;
new_size
=
num_csums
*
sizeof
(
struct
btrfs_csum_item
);
key
.
offset
=
end
;
ret
=
btrfs_insert_empty_item
(
trans
,
root
,
path
,
&
key
,
new_size
);
BUG_ON
(
ret
);
dst
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
char
);
memcpy
(
dst
,
old_block
+
item_size
-
new_size
,
new_size
);
item
=
(
struct
btrfs_csum_item
*
)
dst
;
for
(
i
=
0
;
i
<
num_csums
;
i
++
)
{
btrfs_set_csum_extent_offset
(
item
,
end
);
item
++
;
}
mark_buffer_dirty
(
path
->
nodes
[
0
]);
kfree
(
old_block
);
break
;
}
}
btrfs_free_path
(
path
);
return
0
;
}
static
int
drop_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
inode
*
inode
,
u64
start
,
u64
end
)
{
int
ret
;
struct
btrfs_key
key
;
struct
btrfs_leaf
*
leaf
;
int
slot
;
struct
btrfs_file_extent_item
*
extent
;
u64
extent_end
;
int
keep
;
struct
btrfs_file_extent_item
old
;
struct
btrfs_path
*
path
;
u64
search_start
=
start
;
int
bookend
;
path
=
btrfs_alloc_path
();
if
(
!
path
)
return
-
ENOMEM
;
search_again:
printk
(
"drop extent inode %lu start %Lu end %Lu
\n
"
,
inode
->
i_ino
,
start
,
end
);
ret
=
btrfs_lookup_file_extent
(
trans
,
root
,
path
,
inode
->
i_ino
,
search_start
,
-
1
);
if
(
ret
!=
0
)
{
printk
(
"lookup failed
\n
"
);
goto
out
;
}
while
(
1
)
{
keep
=
0
;
bookend
=
0
;
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
slot
=
path
->
slots
[
0
];
btrfs_disk_key_to_cpu
(
&
key
,
&
leaf
->
items
[
slot
].
key
);
printk
(
"found key %Lu %Lu %u
\n
"
,
key
.
objectid
,
key
.
offset
,
key
.
flags
);
extent
=
btrfs_item_ptr
(
leaf
,
slot
,
struct
btrfs_file_extent_item
);
extent_end
=
key
.
offset
+
(
btrfs_file_extent_num_blocks
(
extent
)
<<
inode
->
i_blkbits
);
printk
(
"extent end is %Lu
\n
"
,
extent_end
);
if
(
key
.
offset
>=
end
||
key
.
objectid
!=
inode
->
i_ino
)
{
ret
=
0
;
goto
out
;
}
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_EXTENT_DATA_KEY
)
goto
next_leaf
;
if
(
end
<
extent_end
&&
end
>=
key
.
offset
)
{
memcpy
(
&
old
,
extent
,
sizeof
(
old
));
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
btrfs_file_extent_disk_blocknr
(
&
old
),
btrfs_file_extent_disk_num_blocks
(
&
old
));
BUG_ON
(
ret
);
bookend
=
1
;
}
if
(
start
>
key
.
offset
)
{
u64
new_num
;
/* truncate existing extent */
keep
=
1
;
WARN_ON
(
start
&
(
root
->
blocksize
-
1
));
new_num
=
(
start
-
key
.
offset
)
>>
inode
->
i_blkbits
;
printk
(
"truncating existing extent, was %Lu "
,
btrfs_file_extent_num_blocks
(
extent
));
btrfs_set_file_extent_num_blocks
(
extent
,
new_num
);
printk
(
"now %Lu
\n
"
,
btrfs_file_extent_num_blocks
(
extent
));
mark_buffer_dirty
(
path
->
nodes
[
0
]);
}
if
(
!
keep
)
{
u64
disk_blocknr
;
u64
disk_num_blocks
;
printk
(
"del old
\n
"
);
disk_blocknr
=
btrfs_file_extent_disk_blocknr
(
extent
);
disk_num_blocks
=
btrfs_file_extent_disk_num_blocks
(
extent
);
search_start
=
key
.
offset
+
(
btrfs_file_extent_num_blocks
(
extent
)
<<
inode
->
i_blkbits
);
ret
=
btrfs_del_item
(
trans
,
root
,
path
);
BUG_ON
(
ret
);
btrfs_release_path
(
root
,
path
);
ret
=
btrfs_free_extent
(
trans
,
root
,
disk_blocknr
,
disk_num_blocks
,
0
);
BUG_ON
(
ret
);
if
(
!
bookend
&&
search_start
>=
end
)
{
ret
=
0
;
goto
out
;
}
if
(
!
bookend
)
goto
search_again
;
}
if
(
bookend
)
{
/* create bookend */
struct
btrfs_key
ins
;
printk
(
"bookend! extent end %Lu
\n
"
,
extent_end
);
ins
.
objectid
=
inode
->
i_ino
;
ins
.
offset
=
end
;
ins
.
flags
=
0
;
btrfs_set_key_type
(
&
ins
,
BTRFS_EXTENT_DATA_KEY
);
btrfs_release_path
(
root
,
path
);
ret
=
drop_csums
(
trans
,
root
,
inode
,
start
,
end
);
BUG_ON
(
ret
);
ret
=
btrfs_insert_empty_item
(
trans
,
root
,
path
,
&
ins
,
sizeof
(
*
extent
));
BUG_ON
(
ret
);
extent
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_file_extent_item
);
btrfs_set_file_extent_disk_blocknr
(
extent
,
btrfs_file_extent_disk_blocknr
(
&
old
));
btrfs_set_file_extent_disk_num_blocks
(
extent
,
btrfs_file_extent_disk_num_blocks
(
&
old
));
btrfs_set_file_extent_offset
(
extent
,
btrfs_file_extent_offset
(
&
old
)
+
((
end
-
key
.
offset
)
>>
inode
->
i_blkbits
));
WARN_ON
(
btrfs_file_extent_num_blocks
(
&
old
)
<
(
end
-
key
.
offset
)
>>
inode
->
i_blkbits
);
btrfs_set_file_extent_num_blocks
(
extent
,
btrfs_file_extent_num_blocks
(
&
old
)
-
((
end
-
key
.
offset
)
>>
inode
->
i_blkbits
));
btrfs_set_file_extent_generation
(
extent
,
btrfs_file_extent_generation
(
&
old
));
printk
(
"new bookend at offset %Lu, file_extent_offset %Lu, file_extent_num_blocks %Lu
\n
"
,
end
,
btrfs_file_extent_offset
(
extent
),
btrfs_file_extent_num_blocks
(
extent
));
btrfs_mark_buffer_dirty
(
path
->
nodes
[
0
]);
ret
=
0
;
goto
out_nocsum
;
}
next_leaf:
if
(
slot
>=
btrfs_header_nritems
(
&
leaf
->
header
)
-
1
)
{
ret
=
btrfs_next_leaf
(
root
,
path
);
if
(
ret
)
{
ret
=
0
;
goto
out
;
}
}
else
{
path
->
slots
[
0
]
++
;
}
}
out:
ret
=
drop_csums
(
trans
,
root
,
inode
,
start
,
end
);
BUG_ON
(
ret
);
out_nocsum:
btrfs_free_path
(
path
);
return
ret
;
}
static
int
prepare_pages
(
struct
btrfs_root
*
root
,
struct
file
*
file
,
struct
page
**
pages
,
size_t
num_pages
,
...
...
@@ -1289,7 +1527,6 @@ static int prepare_pages(struct btrfs_trans_handle *trans,
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
int
offset
;
int
err
=
0
;
int
ret
;
int
this_write
;
struct
buffer_head
*
bh
;
struct
buffer_head
*
head
;
...
...
@@ -1305,18 +1542,21 @@ static int prepare_pages(struct btrfs_trans_handle *trans,
}
offset
=
pos
&
(
PAGE_CACHE_SIZE
-
1
);
this_write
=
min
(
PAGE_CACHE_SIZE
-
offset
,
write_bytes
);
if
(
!
PageUptodate
(
pages
[
i
])
&&
(
pages
[
i
]
->
index
==
first_index
||
pages
[
i
]
->
index
==
last_index
)
&&
pos
<
isize
)
{
#if 0
if ((pages[i]->index == first_index ||
pages[i]->index == last_index) && pos < isize &&
!PageUptodate(pages[i])) {
ret = mpage_readpage(pages[i], btrfs_get_block);
BUG_ON(ret);
lock_page(pages[i]);
}
#endif
create_empty_buffers
(
pages
[
i
],
root
->
fs_info
->
sb
->
s_blocksize
,
(
1
<<
BH_Uptodate
));
head
=
page_buffers
(
pages
[
i
]);
bh
=
head
;
do
{
printk
(
"mapping page %lu to block %Lu
\n
"
,
pages
[
i
]
->
index
,
alloc_extent_start
);
err
=
btrfs_map_bh_to_logical
(
root
,
bh
,
alloc_extent_start
);
BUG_ON
(
err
);
...
...
@@ -1351,7 +1591,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
int
ret
=
0
;
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
struct
page
*
pages
[
1
];
struct
page
*
pages
[
8
];
unsigned
long
first_index
;
unsigned
long
last_index
;
u64
start_pos
;
...
...
@@ -1359,6 +1599,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
u64
alloc_extent_start
;
u64
orig_extent_start
;
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_key
ins
;
if
(
file
->
f_flags
&
O_DIRECT
)
return
-
EINVAL
;
...
...
@@ -1390,16 +1631,24 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
trans
=
btrfs_start_transaction
(
root
,
1
);
if
(
!
trans
)
{
err
=
-
ENOMEM
;
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
goto
out_unlock
;
}
ret
=
btrfs_alloc_file_extent
(
trans
,
root
,
inode
->
i_ino
,
start_pos
,
num_blocks
,
1
,
&
alloc_extent_start
);
BUG_ON
(
ret
);
if
(
start_pos
<
inode
->
i_size
)
{
ret
=
drop_extents
(
trans
,
root
,
inode
,
start_pos
,
(
pos
+
count
+
root
->
blocksize
-
1
)
&
~
(
root
->
blocksize
-
1
));
}
orig_extent_start
=
start_pos
;
ret
=
btrfs_end_transaction
(
trans
,
root
);
ret
=
btrfs_alloc_extent
(
trans
,
root
,
num_blocks
,
1
,
(
u64
)
-
1
,
&
ins
);
BUG_ON
(
ret
);
ret
=
btrfs_insert_file_extent
(
trans
,
root
,
inode
->
i_ino
,
start_pos
,
ins
.
objectid
,
ins
.
offset
);
BUG_ON
(
ret
);
alloc_extent_start
=
ins
.
objectid
;
ret
=
btrfs_end_transaction
(
trans
,
root
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
while
(
count
>
0
)
{
...
...
@@ -1407,16 +1656,21 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
size_t
write_bytes
=
min
(
count
,
PAGE_CACHE_SIZE
-
offset
);
size_t
num_pages
=
(
write_bytes
+
PAGE_CACHE_SIZE
-
1
)
>>
PAGE_CACHE_SHIFT
;
ret
=
prepare_pages
(
NULL
,
root
,
file
,
pages
,
num_pages
,
printk
(
"num_pages is %lu
\n
"
,
num_pages
);
memset
(
pages
,
0
,
sizeof
(
pages
));
ret
=
prepare_pages
(
root
,
file
,
pages
,
num_pages
,
pos
,
first_index
,
last_index
,
write_bytes
,
alloc_extent_start
);
BUG_ON
(
ret
);
/* FIXME blocks != pagesize */
alloc_extent_start
+=
num_pages
;
ret
=
btrfs_copy_from_user
(
pos
,
num_pages
,
write_bytes
,
pages
,
buf
);
BUG_ON
(
ret
);
printk
(
"2num_pages is %lu
\n
"
,
num_pages
);
ret
=
dirty_and_release_pages
(
NULL
,
root
,
file
,
pages
,
num_pages
,
orig_extent_start
,
pos
,
write_bytes
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录