Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
db94535d
Commit
db94535d
authored
Oct 15, 2007
by
Chris Mason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: Allow tree blocks larger than the page size
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
1a5bc167
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
738 additions
and
497 deletions
+738
-497
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+229
-90
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+66
-46
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+58
-34
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+5
-4
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+147
-138
fs/btrfs/extent_map.c
fs/btrfs/extent_map.c
+66
-25
fs/btrfs/extent_map.h
fs/btrfs/extent_map.h
+5
-5
fs/btrfs/file-item.c
fs/btrfs/file-item.c
+5
-5
fs/btrfs/file.c
fs/btrfs/file.c
+60
-66
fs/btrfs/inode.c
fs/btrfs/inode.c
+44
-46
fs/btrfs/print-tree.c
fs/btrfs/print-tree.c
+13
-10
fs/btrfs/super.c
fs/btrfs/super.c
+4
-2
fs/btrfs/sysfs.c
fs/btrfs/sysfs.c
+3
-2
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+22
-17
fs/btrfs/tree-defrag.c
fs/btrfs/tree-defrag.c
+11
-7
No files found.
fs/btrfs/ctree.c
View file @
db94535d
...
...
@@ -83,16 +83,15 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans,
WARN_ON
(
root
->
ref_cows
&&
trans
->
transid
!=
root
->
last_trans
);
cow
=
btrfs_alloc_free_block
(
trans
,
root
,
search_start
,
empty_size
);
cow
=
btrfs_alloc_free_block
(
trans
,
root
,
buf
->
len
,
search_start
,
empty_size
);
if
(
IS_ERR
(
cow
))
return
PTR_ERR
(
cow
);
cow
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
if
(
buf
->
len
!=
root
->
sectorsize
||
cow
->
len
!=
root
->
sectorsize
)
WARN_ON
(
1
);
copy_extent_buffer
(
cow
,
buf
,
0
,
0
,
cow
->
len
);
btrfs_set_header_b
locknr
(
cow
,
extent_buffer_blocknr
(
cow
)
);
btrfs_set_header_b
ytenr
(
cow
,
cow
->
start
);
btrfs_set_header_generation
(
cow
,
trans
->
transid
);
btrfs_set_header_owner
(
cow
,
root
->
root_key
.
objectid
);
...
...
@@ -110,16 +109,16 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans,
root
->
node
=
cow
;
extent_buffer_get
(
cow
);
if
(
buf
!=
root
->
commit_root
)
{
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
buf
),
1
,
1
);
btrfs_free_extent
(
trans
,
root
,
buf
->
start
,
buf
->
len
,
1
);
}
free_extent_buffer
(
buf
);
}
else
{
btrfs_set_node_blockptr
(
parent
,
parent_slot
,
extent_buffer_blocknr
(
cow
)
);
cow
->
start
);
btrfs_mark_buffer_dirty
(
parent
);
WARN_ON
(
btrfs_header_generation
(
parent
)
!=
trans
->
transid
);
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
buf
),
1
,
1
);
btrfs_free_extent
(
trans
,
root
,
buf
->
start
,
buf
->
len
,
1
);
}
free_extent_buffer
(
buf
);
btrfs_mark_buffer_dirty
(
cow
);
...
...
@@ -149,13 +148,14 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
return
0
;
}
search_start
=
extent_buffer_blocknr
(
buf
)
&
~
((
u64
)
65535
);
search_start
=
buf
->
start
&
~
((
u64
)
BTRFS_BLOCK_GROUP_SIZE
-
1
);
ret
=
__btrfs_cow_block
(
trans
,
root
,
buf
,
parent
,
parent_slot
,
cow_ret
,
search_start
,
0
);
(
*
cow_ret
)
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
return
ret
;
}
#if 0
static int close_blocks(u64 blocknr, u64 other)
{
if (blocknr < other && other - blocknr < 8)
...
...
@@ -165,7 +165,6 @@ static int close_blocks(u64 blocknr, u64 other)
return 0;
}
#if 0
static int should_defrag_leaf(struct extent_buffer *eb)
{
return 0;
...
...
@@ -355,7 +354,7 @@ static int check_node(struct btrfs_root *root, struct btrfs_path *path,
BUG_ON
(
memcmp
(
&
parent_key
,
&
node_key
,
sizeof
(
struct
btrfs_disk_key
)));
BUG_ON
(
btrfs_node_blockptr
(
parent
,
parent_slot
)
!=
btrfs_header_b
lock
nr
(
node
));
btrfs_header_b
yte
nr
(
node
));
}
BUG_ON
(
nritems
>
BTRFS_NODEPTRS_PER_BLOCK
(
root
));
if
(
slot
!=
0
)
{
...
...
@@ -398,7 +397,7 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
BUG_ON
(
memcmp
(
&
parent_key
,
&
leaf_key
,
sizeof
(
struct
btrfs_disk_key
)));
BUG_ON
(
btrfs_node_blockptr
(
parent
,
parent_slot
)
!=
btrfs_header_b
lock
nr
(
leaf
));
btrfs_header_b
yte
nr
(
leaf
));
}
#if 0
for (i = 0; nritems > 1 && i < nritems - 2; i++) {
...
...
@@ -467,14 +466,16 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
static
int
check_block
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
)
{
#if 0
struct extent_buffer *buf = path->nodes[level];
if (memcmp_extent_buffer(buf, root->fs_info->fsid,
(unsigned long)btrfs_header_fsid(buf),
BTRFS_FSID_SIZE)) {
printk("warning bad block %Lu\n", buf->start);
BUG
()
;
return 1
;
}
#endif
if
(
level
==
0
)
return
check_leaf
(
root
,
path
,
level
);
return
check_node
(
root
,
path
,
level
);
...
...
@@ -585,7 +586,8 @@ static struct extent_buffer *read_node_slot(struct btrfs_root *root,
return
NULL
;
if
(
slot
>=
btrfs_header_nritems
(
parent
))
return
NULL
;
return
read_tree_block
(
root
,
btrfs_node_blockptr
(
parent
,
slot
));
return
read_tree_block
(
root
,
btrfs_node_blockptr
(
parent
,
slot
),
btrfs_level_size
(
root
,
btrfs_header_level
(
parent
)
-
1
));
}
static
int
balance_level
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
...
...
@@ -618,7 +620,6 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
*/
if
(
!
parent
)
{
struct
extent_buffer
*
child
;
u64
blocknr
=
extent_buffer_blocknr
(
mid
);
if
(
btrfs_header_nritems
(
mid
)
!=
1
)
return
0
;
...
...
@@ -632,9 +633,10 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
wait_on_tree_block_writeback
(
root
,
mid
);
/* once for the path */
free_extent_buffer
(
mid
);
ret
=
btrfs_free_extent
(
trans
,
root
,
mid
->
start
,
mid
->
len
,
1
);
/* once for the root ptr */
free_extent_buffer
(
mid
);
return
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
1
)
;
return
ret
;
}
if
(
btrfs_header_nritems
(
mid
)
>
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
/
4
)
...
...
@@ -680,7 +682,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
wret
<
0
&&
wret
!=
-
ENOSPC
)
ret
=
wret
;
if
(
btrfs_header_nritems
(
right
)
==
0
)
{
u64
blocknr
=
extent_buffer_blocknr
(
right
);
u64
bytenr
=
right
->
start
;
u32
blocksize
=
right
->
len
;
clean_tree_block
(
trans
,
root
,
right
);
wait_on_tree_block_writeback
(
root
,
right
);
free_extent_buffer
(
right
);
...
...
@@ -689,7 +693,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
1
);
if
(
wret
)
ret
=
wret
;
wret
=
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
1
);
wret
=
btrfs_free_extent
(
trans
,
root
,
bytenr
,
blocksize
,
1
);
if
(
wret
)
ret
=
wret
;
}
else
{
...
...
@@ -719,7 +724,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
}
if
(
btrfs_header_nritems
(
mid
)
==
0
)
{
/* we've managed to empty the middle node, drop it */
u64
blocknr
=
extent_buffer_blocknr
(
mid
);
u64
bytenr
=
mid
->
start
;
u32
blocksize
=
mid
->
len
;
clean_tree_block
(
trans
,
root
,
mid
);
wait_on_tree_block_writeback
(
root
,
mid
);
free_extent_buffer
(
mid
);
...
...
@@ -727,7 +733,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
wret
=
del_ptr
(
trans
,
root
,
path
,
level
+
1
,
pslot
);
if
(
wret
)
ret
=
wret
;
wret
=
btrfs_free_extent
(
trans
,
root
,
b
locknr
,
1
,
1
);
wret
=
btrfs_free_extent
(
trans
,
root
,
b
ytenr
,
blocksize
,
1
);
if
(
wret
)
ret
=
wret
;
}
else
{
...
...
@@ -830,7 +836,6 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
path
->
slots
[
level
]
=
orig_slot
;
free_extent_buffer
(
left
);
}
check_node
(
root
,
path
,
level
);
return
0
;
}
free_extent_buffer
(
left
);
...
...
@@ -874,12 +879,10 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
}
else
{
free_extent_buffer
(
right
);
}
check_node
(
root
,
path
,
level
);
return
0
;
}
free_extent_buffer
(
right
);
}
check_node
(
root
,
path
,
level
);
return
1
;
}
...
...
@@ -889,19 +892,23 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
static
void
reada_for_search
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
,
int
slot
)
{
return
;
#if 0
struct extent_buffer *node;
int i;
u32 nritems;
u64
b
lock
nr
;
u64 b
yte
nr;
u64 search;
u64 cluster_start;
int ret;
int nread = 0;
int direction = path->reada;
int level;
struct radix_tree_root found;
unsigned long gang[8];
struct extent_buffer *eb;
if (level == 0)
return;
...
...
@@ -918,8 +925,9 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
init_bit_radix(&found);
nritems = btrfs_header_nritems(node);
level = btrfs_header_level(node) - 1;
for (i = slot; i < nritems; i++) {
b
lock
nr
=
btrfs_node_blockptr
(
node
,
i
);
b
yte
nr = btrfs_node_blockptr(node, i);
set_radix_bit(&found, blocknr);
}
if (direction > 0) {
...
...
@@ -944,6 +952,7 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
}
}
}
#endif
}
/*
* look for key in the tree. path is filled in with nodes along the way
...
...
@@ -963,7 +972,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
ins_len
,
int
cow
)
{
struct
extent_buffer
*
b
;
u64
b
lock
nr
;
u64
b
yte
nr
;
int
slot
;
int
ret
;
int
level
;
...
...
@@ -1027,10 +1036,11 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
/* this is only true while dropping a snapshot */
if
(
level
==
lowest_level
)
break
;
b
lock
nr
=
btrfs_node_blockptr
(
b
,
slot
);
b
yte
nr
=
btrfs_node_blockptr
(
b
,
slot
);
if
(
should_reada
)
reada_for_search
(
root
,
p
,
level
,
slot
);
b
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
b
,
slot
));
b
=
read_tree_block
(
root
,
bytenr
,
btrfs_level_size
(
root
,
level
-
1
));
}
else
{
p
->
slots
[
level
]
=
slot
;
if
(
ins_len
>
0
&&
btrfs_leaf_free_space
(
root
,
b
)
<
...
...
@@ -1193,14 +1203,14 @@ static int insert_new_root(struct btrfs_trans_handle *trans,
BUG_ON
(
path
->
nodes
[
level
]);
BUG_ON
(
path
->
nodes
[
level
-
1
]
!=
root
->
node
);
c
=
btrfs_alloc_free_block
(
trans
,
root
,
extent_buffer_blocknr
(
root
->
node
)
,
0
);
c
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
nodesize
,
root
->
node
->
start
,
0
);
if
(
IS_ERR
(
c
))
return
PTR_ERR
(
c
);
memset_extent_buffer
(
c
,
0
,
0
,
root
->
nodesize
);
btrfs_set_header_nritems
(
c
,
1
);
btrfs_set_header_level
(
c
,
level
);
btrfs_set_header_b
locknr
(
c
,
extent_buffer_blocknr
(
c
)
);
btrfs_set_header_b
ytenr
(
c
,
c
->
start
);
btrfs_set_header_generation
(
c
,
trans
->
transid
);
btrfs_set_header_owner
(
c
,
root
->
root_key
.
objectid
);
lower
=
path
->
nodes
[
level
-
1
];
...
...
@@ -1213,7 +1223,7 @@ static int insert_new_root(struct btrfs_trans_handle *trans,
else
btrfs_node_key
(
lower
,
&
lower_key
,
0
);
btrfs_set_node_key
(
c
,
&
lower_key
,
0
);
btrfs_set_node_blockptr
(
c
,
0
,
extent_buffer_blocknr
(
lower
)
);
btrfs_set_node_blockptr
(
c
,
0
,
lower
->
start
);
btrfs_mark_buffer_dirty
(
c
);
...
...
@@ -1237,7 +1247,7 @@ static int insert_new_root(struct btrfs_trans_handle *trans,
*/
static
int
insert_ptr
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
btrfs_disk_key
*
key
,
u64
b
lock
nr
,
int
slot
,
int
level
)
*
key
,
u64
b
yte
nr
,
int
slot
,
int
level
)
{
struct
extent_buffer
*
lower
;
int
nritems
;
...
...
@@ -1256,10 +1266,9 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
(
nritems
-
slot
)
*
sizeof
(
struct
btrfs_key_ptr
));
}
btrfs_set_node_key
(
lower
,
key
,
slot
);
btrfs_set_node_blockptr
(
lower
,
slot
,
b
lock
nr
);
btrfs_set_node_blockptr
(
lower
,
slot
,
b
yte
nr
);
btrfs_set_header_nritems
(
lower
,
nritems
+
1
);
btrfs_mark_buffer_dirty
(
lower
);
check_node
(
root
,
path
,
level
);
return
0
;
}
...
...
@@ -1300,14 +1309,14 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
}
c_nritems
=
btrfs_header_nritems
(
c
);
split
=
btrfs_alloc_free_block
(
trans
,
root
,
extent_buffer_blocknr
(
c
)
,
0
);
split
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
nodesize
,
c
->
start
,
0
);
if
(
IS_ERR
(
split
))
return
PTR_ERR
(
split
);
btrfs_set_header_flags
(
split
,
btrfs_header_flags
(
c
));
btrfs_set_header_level
(
split
,
btrfs_header_level
(
c
));
btrfs_set_header_b
locknr
(
split
,
extent_buffer_blocknr
(
split
)
);
btrfs_set_header_b
ytenr
(
split
,
split
->
start
);
btrfs_set_header_generation
(
split
,
trans
->
transid
);
btrfs_set_header_owner
(
split
,
root
->
root_key
.
objectid
);
write_extent_buffer
(
split
,
root
->
fs_info
->
fsid
,
...
...
@@ -1328,8 +1337,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_mark_buffer_dirty
(
split
);
btrfs_node_key
(
split
,
&
disk_key
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
split
),
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
split
->
start
,
path
->
slots
[
level
+
1
]
+
1
,
level
+
1
);
if
(
wret
)
...
...
@@ -1407,6 +1415,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
u32
left_nritems
;
u32
right_nritems
;
u32
data_end
;
u32
this_item_size
;
int
ret
;
slot
=
path
->
slots
[
1
];
...
...
@@ -1417,7 +1426,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
slot
>=
btrfs_header_nritems
(
upper
)
-
1
)
return
1
;
right
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
upper
,
slot
+
1
));
right
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
upper
,
slot
+
1
),
root
->
leafsize
);
free_space
=
btrfs_leaf_free_space
(
root
,
right
);
if
(
free_space
<
data_size
+
sizeof
(
struct
btrfs_item
))
{
free_extent_buffer
(
right
);
...
...
@@ -1445,13 +1455,27 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
for
(
i
=
left_nritems
-
1
;
i
>=
1
;
i
--
)
{
item
=
btrfs_item_nr
(
left
,
i
);
if
(
path
->
slots
[
0
]
==
i
)
push_space
+=
data_size
+
sizeof
(
*
item
);
if
(
btrfs_item_size
(
left
,
item
)
+
sizeof
(
*
item
)
+
push_space
>
free_space
)
if
(
!
left
->
map_token
)
{
map_extent_buffer
(
left
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
left
->
map_token
,
&
left
->
kaddr
,
&
left
->
map_start
,
&
left
->
map_len
,
KM_USER1
);
}
this_item_size
=
btrfs_item_size
(
left
,
item
);
if
(
this_item_size
+
sizeof
(
*
item
)
+
push_space
>
free_space
)
break
;
push_items
++
;
push_space
+=
btrfs_item_size
(
left
,
item
)
+
sizeof
(
*
item
);
push_space
+=
this_item_size
+
sizeof
(
*
item
);
}
if
(
left
->
map_token
)
{
unmap_extent_buffer
(
left
,
left
->
map_token
,
KM_USER1
);
left
->
map_token
=
NULL
;
}
if
(
push_items
==
0
)
{
...
...
@@ -1493,11 +1517,23 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
right_nritems
+=
push_items
;
btrfs_set_header_nritems
(
right
,
right_nritems
);
push_space
=
BTRFS_LEAF_DATA_SIZE
(
root
);
for
(
i
=
0
;
i
<
right_nritems
;
i
++
)
{
item
=
btrfs_item_nr
(
right
,
i
);
btrfs_set_item_offset
(
right
,
item
,
push_space
-
btrfs_item_size
(
right
,
item
));
push_space
=
btrfs_item_offset
(
right
,
item
);
if
(
!
right
->
map_token
)
{
map_extent_buffer
(
right
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
right
->
map_token
,
&
right
->
kaddr
,
&
right
->
map_start
,
&
right
->
map_len
,
KM_USER1
);
}
push_space
-=
btrfs_item_size
(
right
,
item
);
btrfs_set_item_offset
(
right
,
item
,
push_space
);
}
if
(
right
->
map_token
)
{
unmap_extent_buffer
(
right
,
right
->
map_token
,
KM_USER1
);
right
->
map_token
=
NULL
;
}
left_nritems
-=
push_items
;
btrfs_set_header_nritems
(
left
,
left_nritems
);
...
...
@@ -1518,8 +1554,6 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
}
else
{
free_extent_buffer
(
right
);
}
if
(
path
->
nodes
[
1
])
check_node
(
root
,
path
,
1
);
return
0
;
}
/*
...
...
@@ -1542,6 +1576,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
u32
right_nritems
;
int
ret
=
0
;
int
wret
;
u32
this_item_size
;
u32
old_left_item_size
;
slot
=
path
->
slots
[
1
];
if
(
slot
==
0
)
...
...
@@ -1550,7 +1586,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
return
1
;
left
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
path
->
nodes
[
1
],
slot
-
1
)
);
slot
-
1
),
root
->
leafsize
);
free_space
=
btrfs_leaf_free_space
(
root
,
left
);
if
(
free_space
<
data_size
+
sizeof
(
struct
btrfs_item
))
{
free_extent_buffer
(
left
);
...
...
@@ -1579,14 +1615,30 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
for
(
i
=
0
;
i
<
right_nritems
-
1
;
i
++
)
{
item
=
btrfs_item_nr
(
right
,
i
);
if
(
!
right
->
map_token
)
{
map_extent_buffer
(
right
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
right
->
map_token
,
&
right
->
kaddr
,
&
right
->
map_start
,
&
right
->
map_len
,
KM_USER1
);
}
if
(
path
->
slots
[
0
]
==
i
)
push_space
+=
data_size
+
sizeof
(
*
item
);
if
(
btrfs_item_size
(
right
,
item
)
+
sizeof
(
*
item
)
+
push_space
>
free_space
)
this_item_size
=
btrfs_item_size
(
right
,
item
);
if
(
this_item_size
+
sizeof
(
*
item
)
+
push_space
>
free_space
)
break
;
push_items
++
;
push_space
+=
btrfs_item_size
(
right
,
item
)
+
sizeof
(
*
item
);
push_space
+=
this_item_size
+
sizeof
(
*
item
);
}
if
(
right
->
map_token
)
{
unmap_extent_buffer
(
right
,
right
->
map_token
,
KM_USER1
);
right
->
map_token
=
NULL
;
}
if
(
push_items
==
0
)
{
free_extent_buffer
(
left
);
return
1
;
...
...
@@ -1611,15 +1663,28 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
old_left_nritems
=
btrfs_header_nritems
(
left
);
BUG_ON
(
old_left_nritems
<
0
);
old_left_item_size
=
btrfs_item_offset_nr
(
left
,
old_left_nritems
-
1
);
for
(
i
=
old_left_nritems
;
i
<
old_left_nritems
+
push_items
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
left
,
i
);
if
(
!
left
->
map_token
)
{
map_extent_buffer
(
left
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
left
->
map_token
,
&
left
->
kaddr
,
&
left
->
map_start
,
&
left
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
left
,
item
);
btrfs_set_item_offset
(
left
,
item
,
ioff
-
(
BTRFS_LEAF_DATA_SIZE
(
root
)
-
btrfs_item_offset_nr
(
left
,
old_left_nritems
-
1
)));
ioff
-
(
BTRFS_LEAF_DATA_SIZE
(
root
)
-
old_left_item_size
));
}
btrfs_set_header_nritems
(
left
,
old_left_nritems
+
push_items
);
if
(
left
->
map_token
)
{
unmap_extent_buffer
(
left
,
left
->
map_token
,
KM_USER1
);
left
->
map_token
=
NULL
;
}
/* fixup right node */
push_space
=
btrfs_item_offset_nr
(
right
,
push_items
-
1
)
-
...
...
@@ -1640,9 +1705,21 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
for
(
i
=
0
;
i
<
right_nritems
;
i
++
)
{
item
=
btrfs_item_nr
(
right
,
i
);
btrfs_set_item_offset
(
right
,
item
,
push_space
-
btrfs_item_size
(
right
,
item
));
push_space
=
btrfs_item_offset
(
right
,
item
);
if
(
!
right
->
map_token
)
{
map_extent_buffer
(
right
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
right
->
map_token
,
&
right
->
kaddr
,
&
right
->
map_start
,
&
right
->
map_len
,
KM_USER1
);
}
push_space
=
push_space
-
btrfs_item_size
(
right
,
item
);
btrfs_set_item_offset
(
right
,
item
,
push_space
);
}
if
(
right
->
map_token
)
{
unmap_extent_buffer
(
right
,
right
->
map_token
,
KM_USER1
);
right
->
map_token
=
NULL
;
}
btrfs_mark_buffer_dirty
(
left
);
...
...
@@ -1664,8 +1741,6 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
path
->
slots
[
0
]
-=
push_items
;
}
BUG_ON
(
path
->
slots
[
0
]
<
0
);
if
(
path
->
nodes
[
1
])
check_node
(
root
,
path
,
1
);
return
ret
;
}
...
...
@@ -1718,13 +1793,13 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
nritems
=
btrfs_header_nritems
(
l
);
mid
=
(
nritems
+
1
)
/
2
;
right
=
btrfs_alloc_free_block
(
trans
,
root
,
extent_buffer_blocknr
(
l
)
,
0
);
right
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
leafsize
,
l
->
start
,
0
);
if
(
IS_ERR
(
right
))
return
PTR_ERR
(
right
);
memset_extent_buffer
(
right
,
0
,
0
,
sizeof
(
struct
btrfs_header
));
btrfs_set_header_b
locknr
(
right
,
extent_buffer_blocknr
(
right
)
);
btrfs_set_header_b
ytenr
(
right
,
right
->
start
);
btrfs_set_header_generation
(
right
,
trans
->
transid
);
btrfs_set_header_owner
(
right
,
root
->
root_key
.
objectid
);
btrfs_set_header_level
(
right
,
0
);
...
...
@@ -1740,8 +1815,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_cpu_key_to_disk
(
&
disk_key
,
ins_key
);
btrfs_set_header_nritems
(
right
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
right
),
&
disk_key
,
right
->
start
,
path
->
slots
[
1
]
+
1
,
1
);
if
(
wret
)
ret
=
wret
;
...
...
@@ -1762,7 +1836,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_header_nritems
(
right
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
right
)
,
right
->
start
,
path
->
slots
[
1
],
1
);
if
(
wret
)
ret
=
wret
;
...
...
@@ -1799,15 +1873,30 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
struct
btrfs_item
*
item
=
btrfs_item_nr
(
right
,
i
);
u32
ioff
=
btrfs_item_offset
(
right
,
item
);
u32
ioff
;
if
(
!
right
->
map_token
)
{
map_extent_buffer
(
right
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
right
->
map_token
,
&
right
->
kaddr
,
&
right
->
map_start
,
&
right
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
right
,
item
);
btrfs_set_item_offset
(
right
,
item
,
ioff
+
rt_data_off
);
}
if
(
right
->
map_token
)
{
unmap_extent_buffer
(
right
,
right
->
map_token
,
KM_USER1
);
right
->
map_token
=
NULL
;
}
btrfs_set_header_nritems
(
l
,
mid
);
ret
=
0
;
btrfs_item_key
(
right
,
&
disk_key
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
right
),
path
->
slots
[
1
]
+
1
,
1
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
right
->
start
,
path
->
slots
[
1
]
+
1
,
1
);
if
(
wret
)
ret
=
wret
;
...
...
@@ -1824,19 +1913,17 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
free_extent_buffer
(
right
);
BUG_ON
(
path
->
slots
[
0
]
<
0
);
check_node
(
root
,
path
,
1
);
check_leaf
(
root
,
path
,
0
);
if
(
!
double_split
)
return
ret
;
right
=
btrfs_alloc_free_block
(
trans
,
root
,
extent_buffer_blocknr
(
l
)
,
0
);
right
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
leafsize
,
l
->
start
,
0
);
if
(
IS_ERR
(
right
))
return
PTR_ERR
(
right
);
memset_extent_buffer
(
right
,
0
,
0
,
sizeof
(
struct
btrfs_header
));
btrfs_set_header_b
locknr
(
right
,
extent_buffer_blocknr
(
right
)
);
btrfs_set_header_b
ytenr
(
right
,
right
->
start
);
btrfs_set_header_generation
(
right
,
trans
->
transid
);
btrfs_set_header_owner
(
right
,
root
->
root_key
.
objectid
);
btrfs_set_header_level
(
right
,
0
);
...
...
@@ -1847,8 +1934,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_cpu_key_to_disk
(
&
disk_key
,
ins_key
);
btrfs_set_header_nritems
(
right
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
extent_buffer_blocknr
(
right
),
&
disk_key
,
right
->
start
,
path
->
slots
[
1
],
1
);
if
(
wret
)
ret
=
wret
;
...
...
@@ -1860,8 +1946,6 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
free_extent_buffer
(
path
->
nodes
[
0
]);
path
->
nodes
[
0
]
=
right
;
path
->
slots
[
0
]
=
0
;
check_node
(
root
,
path
,
1
);
check_leaf
(
root
,
path
,
0
);
return
ret
;
}
...
...
@@ -1904,9 +1988,24 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
for
(
i
=
slot
;
i
<
nritems
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
leaf
,
i
);
if
(
!
leaf
->
map_token
)
{
map_extent_buffer
(
leaf
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
leaf
->
map_token
,
&
leaf
->
kaddr
,
&
leaf
->
map_start
,
&
leaf
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
leaf
,
item
);
btrfs_set_item_offset
(
leaf
,
item
,
ioff
+
size_diff
);
}
if
(
leaf
->
map_token
)
{
unmap_extent_buffer
(
leaf
,
leaf
->
map_token
,
KM_USER1
);
leaf
->
map_token
=
NULL
;
}
/* shift the data */
memmove_extent_buffer
(
leaf
,
btrfs_leaf_data
(
leaf
)
+
data_end
+
size_diff
,
btrfs_leaf_data
(
leaf
)
+
...
...
@@ -1921,7 +2020,6 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
btrfs_print_leaf
(
root
,
leaf
);
BUG
();
}
check_leaf
(
root
,
path
,
0
);
return
ret
;
}
...
...
@@ -1963,10 +2061,23 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans,
for
(
i
=
slot
;
i
<
nritems
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
leaf
,
i
);
if
(
!
leaf
->
map_token
)
{
map_extent_buffer
(
leaf
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
leaf
->
map_token
,
&
leaf
->
kaddr
,
&
leaf
->
map_start
,
&
leaf
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
leaf
,
item
);
btrfs_set_item_offset
(
leaf
,
item
,
ioff
-
data_size
);
}
if
(
leaf
->
map_token
)
{
unmap_extent_buffer
(
leaf
,
leaf
->
map_token
,
KM_USER1
);
leaf
->
map_token
=
NULL
;
}
/* shift the data */
memmove_extent_buffer
(
leaf
,
btrfs_leaf_data
(
leaf
)
+
data_end
-
data_size
,
btrfs_leaf_data
(
leaf
)
+
...
...
@@ -1983,7 +2094,6 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans,
btrfs_print_leaf
(
root
,
leaf
);
BUG
();
}
check_leaf
(
root
,
path
,
0
);
return
ret
;
}
...
...
@@ -2046,12 +2156,26 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
* item0..itemN ... dataN.offset..dataN.size .. data0.size
*/
/* first correct the data pointers */
WARN_ON
(
leaf
->
map_token
);
for
(
i
=
slot
;
i
<
nritems
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
leaf
,
i
);
if
(
!
leaf
->
map_token
)
{
map_extent_buffer
(
leaf
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
leaf
->
map_token
,
&
leaf
->
kaddr
,
&
leaf
->
map_start
,
&
leaf
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
leaf
,
item
);
btrfs_set_item_offset
(
leaf
,
item
,
ioff
-
data_size
);
}
if
(
leaf
->
map_token
)
{
unmap_extent_buffer
(
leaf
,
leaf
->
map_token
,
KM_USER1
);
leaf
->
map_token
=
NULL
;
}
/* shift the items */
memmove_extent_buffer
(
leaf
,
btrfs_item_nr_offset
(
slot
+
1
),
...
...
@@ -2081,7 +2205,6 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
btrfs_print_leaf
(
root
,
leaf
);
BUG
();
}
check_leaf
(
root
,
path
,
0
);
out:
return
ret
;
}
...
...
@@ -2186,10 +2309,24 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
for
(
i
=
slot
+
1
;
i
<
nritems
;
i
++
)
{
u32
ioff
;
item
=
btrfs_item_nr
(
leaf
,
i
);
if
(
!
leaf
->
map_token
)
{
map_extent_buffer
(
leaf
,
(
unsigned
long
)
item
,
sizeof
(
struct
btrfs_item
),
&
leaf
->
map_token
,
&
leaf
->
kaddr
,
&
leaf
->
map_start
,
&
leaf
->
map_len
,
KM_USER1
);
}
ioff
=
btrfs_item_offset
(
leaf
,
item
);
btrfs_set_item_offset
(
leaf
,
item
,
ioff
+
dsize
);
}
if
(
leaf
->
map_token
)
{
unmap_extent_buffer
(
leaf
,
leaf
->
map_token
,
KM_USER1
);
leaf
->
map_token
=
NULL
;
}
memmove_extent_buffer
(
leaf
,
btrfs_item_nr_offset
(
slot
),
btrfs_item_nr_offset
(
slot
+
1
),
sizeof
(
struct
btrfs_item
)
*
...
...
@@ -2209,8 +2346,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
wret
)
ret
=
wret
;
wret
=
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
leaf
),
1
,
1
);
leaf
->
start
,
leaf
->
len
,
1
);
if
(
wret
)
ret
=
wret
;
}
...
...
@@ -2247,7 +2383,8 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
}
if
(
btrfs_header_nritems
(
leaf
)
==
0
)
{
u64
blocknr
=
extent_buffer_blocknr
(
leaf
);
u64
bytenr
=
leaf
->
start
;
u32
blocksize
=
leaf
->
len
;
clean_tree_block
(
trans
,
root
,
leaf
);
wait_on_tree_block_writeback
(
root
,
leaf
);
...
...
@@ -2257,8 +2394,8 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
ret
=
wret
;
free_extent_buffer
(
leaf
);
wret
=
btrfs_free_extent
(
trans
,
root
,
b
lock
nr
,
1
,
1
);
wret
=
btrfs_free_extent
(
trans
,
root
,
b
yte
nr
,
blocksize
,
1
);
if
(
wret
)
ret
=
wret
;
}
else
{
...
...
@@ -2281,7 +2418,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
{
int
slot
;
int
level
=
1
;
u64
b
lock
nr
;
u64
b
yte
nr
;
struct
extent_buffer
*
c
;
struct
extent_buffer
*
next
=
NULL
;
...
...
@@ -2296,14 +2433,15 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
continue
;
}
b
lock
nr
=
btrfs_node_blockptr
(
c
,
slot
);
b
yte
nr
=
btrfs_node_blockptr
(
c
,
slot
);
if
(
next
)
free_extent_buffer
(
next
);
if
(
path
->
reada
)
reada_for_search
(
root
,
path
,
level
,
slot
);
next
=
read_tree_block
(
root
,
blocknr
);
next
=
read_tree_block
(
root
,
bytenr
,
btrfs_level_size
(
root
,
level
-
1
));
break
;
}
path
->
slots
[
level
]
=
slot
;
...
...
@@ -2317,7 +2455,8 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
break
;
if
(
path
->
reada
)
reada_for_search
(
root
,
path
,
level
,
0
);
next
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
next
,
0
));
next
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
next
,
0
),
btrfs_level_size
(
root
,
level
-
1
));
}
return
0
;
}
fs/btrfs/ctree.h
View file @
db94535d
...
...
@@ -96,7 +96,7 @@ struct btrfs_key {
struct
btrfs_header
{
u8
csum
[
BTRFS_CSUM_SIZE
];
u8
fsid
[
BTRFS_FSID_SIZE
];
/* FS specific uuid */
__le64
b
lock
nr
;
/* which block this node is supposed to live in */
__le64
b
yte
nr
;
/* which block this node is supposed to live in */
__le64
generation
;
__le64
owner
;
__le32
nritems
;
...
...
@@ -122,16 +122,17 @@ struct btrfs_super_block {
u8
csum
[
BTRFS_CSUM_SIZE
];
/* the first 3 fields must match struct btrfs_header */
u8
fsid
[
16
];
/* FS specific uuid */
__le64
b
lock
nr
;
/* this block number */
__le64
b
yte
nr
;
/* this block number */
__le64
magic
;
__le64
generation
;
__le64
root
;
__le64
total_b
lock
s
;
__le64
b
lock
s_used
;
__le64
total_b
yte
s
;
__le64
b
yte
s_used
;
__le64
root_dir_objectid
;
__le32
sectorsize
;
__le32
nodesize
;
__le32
leafsize
;
u8
root_level
;
}
__attribute__
((
__packed__
));
/*
...
...
@@ -231,13 +232,14 @@ struct btrfs_dir_item {
struct
btrfs_root_item
{
struct
btrfs_inode_item
inode
;
__le64
root_dirid
;
__le64
b
lock
nr
;
__le64
b
lock
_limit
;
__le64
b
lock
s_used
;
__le64
b
yte
nr
;
__le64
b
yte
_limit
;
__le64
b
yte
s_used
;
__le32
flags
;
__le32
refs
;
struct
btrfs_disk_key
drop_progress
;
u8
drop_level
;
u8
level
;
}
__attribute__
((
__packed__
));
#define BTRFS_FILE_EXTENT_REG 0
...
...
@@ -250,8 +252,8 @@ struct btrfs_file_extent_item {
* disk space consumed by the extent, checksum blocks are included
* in these numbers
*/
__le64
disk_b
lock
nr
;
__le64
disk_num_b
lock
s
;
__le64
disk_b
yte
nr
;
__le64
disk_num_b
yte
s
;
/*
* the logical offset in file blocks (no csums)
* this extent record is for. This allows a file extent to point
...
...
@@ -263,7 +265,7 @@ struct btrfs_file_extent_item {
/*
* the logical number of file blocks (no csums included)
*/
__le64
num_b
lock
s
;
__le64
num_b
yte
s
;
}
__attribute__
((
__packed__
));
struct
btrfs_csum_item
{
...
...
@@ -429,6 +431,7 @@ static inline u##bits btrfs_##name(struct extent_buffer *eb, \
int err; \
char *map_token; \
char *kaddr; \
int unmap_on_exit = (eb->map_token == NULL); \
unsigned long map_start; \
unsigned long map_len; \
unsigned long offset = (unsigned long)s + \
...
...
@@ -436,12 +439,13 @@ static inline u##bits btrfs_##name(struct extent_buffer *eb, \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER
0
); \
&map_start, &map_len, KM_USER
1
); \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
u##bits res = le##bits##_to_cpu(*tmp); \
unmap_extent_buffer(eb, map_token, KM_USER0); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
return res; \
} else { \
__le##bits res; \
...
...
@@ -457,17 +461,19 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
char *kaddr; \
unsigned long map_start; \
unsigned long map_len; \
int unmap_on_exit = (eb->map_token == NULL); \
unsigned long offset = (unsigned long)s + \
offsetof(type, member); \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER
0
); \
&map_start, &map_len, KM_USER
1
); \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
*tmp = cpu_to_le##bits(val); \
unmap_extent_buffer(eb, map_token, KM_USER0); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
} else { \
val = cpu_to_le##bits(val); \
write_eb_member(eb, s, type, member, &val); \
...
...
@@ -483,15 +489,17 @@ static inline u##bits btrfs_##name(struct extent_buffer *eb) \
unsigned long map_start; \
unsigned long map_len; \
unsigned long offset = offsetof(type, member); \
int unmap_on_exit = (eb->map_token == NULL); \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER
0
); \
&map_start, &map_len, KM_USER
1
); \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
u##bits res = le##bits##_to_cpu(*tmp); \
unmap_extent_buffer(eb, map_token, KM_USER0); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
return res; \
} else { \
__le##bits res; \
...
...
@@ -508,15 +516,17 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
unsigned long map_start; \
unsigned long map_len; \
unsigned long offset = offsetof(type, member); \
int unmap_on_exit = (eb->map_token == NULL); \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER
0
); \
&map_start, &map_len, KM_USER
1
); \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
*tmp = cpu_to_le##bits(val); \
unmap_extent_buffer(eb, map_token, KM_USER0); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
} else { \
val = cpu_to_le##bits(val); \
write_eb_member(eb, NULL, type, member, &val); \
...
...
@@ -769,7 +779,7 @@ static inline void btrfs_set_key_type(struct btrfs_key *key, u8 val)
}
/* struct btrfs_header */
BTRFS_SETGET_HEADER_FUNCS
(
header_b
locknr
,
struct
btrfs_header
,
block
nr
,
64
);
BTRFS_SETGET_HEADER_FUNCS
(
header_b
ytenr
,
struct
btrfs_header
,
byte
nr
,
64
);
BTRFS_SETGET_HEADER_FUNCS
(
header_generation
,
struct
btrfs_header
,
generation
,
64
);
BTRFS_SETGET_HEADER_FUNCS
(
header_owner
,
struct
btrfs_header
,
owner
,
64
);
...
...
@@ -817,24 +827,28 @@ static inline int btrfs_is_leaf(struct extent_buffer *eb)
/* struct btrfs_root_item */
BTRFS_SETGET_FUNCS
(
disk_root_refs
,
struct
btrfs_root_item
,
refs
,
32
);
BTRFS_SETGET_FUNCS
(
disk_root_blocknr
,
struct
btrfs_root_item
,
blocknr
,
64
);
BTRFS_SETGET_FUNCS
(
disk_root_bytenr
,
struct
btrfs_root_item
,
bytenr
,
64
);
BTRFS_SETGET_FUNCS
(
disk_root_level
,
struct
btrfs_root_item
,
level
,
8
);
BTRFS_SETGET_STACK_FUNCS
(
root_blocknr
,
struct
btrfs_root_item
,
blocknr
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_bytenr
,
struct
btrfs_root_item
,
bytenr
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_level
,
struct
btrfs_root_item
,
level
,
8
);
BTRFS_SETGET_STACK_FUNCS
(
root_dirid
,
struct
btrfs_root_item
,
root_dirid
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_refs
,
struct
btrfs_root_item
,
refs
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
root_flags
,
struct
btrfs_root_item
,
flags
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
root_used
,
struct
btrfs_root_item
,
b
lock
s_used
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_limit
,
struct
btrfs_root_item
,
b
lock
_limit
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_used
,
struct
btrfs_root_item
,
b
yte
s_used
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
root_limit
,
struct
btrfs_root_item
,
b
yte
_limit
,
64
);
/* struct btrfs_super_block */
BTRFS_SETGET_STACK_FUNCS
(
super_b
locknr
,
struct
btrfs_super_block
,
block
nr
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_b
ytenr
,
struct
btrfs_super_block
,
byte
nr
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_generation
,
struct
btrfs_super_block
,
generation
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_root
,
struct
btrfs_super_block
,
root
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_total_blocks
,
struct
btrfs_super_block
,
total_blocks
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_blocks_used
,
struct
btrfs_super_block
,
blocks_used
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_root_level
,
struct
btrfs_super_block
,
root_level
,
8
);
BTRFS_SETGET_STACK_FUNCS
(
super_total_bytes
,
struct
btrfs_super_block
,
total_bytes
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_bytes_used
,
struct
btrfs_super_block
,
bytes_used
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_sectorsize
,
struct
btrfs_super_block
,
sectorsize
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
super_nodesize
,
struct
btrfs_super_block
,
...
...
@@ -856,33 +870,33 @@ static inline unsigned long btrfs_file_extent_inline_start(struct
btrfs_file_extent_item
*
e
)
{
unsigned
long
offset
=
(
unsigned
long
)
e
;
offset
+=
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
lock
nr
);
offset
+=
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
yte
nr
);
return
offset
;
}
static
inline
u32
btrfs_file_extent_calc_inline_size
(
u32
datasize
)
{
return
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
lock
nr
)
+
datasize
;
return
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
yte
nr
)
+
datasize
;
}
static
inline
u32
btrfs_file_extent_inline_len
(
struct
extent_buffer
*
eb
,
struct
btrfs_item
*
e
)
{
unsigned
long
offset
;
offset
=
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
lock
nr
);
offset
=
offsetof
(
struct
btrfs_file_extent_item
,
disk_b
yte
nr
);
return
btrfs_item_size
(
eb
,
e
)
-
offset
;
}
BTRFS_SETGET_FUNCS
(
file_extent_disk_b
lock
nr
,
struct
btrfs_file_extent_item
,
disk_b
lock
nr
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_disk_b
yte
nr
,
struct
btrfs_file_extent_item
,
disk_b
yte
nr
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_generation
,
struct
btrfs_file_extent_item
,
generation
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_disk_num_b
lock
s
,
struct
btrfs_file_extent_item
,
disk_num_b
lock
s
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_disk_num_b
yte
s
,
struct
btrfs_file_extent_item
,
disk_num_b
yte
s
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_offset
,
struct
btrfs_file_extent_item
,
offset
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_num_b
lock
s
,
struct
btrfs_file_extent_item
,
num_b
lock
s
,
64
);
BTRFS_SETGET_FUNCS
(
file_extent_num_b
yte
s
,
struct
btrfs_file_extent_item
,
num_b
yte
s
,
64
);
static
inline
struct
btrfs_root
*
btrfs_sb
(
struct
super_block
*
sb
)
{
...
...
@@ -906,6 +920,12 @@ static inline int btrfs_set_root_name(struct btrfs_root *root,
return
0
;
}
static
inline
u32
btrfs_level_size
(
struct
btrfs_root
*
root
,
int
level
)
{
if
(
level
==
0
)
return
root
->
leafsize
;
return
root
->
nodesize
;
}
/* helper function to cast into the data area of the leaf. */
#define btrfs_item_ptr(leaf, slot, type) \
((type *)(btrfs_leaf_data(leaf) + \
...
...
@@ -927,7 +947,7 @@ int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
int
btrfs_copy_pinned
(
struct
btrfs_root
*
root
,
struct
extent_map_tree
*
copy
);
struct
btrfs_block_group_cache
*
btrfs_lookup_block_group
(
struct
btrfs_fs_info
*
info
,
u64
b
lock
nr
);
u64
b
yte
nr
);
struct
btrfs_block_group_cache
*
btrfs_find_block_group
(
struct
btrfs_root
*
root
,
struct
btrfs_block_group_cache
*
hint
,
u64
search_start
,
...
...
@@ -935,22 +955,22 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
int
btrfs_inc_root_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
struct
extent_buffer
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u
64
hint
,
u64
empty_size
);
struct
btrfs_root
*
root
,
u
32
size
,
u64
hint
,
u64
empty_size
);
int
btrfs_alloc_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
owner
,
u64
num_b
lock
s
,
u64
empty_size
,
u64
search_start
,
u64
num_b
yte
s
,
u64
empty_size
,
u64
search_start
,
u64
search_end
,
struct
btrfs_key
*
ins
,
int
data
);
int
btrfs_inc_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
);
int
btrfs_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
,
int
pin
);
*
root
,
u64
b
ytenr
,
u64
num_byte
s
,
int
pin
);
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_map_tree
*
unpin
);
int
btrfs_inc_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
);
u64
b
ytenr
,
u64
num_byte
s
);
int
btrfs_write_dirty_block_groups
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
int
btrfs_free_block_groups
(
struct
btrfs_fs_info
*
info
);
...
...
@@ -1040,12 +1060,12 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
int
btrfs_insert_file_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
objectid
,
u64
pos
,
u64
offset
,
u64
disk_num_b
lock
s
,
u64
num_b
lock
s
);
u64
disk_num_b
yte
s
,
u64
num_b
yte
s
);
int
btrfs_lookup_file_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
objectid
,
u64
b
lock
nr
,
int
mod
);
u64
b
yte
nr
,
int
mod
);
int
btrfs_csum_file_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
objectid
,
u64
offset
,
...
...
fs/btrfs/disk-io.c
View file @
db94535d
...
...
@@ -28,6 +28,7 @@
#include "disk-io.h"
#include "transaction.h"
#include "btrfs_inode.h"
#include "print-tree.h"
#if 0
static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
...
...
@@ -43,26 +44,25 @@ static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
#endif
struct
extent_buffer
*
btrfs_find_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
)
u64
b
ytenr
,
u32
blocksize
)
{
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
extent_buffer
*
eb
;
eb
=
find_extent_buffer
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
blocknr
*
root
->
sectorsize
,
root
->
sectorsize
,
GFP_NOFS
);
bytenr
,
blocksize
,
GFP_NOFS
);
if
(
eb
)
eb
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
return
eb
;
}
struct
extent_buffer
*
btrfs_find_create_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
)
u64
b
ytenr
,
u32
blocksize
)
{
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
extent_buffer
*
eb
;
eb
=
alloc_extent_buffer
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
blocknr
*
root
->
sectorsize
,
root
->
sectorsize
,
GFP_NOFS
);
bytenr
,
blocksize
,
GFP_NOFS
);
eb
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
return
eb
;
}
...
...
@@ -208,13 +208,13 @@ static struct address_space_operations btree_aops = {
.
sync_page
=
block_sync_page
,
};
int
readahead_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
)
int
readahead_tree_block
(
struct
btrfs_root
*
root
,
u64
b
ytenr
,
u32
blocksize
)
{
struct
extent_buffer
*
buf
=
NULL
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
int
ret
=
0
;
buf
=
btrfs_find_create_tree_block
(
root
,
b
locknr
);
buf
=
btrfs_find_create_tree_block
(
root
,
b
ytenr
,
blocksize
);
if
(
!
buf
)
return
0
;
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
...
...
@@ -223,12 +223,13 @@ int readahead_tree_block(struct btrfs_root *root, u64 blocknr)
return
ret
;
}
struct
extent_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
struct
extent_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
)
{
struct
extent_buffer
*
buf
=
NULL
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
buf
=
btrfs_find_create_tree_block
(
root
,
b
locknr
);
buf
=
btrfs_find_create_tree_block
(
root
,
b
ytenr
,
blocksize
);
if
(
!
buf
)
return
NULL
;
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
...
...
@@ -261,7 +262,7 @@ int set_tree_block_dirty(struct btrfs_root *root, struct extent_buffer *buf)
return
0
;
}
static
int
__setup_root
(
int
block
size
,
static
int
__setup_root
(
u32
nodesize
,
u32
leafsize
,
u32
sector
size
,
struct
btrfs_root
*
root
,
struct
btrfs_fs_info
*
fs_info
,
u64
objectid
)
...
...
@@ -269,9 +270,9 @@ static int __setup_root(int blocksize,
root
->
node
=
NULL
;
root
->
inode
=
NULL
;
root
->
commit_root
=
NULL
;
root
->
sectorsize
=
block
size
;
root
->
nodesize
=
block
size
;
root
->
leafsize
=
block
size
;
root
->
sectorsize
=
sector
size
;
root
->
nodesize
=
node
size
;
root
->
leafsize
=
leaf
size
;
root
->
ref_cows
=
0
;
root
->
fs_info
=
fs_info
;
root
->
objectid
=
objectid
;
...
...
@@ -291,21 +292,23 @@ static int __setup_root(int blocksize,
return
0
;
}
static
int
find_and_setup_root
(
int
blocksize
,
struct
btrfs_root
*
tree_root
,
static
int
find_and_setup_root
(
struct
btrfs_root
*
tree_root
,
struct
btrfs_fs_info
*
fs_info
,
u64
objectid
,
struct
btrfs_root
*
root
)
{
int
ret
;
u32
blocksize
;
__setup_root
(
blocksize
,
root
,
fs_info
,
objectid
);
__setup_root
(
tree_root
->
nodesize
,
tree_root
->
leafsize
,
tree_root
->
sectorsize
,
root
,
fs_info
,
objectid
);
ret
=
btrfs_find_last_root
(
tree_root
,
objectid
,
&
root
->
root_item
,
&
root
->
root_key
);
BUG_ON
(
ret
);
root
->
node
=
read_tree_block
(
root
,
btrfs_root_blocknr
(
&
root
->
root_item
));
blocksize
=
btrfs_level_size
(
root
,
btrfs_root_level
(
&
root
->
root_item
));
root
->
node
=
read_tree_block
(
root
,
btrfs_root_bytenr
(
&
root
->
root_item
),
blocksize
);
BUG_ON
(
!
root
->
node
);
return
0
;
}
...
...
@@ -318,14 +321,14 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
struct
btrfs_path
*
path
;
struct
extent_buffer
*
l
;
u64
highest_inode
;
u32
blocksize
;
int
ret
=
0
;
root
=
kzalloc
(
sizeof
(
*
root
),
GFP_NOFS
);
if
(
!
root
)
return
ERR_PTR
(
-
ENOMEM
);
if
(
location
->
offset
==
(
u64
)
-
1
)
{
ret
=
find_and_setup_root
(
fs_info
->
sb
->
s_blocksize
,
fs_info
->
tree_root
,
fs_info
,
ret
=
find_and_setup_root
(
tree_root
,
fs_info
,
location
->
objectid
,
root
);
if
(
ret
)
{
kfree
(
root
);
...
...
@@ -334,7 +337,8 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
goto
insert
;
}
__setup_root
(
fs_info
->
sb
->
s_blocksize
,
root
,
fs_info
,
__setup_root
(
tree_root
->
nodesize
,
tree_root
->
leafsize
,
tree_root
->
sectorsize
,
root
,
fs_info
,
location
->
objectid
);
path
=
btrfs_alloc_path
();
...
...
@@ -357,8 +361,9 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
kfree
(
root
);
return
ERR_PTR
(
ret
);
}
root
->
node
=
read_tree_block
(
root
,
btrfs_root_blocknr
(
&
root
->
root_item
));
blocksize
=
btrfs_level_size
(
root
,
btrfs_root_level
(
&
root
->
root_item
));
root
->
node
=
read_tree_block
(
root
,
btrfs_root_bytenr
(
&
root
->
root_item
),
blocksize
);
BUG_ON
(
!
root
->
node
);
insert:
root
->
ref_cows
=
1
;
...
...
@@ -418,6 +423,10 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
)
{
u32
sectorsize
;
u32
nodesize
;
u32
leafsize
;
u32
blocksize
;
struct
btrfs_root
*
extent_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
GFP_NOFS
);
struct
btrfs_root
*
tree_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
...
...
@@ -474,12 +483,12 @@ struct btrfs_root *open_ctree(struct super_block *sb)
mutex_init
(
&
fs_info
->
trans_mutex
);
mutex_init
(
&
fs_info
->
fs_mutex
);
__setup_root
(
sb
->
s_blocksize
,
tree_root
,
__setup_root
(
512
,
512
,
512
,
tree_root
,
fs_info
,
BTRFS_ROOT_TREE_OBJECTID
);
fs_info
->
sb_buffer
=
read_tree_block
(
tree_root
,
BTRFS_SUPER_INFO_OFFSET
/
sb
->
s_blocksize
);
BTRFS_SUPER_INFO_OFFSET
,
512
);
if
(
!
fs_info
->
sb_buffer
)
goto
fail_iput
;
...
...
@@ -494,9 +503,15 @@ struct btrfs_root *open_ctree(struct super_block *sb)
if
(
!
btrfs_super_root
(
disk_super
))
goto
fail_sb_buffer
;
nodesize
=
btrfs_super_nodesize
(
disk_super
);
leafsize
=
btrfs_super_leafsize
(
disk_super
);
sectorsize
=
btrfs_super_sectorsize
(
disk_super
);
tree_root
->
nodesize
=
nodesize
;
tree_root
->
leafsize
=
leafsize
;
tree_root
->
sectorsize
=
sectorsize
;
i_size_write
(
fs_info
->
btree_inode
,
btrfs_super_total_blocks
(
disk_super
)
<<
fs_info
->
btree_inode
->
i_blkbits
);
btrfs_super_total_bytes
(
disk_super
));
if
(
strncmp
((
char
*
)(
&
disk_super
->
magic
),
BTRFS_MAGIC
,
...
...
@@ -504,13 +519,22 @@ struct btrfs_root *open_ctree(struct super_block *sb)
printk
(
"btrfs: valid FS not found on %s
\n
"
,
sb
->
s_id
);
goto
fail_sb_buffer
;
}
blocksize
=
btrfs_level_size
(
tree_root
,
btrfs_super_root_level
(
disk_super
));
tree_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_root
(
disk_super
));
btrfs_super_root
(
disk_super
),
blocksize
);
if
(
!
tree_root
->
node
)
goto
fail_sb_buffer
;
#if 0
btrfs_print_leaf(tree_root, tree_root->node);
err = -EIO;
goto fail_tree_root;
#endif
mutex_lock
(
&
fs_info
->
fs_mutex
);
ret
=
find_and_setup_root
(
sb
->
s_blocksize
,
tree_root
,
fs_info
,
ret
=
find_and_setup_root
(
tree_root
,
fs_info
,
BTRFS_EXTENT_TREE_OBJECTID
,
extent_root
);
if
(
ret
)
{
mutex_unlock
(
&
fs_info
->
fs_mutex
);
...
...
@@ -611,11 +635,11 @@ int close_ctree(struct btrfs_root *root)
free_extent_buffer
(
fs_info
->
tree_root
->
node
);
free_extent_buffer
(
fs_info
->
sb_buffer
);
truncate_inode_pages
(
fs_info
->
btree_inode
->
i_mapping
,
0
);
iput
(
fs_info
->
btree_inode
);
btrfs_free_block_groups
(
root
->
fs_info
);
del_fs_roots
(
fs_info
);
truncate_inode_pages
(
fs_info
->
btree_inode
->
i_mapping
,
0
);
iput
(
fs_info
->
btree_inode
);
kfree
(
fs_info
->
extent_root
);
kfree
(
fs_info
->
tree_root
);
return
0
;
...
...
@@ -642,7 +666,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
if
(
transid
!=
root
->
fs_info
->
generation
)
{
printk
(
KERN_CRIT
"transid mismatch buffer %llu, found %Lu running %Lu
\n
"
,
(
unsigned
long
long
)
extent_buffer_blocknr
(
buf
)
,
(
unsigned
long
long
)
buf
->
start
,
transid
,
root
->
fs_info
->
generation
);
WARN_ON
(
1
);
}
...
...
fs/btrfs/disk-io.h
View file @
db94535d
...
...
@@ -21,10 +21,11 @@
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
struct
extent_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
int
readahead_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
struct
extent_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
);
int
readahead_tree_block
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
);
struct
extent_buffer
*
btrfs_find_create_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
);
u64
b
ytenr
,
u32
blocksize
);
int
clean_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
);
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
);
...
...
@@ -32,7 +33,7 @@ int close_ctree(struct btrfs_root *root);
int
write_ctree_super
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
struct
extent_buffer
*
btrfs_find_tree_block
(
struct
btrfs_root
*
root
,
u64
b
locknr
);
u64
b
ytenr
,
u32
blocksize
);
struct
btrfs_root
*
btrfs_read_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_key
*
location
,
const
char
*
name
,
int
namelen
);
...
...
fs/btrfs/extent-tree.c
View file @
db94535d
...
...
@@ -129,7 +129,7 @@ static int cache_block_group(struct btrfs_root *root,
struct
btrfs_block_group_cache
*
btrfs_lookup_block_group
(
struct
btrfs_fs_info
*
info
,
u64
b
lock
nr
)
u64
b
yte
nr
)
{
struct
extent_map_tree
*
block_group_cache
;
struct
btrfs_block_group_cache
*
block_group
=
NULL
;
...
...
@@ -140,7 +140,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
block_group_cache
=
&
info
->
block_group_cache
;
ret
=
find_first_extent_bit
(
block_group_cache
,
b
lock
nr
,
&
start
,
&
end
,
b
yte
nr
,
&
start
,
&
end
,
BLOCK_GROUP_DATA
|
BLOCK_GROUP_METADATA
);
if
(
ret
)
{
return
NULL
;
...
...
@@ -152,7 +152,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
block_group
=
(
struct
btrfs_block_group_cache
*
)
ptr
;
if
(
block_group
->
key
.
objectid
<=
b
locknr
&&
block
nr
<=
if
(
block_group
->
key
.
objectid
<=
b
ytenr
&&
byte
nr
<=
block_group
->
key
.
objectid
+
block_group
->
key
.
offset
)
return
block_group
;
...
...
@@ -315,7 +315,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
int
btrfs_inc_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
)
u64
b
ytenr
,
u64
num_byte
s
)
{
struct
btrfs_path
*
path
;
int
ret
;
...
...
@@ -324,13 +324,14 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
struct
btrfs_extent_item
*
item
;
u32
refs
;
WARN_ON
(
num_bytes
<
root
->
sectorsize
);
path
=
btrfs_alloc_path
();
if
(
!
path
)
return
-
ENOMEM
;
key
.
objectid
=
b
lock
nr
;
key
.
objectid
=
b
yte
nr
;
btrfs_set_key_type
(
&
key
,
BTRFS_EXTENT_ITEM_KEY
);
key
.
offset
=
num_b
lock
s
;
key
.
offset
=
num_b
yte
s
;
ret
=
btrfs_search_slot
(
trans
,
root
->
fs_info
->
extent_root
,
&
key
,
path
,
0
,
1
);
if
(
ret
<
0
)
...
...
@@ -361,8 +362,8 @@ int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
}
static
int
lookup_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
lock
nr
,
u64
num_b
lock
s
,
u32
*
refs
)
struct
btrfs_root
*
root
,
u64
b
yte
nr
,
u64
num_b
yte
s
,
u32
*
refs
)
{
struct
btrfs_path
*
path
;
int
ret
;
...
...
@@ -370,9 +371,10 @@ static int lookup_extent_ref(struct btrfs_trans_handle *trans,
struct
extent_buffer
*
l
;
struct
btrfs_extent_item
*
item
;
WARN_ON
(
num_bytes
<
root
->
sectorsize
);
path
=
btrfs_alloc_path
();
key
.
objectid
=
b
lock
nr
;
key
.
offset
=
num_b
lock
s
;
key
.
objectid
=
b
yte
nr
;
key
.
offset
=
num_b
yte
s
;
btrfs_set_key_type
(
&
key
,
BTRFS_EXTENT_ITEM_KEY
);
ret
=
btrfs_search_slot
(
trans
,
root
->
fs_info
->
extent_root
,
&
key
,
path
,
0
,
0
);
...
...
@@ -380,7 +382,7 @@ static int lookup_extent_ref(struct btrfs_trans_handle *trans,
goto
out
;
if
(
ret
!=
0
)
{
btrfs_print_leaf
(
root
,
path
->
nodes
[
0
]);
printk
(
"failed to find block number %Lu
\n
"
,
b
lock
nr
);
printk
(
"failed to find block number %Lu
\n
"
,
b
yte
nr
);
BUG
();
}
l
=
path
->
nodes
[
0
];
...
...
@@ -394,19 +396,19 @@ static int lookup_extent_ref(struct btrfs_trans_handle *trans,
int
btrfs_inc_root_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
return
btrfs_inc_extent_ref
(
trans
,
root
,
extent_buffer_blocknr
(
root
->
node
),
1
);
return
btrfs_inc_extent_ref
(
trans
,
root
,
root
->
node
->
start
,
root
->
node
->
len
);
}
int
btrfs_inc_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
)
{
u64
b
lock
nr
;
u64
b
yte
nr
;
u32
nritems
;
struct
btrfs_key
key
;
struct
btrfs_file_extent_item
*
fi
;
int
i
;
int
le
af
;
int
le
vel
;
int
ret
;
int
faili
;
int
err
;
...
...
@@ -414,11 +416,11 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
!
root
->
ref_cows
)
return
0
;
le
af
=
btrfs_is_leaf
(
buf
);
le
vel
=
btrfs_header_level
(
buf
);
nritems
=
btrfs_header_nritems
(
buf
);
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
if
(
le
af
)
{
u64
disk_b
lock
nr
;
if
(
le
vel
==
0
)
{
u64
disk_b
yte
nr
;
btrfs_item_key_to_cpu
(
buf
,
&
key
,
i
);
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_EXTENT_DATA_KEY
)
continue
;
...
...
@@ -427,18 +429,19 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
btrfs_file_extent_type
(
buf
,
fi
)
==
BTRFS_FILE_EXTENT_INLINE
)
continue
;
disk_b
locknr
=
btrfs_file_extent_disk_block
nr
(
buf
,
fi
);
if
(
disk_b
lock
nr
==
0
)
disk_b
ytenr
=
btrfs_file_extent_disk_byte
nr
(
buf
,
fi
);
if
(
disk_b
yte
nr
==
0
)
continue
;
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
disk_b
lock
nr
,
btrfs_file_extent_disk_num_b
lock
s
(
buf
,
fi
));
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
disk_b
yte
nr
,
btrfs_file_extent_disk_num_b
yte
s
(
buf
,
fi
));
if
(
ret
)
{
faili
=
i
;
goto
fail
;
}
}
else
{
blocknr
=
btrfs_node_blockptr
(
buf
,
i
);
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
blocknr
,
1
);
bytenr
=
btrfs_node_blockptr
(
buf
,
i
);
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
bytenr
,
btrfs_level_size
(
root
,
level
-
1
));
if
(
ret
)
{
faili
=
i
;
goto
fail
;
...
...
@@ -449,8 +452,8 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
fail:
WARN_ON
(
1
);
for
(
i
=
0
;
i
<
faili
;
i
++
)
{
if
(
le
af
)
{
u64
disk_b
lock
nr
;
if
(
le
vel
==
0
)
{
u64
disk_b
yte
nr
;
btrfs_item_key_to_cpu
(
buf
,
&
key
,
i
);
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_EXTENT_DATA_KEY
)
continue
;
...
...
@@ -459,16 +462,17 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
btrfs_file_extent_type
(
buf
,
fi
)
==
BTRFS_FILE_EXTENT_INLINE
)
continue
;
disk_b
locknr
=
btrfs_file_extent_disk_block
nr
(
buf
,
fi
);
if
(
disk_b
lock
nr
==
0
)
disk_b
ytenr
=
btrfs_file_extent_disk_byte
nr
(
buf
,
fi
);
if
(
disk_b
yte
nr
==
0
)
continue
;
err
=
btrfs_free_extent
(
trans
,
root
,
disk_b
lock
nr
,
btrfs_file_extent_disk_num_b
lock
s
(
buf
,
err
=
btrfs_free_extent
(
trans
,
root
,
disk_b
yte
nr
,
btrfs_file_extent_disk_num_b
yte
s
(
buf
,
fi
),
0
);
BUG_ON
(
err
);
}
else
{
blocknr
=
btrfs_node_blockptr
(
buf
,
i
);
err
=
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
0
);
bytenr
=
btrfs_node_blockptr
(
buf
,
i
);
err
=
btrfs_free_extent
(
trans
,
root
,
bytenr
,
btrfs_level_size
(
root
,
level
-
1
),
0
);
BUG_ON
(
err
);
}
}
...
...
@@ -558,31 +562,31 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
static
int
update_block_group
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num
,
int
alloc
,
int
mark_free
,
int
data
)
u64
b
ytenr
,
u64
num_bytes
,
int
alloc
,
int
mark_free
,
int
data
)
{
struct
btrfs_block_group_cache
*
cache
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
u64
total
=
num
;
u64
total
=
num
_bytes
;
u64
old_val
;
u64
b
lock
_in_group
;
u64
b
yte
_in_group
;
u64
start
;
u64
end
;
while
(
total
)
{
cache
=
btrfs_lookup_block_group
(
info
,
b
lock
nr
);
cache
=
btrfs_lookup_block_group
(
info
,
b
yte
nr
);
if
(
!
cache
)
{
return
-
1
;
}
b
lock_in_group
=
block
nr
-
cache
->
key
.
objectid
;
WARN_ON
(
b
lock
_in_group
>
cache
->
key
.
offset
);
b
yte_in_group
=
byte
nr
-
cache
->
key
.
objectid
;
WARN_ON
(
b
yte
_in_group
>
cache
->
key
.
offset
);
start
=
cache
->
key
.
objectid
;
end
=
start
+
cache
->
key
.
offset
-
1
;
set_extent_bits
(
&
info
->
block_group_cache
,
start
,
end
,
BLOCK_GROUP_DIRTY
,
GFP_NOFS
);
old_val
=
btrfs_block_group_used
(
&
cache
->
item
);
num
=
min
(
total
,
cache
->
key
.
offset
-
block
_in_group
);
num
_bytes
=
min
(
total
,
cache
->
key
.
offset
-
byte
_in_group
);
if
(
alloc
)
{
if
(
cache
->
data
!=
data
&&
old_val
<
(
cache
->
key
.
offset
>>
1
))
{
...
...
@@ -608,18 +612,18 @@ static int update_block_group(struct btrfs_trans_handle *trans,
start
,
end
,
bit_to_set
,
GFP_NOFS
);
}
old_val
+=
num
;
old_val
+=
num
_bytes
;
}
else
{
old_val
-=
num
;
old_val
-=
num
_bytes
;
if
(
mark_free
)
{
set_extent_dirty
(
&
info
->
free_space_cache
,
b
locknr
,
blocknr
+
num
-
1
,
b
ytenr
,
bytenr
+
num_bytes
-
1
,
GFP_NOFS
);
}
}
btrfs_set_block_group_used
(
&
cache
->
item
,
old_val
);
total
-=
num
;
b
locknr
+=
num
;
total
-=
num
_bytes
;
b
ytenr
+=
num_bytes
;
}
return
0
;
}
...
...
@@ -701,13 +705,14 @@ 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
pending
)
static
int
pin_down_bytes
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
num_bytes
,
int
pending
)
{
int
err
=
0
;
struct
extent_buffer
*
buf
;
if
(
!
pending
)
{
buf
=
btrfs_find_tree_block
(
root
,
b
locknr
);
buf
=
btrfs_find_tree_block
(
root
,
b
ytenr
,
num_bytes
);
if
(
buf
)
{
if
(
btrfs_buffer_uptodate
(
buf
))
{
u64
transid
=
...
...
@@ -720,10 +725,11 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
free_extent_buffer
(
buf
);
}
set_extent_dirty
(
&
root
->
fs_info
->
pinned_extents
,
b
locknr
,
blocknr
,
GFP_NOFS
);
b
ytenr
,
bytenr
+
num_bytes
-
1
,
GFP_NOFS
);
}
else
{
set_extent_bits
(
&
root
->
fs_info
->
pending_del
,
blocknr
,
blocknr
,
EXTENT_LOCKED
,
GFP_NOFS
);
bytenr
,
bytenr
+
num_bytes
-
1
,
EXTENT_LOCKED
,
GFP_NOFS
);
}
BUG_ON
(
err
<
0
);
return
0
;
...
...
@@ -733,7 +739,7 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
* remove an extent from the root, returns 0 on success
*/
static
int
__free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
,
int
pin
,
*
root
,
u64
b
ytenr
,
u64
num_byte
s
,
int
pin
,
int
mark_free
)
{
struct
btrfs_path
*
path
;
...
...
@@ -745,9 +751,9 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
struct
btrfs_extent_item
*
ei
;
u32
refs
;
key
.
objectid
=
b
lock
nr
;
key
.
objectid
=
b
yte
nr
;
btrfs_set_key_type
(
&
key
,
BTRFS_EXTENT_ITEM_KEY
);
key
.
offset
=
num_b
lock
s
;
key
.
offset
=
num_b
yte
s
;
path
=
btrfs_alloc_path
();
if
(
!
path
)
...
...
@@ -768,28 +774,29 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_mark_buffer_dirty
(
leaf
);
if
(
refs
==
0
)
{
u64
super_blocks_used
,
root_blocks_used
;
u64
super_used
;
u64
root_used
;
if
(
pin
)
{
ret
=
pin_down_b
lock
(
root
,
blocknr
,
0
);
ret
=
pin_down_b
ytes
(
root
,
bytenr
,
num_bytes
,
0
);
BUG_ON
(
ret
);
}
/* block accounting for super block */
super_
blocks_used
=
btrfs_super_block
s_used
(
&
info
->
super_copy
);
btrfs_set_super_b
lock
s_used
(
&
info
->
super_copy
,
super_blocks_used
-
num_block
s
);
super_
used
=
btrfs_super_byte
s_used
(
&
info
->
super_copy
);
btrfs_set_super_b
yte
s_used
(
&
info
->
super_copy
,
super_used
-
num_byte
s
);
/* block accounting for root item */
root_
blocks_
used
=
btrfs_root_used
(
&
root
->
root_item
);
root_used
=
btrfs_root_used
(
&
root
->
root_item
);
btrfs_set_root_used
(
&
root
->
root_item
,
root_
blocks_used
-
num_block
s
);
root_
used
-
num_byte
s
);
ret
=
btrfs_del_item
(
trans
,
extent_root
,
path
);
if
(
ret
)
{
return
ret
;
}
ret
=
update_block_group
(
trans
,
root
,
b
locknr
,
num_block
s
,
0
,
ret
=
update_block_group
(
trans
,
root
,
b
ytenr
,
num_byte
s
,
0
,
mark_free
,
0
);
BUG_ON
(
ret
);
}
...
...
@@ -836,17 +843,18 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
* remove an extent from the root, returns 0 on success
*/
int
btrfs_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
b
locknr
,
u64
num_block
s
,
int
pin
)
*
root
,
u64
b
ytenr
,
u64
num_byte
s
,
int
pin
)
{
struct
btrfs_root
*
extent_root
=
root
->
fs_info
->
extent_root
;
int
pending_ret
;
int
ret
;
WARN_ON
(
num_bytes
<
root
->
sectorsize
);
if
(
root
==
extent_root
)
{
pin_down_b
lock
(
root
,
blocknr
,
1
);
pin_down_b
ytes
(
root
,
bytenr
,
num_bytes
,
1
);
return
0
;
}
ret
=
__free_extent
(
trans
,
root
,
b
locknr
,
num_block
s
,
pin
,
pin
==
0
);
ret
=
__free_extent
(
trans
,
root
,
b
ytenr
,
num_byte
s
,
pin
,
pin
==
0
);
pending_ret
=
del_pending_extents
(
trans
,
root
->
fs_info
->
extent_root
);
return
ret
?
ret
:
pending_ret
;
}
...
...
@@ -860,8 +868,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
* Any available blocks before search_start are skipped.
*/
static
int
find_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
orig_root
,
u64
num_b
lock
s
,
u64
empty_size
,
u64
search_start
,
u64
search_end
,
u64
hint_b
lock
,
*
orig_root
,
u64
num_b
yte
s
,
u64
empty_size
,
u64
search_start
,
u64
search_end
,
u64
hint_b
yte
,
struct
btrfs_key
*
ins
,
u64
exclude_start
,
u64
exclude_nr
,
int
data
)
{
...
...
@@ -870,30 +878,29 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
int
ret
;
u64
hole_size
=
0
;
int
slot
=
0
;
u64
last_b
lock
=
0
;
u64
last_b
yte
=
0
;
u64
orig_search_start
=
search_start
;
int
start_found
;
struct
extent_buffer
*
l
;
struct
btrfs_root
*
root
=
orig_root
->
fs_info
->
extent_root
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
int
total_needed
=
num_block
s
;
u64
total_needed
=
num_byte
s
;
int
level
;
struct
btrfs_block_group_cache
*
block_group
;
int
full_scan
=
0
;
int
wrapped
=
0
;
u64
cached_search_start
=
0
;
WARN_ON
(
num_b
locks
<
1
);
WARN_ON
(
num_b
ytes
<
root
->
sectorsize
);
btrfs_set_key_type
(
ins
,
BTRFS_EXTENT_ITEM_KEY
);
level
=
btrfs_header_level
(
root
->
node
);
if
(
search_end
==
(
u64
)
-
1
)
search_end
=
btrfs_super_total_b
lock
s
(
&
info
->
super_copy
);
if
(
hint_b
lock
)
{
block_group
=
btrfs_lookup_block_group
(
info
,
hint_b
lock
);
search_end
=
btrfs_super_total_b
yte
s
(
&
info
->
super_copy
);
if
(
hint_b
yte
)
{
block_group
=
btrfs_lookup_block_group
(
info
,
hint_b
yte
);
block_group
=
btrfs_find_block_group
(
root
,
block_group
,
hint_b
lock
,
data
,
1
);
hint_b
yte
,
data
,
1
);
}
else
{
block_group
=
btrfs_find_block_group
(
root
,
trans
->
block_group
,
0
,
...
...
@@ -906,7 +913,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
check_failed:
search_start
=
find_search_start
(
root
,
&
block_group
,
search_start
,
total_needed
,
data
);
cached_search_start
=
search_start
;
btrfs_init_path
(
path
);
ins
->
objectid
=
search_start
;
...
...
@@ -958,27 +964,27 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
start_found
=
1
;
goto
check_pending
;
}
ins
->
objectid
=
last_b
lock
>
search_start
?
last_b
lock
:
search_start
;
ins
->
objectid
=
last_b
yte
>
search_start
?
last_b
yte
:
search_start
;
ins
->
offset
=
search_end
-
ins
->
objectid
;
goto
check_pending
;
}
btrfs_item_key_to_cpu
(
l
,
&
key
,
slot
);
if
(
key
.
objectid
>=
search_start
&&
key
.
objectid
>
last_b
lock
&&
if
(
key
.
objectid
>=
search_start
&&
key
.
objectid
>
last_b
yte
&&
start_found
)
{
if
(
last_b
lock
<
search_start
)
last_b
lock
=
search_start
;
hole_size
=
key
.
objectid
-
last_b
lock
;
if
(
hole_size
>=
num_b
lock
s
)
{
ins
->
objectid
=
last_b
lock
;
if
(
last_b
yte
<
search_start
)
last_b
yte
=
search_start
;
hole_size
=
key
.
objectid
-
last_b
yte
;
if
(
hole_size
>=
num_b
yte
s
)
{
ins
->
objectid
=
last_b
yte
;
ins
->
offset
=
hole_size
;
goto
check_pending
;
}
}
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_EXTENT_ITEM_KEY
)
{
if
(
!
start_found
)
{
last_b
lock
=
key
.
objectid
;
last_b
yte
=
key
.
objectid
;
start_found
=
1
;
}
goto
next
;
...
...
@@ -986,9 +992,9 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
start_found
=
1
;
last_b
lock
=
key
.
objectid
+
key
.
offset
;
last_b
yte
=
key
.
objectid
+
key
.
offset
;
if
(
!
full_scan
&&
last_b
lock
>=
block_group
->
key
.
objectid
+
if
(
!
full_scan
&&
last_b
yte
>=
block_group
->
key
.
objectid
+
block_group
->
key
.
offset
)
{
btrfs_release_path
(
root
,
path
);
search_start
=
block_group
->
key
.
objectid
+
...
...
@@ -1006,20 +1012,20 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_release_path
(
root
,
path
);
BUG_ON
(
ins
->
objectid
<
search_start
);
if
(
ins
->
objectid
+
num_b
lock
s
>=
search_end
)
if
(
ins
->
objectid
+
num_b
yte
s
>=
search_end
)
goto
enospc
;
if
(
test_range_bit
(
&
info
->
extent_ins
,
ins
->
objectid
,
ins
->
objectid
+
num_b
lock
s
-
1
,
EXTENT_LOCKED
,
0
))
{
search_start
=
ins
->
objectid
+
num_b
lock
s
;
ins
->
objectid
+
num_b
yte
s
-
1
,
EXTENT_LOCKED
,
0
))
{
search_start
=
ins
->
objectid
+
num_b
yte
s
;
goto
new_group
;
}
if
(
test_range_bit
(
&
info
->
pinned_extents
,
ins
->
objectid
,
ins
->
objectid
+
num_b
lock
s
-
1
,
EXTENT_DIRTY
,
0
))
{
search_start
=
ins
->
objectid
+
num_b
lock
s
;
ins
->
objectid
+
num_b
yte
s
-
1
,
EXTENT_DIRTY
,
0
))
{
search_start
=
ins
->
objectid
+
num_b
yte
s
;
goto
new_group
;
}
if
(
exclude_nr
>
0
&&
(
ins
->
objectid
+
num_b
lock
s
>
exclude_start
&&
if
(
exclude_nr
>
0
&&
(
ins
->
objectid
+
num_b
yte
s
>
exclude_start
&&
ins
->
objectid
<
exclude_start
+
exclude_nr
))
{
search_start
=
exclude_start
+
exclude_nr
;
goto
new_group
;
...
...
@@ -1029,12 +1035,12 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
block_group
)
trans
->
block_group
=
block_group
;
}
ins
->
offset
=
num_b
lock
s
;
ins
->
offset
=
num_b
yte
s
;
btrfs_free_path
(
path
);
return
0
;
new_group:
if
(
search_start
+
num_b
lock
s
>=
search_end
)
{
if
(
search_start
+
num_b
yte
s
>=
search_end
)
{
enospc:
search_start
=
orig_search_start
;
if
(
full_scan
)
{
...
...
@@ -1069,12 +1075,12 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*/
int
btrfs_alloc_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
owner
,
u64
num_b
locks
,
u64
empty_size
,
u64
hint_block
,
u64
num_b
ytes
,
u64
empty_size
,
u64
hint_byte
,
u64
search_end
,
struct
btrfs_key
*
ins
,
int
data
)
{
int
ret
;
int
pending_ret
;
u64
super_
blocks_used
,
root_blocks
_used
;
u64
super_
used
,
root
_used
;
u64
search_start
=
0
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
struct
btrfs_root
*
extent_root
=
info
->
extent_root
;
...
...
@@ -1083,9 +1089,9 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
btrfs_set_stack_extent_refs
(
&
extent_item
,
1
);
btrfs_set_stack_extent_owner
(
&
extent_item
,
owner
);
WARN_ON
(
num_b
locks
<
1
);
ret
=
find_free_extent
(
trans
,
root
,
num_b
lock
s
,
empty_size
,
search_start
,
search_end
,
hint_b
lock
,
ins
,
WARN_ON
(
num_b
ytes
<
root
->
sectorsize
);
ret
=
find_free_extent
(
trans
,
root
,
num_b
yte
s
,
empty_size
,
search_start
,
search_end
,
hint_b
yte
,
ins
,
trans
->
alloc_exclude_start
,
trans
->
alloc_exclude_nr
,
data
);
BUG_ON
(
ret
);
...
...
@@ -1093,21 +1099,18 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
return
ret
;
/* block accounting for super block */
super_blocks_used
=
btrfs_super_blocks_used
(
&
info
->
super_copy
);
btrfs_set_super_blocks_used
(
&
info
->
super_copy
,
super_blocks_used
+
num_blocks
);
super_used
=
btrfs_super_bytes_used
(
&
info
->
super_copy
);
btrfs_set_super_bytes_used
(
&
info
->
super_copy
,
super_used
+
num_bytes
);
/* block accounting for root item */
root_blocks_used
=
btrfs_root_used
(
&
root
->
root_item
);
btrfs_set_root_used
(
&
root
->
root_item
,
root_blocks_used
+
num_blocks
);
root_used
=
btrfs_root_used
(
&
root
->
root_item
);
btrfs_set_root_used
(
&
root
->
root_item
,
root_used
+
num_bytes
);
clear_extent_dirty
(
&
root
->
fs_info
->
free_space_cache
,
ins
->
objectid
,
ins
->
objectid
+
ins
->
offset
-
1
,
GFP_NOFS
);
if
(
root
==
extent_root
)
{
BUG_ON
(
num_blocks
!=
1
);
set_extent_bits
(
&
root
->
fs_info
->
extent_ins
,
ins
->
objectid
,
ins
->
objectid
+
ins
->
offset
-
1
,
EXTENT_LOCKED
,
GFP_NOFS
);
...
...
@@ -1146,7 +1149,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
* returns the tree buffer or NULL.
*/
struct
extent_buffer
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
hint
,
struct
btrfs_root
*
root
,
u32
blocksize
,
u64
hint
,
u64
empty_size
)
{
struct
btrfs_key
ins
;
...
...
@@ -1154,14 +1158,15 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
struct
extent_buffer
*
buf
;
ret
=
btrfs_alloc_extent
(
trans
,
root
,
root
->
root_key
.
objectid
,
1
,
empty_size
,
hint
,
(
u64
)
-
1
,
&
ins
,
0
);
blocksize
,
empty_size
,
hint
,
(
u64
)
-
1
,
&
ins
,
0
);
if
(
ret
)
{
BUG_ON
(
ret
>
0
);
return
ERR_PTR
(
ret
);
}
buf
=
btrfs_find_create_tree_block
(
root
,
ins
.
objectid
);
buf
=
btrfs_find_create_tree_block
(
root
,
ins
.
objectid
,
blocksize
);
if
(
!
buf
)
{
btrfs_free_extent
(
trans
,
root
,
ins
.
objectid
,
1
,
0
);
btrfs_free_extent
(
trans
,
root
,
ins
.
objectid
,
blocksize
,
0
);
return
ERR_PTR
(
-
ENOMEM
);
}
btrfs_set_buffer_uptodate
(
buf
);
...
...
@@ -1191,7 +1196,7 @@ static int drop_leaf_ref(struct btrfs_trans_handle *trans,
BUG_ON
(
!
btrfs_is_leaf
(
leaf
));
nritems
=
btrfs_header_nritems
(
leaf
);
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
u64
disk_b
lock
nr
;
u64
disk_b
yte
nr
;
btrfs_item_key_to_cpu
(
leaf
,
&
key
,
i
);
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_EXTENT_DATA_KEY
)
...
...
@@ -1204,11 +1209,11 @@ static int drop_leaf_ref(struct btrfs_trans_handle *trans,
* FIXME make sure to insert a trans record that
* repeats the snapshot del on crash
*/
disk_b
locknr
=
btrfs_file_extent_disk_block
nr
(
leaf
,
fi
);
if
(
disk_b
lock
nr
==
0
)
disk_b
ytenr
=
btrfs_file_extent_disk_byte
nr
(
leaf
,
fi
);
if
(
disk_b
yte
nr
==
0
)
continue
;
ret
=
btrfs_free_extent
(
trans
,
root
,
disk_b
lock
nr
,
btrfs_file_extent_disk_num_b
lock
s
(
leaf
,
fi
),
0
);
ret
=
btrfs_free_extent
(
trans
,
root
,
disk_b
yte
nr
,
btrfs_file_extent_disk_num_b
yte
s
(
leaf
,
fi
),
0
);
BUG_ON
(
ret
);
}
return
0
;
...
...
@@ -1219,19 +1224,23 @@ static void reada_walk_down(struct btrfs_root *root,
{
int
i
;
u32
nritems
;
u64
b
lock
nr
;
u64
b
yte
nr
;
int
ret
;
u32
refs
;
int
level
;
u32
blocksize
;
nritems
=
btrfs_header_nritems
(
node
);
level
=
btrfs_header_level
(
node
);
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
blocknr
=
btrfs_node_blockptr
(
node
,
i
);
ret
=
lookup_extent_ref
(
NULL
,
root
,
blocknr
,
1
,
&
refs
);
bytenr
=
btrfs_node_blockptr
(
node
,
i
);
blocksize
=
btrfs_level_size
(
root
,
level
-
1
);
ret
=
lookup_extent_ref
(
NULL
,
root
,
bytenr
,
blocksize
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
!=
1
)
continue
;
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
ret
=
readahead_tree_block
(
root
,
b
locknr
);
ret
=
readahead_tree_block
(
root
,
b
ytenr
,
blocksize
);
cond_resched
();
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
if
(
ret
)
...
...
@@ -1248,15 +1257,16 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
{
struct
extent_buffer
*
next
;
struct
extent_buffer
*
cur
;
u64
blocknr
;
u64
bytenr
;
u32
blocksize
;
int
ret
;
u32
refs
;
WARN_ON
(
*
level
<
0
);
WARN_ON
(
*
level
>=
BTRFS_MAX_LEVEL
);
ret
=
lookup_extent_ref
(
trans
,
root
,
extent_buffer_blocknr
(
path
->
nodes
[
*
level
])
,
1
,
&
refs
);
path
->
nodes
[
*
level
]
->
start
,
path
->
nodes
[
*
level
]
->
len
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
>
1
)
goto
out
;
...
...
@@ -1283,30 +1293,33 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
BUG_ON
(
ret
);
break
;
}
blocknr
=
btrfs_node_blockptr
(
cur
,
path
->
slots
[
*
level
]);
ret
=
lookup_extent_ref
(
trans
,
root
,
blocknr
,
1
,
&
refs
);
bytenr
=
btrfs_node_blockptr
(
cur
,
path
->
slots
[
*
level
]);
blocksize
=
btrfs_level_size
(
root
,
*
level
-
1
);
ret
=
lookup_extent_ref
(
trans
,
root
,
bytenr
,
blocksize
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
!=
1
)
{
path
->
slots
[
*
level
]
++
;
ret
=
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
1
);
ret
=
btrfs_free_extent
(
trans
,
root
,
bytenr
,
blocksize
,
1
);
BUG_ON
(
ret
);
continue
;
}
next
=
btrfs_find_tree_block
(
root
,
b
locknr
);
next
=
btrfs_find_tree_block
(
root
,
b
ytenr
,
blocksize
);
if
(
!
next
||
!
btrfs_buffer_uptodate
(
next
))
{
free_extent_buffer
(
next
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
next
=
read_tree_block
(
root
,
b
locknr
);
next
=
read_tree_block
(
root
,
b
ytenr
,
blocksize
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
/* we dropped the lock, check one more time */
ret
=
lookup_extent_ref
(
trans
,
root
,
blocknr
,
1
,
&
refs
);
ret
=
lookup_extent_ref
(
trans
,
root
,
bytenr
,
blocksize
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
!=
1
)
{
path
->
slots
[
*
level
]
++
;
free_extent_buffer
(
next
);
ret
=
btrfs_free_extent
(
trans
,
root
,
b
locknr
,
1
,
1
);
b
ytenr
,
blocksize
,
1
);
BUG_ON
(
ret
);
continue
;
}
...
...
@@ -1321,8 +1334,8 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
out:
WARN_ON
(
*
level
<
0
);
WARN_ON
(
*
level
>=
BTRFS_MAX_LEVEL
);
ret
=
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
path
->
nodes
[
*
level
]),
1
,
1
);
ret
=
btrfs_free_extent
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
start
,
path
->
nodes
[
*
level
]
->
len
,
1
);
free_extent_buffer
(
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
*
level
+=
1
;
...
...
@@ -1359,8 +1372,8 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
return
0
;
}
else
{
ret
=
btrfs_free_extent
(
trans
,
root
,
extent_buffer_blocknr
(
path
->
nodes
[
*
level
])
,
1
,
1
);
path
->
nodes
[
*
level
]
->
start
,
path
->
nodes
[
*
level
]
->
len
,
1
);
BUG_ON
(
ret
);
free_extent_buffer
(
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
...
...
@@ -1476,16 +1489,12 @@ int btrfs_read_block_groups(struct btrfs_root *root)
struct
btrfs_key
key
;
struct
btrfs_key
found_key
;
struct
extent_buffer
*
leaf
;
u64
group_size_blocks
;
block_group_cache
=
&
info
->
block_group_cache
;
group_size_blocks
=
BTRFS_BLOCK_GROUP_SIZE
>>
info
->
sb
->
s_blocksize_bits
;
root
=
info
->
extent_root
;
key
.
objectid
=
0
;
key
.
offset
=
group_size_blocks
;
key
.
offset
=
BTRFS_BLOCK_GROUP_SIZE
;
btrfs_set_key_type
(
&
key
,
BTRFS_BLOCK_GROUP_ITEM_KEY
);
path
=
btrfs_alloc_path
();
...
...
@@ -1532,7 +1541,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
(
u64
)
cache
);
if
(
key
.
objectid
>=
btrfs_super_total_b
lock
s
(
&
info
->
super_copy
))
btrfs_super_total_b
yte
s
(
&
info
->
super_copy
))
break
;
}
...
...
fs/btrfs/extent_map.c
View file @
db94535d
...
...
@@ -1963,18 +1963,27 @@ static inline struct page *extent_buffer_page(struct extent_buffer *eb, int i)
struct
page
*
p
;
if
(
i
==
0
)
return
eb
->
first_page
;
i
+=
eb
->
start
>>
PAGE_CACHE_SHIFT
;
if
(
eb
->
last_page
&&
eb
->
last_page
->
index
==
i
)
return
eb
->
last_page
;
p
=
find_get_page
(
eb
->
first_page
->
mapping
,
i
);
page_cache_release
(
p
);
eb
->
last_page
=
p
;
return
p
;
}
static
inline
unsigned
long
num_extent_pages
(
u64
start
,
u64
len
)
{
return
((
start
+
len
+
PAGE_CACHE_SIZE
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
start
>>
PAGE_CACHE_SHIFT
);
}
struct
extent_buffer
*
alloc_extent_buffer
(
struct
extent_map_tree
*
tree
,
u64
start
,
unsigned
long
len
,
gfp_t
mask
)
{
unsigned
long
num_pages
=
((
start
+
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
unsigned
long
num_pages
=
num_extent_pages
(
start
,
len
);
unsigned
long
i
;
unsigned
long
index
=
start
>>
PAGE_CACHE_SHIFT
;
struct
extent_buffer
*
eb
;
...
...
@@ -1986,7 +1995,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
if
(
!
eb
||
IS_ERR
(
eb
))
return
NULL
;
eb
->
alloc_addr
=
__builtin_return_address
(
0
);
eb
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
eb
->
start
=
start
;
eb
->
len
=
len
;
atomic_set
(
&
eb
->
refs
,
1
);
...
...
@@ -1994,6 +2003,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
for
(
i
=
0
;
i
<
num_pages
;
i
++
,
index
++
)
{
p
=
find_or_create_page
(
mapping
,
index
,
mask
|
__GFP_HIGHMEM
);
if
(
!
p
)
{
WARN_ON
(
1
);
/* make sure the free only frees the pages we've
* grabbed a reference on
*/
...
...
@@ -2021,8 +2031,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
u64
start
,
unsigned
long
len
,
gfp_t
mask
)
{
unsigned
long
num_pages
=
((
start
+
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
unsigned
long
num_pages
=
num_extent_pages
(
start
,
len
);
unsigned
long
i
;
unsigned
long
index
=
start
>>
PAGE_CACHE_SHIFT
;
struct
extent_buffer
*
eb
;
...
...
@@ -2033,7 +2042,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
if
(
!
eb
||
IS_ERR
(
eb
))
return
NULL
;
eb
->
alloc_addr
=
__builtin_return_address
(
0
);
eb
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
eb
->
start
=
start
;
eb
->
len
=
len
;
atomic_set
(
&
eb
->
refs
,
1
);
...
...
@@ -2070,8 +2079,7 @@ void free_extent_buffer(struct extent_buffer *eb)
if
(
!
atomic_dec_and_test
(
&
eb
->
refs
))
return
;
num_pages
=
((
eb
->
start
+
eb
->
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
eb
->
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
if
(
eb
->
first_page
)
page_cache_release
(
eb
->
first_page
);
...
...
@@ -2094,8 +2102,7 @@ int clear_extent_buffer_dirty(struct extent_map_tree *tree,
u64
end
=
start
+
eb
->
len
-
1
;
set
=
clear_extent_dirty
(
tree
,
start
,
end
,
GFP_NOFS
);
num_pages
=
((
eb
->
start
+
eb
->
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
eb
->
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
page
=
extent_buffer_page
(
eb
,
i
);
...
...
@@ -2145,8 +2152,7 @@ int set_extent_buffer_uptodate(struct extent_map_tree *tree,
struct
page
*
page
;
unsigned
long
num_pages
;
num_pages
=
((
eb
->
start
+
eb
->
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
eb
->
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
set_extent_uptodate
(
tree
,
eb
->
start
,
eb
->
start
+
eb
->
len
-
1
,
GFP_NOFS
);
...
...
@@ -2191,8 +2197,7 @@ int read_extent_buffer_pages(struct extent_map_tree *tree,
return
0
;
}
num_pages
=
((
eb
->
start
+
eb
->
len
-
1
)
>>
PAGE_CACHE_SHIFT
)
-
(
eb
->
start
>>
PAGE_CACHE_SHIFT
)
+
1
;
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
page
=
extent_buffer_page
(
eb
,
i
);
if
(
PageUptodate
(
page
))
{
...
...
@@ -2267,14 +2272,14 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
}
EXPORT_SYMBOL
(
read_extent_buffer
);
int
map_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
static
int
__map_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
*
map_start
,
unsigned
long
*
map_len
,
int
km
)
{
size_t
offset
=
start
&
(
PAGE_CACHE_SIZE
-
1
);
char
*
kaddr
;
struct
page
*
p
;
size_t
start_offset
=
eb
->
start
&
((
u64
)
PAGE_CACHE_SIZE
-
1
);
unsigned
long
i
=
(
start_offset
+
start
)
>>
PAGE_CACHE_SHIFT
;
unsigned
long
end_i
=
(
start_offset
+
start
+
min_len
)
>>
...
...
@@ -2283,21 +2288,59 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
if
(
i
!=
end_i
)
return
-
EINVAL
;
WARN_ON
(
start
>
eb
->
len
);
if
(
start
>=
eb
->
len
)
{
printk
(
"bad start in map eb start %Lu len %lu caller start %lu min %lu
\n
"
,
eb
->
start
,
eb
->
len
,
start
,
min_len
);
WARN_ON
(
1
);
}
if
(
i
==
0
)
{
offset
=
start_offset
;
*
map_start
=
0
;
}
else
{
offset
=
0
;
*
map_start
=
(
i
<<
PAGE_CACHE_SHIFT
)
-
start_offset
;
}
kaddr
=
kmap_atomic
(
extent_buffer_page
(
eb
,
i
),
km
);
p
=
extent_buffer_page
(
eb
,
i
);
WARN_ON
(
!
PageUptodate
(
p
));
kaddr
=
kmap_atomic
(
p
,
km
);
*
token
=
kaddr
;
*
map
=
kaddr
+
offset
;
*
map_len
=
PAGE_CACHE_SIZE
-
offset
;
return
0
;
}
int
map_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
*
map_start
,
unsigned
long
*
map_len
,
int
km
)
{
int
err
;
int
save
=
0
;
if
(
eb
->
map_token
)
{
if
(
start
>=
eb
->
map_start
&&
start
+
min_len
<=
eb
->
map_start
+
eb
->
map_len
)
{
*
token
=
eb
->
map_token
;
*
map
=
eb
->
kaddr
;
*
map_start
=
eb
->
map_start
;
*
map_len
=
eb
->
map_len
;
return
0
;
}
unmap_extent_buffer
(
eb
,
eb
->
map_token
,
km
);
eb
->
map_token
=
NULL
;
save
=
1
;
}
err
=
__map_extent_buffer
(
eb
,
start
,
min_len
,
token
,
map
,
map_start
,
map_len
,
km
);
if
(
!
err
&&
save
)
{
eb
->
map_token
=
*
token
;
eb
->
kaddr
=
*
map
;
eb
->
map_start
=
*
map_start
;
eb
->
map_len
=
*
map_len
;
}
return
err
;
}
EXPORT_SYMBOL
(
map_extent_buffer
);
void
unmap_extent_buffer
(
struct
extent_buffer
*
eb
,
char
*
token
,
int
km
)
...
...
@@ -2574,7 +2617,6 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
((
unsigned
long
)
PAGE_CACHE_SIZE
-
1
);
src_off_in_page
=
src_end
&
((
unsigned
long
)
PAGE_CACHE_SIZE
-
1
);
if
(
src_i
==
0
)
src_off_in_page
+=
start_offset
;
if
(
dst_i
==
0
)
...
...
@@ -2582,14 +2624,13 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
cur
=
min
(
len
,
src_off_in_page
+
1
);
cur
=
min
(
cur
,
dst_off_in_page
+
1
);
move_pages
(
extent_buffer_page
(
dst
,
dst_i
),
extent_buffer_page
(
dst
,
src_i
),
dst_off_in_page
-
cur
+
1
,
src_off_in_page
-
cur
+
1
,
cur
);
dst_end
-=
cur
-
1
;
src_end
-=
cur
-
1
;
dst_end
-=
cur
;
src_end
-=
cur
;
len
-=
cur
;
}
}
...
...
fs/btrfs/extent_map.h
View file @
db94535d
...
...
@@ -70,7 +70,12 @@ struct extent_buffer {
struct
list_head
list
;
struct
list_head
leak_list
;
struct
page
*
first_page
;
struct
page
*
last_page
;
unsigned
long
alloc_addr
;
char
*
map_token
;
char
*
kaddr
;
unsigned
long
map_start
;
unsigned
long
map_len
;
};
typedef
struct
extent_map
*
(
get_extent_t
)(
struct
inode
*
inode
,
...
...
@@ -147,11 +152,6 @@ static inline void extent_buffer_get(struct extent_buffer *eb)
atomic_inc
(
&
eb
->
refs
);
}
static
inline
u64
extent_buffer_blocknr
(
struct
extent_buffer
*
eb
)
{
return
eb
->
start
/
4096
;
}
int
memcmp_extent_buffer
(
struct
extent_buffer
*
eb
,
const
void
*
ptrv
,
unsigned
long
start
,
unsigned
long
len
);
...
...
fs/btrfs/file-item.c
View file @
db94535d
...
...
@@ -27,8 +27,8 @@
int
btrfs_insert_file_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
objectid
,
u64
pos
,
u64
offset
,
u64
disk_num_b
lock
s
,
u64
num_b
lock
s
)
u64
offset
,
u64
disk_num_b
yte
s
,
u64
num_b
yte
s
)
{
int
ret
=
0
;
struct
btrfs_file_extent_item
*
item
;
...
...
@@ -50,10 +50,10 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
leaf
=
path
->
nodes
[
0
];
item
=
btrfs_item_ptr
(
leaf
,
path
->
slots
[
0
],
struct
btrfs_file_extent_item
);
btrfs_set_file_extent_disk_b
lock
nr
(
leaf
,
item
,
offset
);
btrfs_set_file_extent_disk_num_b
locks
(
leaf
,
item
,
disk_num_block
s
);
btrfs_set_file_extent_disk_b
yte
nr
(
leaf
,
item
,
offset
);
btrfs_set_file_extent_disk_num_b
ytes
(
leaf
,
item
,
disk_num_byte
s
);
btrfs_set_file_extent_offset
(
leaf
,
item
,
0
);
btrfs_set_file_extent_num_b
locks
(
leaf
,
item
,
num_block
s
);
btrfs_set_file_extent_num_b
ytes
(
leaf
,
item
,
num_byte
s
);
btrfs_set_file_extent_generation
(
leaf
,
item
,
trans
->
transid
);
btrfs_set_file_extent_type
(
leaf
,
item
,
BTRFS_FILE_EXTENT_REG
);
btrfs_mark_buffer_dirty
(
leaf
);
...
...
fs/btrfs/file.c
View file @
db94535d
...
...
@@ -120,9 +120,9 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
btrfs_set_file_extent_type
(
leaf
,
ei
,
BTRFS_FILE_EXTENT_INLINE
);
ptr
=
btrfs_file_extent_inline_start
(
ei
);
kaddr
=
kmap_atomic
(
page
,
KM_USER
0
);
kaddr
=
kmap_atomic
(
page
,
KM_USER
1
);
write_extent_buffer
(
leaf
,
kaddr
+
page_offset
,
ptr
,
size
);
kunmap_atomic
(
kaddr
,
KM_USER
0
);
kunmap_atomic
(
kaddr
,
KM_USER
1
);
btrfs_mark_buffer_dirty
(
leaf
);
fail:
btrfs_free_path
(
path
);
...
...
@@ -142,11 +142,12 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
struct
extent_map
*
em
;
struct
extent_map_tree
*
em_tree
=
&
BTRFS_I
(
inode
)
->
extent_tree
;
u64
hint_b
lock
;
u64
num_b
lock
s
;
u64
hint_b
yte
;
u64
num_b
yte
s
;
u64
start_pos
;
u64
end_of_last_block
;
u64
end_pos
=
pos
+
write_bytes
;
u32
inline_size
;
loff_t
isize
=
i_size_read
(
inode
);
em
=
alloc_extent_map
(
GFP_NOFS
);
...
...
@@ -156,11 +157,12 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
em
->
bdev
=
inode
->
i_sb
->
s_bdev
;
start_pos
=
pos
&
~
((
u64
)
root
->
sectorsize
-
1
);
num_b
locks
=
(
write_bytes
+
pos
-
start_pos
+
root
->
sectorsize
-
1
)
>>
inode
->
i_blkbits
;
num_b
ytes
=
(
write_bytes
+
pos
-
start_pos
+
root
->
sectorsize
-
1
)
&
~
((
u64
)
root
->
sectorsize
-
1
)
;
down_read
(
&
BTRFS_I
(
inode
)
->
root
->
snap_sem
);
end_of_last_block
=
start_pos
+
(
num_blocks
<<
inode
->
i_blkbits
)
-
1
;
end_of_last_block
=
start_pos
+
num_bytes
-
1
;
lock_extent
(
em_tree
,
start_pos
,
end_of_last_block
,
GFP_NOFS
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
...
...
@@ -169,8 +171,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
goto
out_unlock
;
}
btrfs_set_trans_block_group
(
trans
,
inode
);
inode
->
i_blocks
+=
num_b
locks
<<
3
;
hint_b
lock
=
0
;
inode
->
i_blocks
+=
num_b
ytes
>>
9
;
hint_b
yte
=
0
;
if
((
end_of_last_block
&
4095
)
==
0
)
{
printk
(
"strange end of last %Lu %zu %Lu
\n
"
,
start_pos
,
write_bytes
,
end_of_last_block
);
...
...
@@ -191,11 +193,10 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
err
=
btrfs_drop_extents
(
trans
,
root
,
inode
,
last_pos_in_file
,
last_pos_in_file
+
hole_size
,
&
hint_b
lock
);
&
hint_b
yte
);
if
(
err
)
goto
failed
;
hole_size
>>=
inode
->
i_blkbits
;
err
=
btrfs_insert_file_extent
(
trans
,
root
,
inode
->
i_ino
,
last_pos_in_file
,
...
...
@@ -209,8 +210,10 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
* either allocate an extent for the new bytes or setup the key
* to show we are doing inline data in the extent
*/
inline_size
=
end_pos
-
start_pos
;
if
(
isize
>=
PAGE_CACHE_SIZE
||
pos
+
write_bytes
<
inode
->
i_size
||
pos
+
write_bytes
-
start_pos
>
BTRFS_MAX_INLINE_DATA_SIZE
(
root
))
{
inline_size
>=
BTRFS_MAX_INLINE_DATA_SIZE
(
root
)
||
inline_size
>=
PAGE_CACHE_SIZE
)
{
u64
last_end
;
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
struct
page
*
p
=
pages
[
i
];
...
...
@@ -224,10 +227,9 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
}
else
{
struct
page
*
p
=
pages
[
0
];
/* step one, delete the existing extents in this range */
/* FIXME blocksize != pagesize */
err
=
btrfs_drop_extents
(
trans
,
root
,
inode
,
start_pos
,
(
pos
+
write_bytes
+
root
->
sectorsize
-
1
)
&
~
((
u64
)
root
->
sectorsize
-
1
),
&
hint_b
lock
);
~
((
u64
)
root
->
sectorsize
-
1
),
&
hint_b
yte
);
if
(
err
)
goto
failed
;
...
...
@@ -283,7 +285,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
*/
int
btrfs_drop_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
inode
*
inode
,
u64
start
,
u64
end
,
u64
*
hint_b
lock
)
u64
start
,
u64
end
,
u64
*
hint_b
yte
)
{
int
ret
;
struct
btrfs_key
key
;
...
...
@@ -346,8 +348,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
found_type
=
btrfs_file_extent_type
(
leaf
,
extent
);
if
(
found_type
==
BTRFS_FILE_EXTENT_REG
)
{
extent_end
=
key
.
offset
+
(
btrfs_file_extent_num_blocks
(
leaf
,
extent
)
<<
inode
->
i_blkbits
);
btrfs_file_extent_num_bytes
(
leaf
,
extent
);
found_extent
=
1
;
}
else
if
(
found_type
==
BTRFS_FILE_EXTENT_INLINE
)
{
struct
btrfs_item
*
item
;
...
...
@@ -386,17 +387,17 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
if
(
end
<
extent_end
&&
end
>=
key
.
offset
)
{
if
(
found_extent
)
{
u64
disk_b
lock
nr
=
btrfs_file_extent_disk_b
locknr
(
leaf
,
extent
);
u64
disk_num_b
lock
s
=
btrfs_file_extent_disk_num_b
lock
s
(
leaf
,
u64
disk_b
yte
nr
=
btrfs_file_extent_disk_b
ytenr
(
leaf
,
extent
);
u64
disk_num_b
yte
s
=
btrfs_file_extent_disk_num_b
yte
s
(
leaf
,
extent
);
read_extent_buffer
(
leaf
,
&
old
,
(
unsigned
long
)
extent
,
sizeof
(
old
));
if
(
disk_b
lock
nr
!=
0
)
{
if
(
disk_b
yte
nr
!=
0
)
{
ret
=
btrfs_inc_extent_ref
(
trans
,
root
,
disk_b
locknr
,
disk_num_block
s
);
disk_b
ytenr
,
disk_num_byte
s
);
BUG_ON
(
ret
);
}
}
...
...
@@ -410,20 +411,18 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
keep
=
1
;
WARN_ON
(
start
&
(
root
->
sectorsize
-
1
));
if
(
found_extent
)
{
new_num
=
(
start
-
key
.
offset
)
>>
inode
->
i_blkbits
;
old_num
=
btrfs_file_extent_num_blocks
(
leaf
,
new_num
=
start
-
key
.
offset
;
old_num
=
btrfs_file_extent_num_bytes
(
leaf
,
extent
);
*
hint_b
lock
=
btrfs_file_extent_disk_b
lock
nr
(
leaf
,
*
hint_b
yte
=
btrfs_file_extent_disk_b
yte
nr
(
leaf
,
extent
);
if
(
btrfs_file_extent_disk_b
lock
nr
(
leaf
,
if
(
btrfs_file_extent_disk_b
yte
nr
(
leaf
,
extent
))
{
inode
->
i_blocks
-=
(
old_num
-
new_num
)
<<
3
;
(
old_num
-
new_num
)
>>
9
;
}
btrfs_set_file_extent_num_blocks
(
leaf
,
extent
,
btrfs_set_file_extent_num_bytes
(
leaf
,
extent
,
new_num
);
btrfs_mark_buffer_dirty
(
leaf
);
}
else
{
...
...
@@ -432,21 +431,20 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
}
/* delete the entire extent */
if
(
!
keep
)
{
u64
disk_b
lock
nr
=
0
;
u64
disk_num_b
lock
s
=
0
;
u64
extent_num_b
lock
s
=
0
;
u64
disk_b
yte
nr
=
0
;
u64
disk_num_b
yte
s
=
0
;
u64
extent_num_b
yte
s
=
0
;
if
(
found_extent
)
{
disk_blocknr
=
btrfs_file_extent_disk_blocknr
(
leaf
,
extent
);
disk_num_blocks
=
btrfs_file_extent_disk_num_blocks
(
leaf
,
disk_bytenr
=
btrfs_file_extent_disk_bytenr
(
leaf
,
extent
);
extent_num_block
s
=
btrfs_file_extent_
num_block
s
(
leaf
,
disk_num_byte
s
=
btrfs_file_extent_
disk_num_byte
s
(
leaf
,
extent
);
*
hint_block
=
btrfs_file_extent_disk_blocknr
(
leaf
,
extent_num_bytes
=
btrfs_file_extent_num_bytes
(
leaf
,
extent
);
*
hint_byte
=
btrfs_file_extent_disk_bytenr
(
leaf
,
extent
);
}
ret
=
btrfs_del_item
(
trans
,
root
,
path
);
...
...
@@ -454,11 +452,11 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
BUG_ON
(
ret
);
btrfs_release_path
(
root
,
path
);
extent
=
NULL
;
if
(
found_extent
&&
disk_b
lock
nr
!=
0
)
{
inode
->
i_blocks
-=
extent_num_b
locks
<<
3
;
if
(
found_extent
&&
disk_b
yte
nr
!=
0
)
{
inode
->
i_blocks
-=
extent_num_b
ytes
>>
9
;
ret
=
btrfs_free_extent
(
trans
,
root
,
disk_b
lock
nr
,
disk_num_b
lock
s
,
0
);
disk_b
yte
nr
,
disk_num_b
yte
s
,
0
);
}
BUG_ON
(
ret
);
...
...
@@ -491,20 +489,19 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
(
unsigned
long
)
extent
,
sizeof
(
old
));
btrfs_set_file_extent_offset
(
leaf
,
extent
,
le64_to_cpu
(
old
.
offset
)
+
((
end
-
key
.
offset
)
>>
inode
->
i_blkbits
));
WARN_ON
(
le64_to_cpu
(
old
.
num_blocks
)
<
(
extent_end
-
end
)
>>
inode
->
i_blkbits
);
btrfs_set_file_extent_num_blocks
(
leaf
,
extent
,
(
extent_end
-
end
)
>>
inode
->
i_blkbits
);
le64_to_cpu
(
old
.
offset
)
+
end
-
key
.
offset
);
WARN_ON
(
le64_to_cpu
(
old
.
num_bytes
)
<
(
extent_end
-
end
));
btrfs_set_file_extent_num_bytes
(
leaf
,
extent
,
extent_end
-
end
);
btrfs_set_file_extent_type
(
leaf
,
extent
,
BTRFS_FILE_EXTENT_REG
);
btrfs_mark_buffer_dirty
(
path
->
nodes
[
0
]);
if
(
le64_to_cpu
(
old
.
disk_b
lock
nr
)
!=
0
)
{
if
(
le64_to_cpu
(
old
.
disk_b
yte
nr
)
!=
0
)
{
inode
->
i_blocks
+=
btrfs_file_extent_num_b
lock
s
(
leaf
,
extent
)
<<
3
;
btrfs_file_extent_num_b
yte
s
(
leaf
,
extent
)
>>
9
;
}
ret
=
0
;
goto
out
;
...
...
@@ -531,12 +528,9 @@ static int prepare_pages(struct btrfs_root *root,
unsigned
long
index
=
pos
>>
PAGE_CACHE_SHIFT
;
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
int
err
=
0
;
u64
num_blocks
;
u64
start_pos
;
start_pos
=
pos
&
~
((
u64
)
root
->
sectorsize
-
1
);
num_blocks
=
(
write_bytes
+
pos
-
start_pos
+
root
->
sectorsize
-
1
)
>>
inode
->
i_blkbits
;
memset
(
pages
,
0
,
num_pages
*
sizeof
(
struct
page
*
));
...
...
fs/btrfs/inode.c
View file @
db94535d
...
...
@@ -77,19 +77,19 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end)
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_key
ins
;
u64
alloc_hint
=
0
;
u64
num_b
lock
s
;
u64
num_b
yte
s
;
int
ret
;
u64
blocksize
=
1
<<
inode
->
i_blkbits
;
u64
blocksize
=
root
->
sectorsize
;
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
btrfs_set_trans_block_group
(
trans
,
inode
);
BUG_ON
(
!
trans
);
num_b
lock
s
=
(
end
-
start
+
blocksize
)
&
~
(
blocksize
-
1
);
num_b
yte
s
=
(
end
-
start
+
blocksize
)
&
~
(
blocksize
-
1
);
ret
=
btrfs_drop_extents
(
trans
,
root
,
inode
,
start
,
start
+
num_b
lock
s
,
&
alloc_hint
);
num_blocks
=
num_blocks
>>
inode
->
i_blkbits
;
ret
=
btrfs_alloc_extent
(
trans
,
root
,
inode
->
i_ino
,
num_b
lock
s
,
0
,
start
,
start
+
num_b
yte
s
,
&
alloc_hint
);
ret
=
btrfs_alloc_extent
(
trans
,
root
,
inode
->
i_ino
,
num_b
yte
s
,
0
,
alloc_hint
,
(
u64
)
-
1
,
&
ins
,
1
);
if
(
ret
)
{
WARN_ON
(
1
);
...
...
@@ -186,7 +186,8 @@ int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end)
zeroit:
printk
(
"btrfs csum failed ino %lu off %llu
\n
"
,
page
->
mapping
->
host
->
i_ino
,
(
unsigned
long
long
)
start
);
memset
(
kaddr
+
offset
,
1
,
end
-
start
+
1
);
flush_dcache_page
(
page
);
memset
(
kaddr
+
offset
,
1
,
end
-
start
+
1
);
flush_dcache_page
(
page
);
kunmap_atomic
(
kaddr
,
KM_IRQ0
);
return
0
;
}
...
...
@@ -547,7 +548,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
struct
extent_buffer
*
leaf
;
struct
btrfs_file_extent_item
*
fi
;
u64
extent_start
=
0
;
u64
extent_num_b
lock
s
=
0
;
u64
extent_num_b
yte
s
=
0
;
u64
item_end
=
0
;
int
found_extent
;
int
del_item
;
...
...
@@ -593,8 +594,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
if
(
btrfs_file_extent_type
(
leaf
,
fi
)
!=
BTRFS_FILE_EXTENT_INLINE
)
{
item_end
+=
btrfs_file_extent_num_blocks
(
leaf
,
fi
)
<<
inode
->
i_blkbits
;
btrfs_file_extent_num_bytes
(
leaf
,
fi
);
}
}
if
(
found_type
==
BTRFS_CSUM_ITEM_KEY
)
{
...
...
@@ -626,28 +626,27 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
btrfs_file_extent_type
(
leaf
,
fi
)
!=
BTRFS_FILE_EXTENT_INLINE
)
{
u64
num_dec
;
extent_start
=
btrfs_file_extent_disk_b
lock
nr
(
leaf
,
fi
);
extent_start
=
btrfs_file_extent_disk_b
yte
nr
(
leaf
,
fi
);
if
(
!
del_item
)
{
u64
orig_num_b
lock
s
=
btrfs_file_extent_num_b
lock
s
(
leaf
,
fi
);
extent_num_b
lock
s
=
inode
->
i_size
-
u64
orig_num_b
yte
s
=
btrfs_file_extent_num_b
yte
s
(
leaf
,
fi
);
extent_num_b
yte
s
=
inode
->
i_size
-
found_key
.
offset
+
root
->
sectorsize
-
1
;
extent_num_blocks
>>=
inode
->
i_blkbits
;
btrfs_set_file_extent_num_blocks
(
leaf
,
fi
,
extent_num_blocks
);
num_dec
=
(
orig_num_blocks
-
extent_num_blocks
)
<<
3
;
btrfs_set_file_extent_num_bytes
(
leaf
,
fi
,
extent_num_bytes
);
num_dec
=
(
orig_num_bytes
-
extent_num_bytes
)
>>
9
;
if
(
extent_start
!=
0
)
{
inode
->
i_blocks
-=
num_dec
;
}
btrfs_mark_buffer_dirty
(
leaf
);
}
else
{
extent_num_b
lock
s
=
btrfs_file_extent_disk_num_b
lock
s
(
leaf
,
extent_num_b
yte
s
=
btrfs_file_extent_disk_num_b
yte
s
(
leaf
,
fi
);
/* FIXME blocksize != 4096 */
num_dec
=
btrfs_file_extent_num_b
lock
s
(
leaf
,
fi
)
<<
3
;
num_dec
=
btrfs_file_extent_num_b
yte
s
(
leaf
,
fi
)
>>
9
;
if
(
extent_start
!=
0
)
{
found_extent
=
1
;
inode
->
i_blocks
-=
num_dec
;
...
...
@@ -664,7 +663,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
btrfs_release_path
(
root
,
path
);
if
(
found_extent
)
{
ret
=
btrfs_free_extent
(
trans
,
root
,
extent_start
,
extent_num_b
lock
s
,
0
);
extent_num_b
yte
s
,
0
);
BUG_ON
(
ret
);
}
}
...
...
@@ -709,7 +708,8 @@ static int btrfs_cow_one_page(struct inode *inode, struct page *page,
static
int
btrfs_truncate_page
(
struct
address_space
*
mapping
,
loff_t
from
)
{
struct
inode
*
inode
=
mapping
->
host
;
unsigned
blocksize
=
1
<<
inode
->
i_blkbits
;
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
u32
blocksize
=
root
->
sectorsize
;
pgoff_t
index
=
from
>>
PAGE_CACHE_SHIFT
;
unsigned
offset
=
from
&
(
PAGE_CACHE_SIZE
-
1
);
struct
page
*
page
;
...
...
@@ -719,7 +719,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
if
((
offset
&
(
blocksize
-
1
))
==
0
)
goto
out
;
down_read
(
&
BTRFS_I
(
inode
)
->
root
->
snap_sem
);
down_read
(
&
root
->
snap_sem
);
ret
=
-
ENOMEM
;
page
=
grab_cache_page
(
mapping
,
index
);
if
(
!
page
)
...
...
@@ -778,8 +778,6 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
err
=
btrfs_drop_extents
(
trans
,
root
,
inode
,
pos
,
pos
+
hole_size
,
&
alloc_hint
);
hole_size
>>=
inode
->
i_blkbits
;
err
=
btrfs_insert_file_extent
(
trans
,
root
,
inode
->
i_ino
,
pos
,
0
,
0
,
hole_size
);
btrfs_end_transaction
(
trans
,
root
);
...
...
@@ -1490,7 +1488,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
{
int
ret
;
int
err
=
0
;
u64
b
lock
nr
;
u64
b
yte
nr
;
u64
extent_start
=
0
;
u64
extent_end
=
0
;
u64
objectid
=
inode
->
i_ino
;
...
...
@@ -1540,10 +1538,6 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
leaf
=
path
->
nodes
[
0
];
item
=
btrfs_item_ptr
(
leaf
,
path
->
slots
[
0
],
struct
btrfs_file_extent_item
);
blocknr
=
btrfs_file_extent_disk_blocknr
(
leaf
,
item
);
blocknr
+=
btrfs_file_extent_offset
(
leaf
,
item
);
/* are we inside the extent that was found? */
btrfs_item_key_to_cpu
(
leaf
,
&
found_key
,
path
->
slots
[
0
]);
found_type
=
btrfs_key_type
(
&
found_key
);
...
...
@@ -1556,8 +1550,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
extent_start
=
found_key
.
offset
;
if
(
found_type
==
BTRFS_FILE_EXTENT_REG
)
{
extent_end
=
extent_start
+
(
btrfs_file_extent_num_blocks
(
leaf
,
item
)
<<
inode
->
i_blkbits
);
btrfs_file_extent_num_bytes
(
leaf
,
item
);
err
=
0
;
if
(
start
<
extent_start
||
start
>=
extent_end
)
{
em
->
start
=
start
;
...
...
@@ -1570,17 +1563,18 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
}
goto
not_found_em
;
}
if
(
btrfs_file_extent_disk_blocknr
(
leaf
,
item
)
==
0
)
{
bytenr
=
btrfs_file_extent_disk_bytenr
(
leaf
,
item
);
if
(
bytenr
==
0
)
{
em
->
start
=
extent_start
;
em
->
end
=
extent_end
-
1
;
em
->
block_start
=
EXTENT_MAP_HOLE
;
em
->
block_end
=
EXTENT_MAP_HOLE
;
goto
insert
;
}
em
->
block_start
=
blocknr
<<
inode
->
i_blkbits
;
bytenr
+=
btrfs_file_extent_offset
(
leaf
,
item
);
em
->
block_start
=
bytenr
;
em
->
block_end
=
em
->
block_start
+
(
btrfs_file_extent_num_blocks
(
leaf
,
item
)
<<
inode
->
i_blkbits
)
-
1
;
btrfs_file_extent_num_bytes
(
leaf
,
item
)
-
1
;
em
->
start
=
extent_start
;
em
->
end
=
extent_end
-
1
;
goto
insert
;
...
...
@@ -1592,7 +1586,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
size
=
btrfs_file_extent_inline_len
(
leaf
,
btrfs_item_nr
(
leaf
,
path
->
slots
[
0
]));
extent_end
=
extent_start
|
((
u64
)
root
->
sectorsize
-
1
);
extent_end
=
(
extent_start
+
size
)
|
((
u64
)
root
->
sectorsize
-
1
);
if
(
start
<
extent_start
||
start
>=
extent_end
)
{
em
->
start
=
start
;
if
(
start
<
extent_start
)
{
...
...
@@ -1617,8 +1612,10 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
ptr
=
btrfs_file_extent_inline_start
(
item
);
map
=
kmap
(
page
);
read_extent_buffer
(
leaf
,
map
+
page_offset
,
ptr
,
size
);
/*
memset(map + page_offset + size, 0,
root->sectorsize - (page_offset + size));
*/
flush_dcache_page
(
page
);
kunmap
(
page
);
set_extent_uptodate
(
em_tree
,
extent_start
,
...
...
@@ -1836,13 +1833,13 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
trans
=
btrfs_start_transaction
(
root
,
1
);
BUG_ON
(
!
trans
);
leaf
=
btrfs_alloc_free_block
(
trans
,
root
,
0
,
0
);
leaf
=
btrfs_alloc_free_block
(
trans
,
root
,
root
->
leafsize
,
0
,
0
);
if
(
IS_ERR
(
leaf
))
return
PTR_ERR
(
leaf
);
btrfs_set_header_nritems
(
leaf
,
0
);
btrfs_set_header_level
(
leaf
,
0
);
btrfs_set_header_b
locknr
(
leaf
,
extent_buffer_blocknr
(
leaf
)
);
btrfs_set_header_b
ytenr
(
leaf
,
leaf
->
start
);
btrfs_set_header_generation
(
leaf
,
trans
->
transid
);
btrfs_set_header_owner
(
leaf
,
root
->
root_key
.
objectid
);
write_extent_buffer
(
leaf
,
root
->
fs_info
->
fsid
,
...
...
@@ -1858,7 +1855,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
inode_item
->
nblocks
=
cpu_to_le64
(
1
);
inode_item
->
mode
=
cpu_to_le32
(
S_IFDIR
|
0755
);
btrfs_set_root_blocknr
(
&
root_item
,
extent_buffer_blocknr
(
leaf
));
btrfs_set_root_bytenr
(
&
root_item
,
leaf
->
start
);
btrfs_set_root_level
(
&
root_item
,
0
);
btrfs_set_root_refs
(
&
root_item
,
1
);
btrfs_set_root_used
(
&
root_item
,
0
);
...
...
@@ -1971,8 +1969,8 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
btrfs_set_key_type
(
&
key
,
BTRFS_ROOT_ITEM_KEY
);
btrfs_cow_block
(
trans
,
root
,
root
->
node
,
NULL
,
0
,
&
tmp
);
btrfs_set_root_b
locknr
(
&
new_root_item
,
extent_buffer_blocknr
(
root
->
node
));
btrfs_set_root_b
ytenr
(
&
new_root_item
,
root
->
node
->
start
);
btrfs_set_root_level
(
&
new_root_item
,
btrfs_header_level
(
root
->
node
));
ret
=
btrfs_insert_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
key
,
&
new_root_item
);
...
...
fs/btrfs/print-tree.c
View file @
db94535d
...
...
@@ -36,7 +36,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
u32
type
;
printk
(
"leaf %llu total ptrs %d free space %d
\n
"
,
(
unsigned
long
long
)
btrfs_header_b
lock
nr
(
l
),
nr
,
(
unsigned
long
long
)
btrfs_header_b
yte
nr
(
l
),
nr
,
btrfs_leaf_free_space
(
root
,
l
));
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
item
=
btrfs_item_nr
(
l
,
i
);
...
...
@@ -65,8 +65,8 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
break
;
case
BTRFS_ROOT_ITEM_KEY
:
ri
=
btrfs_item_ptr
(
l
,
i
,
struct
btrfs_root_item
);
printk
(
"
\t\t
root data b
lock
nr %llu refs %u
\n
"
,
(
unsigned
long
long
)
btrfs_disk_root_b
lock
nr
(
l
,
ri
),
printk
(
"
\t\t
root data b
yte
nr %llu refs %u
\n
"
,
(
unsigned
long
long
)
btrfs_disk_root_b
yte
nr
(
l
,
ri
),
btrfs_disk_root_refs
(
l
,
ri
));
break
;
case
BTRFS_EXTENT_ITEM_KEY
:
...
...
@@ -84,12 +84,12 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
btrfs_file_extent_inline_len
(
l
,
item
));
break
;
}
printk
(
"
\t\t
extent data disk b
lock
%llu nr %llu
\n
"
,
(
unsigned
long
long
)
btrfs_file_extent_disk_b
lock
nr
(
l
,
fi
),
(
unsigned
long
long
)
btrfs_file_extent_disk_num_b
lock
s
(
l
,
fi
));
printk
(
"
\t\t
extent data disk b
ytenr
%llu nr %llu
\n
"
,
(
unsigned
long
long
)
btrfs_file_extent_disk_b
yte
nr
(
l
,
fi
),
(
unsigned
long
long
)
btrfs_file_extent_disk_num_b
yte
s
(
l
,
fi
));
printk
(
"
\t\t
extent data offset %llu nr %llu
\n
"
,
(
unsigned
long
long
)
btrfs_file_extent_offset
(
l
,
fi
),
(
unsigned
long
long
)
btrfs_file_extent_num_b
lock
s
(
l
,
fi
));
(
unsigned
long
long
)
btrfs_file_extent_num_b
yte
s
(
l
,
fi
));
break
;
case
BTRFS_BLOCK_GROUP_ITEM_KEY
:
bi
=
btrfs_item_ptr
(
l
,
i
,
...
...
@@ -106,16 +106,18 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
int
i
;
u32
nr
;
struct
btrfs_key
key
;
int
level
;
if
(
!
c
)
return
;
nr
=
btrfs_header_nritems
(
c
);
if
(
btrfs_is_leaf
(
c
))
{
level
=
btrfs_header_level
(
c
);
if
(
level
==
0
)
{
btrfs_print_leaf
(
root
,
c
);
return
;
}
printk
(
"node %llu level %d total ptrs %d free spc %u
\n
"
,
(
unsigned
long
long
)
btrfs_header_b
lock
nr
(
c
),
(
unsigned
long
long
)
btrfs_header_b
yte
nr
(
c
),
btrfs_header_level
(
c
),
nr
,
(
u32
)
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
-
nr
);
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
...
...
@@ -129,7 +131,8 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
}
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
struct
extent_buffer
*
next
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
c
,
i
));
btrfs_node_blockptr
(
c
,
i
),
btrfs_level_size
(
root
,
level
-
1
));
if
(
btrfs_is_leaf
(
next
)
&&
btrfs_header_level
(
c
)
!=
1
)
BUG
();
...
...
fs/btrfs/super.c
View file @
db94535d
...
...
@@ -303,10 +303,12 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct
btrfs_root
*
root
=
btrfs_sb
(
dentry
->
d_sb
);
struct
btrfs_super_block
*
disk_super
=
&
root
->
fs_info
->
super_copy
;
int
bits
=
dentry
->
d_sb
->
s_blocksize_bits
;
buf
->
f_namelen
=
BTRFS_NAME_LEN
;
buf
->
f_blocks
=
btrfs_super_total_blocks
(
disk_super
);
buf
->
f_bfree
=
buf
->
f_blocks
-
btrfs_super_blocks_used
(
disk_super
);
buf
->
f_blocks
=
btrfs_super_total_bytes
(
disk_super
)
>>
bits
;
buf
->
f_bfree
=
buf
->
f_blocks
-
(
btrfs_super_bytes_used
(
disk_super
)
>>
bits
);
buf
->
f_bavail
=
buf
->
f_bfree
;
buf
->
f_bsize
=
dentry
->
d_sb
->
s_blocksize
;
buf
->
f_type
=
BTRFS_SUPER_MAGIC
;
...
...
fs/btrfs/sysfs.c
View file @
db94535d
...
...
@@ -42,14 +42,15 @@ static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf)
static
ssize_t
super_blocks_used_show
(
struct
btrfs_fs_info
*
fs
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%llu
\n
"
,
(
unsigned
long
long
)
btrfs_super_b
lock
s_used
(
&
fs
->
super_copy
));
(
unsigned
long
long
)
btrfs_super_b
yte
s_used
(
&
fs
->
super_copy
));
}
static
ssize_t
super_total_blocks_show
(
struct
btrfs_fs_info
*
fs
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%llu
\n
"
,
(
unsigned
long
long
)
btrfs_super_total_b
lock
s
(
&
fs
->
super_copy
));
(
unsigned
long
long
)
btrfs_super_total_b
yte
s
(
&
fs
->
super_copy
));
}
static
ssize_t
super_blocksize_show
(
struct
btrfs_fs_info
*
fs
,
char
*
buf
)
...
...
fs/btrfs/transaction.c
View file @
db94535d
...
...
@@ -205,12 +205,13 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
btrfs_write_dirty_block_groups
(
trans
,
extent_root
);
while
(
1
)
{
old_extent_block
=
btrfs_root_blocknr
(
&
extent_root
->
root_item
);
if
(
old_extent_block
==
extent_buffer_blocknr
(
extent_root
->
node
))
old_extent_block
=
btrfs_root_bytenr
(
&
extent_root
->
root_item
);
if
(
old_extent_block
==
extent_root
->
node
->
start
)
break
;
btrfs_set_root_blocknr
(
&
extent_root
->
root_item
,
extent_buffer_blocknr
(
extent_root
->
node
));
btrfs_set_root_bytenr
(
&
extent_root
->
root_item
,
extent_root
->
node
->
start
);
btrfs_set_root_level
(
&
extent_root
->
root_item
,
btrfs_header_level
(
extent_root
->
node
));
ret
=
btrfs_update_root
(
trans
,
tree_root
,
&
extent_root
->
root_key
,
&
extent_root
->
root_item
);
...
...
@@ -284,8 +285,8 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
(
unsigned
long
)
root
->
root_key
.
objectid
,
BTRFS_ROOT_TRANS_TAG
);
if
(
root
->
commit_root
==
root
->
node
)
{
WARN_ON
(
extent_buffer_blocknr
(
root
->
node
)
!=
btrfs_root_b
lock
nr
(
&
root
->
root_item
));
WARN_ON
(
root
->
node
->
start
!=
btrfs_root_b
yte
nr
(
&
root
->
root_item
));
free_extent_buffer
(
root
->
commit_root
);
root
->
commit_root
=
NULL
;
...
...
@@ -314,8 +315,10 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
root
->
commit_root
=
NULL
;
root
->
root_key
.
offset
=
root
->
fs_info
->
generation
;
btrfs_set_root_blocknr
(
&
root
->
root_item
,
extent_buffer_blocknr
(
root
->
node
));
btrfs_set_root_bytenr
(
&
root
->
root_item
,
root
->
node
->
start
);
btrfs_set_root_level
(
&
root
->
root_item
,
btrfs_header_level
(
root
->
node
));
err
=
btrfs_insert_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
root
->
root_key
,
&
root
->
root_item
);
...
...
@@ -407,8 +410,8 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
struct
dirty_root
*
dirty
;
struct
btrfs_trans_handle
*
trans
;
unsigned
long
nr
;
u64
num_b
lock
s
;
u64
b
lock
s_used
;
u64
num_b
yte
s
;
u64
b
yte
s_used
;
int
ret
=
0
;
int
err
;
...
...
@@ -419,7 +422,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
dirty
=
list_entry
(
list
->
next
,
struct
dirty_root
,
list
);
list_del_init
(
&
dirty
->
list
);
num_b
lock
s
=
btrfs_root_used
(
&
dirty
->
root
->
root_item
);
num_b
yte
s
=
btrfs_root_used
(
&
dirty
->
root
->
root_item
);
root
=
dirty
->
latest_root
;
while
(
1
)
{
...
...
@@ -446,12 +449,12 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
}
BUG_ON
(
ret
);
num_b
lock
s
-=
btrfs_root_used
(
&
dirty
->
root
->
root_item
);
b
lock
s_used
=
btrfs_root_used
(
&
root
->
root_item
);
if
(
num_b
lock
s
)
{
num_b
yte
s
-=
btrfs_root_used
(
&
dirty
->
root
->
root_item
);
b
yte
s_used
=
btrfs_root_used
(
&
root
->
root_item
);
if
(
num_b
yte
s
)
{
record_root_in_trans
(
root
);
btrfs_set_root_used
(
&
root
->
root_item
,
blocks_used
-
num_block
s
);
bytes_used
-
num_byte
s
);
}
ret
=
btrfs_del_root
(
trans
,
tree_root
,
&
dirty
->
root
->
root_key
);
if
(
ret
)
{
...
...
@@ -560,7 +563,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
btrfs_set_super_generation
(
&
root
->
fs_info
->
super_copy
,
cur_trans
->
transid
);
btrfs_set_super_root
(
&
root
->
fs_info
->
super_copy
,
extent_buffer_blocknr
(
root
->
fs_info
->
tree_root
->
node
));
root
->
fs_info
->
tree_root
->
node
->
start
);
btrfs_set_super_root_level
(
&
root
->
fs_info
->
super_copy
,
btrfs_header_level
(
root
->
fs_info
->
tree_root
->
node
));
write_extent_buffer
(
root
->
fs_info
->
sb_buffer
,
&
root
->
fs_info
->
super_copy
,
0
,
...
...
fs/btrfs/tree-defrag.c
View file @
db94535d
...
...
@@ -27,13 +27,15 @@ static void reada_defrag(struct btrfs_root *root,
{
int
i
;
u32
nritems
;
u64
blocknr
;
u64
bytenr
;
u32
blocksize
;
int
ret
;
blocksize
=
btrfs_level_size
(
root
,
btrfs_header_level
(
node
)
-
1
);
nritems
=
btrfs_header_nritems
(
node
);
for
(
i
=
0
;
i
<
nritems
;
i
++
)
{
b
lock
nr
=
btrfs_node_blockptr
(
node
,
i
);
ret
=
readahead_tree_block
(
root
,
b
locknr
);
b
yte
nr
=
btrfs_node_blockptr
(
node
,
i
);
ret
=
readahead_tree_block
(
root
,
b
ytenr
,
blocksize
);
if
(
ret
)
break
;
}
...
...
@@ -46,7 +48,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
{
struct
extent_buffer
*
next
;
struct
extent_buffer
*
cur
;
u64
b
lock
nr
;
u64
b
yte
nr
;
int
ret
=
0
;
int
is_extent
=
0
;
...
...
@@ -80,10 +82,11 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
break
;
}
b
lock
nr
=
btrfs_node_blockptr
(
cur
,
path
->
slots
[
*
level
]);
b
yte
nr
=
btrfs_node_blockptr
(
cur
,
path
->
slots
[
*
level
]);
if
(
cache_only
)
{
next
=
btrfs_find_tree_block
(
root
,
blocknr
);
next
=
btrfs_find_tree_block
(
root
,
bytenr
,
btrfs_level_size
(
root
,
*
level
-
1
));
/* FIXME, test for defrag */
if
(
!
next
||
!
btrfs_buffer_uptodate
(
next
))
{
free_extent_buffer
(
next
);
...
...
@@ -91,7 +94,8 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
continue
;
}
}
else
{
next
=
read_tree_block
(
root
,
blocknr
);
next
=
read_tree_block
(
root
,
bytenr
,
btrfs_level_size
(
root
,
*
level
-
1
));
}
ret
=
btrfs_cow_block
(
trans
,
root
,
next
,
path
->
nodes
[
*
level
],
path
->
slots
[
*
level
],
&
next
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment