Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Linux-御风守护者
linux
提交
7e38180e
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,发现更多精彩内容 >>
提交
7e38180e
编写于
4月 19, 2007
作者:
C
Chris Mason
提交者:
David Woodhouse
4月 19, 2007
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Btrfs: directory inode index is back
Signed-off-by:
N
Chris Mason
<
chris.mason@oracle.com
>
上级
236454df
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
206 addition
and
362 deletion
+206
-362
fs/btrfs/TODO
fs/btrfs/TODO
+2
-2
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+17
-41
fs/btrfs/dir-item.c
fs/btrfs/dir-item.c
+144
-60
fs/btrfs/super.c
fs/btrfs/super.c
+43
-259
未找到文件。
fs/btrfs/TODO
浏览文件 @
7e38180e
* cleanup, add more error checking, get rid of BUG_ONs
* Fix ENOSPC handling
* Add block mapping tree (simple dm layer)
* Make allocator smarter
* add a block group to struct inode
* Make sure nobh stuff is working properly for cows
* Do actual block accounting
* Check compat and incompat flags on the inode
* Get rid of struct ctree_path, limiting tree levels held at one time
* Add generation number to key pointer in nodes
* Add parent pointer back to extent map.
* Release
* Do real tree locking
* Add extent mirroring (backup copies of blocks)
...
...
fs/btrfs/ctree.h
浏览文件 @
7e38180e
...
...
@@ -185,11 +185,6 @@ struct btrfs_inode_item {
struct
btrfs_inode_timespec
otime
;
}
__attribute__
((
__packed__
));
/* inline data is just a blob of bytes */
struct
btrfs_inline_data_item
{
u8
data
;
}
__attribute__
((
__packed__
));
struct
btrfs_dir_item
{
struct
btrfs_disk_key
location
;
__le16
flags
;
...
...
@@ -293,9 +288,6 @@ struct btrfs_root {
#define BTRFS_KEY_TYPE_MASK (((u32)BTRFS_KEY_TYPE_MAX - 1) << \
BTRFS_KEY_TYPE_SHIFT)
#define BTRFS_KEY_OVERFLOW_MAX 128
#define BTRFS_KEY_OVERFLOW_MASK ((u32)BTRFS_KEY_OVERFLOW_MAX - 1)
/*
* inode items have the data typically returned from stat and store other
* info about object characteristics. There is one for every file and dir in
...
...
@@ -621,31 +613,6 @@ static inline void btrfs_set_key_type(struct btrfs_key *key, u32 val)
key
->
flags
=
(
key
->
flags
&
~
(
BTRFS_KEY_TYPE_MASK
))
|
val
;
}
static
inline
u32
btrfs_key_overflow
(
struct
btrfs_key
*
key
)
{
return
key
->
flags
&
BTRFS_KEY_OVERFLOW_MASK
;
}
static
inline
void
btrfs_set_key_overflow
(
struct
btrfs_key
*
key
,
u32
over
)
{
BUG_ON
(
over
>=
BTRFS_KEY_OVERFLOW_MAX
);
key
->
flags
=
(
key
->
flags
&
~
BTRFS_KEY_OVERFLOW_MASK
)
|
over
;
}
static
inline
u32
btrfs_disk_key_overflow
(
struct
btrfs_disk_key
*
key
)
{
return
le32_to_cpu
(
key
->
flags
)
&
BTRFS_KEY_OVERFLOW_MASK
;
}
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
);
flags
=
(
flags
&
~
BTRFS_KEY_OVERFLOW_MASK
)
|
over
;
btrfs_set_disk_key_flags
(
key
,
flags
);
}
static
inline
u64
btrfs_header_blocknr
(
struct
btrfs_header
*
h
)
{
return
le64_to_cpu
(
h
->
blocknr
);
...
...
@@ -1079,15 +1046,24 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
int
btrfs_insert_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
const
char
*
name
,
int
name_len
,
u64
dir
,
struct
btrfs_key
*
location
,
u8
type
);
int
btrfs_lookup_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
const
char
*
name
,
int
name_len
,
int
mod
);
int
btrfs_lookup_dir_index_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_dir_item
*
btrfs_lookup_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
u64
objectid
,
int
mod
);
int
btrfs_match_dir_item_name
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
const
char
*
name
,
int
name_len
,
int
mod
);
struct
btrfs_dir_item
*
btrfs_lookup_dir_index_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
u64
objectid
,
const
char
*
name
,
int
name_len
,
int
mod
);
struct
btrfs_dir_item
*
btrfs_match_dir_item_name
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
const
char
*
name
,
int
name_len
);
int
btrfs_delete_one_dir_name
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
btrfs_dir_item
*
di
);
/* inode-map.c */
int
btrfs_find_free_objectid
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
fs_root
,
...
...
fs/btrfs/dir-item.c
浏览文件 @
7e38180e
...
...
@@ -4,24 +4,31 @@
#include "hash.h"
#include "transaction.h"
int
insert_with_overflow
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
btrfs_key
*
cpu_key
,
u32
data_size
)
struct
btrfs_dir_item
*
insert_with_overflow
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
btrfs_key
*
cpu_key
,
u32
data_size
)
{
int
overflow
;
int
ret
;
char
*
ptr
;
struct
btrfs_item
*
item
;
struct
btrfs_leaf
*
leaf
;
ret
=
btrfs_insert_empty_item
(
trans
,
root
,
path
,
cpu_key
,
data_size
);
overflow
=
btrfs_key_overflow
(
cpu_key
);
while
(
ret
==
-
EEXIST
&&
overflow
<
BTRFS_KEY_OVERFLOW_MAX
)
{
overflow
++
;
btrfs_set_key_overflow
(
cpu_key
,
overflow
);
btrfs_release_path
(
root
,
path
);
ret
=
btrfs_insert_empty_item
(
trans
,
root
,
path
,
cpu_key
,
data_size
);
if
(
ret
==
-
EEXIST
)
{
ret
=
btrfs_extend_item
(
trans
,
root
,
path
,
data_size
);
WARN_ON
(
ret
>
0
);
if
(
ret
)
return
ERR_PTR
(
ret
);
}
return
ret
;
WARN_ON
(
ret
>
0
);
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
item
=
leaf
->
items
+
path
->
slots
[
0
];
ptr
=
btrfs_item_ptr
(
leaf
,
path
->
slots
[
0
],
char
);
BUG_ON
(
data_size
>
btrfs_item_size
(
item
));
ptr
+=
btrfs_item_size
(
item
)
-
data_size
;
return
(
struct
btrfs_dir_item
*
)
ptr
;
}
int
btrfs_insert_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
...
...
@@ -43,13 +50,12 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
path
=
btrfs_alloc_path
();
btrfs_init_path
(
path
);
data_size
=
sizeof
(
*
dir_item
)
+
name_len
;
ret
=
insert_with_overflow
(
trans
,
root
,
path
,
&
key
,
data_size
);
if
(
ret
)
dir_item
=
insert_with_overflow
(
trans
,
root
,
path
,
&
key
,
data_size
);
if
(
IS_ERR
(
dir_item
))
{
ret
=
PTR_ERR
(
dir_item
);
goto
out
;
}
dir_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_dir_item
);
btrfs_cpu_key_to_disk
(
&
dir_item
->
location
,
location
);
btrfs_set_dir_type
(
dir_item
,
type
);
btrfs_set_dir_flags
(
dir_item
,
0
);
...
...
@@ -58,15 +64,39 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_memcpy
(
root
,
path
->
nodes
[
0
]
->
b_data
,
name_ptr
,
name
,
name_len
);
btrfs_mark_buffer_dirty
(
path
->
nodes
[
0
]);
out:
/* FIXME, use some real flag for selecting the extra index */
if
(
root
==
root
->
fs_info
->
tree_root
)
{
ret
=
0
;
goto
out
;
}
btrfs_release_path
(
root
,
path
);
btrfs_set_key_type
(
&
key
,
BTRFS_DIR_INDEX_KEY
);
key
.
offset
=
location
->
objectid
;
dir_item
=
insert_with_overflow
(
trans
,
root
,
path
,
&
key
,
data_size
);
if
(
IS_ERR
(
dir_item
))
{
ret
=
PTR_ERR
(
dir_item
);
goto
out
;
}
btrfs_cpu_key_to_disk
(
&
dir_item
->
location
,
location
);
btrfs_set_dir_type
(
dir_item
,
type
);
btrfs_set_dir_flags
(
dir_item
,
0
);
btrfs_set_dir_name_len
(
dir_item
,
name_len
);
name_ptr
=
(
char
*
)(
dir_item
+
1
);
btrfs_memcpy
(
root
,
path
->
nodes
[
0
]
->
b_data
,
name_ptr
,
name
,
name_len
);
btrfs_mark_buffer_dirty
(
path
->
nodes
[
0
]);
out:
btrfs_free_path
(
path
);
return
ret
;
}
int
btrfs_lookup_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
const
char
*
name
,
int
name_len
,
int
mod
)
struct
btrfs_dir_item
*
btrfs_lookup_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
const
char
*
name
,
int
name_len
,
int
mod
)
{
int
ret
;
struct
btrfs_key
key
;
...
...
@@ -74,21 +104,18 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
int
cow
=
mod
!=
0
;
struct
btrfs_disk_key
*
found_key
;
struct
btrfs_leaf
*
leaf
;
u32
overflow
;
key
.
objectid
=
dir
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_DIR_ITEM_KEY
);
// btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX - 1);
ret
=
btrfs_name_hash
(
name
,
name_len
,
&
key
.
offset
);
BUG_ON
(
ret
);
while
(
1
)
{
ret
=
btrfs_search_slot
(
trans
,
root
,
&
key
,
path
,
ins_len
,
cow
);
if
(
ret
<
0
)
return
ret
;
return
ERR_PTR
(
ret
)
;
if
(
ret
>
0
)
{
if
(
path
->
slots
[
0
]
==
0
)
return
1
;
return
NULL
;
path
->
slots
[
0
]
--
;
}
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
...
...
@@ -97,34 +124,91 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
btrfs_disk_key_objectid
(
found_key
)
!=
dir
||
btrfs_disk_key_type
(
found_key
)
!=
BTRFS_DIR_ITEM_KEY
||
btrfs_disk_key_offset
(
found_key
)
!=
key
.
offset
)
return
1
;
return
NULL
;
if
(
btrfs_match_dir_item_name
(
root
,
path
,
name
,
name_len
))
return
0
;
return
btrfs_match_dir_item_name
(
root
,
path
,
name
,
name_len
);
}
overflow
=
btrfs_disk_key_overflow
(
found_key
);
if
(
overflow
==
0
)
return
1
;
btrfs_set_key_overflow
(
&
key
,
overflow
-
1
);
btrfs_release_path
(
root
,
path
);
}
return
1
;
struct
btrfs_dir_item
*
btrfs_lookup_dir_index_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
u64
objectid
,
const
char
*
name
,
int
name_len
,
int
mod
)
{
int
ret
;
struct
btrfs_key
key
;
int
ins_len
=
mod
<
0
?
-
1
:
0
;
int
cow
=
mod
!=
0
;
key
.
objectid
=
dir
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_DIR_INDEX_KEY
);
key
.
offset
=
objectid
;
ret
=
btrfs_search_slot
(
trans
,
root
,
&
key
,
path
,
ins_len
,
cow
);
if
(
ret
<
0
)
return
ERR_PTR
(
ret
);
if
(
ret
>
0
)
return
ERR_PTR
(
-
ENOENT
);
return
btrfs_match_dir_item_name
(
root
,
path
,
name
,
name_len
);
}
int
btrfs_match_dir_item_name
(
struct
btrfs_root
*
root
,
struct
btrfs_dir_item
*
btrfs_match_dir_item_name
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
const
char
*
name
,
int
name_len
)
{
struct
btrfs_dir_item
*
dir_item
;
char
*
name_ptr
;
u32
total_len
;
u32
cur
=
0
;
u32
this_len
;
struct
btrfs_leaf
*
leaf
;
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
;
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
dir_item
=
btrfs_item_ptr
(
leaf
,
path
->
slots
[
0
],
struct
btrfs_dir_item
);
total_len
=
btrfs_item_size
(
leaf
->
items
+
path
->
slots
[
0
]
);
while
(
cur
<
total_len
)
{
this_len
=
sizeof
(
*
dir_item
)
+
btrfs_dir_name_len
(
dir_item
)
;
name_ptr
=
(
char
*
)(
dir_item
+
1
);
if
(
memcmp
(
name_ptr
,
name
,
name_len
))
if
(
btrfs_dir_name_len
(
dir_item
)
==
name_len
&&
memcmp
(
name_ptr
,
name
,
name_len
)
==
0
)
return
dir_item
;
cur
+=
this_len
;
dir_item
=
(
struct
btrfs_dir_item
*
)((
char
*
)
dir_item
+
this_len
);
}
return
NULL
;
}
int
btrfs_delete_one_dir_name
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
btrfs_dir_item
*
di
)
{
struct
btrfs_leaf
*
leaf
;
u32
sub_item_len
;
u32
item_len
;
int
ret
;
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
sub_item_len
=
sizeof
(
*
di
)
+
btrfs_dir_name_len
(
di
);
item_len
=
btrfs_item_size
(
leaf
->
items
+
path
->
slots
[
0
]);
if
(
sub_item_len
==
btrfs_item_size
(
leaf
->
items
+
path
->
slots
[
0
]))
{
ret
=
btrfs_del_item
(
trans
,
root
,
path
);
BUG_ON
(
ret
);
}
else
{
char
*
ptr
=
(
char
*
)
di
;
char
*
start
=
btrfs_item_ptr
(
leaf
,
path
->
slots
[
0
],
char
);
btrfs_memmove
(
root
,
leaf
,
ptr
,
ptr
+
sub_item_len
,
item_len
-
(
ptr
+
sub_item_len
-
start
));
ret
=
btrfs_truncate_item
(
trans
,
root
,
path
,
item_len
-
sub_item_len
);
BUG_ON
(
ret
);
}
return
0
;
return
1
;
}
fs/btrfs/super.c
浏览文件 @
7e38180e
...
...
@@ -127,32 +127,43 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
struct
btrfs_path
*
path
;
const
char
*
name
=
dentry
->
d_name
.
name
;
int
name_len
=
dentry
->
d_name
.
len
;
int
ret
;
int
ret
=
0
;
u64
objectid
;
struct
btrfs_dir_item
*
di
;
path
=
btrfs_alloc_path
();
BUG_ON
(
!
path
);
btrfs_init_path
(
path
);
ret
=
btrfs_lookup_dir_item
(
trans
,
root
,
path
,
dir
->
i_ino
,
di
=
btrfs_lookup_dir_item
(
trans
,
root
,
path
,
dir
->
i_ino
,
name
,
name_len
,
-
1
);
if
(
ret
<
0
)
if
(
IS_ERR
(
di
))
{
ret
=
PTR_ERR
(
di
);
goto
err
;
if
(
ret
>
0
)
{
}
if
(
!
di
)
{
ret
=
-
ENOENT
;
goto
err
;
}
di
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_dir_item
);
objectid
=
btrfs_disk_key_objectid
(
&
di
->
location
);
ret
=
btrfs_delete_one_dir_name
(
trans
,
root
,
path
,
di
);
BUG_ON
(
ret
);
btrfs_release_path
(
root
,
path
);
ret
=
btrfs_del_item
(
trans
,
root
,
path
);
di
=
btrfs_lookup_dir_index_item
(
trans
,
root
,
path
,
dir
->
i_ino
,
objectid
,
name
,
name_len
,
-
1
);
if
(
IS_ERR
(
di
))
{
ret
=
PTR_ERR
(
di
);
goto
err
;
}
if
(
!
di
)
{
ret
=
-
ENOENT
;
goto
err
;
}
ret
=
btrfs_delete_one_dir_name
(
trans
,
root
,
path
,
di
);
BUG_ON
(
ret
);
btrfs_release_path
(
root
,
path
);
dentry
->
d_inode
->
i_ctime
=
dir
->
i_ctime
;
err:
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
if
(
ret
==
0
)
{
inode_dec_link_count
(
dentry
->
d_inode
);
...
...
@@ -388,15 +399,13 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
path
=
btrfs_alloc_path
();
BUG_ON
(
!
path
);
btrfs_init_path
(
path
);
ret
=
btrfs_lookup_dir_item
(
NULL
,
root
,
path
,
dir
->
i_ino
,
name
,
di
=
btrfs_lookup_dir_item
(
NULL
,
root
,
path
,
dir
->
i_ino
,
name
,
namelen
,
0
);
if
(
ret
||
!
btrfs_match_dir_item_name
(
root
,
path
,
name
,
namelen
))
{
if
(
!
di
||
IS_ERR
(
di
))
{
location
->
objectid
=
0
;
ret
=
0
;
goto
out
;
}
di
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_dir_item
);
btrfs_disk_key_to_cpu
(
location
,
&
di
->
location
);
out:
btrfs_release_path
(
root
,
path
);
...
...
@@ -523,7 +532,10 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
int
advance
;
unsigned
char
d_type
=
DT_UNKNOWN
;
int
over
=
0
;
int
key_type
=
BTRFS_DIR_ITEM_KEY
;
u32
di_cur
;
u32
di_total
;
u32
di_len
;
int
key_type
=
BTRFS_DIR_INDEX_KEY
;
/* FIXME, use a real flag for deciding about the key type */
if
(
root
->
fs_info
->
tree_root
==
root
)
...
...
@@ -567,12 +579,20 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
filp
->
f_pos
=
btrfs_disk_key_offset
(
&
item
->
key
);
advance
=
1
;
di
=
btrfs_item_ptr
(
leaf
,
slot
,
struct
btrfs_dir_item
);
di_cur
=
0
;
di_total
=
btrfs_item_size
(
leaf
->
items
+
slot
);
while
(
di_cur
<
di_total
)
{
over
=
filldir
(
dirent
,
(
const
char
*
)(
di
+
1
),
btrfs_dir_name_len
(
di
),
btrfs_disk_key_offset
(
&
item
->
key
),
btrfs_disk_key_objectid
(
&
di
->
location
),
d_type
);
btrfs_disk_key_objectid
(
&
di
->
location
),
d_type
);
if
(
over
)
goto
nopos
;
di_len
=
btrfs_dir_name_len
(
di
)
+
sizeof
(
*
di
);
di_cur
+=
di_len
;
di
=
(
struct
btrfs_dir_item
*
)((
char
*
)
di
+
di_len
);
}
}
filp
->
f_pos
++
;
nopos:
...
...
@@ -935,75 +955,6 @@ printk("btrfs sync_fs\n");
return
0
;
}
#if 0
static int btrfs_get_block_inline(struct inode *inode, sector_t iblock,
struct buffer_head *result, int create)
{
struct btrfs_root *root = btrfs_sb(inode->i_sb);
struct btrfs_path *path;
struct btrfs_key key;
struct btrfs_leaf *leaf;
int num_bytes = result->b_size;
int item_size;
int ret;
u64 pos;
char *ptr;
int copy_size;
int err = 0;
char *safe_ptr;
char *data_ptr;
path = btrfs_alloc_path();
BUG_ON(!path);
WARN_ON(create);
if (create) {
return 0;
}
pos = iblock << inode->i_blkbits;
key.objectid = inode->i_ino;
key.flags = 0;
btrfs_set_key_type(&key, BTRFS_INLINE_DATA_KEY);
ptr = kmap(result->b_page);
safe_ptr = ptr;
ptr += (pos & (PAGE_CACHE_SIZE -1));
again:
key.offset = pos;
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret) {
if (ret < 0)
err = ret;
else
err = 0;
goto out;
}
leaf = btrfs_buffer_leaf(path->nodes[0]);
item_size = btrfs_item_size(leaf->items + path->slots[0]);
copy_size = min(num_bytes, item_size);
data_ptr = btrfs_item_ptr(leaf, path->slots[0], char);
WARN_ON(safe_ptr + PAGE_CACHE_SIZE < ptr + copy_size);
memcpy(ptr, data_ptr, copy_size);
pos += copy_size;
num_bytes -= copy_size;
WARN_ON(num_bytes < 0);
ptr += copy_size;
btrfs_release_path(root, path);
if (num_bytes != 0) {
if (pos >= i_size_read(inode))
memset(ptr, 0, num_bytes);
else
goto again;
}
set_buffer_uptodate(result);
map_bh(result, inode->i_sb, 0);
err = 0;
out:
btrfs_free_path(path);
kunmap(result->b_page);
return err;
}
#endif
static
int
btrfs_get_block_lock
(
struct
inode
*
inode
,
sector_t
iblock
,
struct
buffer_head
*
result
,
int
create
)
{
...
...
@@ -1907,174 +1858,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
return
num_written
?
num_written
:
err
;
}
#if 0
static ssize_t inline_one_page(struct btrfs_root *root, struct inode *inode,
struct page *page, loff_t pos,
size_t offset, size_t write_bytes)
{
struct btrfs_path *path;
struct btrfs_trans_handle *trans;
struct btrfs_key key;
struct btrfs_leaf *leaf;
struct btrfs_key found_key;
int ret;
size_t copy_size = 0;
char *dst = NULL;
int err = 0;
size_t num_written = 0;
path = btrfs_alloc_path();
BUG_ON(!path);
mutex_lock(&root->fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 1);
key.objectid = inode->i_ino;
key.flags = 0;
btrfs_set_key_type(&key, BTRFS_INLINE_DATA_KEY);
again:
key.offset = pos;
ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
if (ret < 0) {
err = ret;
goto out;
}
if (ret == 0) {
leaf = btrfs_buffer_leaf(path->nodes[0]);
btrfs_disk_key_to_cpu(&found_key,
&leaf->items[path->slots[0]].key);
copy_size = btrfs_item_size(leaf->items + path->slots[0]);
dst = btrfs_item_ptr(leaf, path->slots[0], char);
copy_size = min(write_bytes, copy_size);
goto copyit;
} else {
int slot = path->slots[0];
if (slot > 0) {
slot--;
}
// FIXME find max key
leaf = btrfs_buffer_leaf(path->nodes[0]);
btrfs_disk_key_to_cpu(&found_key,
&leaf->items[slot].key);
if (found_key.objectid != inode->i_ino)
goto insert;
if (btrfs_key_type(&found_key) != BTRFS_INLINE_DATA_KEY)
goto insert;
copy_size = btrfs_item_size(leaf->items + slot);
if (found_key.offset + copy_size <= pos)
goto insert;
dst = btrfs_item_ptr(leaf, path->slots[0], char);
dst += pos - found_key.offset;
copy_size = copy_size - (pos - found_key.offset);
BUG_ON(copy_size < 0);
copy_size = min(write_bytes, copy_size);
WARN_ON(copy_size == 0);
goto copyit;
}
insert:
btrfs_release_path(root, path);
copy_size = min(write_bytes,
(size_t)BTRFS_LEAF_DATA_SIZE(root) -
sizeof(struct btrfs_item) * 4);
ret = btrfs_insert_empty_item(trans, root, path, &key, copy_size);
BUG_ON(ret);
dst = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
path->slots[0], char);
copyit:
WARN_ON(copy_size == 0);
WARN_ON(dst + copy_size >
btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
path->slots[0], char) +
btrfs_item_size(btrfs_buffer_leaf(path->nodes[0])->items +
path->slots[0]));
btrfs_memcpy(root, path->nodes[0]->b_data, dst,
page_address(page) + offset, copy_size);
mark_buffer_dirty(path->nodes[0]);
btrfs_release_path(root, path);
pos += copy_size;
offset += copy_size;
num_written += copy_size;
write_bytes -= copy_size;
if (write_bytes)
goto again;
out:
btrfs_free_path(path);
ret = btrfs_end_transaction(trans, root);
BUG_ON(ret);
mutex_unlock(&root->fs_info->fs_mutex);
return num_written ? num_written : err;
}
static ssize_t btrfs_file_inline_write(struct file *file,
const char __user *buf,
size_t count, loff_t *ppos)
{
loff_t pos;
size_t num_written = 0;
int err = 0;
int ret = 0;
struct inode *inode = file->f_path.dentry->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root;
unsigned long page_index;
if (file->f_flags & O_DIRECT)
return -EINVAL;
pos = *ppos;
vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
current->backing_dev_info = inode->i_mapping->backing_dev_info;
err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
if (err)
goto out;
if (count == 0)
goto out;
err = remove_suid(file->f_path.dentry);
if (err)
goto out;
file_update_time(file);
mutex_lock(&inode->i_mutex);
while(count > 0) {
size_t offset = pos & (PAGE_CACHE_SIZE - 1);
size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset);
struct page *page;
page_index = pos >> PAGE_CACHE_SHIFT;
page = grab_cache_page(inode->i_mapping, page_index);
if (!PageUptodate(page)) {
ret = mpage_readpage(page, btrfs_get_block);
BUG_ON(ret);
lock_page(page);
}
ret = btrfs_copy_from_user(pos, 1,
write_bytes, &page, buf);
BUG_ON(ret);
write_bytes = inline_one_page(root, inode, page, pos,
offset, write_bytes);
SetPageUptodate(page);
if (write_bytes > 0 && pos + write_bytes > inode->i_size) {
i_size_write(inode, pos + write_bytes);
mark_inode_dirty(inode);
}
page_cache_release(page);
unlock_page(page);
if (write_bytes < 0)
goto out_unlock;
buf += write_bytes;
count -= write_bytes;
pos += write_bytes;
num_written += write_bytes;
balance_dirty_pages_ratelimited(inode->i_mapping);
cond_resched();
}
out_unlock:
mutex_unlock(&inode->i_mutex);
out:
*ppos = pos;
current->backing_dev_info = NULL;
return num_written ? num_written : err;
}
#endif
static
int
btrfs_read_actor
(
read_descriptor_t
*
desc
,
struct
page
*
page
,
unsigned
long
offset
,
unsigned
long
size
)
{
...
...
@@ -2422,6 +2205,7 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
struct
btrfs_ioctl_vol_args
vol_args
;
int
ret
=
0
;
struct
btrfs_dir_item
*
di
;
int
namelen
;
struct
btrfs_path
*
path
;
u64
root_dirid
;
...
...
@@ -2440,12 +2224,12 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
return
-
ENOMEM
;
root_dirid
=
root
->
fs_info
->
sb
->
s_root
->
d_inode
->
i_ino
,
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
ret
=
btrfs_lookup_dir_item
(
NULL
,
root
->
fs_info
->
tree_root
,
di
=
btrfs_lookup_dir_item
(
NULL
,
root
->
fs_info
->
tree_root
,
path
,
root_dirid
,
vol_args
.
name
,
namelen
,
0
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
btrfs_free_path
(
path
);
if
(
ret
==
0
)
if
(
di
&&
!
IS_ERR
(
di
)
)
return
-
EEXIST
;
if
(
root
==
root
->
fs_info
->
tree_root
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录