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
Kirill Smelkov
linux
Commits
e20d96d6
Commit
e20d96d6
authored
Mar 22, 2007
by
Chris Mason
Committed by
David Woodhouse
Mar 22, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Mountable btrfs, with readdir
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
2e635a27
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
651 additions
and
490 deletions
+651
-490
fs/btrfs/Makefile
fs/btrfs/Makefile
+3
-2
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+140
-133
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+48
-14
fs/btrfs/dir-item.c
fs/btrfs/dir-item.c
+7
-10
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+83
-198
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+28
-23
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+74
-70
fs/btrfs/hash.c
fs/btrfs/hash.c
+9
-0
fs/btrfs/inode-map.c
fs/btrfs/inode-map.c
+4
-4
fs/btrfs/print-tree.c
fs/btrfs/print-tree.c
+9
-11
fs/btrfs/print-tree.h
fs/btrfs/print-tree.h
+1
-1
fs/btrfs/root-tree.c
fs/btrfs/root-tree.c
+2
-2
fs/btrfs/super.c
fs/btrfs/super.c
+241
-20
fs/btrfs/transaction.h
fs/btrfs/transaction.h
+2
-2
No files found.
fs/btrfs/Makefile
View file @
e20d96d6
...
...
@@ -2,7 +2,8 @@ ifneq ($(KERNELRELEASE),)
# kbuild part of makefile
obj-m
:=
btrfs.o
btrfs-y
:=
super.o
btrfs-y
:=
super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o
\
hash.o file-item.o inode-item.o inode-map.o disk-io.o
#btrfs-y := ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
# root-tree.o dir-item.o hash.o file-item.o inode-item.o \
...
...
@@ -14,7 +15,7 @@ else
KERNELDIR
:=
/lib/modules/
`
uname
-r
`
/build
all
::
$(MAKE)
-C
$(KERNELDIR)
M
=
`
pwd
`
modules
$(MAKE)
C
=
1
-C
$(KERNELDIR)
M
=
`
pwd
`
modules
clean
::
rm
*
.o btrfs.ko
endif
fs/btrfs/ctree.c
View file @
e20d96d6
...
...
@@ -7,11 +7,11 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
static
int
split_leaf
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
data_size
);
static
int
push_node_left
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
dst
,
struct
btrfs_buffer
*
root
,
struct
b
uffer_head
*
dst
,
struct
buffer_head
*
src
);
static
int
balance_node_right
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
dst_buf
,
struct
b
trfs_buffer
*
src_buf
);
btrfs_root
*
root
,
struct
b
uffer_head
*
dst_buf
,
struct
b
uffer_head
*
src_buf
);
static
int
del_ptr
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
,
int
slot
);
...
...
@@ -32,32 +32,34 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
}
static
int
btrfs_cow_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
,
struct
btrfs_buffer
*
parent
,
int
parent_slot
,
struct
b
trfs_buffer
*
root
,
struct
b
uffer_head
*
buf
,
struct
buffer_head
*
parent
,
int
parent_slot
,
struct
b
uffer_head
**
cow_ret
)
{
struct
btrfs_buffer
*
cow
;
struct
buffer_head
*
cow
;
struct
btrfs_node
*
cow_node
;
if
(
!
list_empty
(
&
buf
->
dirty
))
{
if
(
!
buffer_dirty
(
buf
))
{
*
cow_ret
=
buf
;
return
0
;
}
cow
=
btrfs_alloc_free_block
(
trans
,
root
);
memcpy
(
&
cow
->
node
,
&
buf
->
node
,
root
->
blocksize
);
btrfs_set_header_blocknr
(
&
cow
->
node
.
header
,
cow
->
blocknr
);
cow_node
=
btrfs_buffer_node
(
cow
);
memcpy
(
cow_node
,
btrfs_buffer_node
(
buf
),
root
->
blocksize
);
btrfs_set_header_blocknr
(
&
cow_node
->
header
,
cow
->
b_blocknr
);
*
cow_ret
=
cow
;
btrfs_inc_ref
(
trans
,
root
,
buf
);
if
(
buf
==
root
->
node
)
{
root
->
node
=
cow
;
cow
->
count
++
;
get_bh
(
cow
)
;
if
(
buf
!=
root
->
commit_root
)
btrfs_free_extent
(
trans
,
root
,
buf
->
blocknr
,
1
,
1
);
btrfs_free_extent
(
trans
,
root
,
buf
->
b
_b
locknr
,
1
,
1
);
btrfs_block_release
(
root
,
buf
);
}
else
{
btrfs_set_node_blockptr
(
&
parent
->
node
,
parent_slot
,
cow
->
blocknr
);
BUG_ON
(
list_empty
(
&
parent
->
dirty
));
btrfs_free_extent
(
trans
,
root
,
buf
->
blocknr
,
1
,
1
);
btrfs_set_node_blockptr
(
btrfs_buffer_node
(
parent
)
,
parent_slot
,
cow
->
b
_b
locknr
);
BUG_ON
(
!
buffer_dirty
(
parent
));
btrfs_free_extent
(
trans
,
root
,
buf
->
b
_b
locknr
,
1
,
1
);
}
btrfs_block_release
(
root
,
buf
);
return
0
;
...
...
@@ -119,12 +121,12 @@ static int check_node(struct btrfs_root *root, struct btrfs_path *path,
{
int
i
;
struct
btrfs_node
*
parent
=
NULL
;
struct
btrfs_node
*
node
=
&
path
->
nodes
[
level
]
->
node
;
struct
btrfs_node
*
node
=
btrfs_buffer_node
(
path
->
nodes
[
level
])
;
int
parent_slot
;
u32
nritems
=
btrfs_header_nritems
(
&
node
->
header
);
if
(
path
->
nodes
[
level
+
1
])
parent
=
&
path
->
nodes
[
level
+
1
]
->
node
;
parent
=
btrfs_buffer_node
(
path
->
nodes
[
level
+
1
])
;
parent_slot
=
path
->
slots
[
level
+
1
];
BUG_ON
(
nritems
==
0
);
if
(
parent
)
{
...
...
@@ -148,13 +150,13 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
int
level
)
{
int
i
;
struct
btrfs_leaf
*
leaf
=
&
path
->
nodes
[
level
]
->
leaf
;
struct
btrfs_leaf
*
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
level
])
;
struct
btrfs_node
*
parent
=
NULL
;
int
parent_slot
;
u32
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
if
(
path
->
nodes
[
level
+
1
])
parent
=
&
path
->
nodes
[
level
+
1
]
->
node
;
parent
=
btrfs_buffer_node
(
path
->
nodes
[
level
+
1
])
;
parent_slot
=
path
->
slots
[
level
+
1
];
BUG_ON
(
btrfs_leaf_free_space
(
root
,
leaf
)
<
0
);
...
...
@@ -250,11 +252,11 @@ static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot)
return
-
1
;
}
static
struct
b
trfs_buffer
*
read_node_slot
(
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
parent_buf
,
static
struct
b
uffer_head
*
read_node_slot
(
struct
btrfs_root
*
root
,
struct
b
uffer_head
*
parent_buf
,
int
slot
)
{
struct
btrfs_node
*
node
=
&
parent_buf
->
node
;
struct
btrfs_node
*
node
=
btrfs_buffer_node
(
parent_buf
)
;
if
(
slot
<
0
)
return
NULL
;
if
(
slot
>=
btrfs_header_nritems
(
&
node
->
header
))
...
...
@@ -265,10 +267,10 @@ static struct btrfs_buffer *read_node_slot(struct btrfs_root *root,
static
int
balance_level
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
)
{
struct
b
trfs_buffer
*
right_buf
;
struct
b
trfs_buffer
*
mid_buf
;
struct
b
trfs_buffer
*
left_buf
;
struct
b
trfs_buffer
*
parent_buf
=
NULL
;
struct
b
uffer_head
*
right_buf
;
struct
b
uffer_head
*
mid_buf
;
struct
b
uffer_head
*
left_buf
;
struct
b
uffer_head
*
parent_buf
=
NULL
;
struct
btrfs_node
*
right
=
NULL
;
struct
btrfs_node
*
mid
;
struct
btrfs_node
*
left
=
NULL
;
...
...
@@ -283,7 +285,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
return
0
;
mid_buf
=
path
->
nodes
[
level
];
mid
=
&
mid_buf
->
node
;
mid
=
btrfs_buffer_node
(
mid_buf
)
;
orig_ptr
=
btrfs_node_blockptr
(
mid
,
orig_slot
);
if
(
level
<
BTRFS_MAX_LEVEL
-
1
)
...
...
@@ -295,8 +297,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
* by promoting the node below to a root
*/
if
(
!
parent_buf
)
{
struct
b
trfs_buffer
*
child
;
u64
blocknr
=
mid_buf
->
blocknr
;
struct
b
uffer_head
*
child
;
u64
blocknr
=
mid_buf
->
b
_b
locknr
;
if
(
btrfs_header_nritems
(
&
mid
->
header
)
!=
1
)
return
0
;
...
...
@@ -313,7 +315,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
clean_tree_block
(
trans
,
root
,
mid_buf
);
return
btrfs_free_extent
(
trans
,
root
,
blocknr
,
1
,
1
);
}
parent
=
&
parent_buf
->
node
;
parent
=
btrfs_buffer_node
(
parent_buf
)
;
if
(
btrfs_header_nritems
(
&
mid
->
header
)
>
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
/
4
)
...
...
@@ -326,7 +328,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
left_buf
)
{
btrfs_cow_block
(
trans
,
root
,
left_buf
,
parent_buf
,
pslot
-
1
,
&
left_buf
);
left
=
&
left_buf
->
node
;
left
=
btrfs_buffer_node
(
left_buf
)
;
orig_slot
+=
btrfs_header_nritems
(
&
left
->
header
);
wret
=
push_node_left
(
trans
,
root
,
left_buf
,
mid_buf
);
if
(
wret
<
0
)
...
...
@@ -339,12 +341,12 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
right_buf
)
{
btrfs_cow_block
(
trans
,
root
,
right_buf
,
parent_buf
,
pslot
+
1
,
&
right_buf
);
right
=
&
right_buf
->
node
;
right
=
btrfs_buffer_node
(
right_buf
)
;
wret
=
push_node_left
(
trans
,
root
,
mid_buf
,
right_buf
);
if
(
wret
<
0
)
ret
=
wret
;
if
(
btrfs_header_nritems
(
&
right
->
header
)
==
0
)
{
u64
blocknr
=
right_buf
->
blocknr
;
u64
blocknr
=
right_buf
->
b
_b
locknr
;
btrfs_block_release
(
root
,
right_buf
);
clean_tree_block
(
trans
,
root
,
right_buf
);
right_buf
=
NULL
;
...
...
@@ -360,7 +362,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
memcpy
(
&
parent
->
ptrs
[
pslot
+
1
].
key
,
&
right
->
ptrs
[
0
].
key
,
sizeof
(
struct
btrfs_disk_key
));
BUG_ON
(
list_empty
(
&
parent_buf
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
parent_buf
));
}
}
if
(
btrfs_header_nritems
(
&
mid
->
header
)
==
1
)
{
...
...
@@ -381,7 +383,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
}
if
(
btrfs_header_nritems
(
&
mid
->
header
)
==
0
)
{
/* we've managed to empty the middle node, drop it */
u64
blocknr
=
mid_buf
->
blocknr
;
u64
blocknr
=
mid_buf
->
b
_b
locknr
;
btrfs_block_release
(
root
,
mid_buf
);
clean_tree_block
(
trans
,
root
,
mid_buf
);
mid_buf
=
NULL
;
...
...
@@ -396,13 +398,13 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
/* update the parent key to reflect our changes */
memcpy
(
&
parent
->
ptrs
[
pslot
].
key
,
&
mid
->
ptrs
[
0
].
key
,
sizeof
(
struct
btrfs_disk_key
));
BUG_ON
(
list_empty
(
&
parent_buf
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
parent_buf
));
}
/* update the path */
if
(
left_buf
)
{
if
(
btrfs_header_nritems
(
&
left
->
header
)
>
orig_slot
)
{
left_buf
->
count
++
;
// released below
get_bh
(
left_buf
);
path
->
nodes
[
level
]
=
left_buf
;
path
->
slots
[
level
+
1
]
-=
1
;
path
->
slots
[
level
]
=
orig_slot
;
...
...
@@ -415,8 +417,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
}
/* double check we haven't messed things up */
check_block
(
root
,
path
,
level
);
if
(
orig_ptr
!=
btrfs_node_blockptr
(
&
path
->
nodes
[
level
]
->
node
,
path
->
slots
[
level
]))
if
(
orig_ptr
!=
btrfs_node_blockptr
(
btrfs_buffer_node
(
path
->
nodes
[
level
]),
path
->
slots
[
level
]))
BUG
();
if
(
right_buf
)
...
...
@@ -443,8 +446,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
*
root
,
struct
btrfs_key
*
key
,
struct
btrfs_path
*
p
,
int
ins_len
,
int
cow
)
{
struct
b
trfs_buffer
*
b
;
struct
b
trfs_buffer
*
cow_buf
;
struct
b
uffer_head
*
b
;
struct
b
uffer_head
*
cow_buf
;
struct
btrfs_node
*
c
;
int
slot
;
int
ret
;
...
...
@@ -452,18 +455,20 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
again:
b
=
root
->
node
;
b
->
count
++
;
get_bh
(
b
)
;
while
(
b
)
{
level
=
btrfs_header_level
(
&
b
->
node
.
header
);
c
=
btrfs_buffer_node
(
b
);
level
=
btrfs_header_level
(
&
c
->
header
);
if
(
cow
)
{
int
wret
;
wret
=
btrfs_cow_block
(
trans
,
root
,
b
,
p
->
nodes
[
level
+
1
],
p
->
slots
[
level
+
1
],
wret
=
btrfs_cow_block
(
trans
,
root
,
b
,
p
->
nodes
[
level
+
1
],
p
->
slots
[
level
+
1
],
&
cow_buf
);
b
=
cow_buf
;
}
BUG_ON
(
!
cow
&&
ins_len
);
c
=
&
b
->
node
;
c
=
btrfs_buffer_node
(
b
)
;
p
->
nodes
[
level
]
=
b
;
ret
=
check_block
(
root
,
p
,
level
);
if
(
ret
)
...
...
@@ -480,7 +485,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
sret
)
return
sret
;
b
=
p
->
nodes
[
level
];
c
=
&
b
->
node
;
c
=
btrfs_buffer_node
(
b
)
;
slot
=
p
->
slots
[
level
];
}
else
if
(
ins_len
<
0
)
{
int
sret
=
balance_level
(
trans
,
root
,
p
,
...
...
@@ -490,7 +495,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
b
=
p
->
nodes
[
level
];
if
(
!
b
)
goto
again
;
c
=
&
b
->
node
;
c
=
btrfs_buffer_node
(
b
)
;
slot
=
p
->
slots
[
level
];
BUG_ON
(
btrfs_header_nritems
(
&
c
->
header
)
==
1
);
}
...
...
@@ -505,11 +510,9 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
sret
)
return
sret
;
}
BUG_ON
(
root
->
node
->
count
==
1
);
return
ret
;
}
}
BUG_ON
(
root
->
node
->
count
==
1
);
return
1
;
}
...
...
@@ -534,9 +537,9 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root
int
tslot
=
path
->
slots
[
i
];
if
(
!
path
->
nodes
[
i
])
break
;
t
=
&
path
->
nodes
[
i
]
->
node
;
t
=
btrfs_buffer_node
(
path
->
nodes
[
i
])
;
memcpy
(
&
t
->
ptrs
[
tslot
].
key
,
key
,
sizeof
(
*
key
));
BUG_ON
(
list_empty
(
&
path
->
nodes
[
i
]
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
path
->
nodes
[
i
]
));
if
(
tslot
!=
0
)
break
;
}
...
...
@@ -551,11 +554,11 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root
* error, and > 0 if there was no room in the left hand block.
*/
static
int
push_node_left
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
dst_buf
,
struct
b
trfs_buffer
*
src_buf
)
*
root
,
struct
b
uffer_head
*
dst_buf
,
struct
b
uffer_head
*
src_buf
)
{
struct
btrfs_node
*
src
=
&
src_buf
->
node
;
struct
btrfs_node
*
dst
=
&
dst_buf
->
node
;
struct
btrfs_node
*
src
=
btrfs_buffer_node
(
src_buf
)
;
struct
btrfs_node
*
dst
=
btrfs_buffer_node
(
dst_buf
)
;
int
push_items
=
0
;
int
src_nritems
;
int
dst_nritems
;
...
...
@@ -580,8 +583,8 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
}
btrfs_set_header_nritems
(
&
src
->
header
,
src_nritems
-
push_items
);
btrfs_set_header_nritems
(
&
dst
->
header
,
dst_nritems
+
push_items
);
BUG_ON
(
list_empty
(
&
src_buf
->
dirty
));
BUG_ON
(
list_empty
(
&
dst_buf
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
src_buf
));
BUG_ON
(
!
buffer_dirty
(
dst_buf
));
return
ret
;
}
...
...
@@ -595,11 +598,11 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
* this will only push up to 1/2 the contents of the left node over
*/
static
int
balance_node_right
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
dst_buf
,
struct
b
trfs_buffer
*
src_buf
)
btrfs_root
*
root
,
struct
b
uffer_head
*
dst_buf
,
struct
b
uffer_head
*
src_buf
)
{
struct
btrfs_node
*
src
=
&
src_buf
->
node
;
struct
btrfs_node
*
dst
=
&
dst_buf
->
node
;
struct
btrfs_node
*
src
=
btrfs_buffer_node
(
src_buf
)
;
struct
btrfs_node
*
dst
=
btrfs_buffer_node
(
dst_buf
)
;
int
push_items
=
0
;
int
max_push
;
int
src_nritems
;
...
...
@@ -628,8 +631,8 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct
btrfs_set_header_nritems
(
&
src
->
header
,
src_nritems
-
push_items
);
btrfs_set_header_nritems
(
&
dst
->
header
,
dst_nritems
+
push_items
);
BUG_ON
(
list_empty
(
&
src_buf
->
dirty
));
BUG_ON
(
list_empty
(
&
dst_buf
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
src_buf
));
BUG_ON
(
!
buffer_dirty
(
dst_buf
));
return
ret
;
}
...
...
@@ -643,7 +646,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct
static
int
insert_new_root
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
)
{
struct
b
trfs_buffer
*
t
;
struct
b
uffer_head
*
t
;
struct
btrfs_node
*
lower
;
struct
btrfs_node
*
c
;
struct
btrfs_disk_key
*
lower_key
;
...
...
@@ -652,24 +655,24 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
BUG_ON
(
path
->
nodes
[
level
-
1
]
!=
root
->
node
);
t
=
btrfs_alloc_free_block
(
trans
,
root
);
c
=
&
t
->
node
;
c
=
btrfs_buffer_node
(
t
)
;
memset
(
c
,
0
,
root
->
blocksize
);
btrfs_set_header_nritems
(
&
c
->
header
,
1
);
btrfs_set_header_level
(
&
c
->
header
,
level
);
btrfs_set_header_blocknr
(
&
c
->
header
,
t
->
blocknr
);
btrfs_set_header_blocknr
(
&
c
->
header
,
t
->
b
_b
locknr
);
btrfs_set_header_parentid
(
&
c
->
header
,
btrfs_header_parentid
(
&
root
->
node
->
node
.
header
));
lower
=
&
path
->
nodes
[
level
-
1
]
->
node
;
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)
));
lower
=
btrfs_buffer_node
(
path
->
nodes
[
level
-
1
])
;
if
(
btrfs_is_leaf
(
lower
))
lower_key
=
&
((
struct
btrfs_leaf
*
)
lower
)
->
items
[
0
].
key
;
else
lower_key
=
&
lower
->
ptrs
[
0
].
key
;
memcpy
(
&
c
->
ptrs
[
0
].
key
,
lower_key
,
sizeof
(
struct
btrfs_disk_key
));
btrfs_set_node_blockptr
(
c
,
0
,
path
->
nodes
[
level
-
1
]
->
blocknr
);
btrfs_set_node_blockptr
(
c
,
0
,
path
->
nodes
[
level
-
1
]
->
b
_b
locknr
);
/* the super has an extra ref to root->node */
btrfs_block_release
(
root
,
root
->
node
);
root
->
node
=
t
;
t
->
count
++
;
get_bh
(
t
)
;
path
->
nodes
[
level
]
=
t
;
path
->
slots
[
level
]
=
0
;
return
0
;
...
...
@@ -692,7 +695,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
int
nritems
;
BUG_ON
(
!
path
->
nodes
[
level
]);
lower
=
&
path
->
nodes
[
level
]
->
node
;
lower
=
btrfs_buffer_node
(
path
->
nodes
[
level
])
;
nritems
=
btrfs_header_nritems
(
&
lower
->
header
);
if
(
slot
>
nritems
)
BUG
();
...
...
@@ -705,7 +708,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
memcpy
(
&
lower
->
ptrs
[
slot
].
key
,
key
,
sizeof
(
struct
btrfs_disk_key
));
btrfs_set_node_blockptr
(
lower
,
slot
,
blocknr
);
btrfs_set_header_nritems
(
&
lower
->
header
,
nritems
+
1
);
BUG_ON
(
list_empty
(
&
path
->
nodes
[
level
]
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
path
->
nodes
[
level
]
));
return
0
;
}
...
...
@@ -721,9 +724,9 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
static
int
split_node
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
)
{
struct
b
trfs_buffer
*
t
;
struct
b
uffer_head
*
t
;
struct
btrfs_node
*
c
;
struct
b
trfs_buffer
*
split_buffer
;
struct
b
uffer_head
*
split_buffer
;
struct
btrfs_node
*
split
;
int
mid
;
int
ret
;
...
...
@@ -731,7 +734,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
u32
c_nritems
;
t
=
path
->
nodes
[
level
];
c
=
&
t
->
node
;
c
=
btrfs_buffer_node
(
t
)
;
if
(
t
==
root
->
node
)
{
/* trying to split the root, lets make a new one */
ret
=
insert_new_root
(
trans
,
root
,
path
,
level
+
1
);
...
...
@@ -740,11 +743,11 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
}
c_nritems
=
btrfs_header_nritems
(
&
c
->
header
);
split_buffer
=
btrfs_alloc_free_block
(
trans
,
root
);
split
=
&
split_buffer
->
node
;
split
=
btrfs_buffer_node
(
split_buffer
)
;
btrfs_set_header_flags
(
&
split
->
header
,
btrfs_header_flags
(
&
c
->
header
));
btrfs_set_header_blocknr
(
&
split
->
header
,
split_buffer
->
blocknr
);
btrfs_set_header_blocknr
(
&
split
->
header
,
split_buffer
->
b
_b
locknr
);
btrfs_set_header_parentid
(
&
split
->
header
,
btrfs_header_parentid
(
&
root
->
node
->
node
.
header
));
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)
));
mid
=
(
c_nritems
+
1
)
/
2
;
memcpy
(
split
->
ptrs
,
c
->
ptrs
+
mid
,
(
c_nritems
-
mid
)
*
sizeof
(
struct
btrfs_key_ptr
));
...
...
@@ -752,9 +755,9 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_header_nritems
(
&
c
->
header
,
mid
);
ret
=
0
;
BUG_ON
(
list_empty
(
&
t
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
t
));
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
split
->
ptrs
[
0
].
key
,
split_buffer
->
blocknr
,
path
->
slots
[
level
+
1
]
+
1
,
split_buffer
->
b
_b
locknr
,
path
->
slots
[
level
+
1
]
+
1
,
level
+
1
);
if
(
wret
)
ret
=
wret
;
...
...
@@ -798,11 +801,12 @@ static int leaf_space_used(struct btrfs_leaf *l, int start, int nr)
static
int
push_leaf_right
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
data_size
)
{
struct
b
trfs_buffer
*
left_buf
=
path
->
nodes
[
0
];
struct
btrfs_leaf
*
left
=
&
left_buf
->
leaf
;
struct
b
uffer_head
*
left_buf
=
path
->
nodes
[
0
];
struct
btrfs_leaf
*
left
=
btrfs_buffer_leaf
(
left_buf
)
;
struct
btrfs_leaf
*
right
;
struct
btrfs_buffer
*
right_buf
;
struct
btrfs_buffer
*
upper
;
struct
buffer_head
*
right_buf
;
struct
buffer_head
*
upper
;
struct
btrfs_node
*
upper_node
;
int
slot
;
int
i
;
int
free_space
;
...
...
@@ -817,12 +821,13 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
return
1
;
}
upper
=
path
->
nodes
[
1
];
if
(
slot
>=
btrfs_header_nritems
(
&
upper
->
node
.
header
)
-
1
)
{
upper_node
=
btrfs_buffer_node
(
upper
);
if
(
slot
>=
btrfs_header_nritems
(
&
upper_node
->
header
)
-
1
)
{
return
1
;
}
right_buf
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
&
upper
->
node
,
slot
+
1
));
right
=
&
right_buf
->
leaf
;
right_buf
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
btrfs_buffer_node
(
upper
),
slot
+
1
));
right
=
btrfs_buffer_leaf
(
right_buf
)
;
free_space
=
btrfs_leaf_free_space
(
root
,
right
);
if
(
free_space
<
data_size
+
sizeof
(
struct
btrfs_item
))
{
btrfs_block_release
(
root
,
right_buf
);
...
...
@@ -830,7 +835,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
}
/* cow and double check */
btrfs_cow_block
(
trans
,
root
,
right_buf
,
upper
,
slot
+
1
,
&
right_buf
);
right
=
&
right_buf
->
leaf
;
right
=
btrfs_buffer_leaf
(
right_buf
)
;
free_space
=
btrfs_leaf_free_space
(
root
,
right
);
if
(
free_space
<
data_size
+
sizeof
(
struct
btrfs_item
))
{
btrfs_block_release
(
root
,
right_buf
);
...
...
@@ -881,11 +886,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
left_nritems
-=
push_items
;
btrfs_set_header_nritems
(
&
left
->
header
,
left_nritems
);
BUG_ON
(
list_empty
(
&
left_buf
->
dirty
));
BUG_ON
(
list_empty
(
&
right_buf
->
dirty
));
memcpy
(
&
upper
->
node
.
ptrs
[
slot
+
1
].
key
,
BUG_ON
(
!
buffer_dirty
(
left_buf
));
BUG_ON
(
!
buffer_dirty
(
right_buf
));
memcpy
(
&
upper
_node
->
ptrs
[
slot
+
1
].
key
,
&
right
->
items
[
0
].
key
,
sizeof
(
struct
btrfs_disk_key
));
BUG_ON
(
list_empty
(
&
upper
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
upper
));
/* then fixup the leaf pointer in the path */
if
(
path
->
slots
[
0
]
>=
left_nritems
)
{
...
...
@@ -905,9 +910,9 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
static
int
push_leaf_left
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
data_size
)
{
struct
b
trfs_buffer
*
right_buf
=
path
->
nodes
[
0
];
struct
btrfs_leaf
*
right
=
&
right_buf
->
leaf
;
struct
b
trfs_buffer
*
t
;
struct
b
uffer_head
*
right_buf
=
path
->
nodes
[
0
];
struct
btrfs_leaf
*
right
=
btrfs_buffer_leaf
(
right_buf
)
;
struct
b
uffer_head
*
t
;
struct
btrfs_leaf
*
left
;
int
slot
;
int
i
;
...
...
@@ -926,9 +931,9 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
!
path
->
nodes
[
1
])
{
return
1
;
}
t
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
&
path
->
nodes
[
1
]
->
node
,
slot
-
1
));
left
=
&
t
->
leaf
;
t
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
btrfs_buffer_node
(
path
->
nodes
[
1
]),
slot
-
1
));
left
=
btrfs_buffer_leaf
(
t
)
;
free_space
=
btrfs_leaf_free_space
(
root
,
left
);
if
(
free_space
<
data_size
+
sizeof
(
struct
btrfs_item
))
{
btrfs_block_release
(
root
,
t
);
...
...
@@ -937,7 +942,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
/* cow and double check */
btrfs_cow_block
(
trans
,
root
,
t
,
path
->
nodes
[
1
],
slot
-
1
,
&
t
);
left
=
&
t
->
leaf
;
left
=
btrfs_buffer_leaf
(
t
)
;
free_space
=
btrfs_leaf_free_space
(
root
,
left
);
if
(
free_space
<
data_size
+
sizeof
(
struct
btrfs_item
))
{
btrfs_block_release
(
root
,
t
);
...
...
@@ -999,8 +1004,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
push_space
=
btrfs_item_offset
(
right
->
items
+
i
);
}
BUG_ON
(
list_empty
(
&
t
->
dirty
));
BUG_ON
(
list_empty
(
&
right_buf
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
t
));
BUG_ON
(
!
buffer_dirty
(
right_buf
));
wret
=
fixup_low_keys
(
trans
,
root
,
path
,
&
right
->
items
[
0
].
key
,
1
);
if
(
wret
)
...
...
@@ -1029,13 +1034,13 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
static
int
split_leaf
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
data_size
)
{
struct
b
trfs_buffer
*
l_buf
;
struct
b
uffer_head
*
l_buf
;
struct
btrfs_leaf
*
l
;
u32
nritems
;
int
mid
;
int
slot
;
struct
btrfs_leaf
*
right
;
struct
b
trfs_buffer
*
right_buffer
;
struct
b
uffer_head
*
right_buffer
;
int
space_needed
=
data_size
+
sizeof
(
struct
btrfs_item
);
int
data_copy_size
;
int
rt_data_off
;
...
...
@@ -1053,7 +1058,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
return
wret
;
}
l_buf
=
path
->
nodes
[
0
];
l
=
&
l_buf
->
leaf
;
l
=
btrfs_buffer_leaf
(
l_buf
)
;
/* did the pushes work? */
if
(
btrfs_leaf_free_space
(
root
,
l
)
>=
...
...
@@ -1071,7 +1076,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
right_buffer
=
btrfs_alloc_free_block
(
trans
,
root
);
BUG_ON
(
!
right_buffer
);
BUG_ON
(
mid
==
nritems
);
right
=
&
right_buffer
->
leaf
;
right
=
btrfs_buffer_leaf
(
right_buffer
)
;
memset
(
&
right
->
header
,
0
,
sizeof
(
right
->
header
));
if
(
mid
<=
slot
)
{
/* FIXME, just alloc a new leaf here */
...
...
@@ -1085,10 +1090,10 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
BUG
();
}
btrfs_set_header_nritems
(
&
right
->
header
,
nritems
-
mid
);
btrfs_set_header_blocknr
(
&
right
->
header
,
right_buffer
->
blocknr
);
btrfs_set_header_blocknr
(
&
right
->
header
,
right_buffer
->
b
_b
locknr
);
btrfs_set_header_level
(
&
right
->
header
,
0
);
btrfs_set_header_parentid
(
&
right
->
header
,
btrfs_header_parentid
(
&
root
->
node
->
node
.
header
));
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)
));
data_copy_size
=
btrfs_item_end
(
l
->
items
+
mid
)
-
leaf_data_end
(
root
,
l
);
memcpy
(
right
->
items
,
l
->
items
+
mid
,
...
...
@@ -1107,11 +1112,11 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_header_nritems
(
&
l
->
header
,
mid
);
ret
=
0
;
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
right
->
items
[
0
].
key
,
right_buffer
->
blocknr
,
path
->
slots
[
1
]
+
1
,
1
);
right_buffer
->
b
_b
locknr
,
path
->
slots
[
1
]
+
1
,
1
);
if
(
wret
)
ret
=
wret
;
BUG_ON
(
list_empty
(
&
right_buffer
->
dirty
));
BUG_ON
(
list_empty
(
&
l_buf
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
right_buffer
));
BUG_ON
(
!
buffer_dirty
(
l_buf
));
BUG_ON
(
path
->
slots
[
0
]
!=
slot
);
if
(
mid
<=
slot
)
{
btrfs_block_release
(
root
,
path
->
nodes
[
0
]);
...
...
@@ -1136,7 +1141,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
int
slot
;
int
slot_orig
;
struct
btrfs_leaf
*
leaf
;
struct
b
trfs_buffer
*
leaf_buf
;
struct
b
uffer_head
*
leaf_buf
;
u32
nritems
;
unsigned
int
data_end
;
struct
btrfs_disk_key
disk_key
;
...
...
@@ -1156,7 +1161,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
slot_orig
=
path
->
slots
[
0
];
leaf_buf
=
path
->
nodes
[
0
];
leaf
=
&
leaf_buf
->
leaf
;
leaf
=
btrfs_buffer_leaf
(
leaf_buf
)
;
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
data_end
=
leaf_data_end
(
root
,
leaf
);
...
...
@@ -1202,7 +1207,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
slot
==
0
)
ret
=
fixup_low_keys
(
trans
,
root
,
path
,
&
disk_key
,
1
);
BUG_ON
(
list_empty
(
&
leaf_buf
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
leaf_buf
));
if
(
btrfs_leaf_free_space
(
root
,
leaf
)
<
0
)
BUG
();
check_leaf
(
root
,
path
,
0
);
...
...
@@ -1225,7 +1230,8 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_init_path
(
&
path
);
ret
=
btrfs_insert_empty_item
(
trans
,
root
,
&
path
,
cpu_key
,
data_size
);
if
(
!
ret
)
{
ptr
=
btrfs_item_ptr
(
&
path
.
nodes
[
0
]
->
leaf
,
path
.
slots
[
0
],
u8
);
ptr
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
]),
path
.
slots
[
0
],
u8
);
memcpy
(
ptr
,
data
,
data_size
);
}
btrfs_release_path
(
root
,
&
path
);
...
...
@@ -1243,12 +1249,12 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct
btrfs_path
*
path
,
int
level
,
int
slot
)
{
struct
btrfs_node
*
node
;
struct
b
trfs_buffer
*
parent
=
path
->
nodes
[
level
];
struct
b
uffer_head
*
parent
=
path
->
nodes
[
level
];
u32
nritems
;
int
ret
=
0
;
int
wret
;
node
=
&
parent
->
node
;
node
=
btrfs_buffer_node
(
parent
)
;
nritems
=
btrfs_header_nritems
(
&
node
->
header
);
if
(
slot
!=
nritems
-
1
)
{
memmove
(
node
->
ptrs
+
slot
,
node
->
ptrs
+
slot
+
1
,
...
...
@@ -1257,16 +1263,17 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
nritems
--
;
btrfs_set_header_nritems
(
&
node
->
header
,
nritems
);
if
(
nritems
==
0
&&
parent
==
root
->
node
)
{
BUG_ON
(
btrfs_header_level
(
&
root
->
node
->
node
.
header
)
!=
1
);
struct
btrfs_header
*
header
=
btrfs_buffer_header
(
root
->
node
);
BUG_ON
(
btrfs_header_level
(
header
)
!=
1
);
/* just turn the root into a leaf and break */
btrfs_set_header_level
(
&
root
->
node
->
node
.
header
,
0
);
btrfs_set_header_level
(
header
,
0
);
}
else
if
(
slot
==
0
)
{
wret
=
fixup_low_keys
(
trans
,
root
,
path
,
&
node
->
ptrs
[
0
].
key
,
level
+
1
);
if
(
wret
)
ret
=
wret
;
}
BUG_ON
(
list_empty
(
&
parent
->
dirty
));
BUG_ON
(
!
buffer_dirty
(
parent
));
return
ret
;
}
...
...
@@ -1279,7 +1286,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
{
int
slot
;
struct
btrfs_leaf
*
leaf
;
struct
b
trfs_buffer
*
leaf_buf
;
struct
b
uffer_head
*
leaf_buf
;
int
doff
;
int
dsize
;
int
ret
=
0
;
...
...
@@ -1287,7 +1294,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
u32
nritems
;
leaf_buf
=
path
->
nodes
[
0
];
leaf
=
&
leaf_buf
->
leaf
;
leaf
=
btrfs_buffer_leaf
(
leaf_buf
)
;
slot
=
path
->
slots
[
0
];
doff
=
btrfs_item_offset
(
leaf
->
items
+
slot
);
dsize
=
btrfs_item_size
(
leaf
->
items
+
slot
);
...
...
@@ -1313,14 +1320,13 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
nritems
==
0
)
{
if
(
leaf_buf
==
root
->
node
)
{
btrfs_set_header_level
(
&
leaf
->
header
,
0
);
BUG_ON
(
list_empty
(
&
leaf_buf
->
dirty
));
}
else
{
clean_tree_block
(
trans
,
root
,
leaf_buf
);
wret
=
del_ptr
(
trans
,
root
,
path
,
1
,
path
->
slots
[
1
]);
if
(
wret
)
ret
=
wret
;
wret
=
btrfs_free_extent
(
trans
,
root
,
leaf_buf
->
blocknr
,
1
,
1
);
leaf_buf
->
b
_b
locknr
,
1
,
1
);
if
(
wret
)
ret
=
wret
;
}
...
...
@@ -1332,7 +1338,6 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if
(
wret
)
ret
=
wret
;
}
BUG_ON
(
list_empty
(
&
leaf_buf
->
dirty
));
/* delete the leaf if it is mostly empty */
if
(
used
<
BTRFS_LEAF_DATA_SIZE
(
root
)
/
3
)
{
...
...
@@ -1341,7 +1346,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
* for possible call to del_ptr below
*/
slot
=
path
->
slots
[
1
];
leaf_buf
->
count
++
;
get_bh
(
leaf_buf
)
;
wret
=
push_leaf_left
(
trans
,
root
,
path
,
1
);
if
(
wret
<
0
)
ret
=
wret
;
...
...
@@ -1352,7 +1357,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
ret
=
wret
;
}
if
(
btrfs_header_nritems
(
&
leaf
->
header
)
==
0
)
{
u64
blocknr
=
leaf_buf
->
blocknr
;
u64
blocknr
=
leaf_buf
->
b
_b
locknr
;
clean_tree_block
(
trans
,
root
,
leaf_buf
);
wret
=
del_ptr
(
trans
,
root
,
path
,
1
,
slot
);
if
(
wret
)
...
...
@@ -1380,19 +1385,21 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
int
slot
;
int
level
=
1
;
u64
blocknr
;
struct
btrfs_buffer
*
c
;
struct
btrfs_buffer
*
next
=
NULL
;
struct
buffer_head
*
c
;
struct
btrfs_node
*
c_node
;
struct
buffer_head
*
next
=
NULL
;
while
(
level
<
BTRFS_MAX_LEVEL
)
{
if
(
!
path
->
nodes
[
level
])
return
1
;
slot
=
path
->
slots
[
level
]
+
1
;
c
=
path
->
nodes
[
level
];
if
(
slot
>=
btrfs_header_nritems
(
&
c
->
node
.
header
))
{
c_node
=
btrfs_buffer_node
(
c
);
if
(
slot
>=
btrfs_header_nritems
(
&
c_node
->
header
))
{
level
++
;
continue
;
}
blocknr
=
btrfs_node_blockptr
(
&
c
->
node
,
slot
);
blocknr
=
btrfs_node_blockptr
(
c_
node
,
slot
);
if
(
next
)
btrfs_block_release
(
root
,
next
);
next
=
read_tree_block
(
root
,
blocknr
);
...
...
@@ -1408,7 +1415,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
if
(
!
level
)
break
;
next
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
&
next
->
node
,
0
));
btrfs_node_blockptr
(
btrfs_buffer_node
(
next
)
,
0
));
}
return
0
;
}
fs/btrfs/ctree.h
View file @
e20d96d6
#ifndef __BTRFS__
#define __BTRFS__
#include <linux/radix-tree.h>
#include <linux/fs.h>
struct
btrfs_trans_handle
;
#define BTRFS_MAGIC "_BtRfS_M"
...
...
@@ -10,6 +13,12 @@ struct btrfs_trans_handle;
#define BTRFS_INODE_MAP_OBJECTID 3
#define BTRFS_FS_TREE_OBJECTID 4
/*
* we can actually store much bigger names, but lets not confuse the rest
* of linux
*/
#define BTRFS_NAME_LEN 255
/*
* the key defines the order in the tree, and so it also defines (optimal)
* block layout. objectid corresonds to the inode number. The flags
...
...
@@ -57,7 +66,7 @@ struct btrfs_header {
#define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->blocksize))
struct
b
trfs_buffer
;
struct
b
uffer_head
;
/*
* the super block basically lists the main trees of the FS
* it currently lacks any block count etc etc
...
...
@@ -120,7 +129,7 @@ struct btrfs_node {
* used while walking the tree.
*/
struct
btrfs_path
{
struct
b
trfs_buffer
*
nodes
[
BTRFS_MAX_LEVEL
];
struct
b
uffer_head
*
nodes
[
BTRFS_MAX_LEVEL
];
int
slots
[
BTRFS_MAX_LEVEL
];
};
...
...
@@ -211,17 +220,14 @@ struct btrfs_fs_info {
struct
btrfs_root
*
inode_root
;
struct
btrfs_key
current_insert
;
struct
btrfs_key
last_insert
;
struct
radix_tree_root
cache_radix
;
struct
radix_tree_root
pinned_radix
;
struct
list_head
trans
;
struct
list_head
cache
;
u64
last_inode_alloc
;
u64
last_inode_alloc_dirid
;
u64
generation
;
int
cache_size
;
int
fp
;
struct
btrfs_trans_handle
*
running_transaction
;
struct
btrfs_super_block
*
disk_super
;
struct
buffer_head
*
sb_buffer
;
struct
super_block
*
sb
;
};
/*
...
...
@@ -230,8 +236,8 @@ struct btrfs_fs_info {
* only for the extent tree.
*/
struct
btrfs_root
{
struct
b
trfs_buffer
*
node
;
struct
b
trfs_buffer
*
commit_root
;
struct
b
uffer_head
*
node
;
struct
b
uffer_head
*
commit_root
;
struct
btrfs_root_item
root_item
;
struct
btrfs_key
root_key
;
struct
btrfs_fs_info
*
fs_info
;
...
...
@@ -389,6 +395,29 @@ static inline void btrfs_set_inode_compat_flags(struct btrfs_inode_item *i,
i
->
compat_flags
=
cpu_to_le16
(
val
);
}
static
inline
u32
btrfs_timespec_sec
(
struct
btrfs_inode_timespec
*
ts
)
{
return
le32_to_cpu
(
ts
->
sec
);
}
static
inline
void
btrfs_set_timespec_sec
(
struct
btrfs_inode_timespec
*
ts
,
u32
val
)
{
ts
->
sec
=
cpu_to_le32
(
val
);
}
static
inline
u32
btrfs_timespec_nsec
(
struct
btrfs_inode_timespec
*
ts
)
{
return
le32_to_cpu
(
ts
->
nsec
);
}
static
inline
void
btrfs_set_timespec_nsec
(
struct
btrfs_inode_timespec
*
ts
,
u32
val
)
{
ts
->
nsec
=
cpu_to_le32
(
val
);
}
static
inline
u64
btrfs_extent_owner
(
struct
btrfs_extent_item
*
ei
)
{
...
...
@@ -757,15 +786,20 @@ static inline void btrfs_set_file_extent_num_blocks(struct
e
->
num_blocks
=
cpu_to_le64
(
val
);
}
static
inline
struct
btrfs_root
*
btrfs_sb
(
struct
super_block
*
sb
)
{
return
sb
->
s_fs_info
;
}
/* helper function to cast into the data area of the leaf. */
#define btrfs_item_ptr(leaf, slot, type) \
((type *)(btrfs_leaf_data(leaf) + \
btrfs_item_offset((leaf)->items + (slot))))
struct
b
trfs_buffer
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
b
uffer_head
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
int
btrfs_inc_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
);
struct
b
uffer_head
*
buf
);
int
btrfs_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
int
pin
);
int
btrfs_search_slot
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
...
...
@@ -783,7 +817,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
int
btrfs_next_leaf
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
);
int
btrfs_leaf_free_space
(
struct
btrfs_root
*
root
,
struct
btrfs_leaf
*
leaf
);
int
btrfs_drop_snapshot
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
snap
);
*
root
,
struct
b
uffer_head
*
snap
);
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
int
btrfs_del_root
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
...
...
@@ -800,8 +834,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*
root
,
char
*
name
,
int
name_len
,
u64
dir
,
u64
objectid
,
u8
type
);
int
btrfs_lookup_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
char
*
name
,
int
name_len
,
int
mod
);
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
const
char
*
name
,
int
name_len
,
int
mod
);
int
btrfs_match_dir_item_name
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
char
*
name
,
int
name_len
);
int
btrfs_find_free_objectid
(
struct
btrfs_trans_handle
*
trans
,
...
...
fs/btrfs/dir-item.c
View file @
e20d96d6
...
...
@@ -18,12 +18,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
key
.
objectid
=
dir
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_DIR_ITEM_KEY
);
if
(
name_len
==
1
&&
*
name
==
'.'
)
key
.
offset
=
1
;
else
if
(
name_len
==
2
&&
name
[
0
]
==
'.'
&&
name
[
1
]
==
'.'
)
key
.
offset
=
2
;
else
ret
=
btrfs_name_hash
(
name
,
name_len
,
&
key
.
offset
);
ret
=
btrfs_name_hash
(
name
,
name_len
,
&
key
.
offset
);
BUG_ON
(
ret
);
btrfs_init_path
(
&
path
);
data_size
=
sizeof
(
*
dir_item
)
+
name_len
;
...
...
@@ -31,7 +26,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
ret
)
goto
out
;
dir_item
=
btrfs_item_ptr
(
&
path
.
nodes
[
0
]
->
leaf
,
path
.
slots
[
0
],
dir_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
]),
path
.
slots
[
0
],
struct
btrfs_dir_item
);
btrfs_set_dir_objectid
(
dir_item
,
objectid
);
btrfs_set_dir_type
(
dir_item
,
type
);
...
...
@@ -45,8 +41,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
}
int
btrfs_lookup_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
char
*
name
,
int
name_len
,
int
mod
)
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
const
char
*
name
,
int
name_len
,
int
mod
)
{
int
ret
;
struct
btrfs_key
key
;
...
...
@@ -69,7 +65,8 @@ int btrfs_match_dir_item_name(struct btrfs_root *root,
struct
btrfs_dir_item
*
dir_item
;
char
*
name_ptr
;
dir_item
=
btrfs_item_ptr
(
&
path
->
nodes
[
0
]
->
leaf
,
path
->
slots
[
0
],
dir_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_dir_item
);
if
(
btrfs_dir_name_len
(
dir_item
)
!=
name_len
)
return
0
;
...
...
fs/btrfs/disk-io.c
View file @
e20d96d6
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "kerncompat.h"
#include "radix-tree.h"
#include <linux/module.h>
#include <linux/fs.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
static
int
allocated_blocks
=
0
;
int
cache_max
=
10000
;
static
int
check_tree_block
(
struct
btrfs_root
*
root
,
struct
btrfs_buffer
*
buf
)
static
int
check_tree_block
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
buf
)
{
if
(
buf
->
blocknr
!=
btrfs_header_blocknr
(
&
buf
->
node
.
header
))
struct
btrfs_node
*
node
=
btrfs_buffer_node
(
buf
);
if
(
buf
->
b_blocknr
!=
btrfs_header_blocknr
(
&
node
->
header
))
BUG
();
if
(
root
->
node
&&
btrfs_header_parentid
(
&
buf
->
node
.
header
)
!=
btrfs_header_parentid
(
&
root
->
node
->
node
.
header
))
if
(
root
->
node
&&
btrfs_header_parentid
(
&
node
->
header
)
!=
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)
))
BUG
();
return
0
;
}
st
atic
int
free_some_buffers
(
struct
btrfs_root
*
root
)
st
ruct
buffer_head
*
alloc_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
{
struct
list_head
*
node
,
*
next
;
struct
btrfs_buffer
*
b
;
if
(
root
->
fs_info
->
cache_size
<
cache_max
)
return
0
;
list_for_each_safe
(
node
,
next
,
&
root
->
fs_info
->
cache
)
{
b
=
list_entry
(
node
,
struct
btrfs_buffer
,
cache
);
if
(
b
->
count
==
1
)
{
BUG_ON
(
!
list_empty
(
&
b
->
dirty
));
list_del_init
(
&
b
->
cache
);
btrfs_block_release
(
root
,
b
);
if
(
root
->
fs_info
->
cache_size
<
cache_max
)
break
;
}
}
return
0
;
return
sb_getblk
(
root
->
fs_info
->
sb
,
blocknr
);
}
struct
b
trfs_buffer
*
alloc
_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
struct
b
uffer_head
*
find
_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
{
struct
btrfs_buffer
*
buf
;
int
ret
;
buf
=
malloc
(
sizeof
(
struct
btrfs_buffer
)
+
root
->
blocksize
);
if
(
!
buf
)
return
buf
;
allocated_blocks
++
;
buf
->
blocknr
=
blocknr
;
buf
->
count
=
2
;
INIT_LIST_HEAD
(
&
buf
->
dirty
);
free_some_buffers
(
root
);
radix_tree_preload
(
GFP_KERNEL
);
ret
=
radix_tree_insert
(
&
root
->
fs_info
->
cache_radix
,
blocknr
,
buf
);
radix_tree_preload_end
();
list_add_tail
(
&
buf
->
cache
,
&
root
->
fs_info
->
cache
);
root
->
fs_info
->
cache_size
++
;
if
(
ret
)
{
free
(
buf
);
return
NULL
;
}
return
buf
;
return
sb_getblk
(
root
->
fs_info
->
sb
,
blocknr
);
}
struct
b
trfs_buffer
*
fin
d_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
struct
b
uffer_head
*
rea
d_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
{
struct
btrfs_buffer
*
buf
;
buf
=
radix_tree_lookup
(
&
root
->
fs_info
->
cache_radix
,
blocknr
);
if
(
buf
)
{
buf
->
count
++
;
}
else
{
buf
=
alloc_tree_block
(
root
,
blocknr
);
if
(
!
buf
)
{
BUG
();
return
NULL
;
}
}
return
buf
;
}
struct
btrfs_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
)
{
loff_t
offset
=
blocknr
*
root
->
blocksize
;
struct
btrfs_buffer
*
buf
;
int
ret
;
struct
buffer_head
*
buf
=
sb_bread
(
root
->
fs_info
->
sb
,
blocknr
);
buf
=
radix_tree_lookup
(
&
root
->
fs_info
->
cache_radix
,
blocknr
);
if
(
buf
)
{
buf
->
count
++
;
}
else
{
buf
=
alloc_tree_block
(
root
,
blocknr
);
if
(
!
buf
)
return
NULL
;
ret
=
pread
(
root
->
fs_info
->
fp
,
&
buf
->
node
,
root
->
blocksize
,
offset
);
if
(
ret
!=
root
->
blocksize
)
{
free
(
buf
);
return
NULL
;
}
}
if
(
!
buf
)
return
buf
;
if
(
check_tree_block
(
root
,
buf
))
BUG
();
return
buf
;
}
int
dirty_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
struct
b
uffer_head
*
buf
)
{
if
(
!
list_empty
(
&
buf
->
dirty
))
return
0
;
list_add_tail
(
&
buf
->
dirty
,
&
root
->
fs_info
->
trans
);
buf
->
count
++
;
mark_buffer_dirty
(
buf
);
return
0
;
}
int
clean_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
struct
b
uffer_head
*
buf
)
{
if
(
!
list_empty
(
&
buf
->
dirty
))
{
list_del_init
(
&
buf
->
dirty
);
btrfs_block_release
(
root
,
buf
);
}
clear_buffer_dirty
(
buf
);
return
0
;
}
int
write_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
struct
b
uffer_head
*
buf
)
{
u64
blocknr
=
buf
->
blocknr
;
loff_t
offset
=
blocknr
*
root
->
blocksize
;
int
ret
;
if
(
buf
->
blocknr
!=
btrfs_header_blocknr
(
&
buf
->
node
.
header
))
BUG
();
ret
=
pwrite
(
root
->
fs_info
->
fp
,
&
buf
->
node
,
root
->
blocksize
,
offset
);
if
(
ret
!=
root
->
blocksize
)
return
ret
;
mark_buffer_dirty
(
buf
);
return
0
;
}
static
int
__commit_transaction
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
struct
btrfs_buffer
*
b
;
int
ret
=
0
;
int
wret
;
while
(
!
list_empty
(
&
root
->
fs_info
->
trans
))
{
b
=
list_entry
(
root
->
fs_info
->
trans
.
next
,
struct
btrfs_buffer
,
dirty
);
list_del_init
(
&
b
->
dirty
);
wret
=
write_tree_block
(
trans
,
root
,
b
);
if
(
wret
)
ret
=
wret
;
btrfs_block_release
(
root
,
b
);
}
return
ret
;
filemap_write_and_wait
(
root
->
fs_info
->
sb
->
s_bdev
->
bd_inode
->
i_mapping
);
return
0
;
}
static
int
commit_tree_roots
(
struct
btrfs_trans_handle
*
trans
,
...
...
@@ -172,17 +74,17 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans,
struct
btrfs_root
*
inode_root
=
fs_info
->
inode_root
;
btrfs_set_root_blocknr
(
&
inode_root
->
root_item
,
inode_root
->
node
->
blocknr
);
inode_root
->
node
->
b
_b
locknr
);
ret
=
btrfs_update_root
(
trans
,
tree_root
,
&
inode_root
->
root_key
,
&
inode_root
->
root_item
);
BUG_ON
(
ret
);
while
(
1
)
{
old_extent_block
=
btrfs_root_blocknr
(
&
extent_root
->
root_item
);
if
(
old_extent_block
==
extent_root
->
node
->
blocknr
)
if
(
old_extent_block
==
extent_root
->
node
->
b
_b
locknr
)
break
;
btrfs_set_root_blocknr
(
&
extent_root
->
root_item
,
extent_root
->
node
->
blocknr
);
extent_root
->
node
->
b
_b
locknr
);
ret
=
btrfs_update_root
(
trans
,
tree_root
,
&
extent_root
->
root_key
,
&
extent_root
->
root_item
);
...
...
@@ -195,7 +97,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
)
{
int
ret
=
0
;
struct
b
trfs_buffer
*
snap
=
root
->
commit_root
;
struct
b
uffer_head
*
snap
=
root
->
commit_root
;
struct
btrfs_key
snap_key
;
if
(
root
->
commit_root
==
root
->
node
)
...
...
@@ -204,7 +106,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
memcpy
(
&
snap_key
,
&
root
->
root_key
,
sizeof
(
snap_key
));
root
->
root_key
.
offset
++
;
btrfs_set_root_blocknr
(
&
root
->
root_item
,
root
->
node
->
blocknr
);
btrfs_set_root_blocknr
(
&
root
->
root_item
,
root
->
node
->
b
_b
locknr
);
ret
=
btrfs_insert_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
root
->
root_key
,
&
root
->
root_item
);
BUG_ON
(
ret
);
...
...
@@ -220,7 +122,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
btrfs_finish_extent_commit
(
trans
,
root
->
fs_info
->
tree_root
);
root
->
commit_root
=
root
->
node
;
root
->
node
->
count
++
;
get_bh
(
root
->
node
)
;
ret
=
btrfs_drop_snapshot
(
trans
,
root
,
snap
);
BUG_ON
(
ret
);
...
...
@@ -234,7 +136,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
static
int
__setup_root
(
struct
btrfs_super_block
*
super
,
struct
btrfs_root
*
root
,
struct
btrfs_fs_info
*
fs_info
,
u64
objectid
,
int
fp
)
u64
objectid
)
{
root
->
node
=
NULL
;
root
->
commit_root
=
NULL
;
...
...
@@ -250,11 +152,11 @@ static int find_and_setup_root(struct btrfs_super_block *super,
struct
btrfs_root
*
tree_root
,
struct
btrfs_fs_info
*
fs_info
,
u64
objectid
,
struct
btrfs_root
*
root
,
int
fp
)
struct
btrfs_root
*
root
)
{
int
ret
;
__setup_root
(
super
,
root
,
fs_info
,
objectid
,
fp
);
__setup_root
(
super
,
root
,
fs_info
,
objectid
);
ret
=
btrfs_find_last_root
(
tree_root
,
objectid
,
&
root
->
root_item
,
&
root
->
root_key
);
BUG_ON
(
ret
);
...
...
@@ -265,32 +167,26 @@ static int find_and_setup_root(struct btrfs_super_block *super,
return
0
;
}
struct
btrfs_root
*
open_ctree
(
char
*
filename
,
struct
btrfs_super_block
*
super
)
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
,
struct
buffer_head
*
sb_buffer
,
struct
btrfs_super_block
*
disk_super
)
{
int
fp
;
fp
=
open
(
filename
,
O_CREAT
|
O_RDWR
,
0600
);
if
(
fp
<
0
)
{
return
NULL
;
}
return
open_ctree_fd
(
fp
,
super
);
}
struct
btrfs_root
*
open_ctree_fd
(
int
fp
,
struct
btrfs_super_block
*
super
)
{
struct
btrfs_root
*
root
=
malloc
(
sizeof
(
struct
btrfs_root
));
struct
btrfs_root
*
extent_root
=
malloc
(
sizeof
(
struct
btrfs_root
));
struct
btrfs_root
*
tree_root
=
malloc
(
sizeof
(
struct
btrfs_root
));
struct
btrfs_root
*
inode_root
=
malloc
(
sizeof
(
struct
btrfs_root
));
struct
btrfs_fs_info
*
fs_info
=
malloc
(
sizeof
(
*
fs_info
));
struct
btrfs_root
*
root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
GFP_NOFS
);
struct
btrfs_root
*
extent_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
GFP_NOFS
);
struct
btrfs_root
*
tree_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
GFP_NOFS
);
struct
btrfs_root
*
inode_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
GFP_NOFS
);
struct
btrfs_fs_info
*
fs_info
=
kmalloc
(
sizeof
(
*
fs_info
),
GFP_NOFS
);
int
ret
;
INIT_RADIX_TREE
(
&
fs_info
->
cache_radix
,
GFP_KERNEL
);
/* FIXME: don't be stupid */
if
(
!
btrfs_super_root
(
disk_super
))
return
NULL
;
INIT_RADIX_TREE
(
&
fs_info
->
pinned_radix
,
GFP_KERNEL
);
INIT_LIST_HEAD
(
&
fs_info
->
trans
);
INIT_LIST_HEAD
(
&
fs_info
->
cache
);
fs_info
->
cache_size
=
0
;
fs_info
->
fp
=
fp
;
fs_info
->
running_transaction
=
NULL
;
fs_info
->
fs_root
=
root
;
fs_info
->
tree_root
=
tree_root
;
...
...
@@ -298,36 +194,31 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super)
fs_info
->
inode_root
=
inode_root
;
fs_info
->
last_inode_alloc
=
0
;
fs_info
->
last_inode_alloc_dirid
=
0
;
fs_info
->
disk_super
=
super
;
fs_info
->
disk_super
=
disk_super
;
fs_info
->
sb_buffer
=
sb_buffer
;
fs_info
->
sb
=
sb
;
memset
(
&
fs_info
->
current_insert
,
0
,
sizeof
(
fs_info
->
current_insert
));
memset
(
&
fs_info
->
last_insert
,
0
,
sizeof
(
fs_info
->
last_insert
));
ret
=
pread
(
fp
,
super
,
sizeof
(
struct
btrfs_super_block
),
BTRFS_SUPER_INFO_OFFSET
);
if
(
ret
==
0
||
btrfs_super_root
(
super
)
==
0
)
{
BUG
();
return
NULL
;
}
BUG_ON
(
ret
<
0
);
__setup_root
(
super
,
tree_root
,
fs_info
,
BTRFS_ROOT_TREE_OBJECTID
,
fp
);
tree_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_root
(
super
));
__setup_root
(
disk_super
,
tree_root
,
fs_info
,
BTRFS_ROOT_TREE_OBJECTID
);
tree_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_root
(
disk_super
));
BUG_ON
(
!
tree_root
->
node
);
ret
=
find_and_setup_root
(
super
,
tree_root
,
fs_info
,
BTRFS_EXTENT_TREE_OBJECTID
,
extent_root
,
fp
);
ret
=
find_and_setup_root
(
disk_
super
,
tree_root
,
fs_info
,
BTRFS_EXTENT_TREE_OBJECTID
,
extent_root
);
BUG_ON
(
ret
);
ret
=
find_and_setup_root
(
super
,
tree_root
,
fs_info
,
BTRFS_INODE_MAP_OBJECTID
,
inode_root
,
fp
);
ret
=
find_and_setup_root
(
disk_
super
,
tree_root
,
fs_info
,
BTRFS_INODE_MAP_OBJECTID
,
inode_root
);
BUG_ON
(
ret
);
ret
=
find_and_setup_root
(
super
,
tree_root
,
fs_info
,
BTRFS_FS_TREE_OBJECTID
,
root
,
fp
);
ret
=
find_and_setup_root
(
disk_
super
,
tree_root
,
fs_info
,
BTRFS_FS_TREE_OBJECTID
,
root
);
BUG_ON
(
ret
);
root
->
commit_root
=
root
->
node
;
root
->
node
->
count
++
;
get_bh
(
root
->
node
)
;
root
->
ref_cows
=
1
;
root
->
fs_info
->
generation
=
root
->
root_key
.
offset
+
1
;
return
root
;
...
...
@@ -336,8 +227,11 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super)
int
write_ctree_super
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
)
{
return
0
;
#if 0
int ret;
btrfs_set_super_root
(
s
,
root
->
fs_info
->
tree_root
->
node
->
blocknr
);
btrfs_set_super_root(s, root->fs_info->tree_root->node->b_blocknr);
ret = pwrite(root->fs_info->fp, s, sizeof(*s),
BTRFS_SUPER_INFO_OFFSET);
if (ret != sizeof(*s)) {
...
...
@@ -345,35 +239,38 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
return ret;
}
return 0;
#endif
}
static
int
drop_cache
(
struct
btrfs_root
*
root
)
{
return
0
;
#if 0
while(!list_empty(&root->fs_info->cache)) {
struct
b
trfs_buffer
*
b
=
list_entry
(
root
->
fs_info
->
cache
.
next
,
struct
b
trfs_buffer
,
struct b
uffer_head
*b = list_entry(root->fs_info->cache.next,
struct b
uffer_head
,
cache);
list_del_init(&b->cache);
btrfs_block_release(root, b);
}
return 0;
#endif
}
int
close_ctree
(
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
)
int
close_ctree
(
struct
btrfs_root
*
root
)
{
int
ret
;
struct
btrfs_trans_handle
*
trans
;
trans
=
root
->
fs_info
->
running_transaction
;
btrfs_commit_transaction
(
trans
,
root
,
s
);
btrfs_commit_transaction
(
trans
,
root
,
root
->
fs_info
->
disk_super
);
ret
=
commit_tree_roots
(
trans
,
root
->
fs_info
);
BUG_ON
(
ret
);
ret
=
__commit_transaction
(
trans
,
root
);
BUG_ON
(
ret
);
write_ctree_super
(
trans
,
root
,
s
);
write_ctree_super
(
trans
,
root
,
root
->
fs_info
->
disk_super
);
drop_cache
(
root
);
BUG_ON
(
!
list_empty
(
&
root
->
fs_info
->
trans
));
close
(
root
->
fs_info
->
fp
);
if
(
root
->
node
)
btrfs_block_release
(
root
,
root
->
node
);
if
(
root
->
fs_info
->
extent_root
->
node
)
...
...
@@ -386,29 +283,17 @@ int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s)
btrfs_block_release
(
root
->
fs_info
->
tree_root
,
root
->
fs_info
->
tree_root
->
node
);
btrfs_block_release
(
root
,
root
->
commit_root
);
free
(
root
);
printf
(
"on close %d blocks are allocated
\n
"
,
allocated_blocks
);
btrfs_block_release
(
root
,
root
->
fs_info
->
sb_buffer
);
kfree
(
root
->
fs_info
->
extent_root
);
kfree
(
root
->
fs_info
->
inode_root
);
kfree
(
root
->
fs_info
->
tree_root
);
kfree
(
root
->
fs_info
);
kfree
(
root
);
return
0
;
}
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
b
uffer_head
*
buf
)
{
buf
->
count
--
;
if
(
buf
->
count
<
0
)
BUG
();
if
(
buf
->
count
==
0
)
{
BUG_ON
(
!
list_empty
(
&
buf
->
cache
));
BUG_ON
(
!
list_empty
(
&
buf
->
dirty
));
if
(
!
radix_tree_lookup
(
&
root
->
fs_info
->
cache_radix
,
buf
->
blocknr
))
BUG
();
radix_tree_delete
(
&
root
->
fs_info
->
cache_radix
,
buf
->
blocknr
);
memset
(
buf
,
0
,
sizeof
(
*
buf
));
free
(
buf
);
BUG_ON
(
allocated_blocks
==
0
);
allocated_blocks
--
;
BUG_ON
(
root
->
fs_info
->
cache_size
==
0
);
root
->
fs_info
->
cache_size
--
;
}
brelse
(
buf
);
}
fs/btrfs/disk-io.h
View file @
e20d96d6
#ifndef __DISKIO__
#define __DISKIO__
#include "list.h"
struct
btrfs_buffer
{
u64
blocknr
;
int
count
;
struct
list_head
dirty
;
struct
list_head
cache
;
union
{
struct
btrfs_node
node
;
struct
btrfs_leaf
leaf
;
};
};
#include <linux/buffer_head.h>
struct
btrfs_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
struct
btrfs_buffer
*
find_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
static
inline
struct
btrfs_node
*
btrfs_buffer_node
(
struct
buffer_head
*
bh
)
{
return
(
struct
btrfs_node
*
)
bh
->
b_data
;
}
static
inline
struct
btrfs_leaf
*
btrfs_buffer_leaf
(
struct
buffer_head
*
bh
)
{
return
(
struct
btrfs_leaf
*
)
bh
->
b_data
;
}
static
inline
struct
btrfs_header
*
btrfs_buffer_header
(
struct
buffer_head
*
bh
)
{
return
&
((
struct
btrfs_node
*
)
bh
->
b_data
)
->
header
;
}
struct
buffer_head
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
struct
buffer_head
*
find_tree_block
(
struct
btrfs_root
*
root
,
u64
blocknr
);
int
write_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
);
struct
b
uffer_head
*
buf
);
int
dirty_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
);
struct
b
uffer_head
*
buf
);
int
clean_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
);
struct
btrfs_root
*
root
,
struct
b
uffer_head
*
buf
);
int
btrfs_commit_transaction
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
);
struct
btrfs_root
*
open_ctree
(
char
*
filename
,
struct
btrfs_super_block
*
s
);
struct
btrfs_root
*
open_ctree_fd
(
int
fp
,
struct
btrfs_super_block
*
super
);
int
close_ctree
(
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
);
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
btrfs_buffer
*
buf
);
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
,
struct
buffer_head
*
sb_buffer
,
struct
btrfs_super_block
*
disk_super
);
int
close_ctree
(
struct
btrfs_root
*
root
);
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
buf
);
int
write_ctree_super
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_super_block
*
s
);
int
mkfs
(
int
fd
,
u64
num_blocks
,
u32
blocksize
);
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
#endif
fs/btrfs/extent-tree.c
View file @
e20d96d6
...
...
@@ -10,9 +10,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
search_end
,
struct
btrfs_key
*
ins
);
static
int
finish_current_insert
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
);
static
int
run_pending
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
);
static
int
del_pending_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
);
/*
* pending extents are blocks that we're trying to allocate in the extent
* map while trying to grow the map because of other allocations. To avoid
...
...
@@ -21,6 +20,7 @@ static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root
* manner for deletes.
*/
#define CTREE_EXTENT_PENDING_DEL 0
#define CTREE_EXTENT_PINNED 1
static
int
inc_block_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
)
...
...
@@ -45,15 +45,14 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
ret
!=
0
)
BUG
();
BUG_ON
(
ret
!=
0
);
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
item
=
btrfs_item_ptr
(
l
,
path
.
slots
[
0
],
struct
btrfs_extent_item
);
refs
=
btrfs_extent_refs
(
item
);
btrfs_set_extent_refs
(
item
,
refs
+
1
);
BUG_ON
(
list_empty
(
&
path
.
nodes
[
0
]
->
dirty
));
btrfs_release_path
(
root
->
fs_info
->
extent_root
,
&
path
);
finish_current_insert
(
trans
,
root
->
fs_info
->
extent_root
);
run_pending
(
trans
,
root
->
fs_info
->
extent_root
);
del_pending_extents
(
trans
,
root
->
fs_info
->
extent_root
);
return
0
;
}
...
...
@@ -74,7 +73,7 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
0
,
0
);
if
(
ret
!=
0
)
BUG
();
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
item
=
btrfs_item_ptr
(
l
,
path
.
slots
[
0
],
struct
btrfs_extent_item
);
*
refs
=
btrfs_extent_refs
(
item
);
btrfs_release_path
(
root
->
fs_info
->
extent_root
,
&
path
);
...
...
@@ -82,18 +81,20 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
}
int
btrfs_inc_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
buf
)
struct
b
uffer_head
*
buf
)
{
u64
blocknr
;
struct
btrfs_node
*
buf_node
;
int
i
;
if
(
!
root
->
ref_cows
)
return
0
;
if
(
btrfs_is_leaf
(
&
buf
->
node
))
buf_node
=
btrfs_buffer_node
(
buf
);
if
(
btrfs_is_leaf
(
buf_node
))
return
0
;
for
(
i
=
0
;
i
<
btrfs_header_nritems
(
&
buf
->
node
.
header
);
i
++
)
{
blocknr
=
btrfs_node_blockptr
(
&
buf
->
node
,
i
);
for
(
i
=
0
;
i
<
btrfs_header_nritems
(
&
buf
_node
->
header
);
i
++
)
{
blocknr
=
btrfs_node_blockptr
(
buf_
node
,
i
);
inc_block_ref
(
trans
,
root
,
blocknr
);
}
return
0
;
...
...
@@ -108,9 +109,10 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
int
i
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup
(
&
root
->
fs_info
->
pinned_radix
,
ret
=
radix_tree_gang_lookup
_tag
(
&
root
->
fs_info
->
pinned_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
));
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PINNED
);
if
(
!
ret
)
break
;
if
(
!
first
)
...
...
@@ -137,7 +139,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
btrfs_set_extent_refs
(
&
extent_item
,
1
);
btrfs_set_extent_owner
(
&
extent_item
,
btrfs_header_parentid
(
&
extent_root
->
node
->
node
.
header
));
btrfs_header_parentid
(
btrfs_buffer_header
(
extent_root
->
node
)
));
ins
.
offset
=
1
;
ins
.
flags
=
0
;
btrfs_set_key_type
(
&
ins
,
BTRFS_EXTENT_ITEM_KEY
);
...
...
@@ -156,11 +158,24 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
return
0
;
}
static
int
pin_down_block
(
struct
btrfs_root
*
root
,
u64
blocknr
,
int
tag
)
{
int
err
;
err
=
radix_tree_insert
(
&
root
->
fs_info
->
pinned_radix
,
blocknr
,
(
void
*
)
blocknr
);
BUG_ON
(
err
);
if
(
err
)
return
err
;
radix_tree_tag_set
(
&
root
->
fs_info
->
pinned_radix
,
blocknr
,
tag
);
return
0
;
}
/*
* remove an extent from the root, returns 0 on success
*/
static
int
__free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
int
pin
)
*
root
,
u64
blocknr
,
u64
num_blocks
)
{
struct
btrfs_path
path
;
struct
btrfs_key
key
;
...
...
@@ -171,7 +186,6 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
struct
btrfs_key
ins
;
u32
refs
;
BUG_ON
(
pin
&&
num_blocks
!=
1
);
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_EXTENT_ITEM_KEY
);
...
...
@@ -186,26 +200,18 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
printk
(
"failed to find %Lu
\n
"
,
key
.
objectid
);
BUG
();
}
ei
=
btrfs_item_ptr
(
&
path
.
nodes
[
0
]
->
leaf
,
path
.
slots
[
0
],
ei
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
,
path
.
slots
[
0
],
struct
btrfs_extent_item
);
BUG_ON
(
ei
->
refs
==
0
);
refs
=
btrfs_extent_refs
(
ei
)
-
1
;
btrfs_set_extent_refs
(
ei
,
refs
);
if
(
refs
==
0
)
{
u64
super_blocks_used
;
if
(
pin
)
{
int
err
;
radix_tree_preload
(
GFP_KERNEL
);
err
=
radix_tree_insert
(
&
info
->
pinned_radix
,
blocknr
,
(
void
*
)
blocknr
);
BUG_ON
(
err
);
radix_tree_preload_end
();
}
super_blocks_used
=
btrfs_super_blocks_used
(
info
->
disk_super
);
btrfs_set_super_blocks_used
(
info
->
disk_super
,
super_blocks_used
-
num_blocks
);
ret
=
btrfs_del_item
(
trans
,
extent_root
,
&
path
);
if
(
!
pin
&&
extent_root
->
fs_info
->
last_insert
.
objectid
>
if
(
extent_root
->
fs_info
->
last_insert
.
objectid
>
blocknr
)
extent_root
->
fs_info
->
last_insert
.
objectid
=
blocknr
;
if
(
ret
)
...
...
@@ -224,39 +230,32 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
btrfs_root
*
extent_root
)
{
int
ret
;
struct
btrfs_buffer
*
gang
[
4
];
int
wret
;
int
err
=
0
;
unsigned
long
gang
[
4
];
int
i
;
struct
radix_tree_root
*
radix
=
&
extent_root
->
fs_info
->
pinned_radix
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
extent_root
->
fs_info
->
cache
_radix
,
&
extent_root
->
fs_info
->
pinned
_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PENDING_DEL
);
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
ret
=
__free_extent
(
trans
,
extent_root
,
gang
[
i
]
->
blocknr
,
1
,
1
);
radix_tree_tag_clear
(
&
extent_root
->
fs_info
->
cache_radix
,
gang
[
i
]
->
blocknr
,
radix_tree_tag_set
(
radix
,
gang
[
i
],
CTREE_EXTENT_PINNED
);
radix_tree_tag_clear
(
radix
,
gang
[
i
],
CTREE_EXTENT_PENDING_DEL
);
btrfs_block_release
(
extent_root
,
gang
[
i
]);
wret
=
__free_extent
(
trans
,
extent_root
,
gang
[
i
],
1
);
if
(
wret
)
err
=
wret
;
}
}
return
0
;
return
err
;
}
static
int
run_pending
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
)
{
while
(
radix_tree_tagged
(
&
extent_root
->
fs_info
->
cache_radix
,
CTREE_EXTENT_PENDING_DEL
))
del_pending_extents
(
trans
,
extent_root
);
return
0
;
}
/*
* remove an extent from the root, returns 0 on success
*/
...
...
@@ -264,18 +263,21 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
int
pin
)
{
struct
btrfs_root
*
extent_root
=
root
->
fs_info
->
extent_root
;
struct
b
trfs_buffer
*
t
;
struct
b
uffer_head
*
t
;
int
pending_ret
;
int
ret
;
if
(
root
==
extent_root
)
{
t
=
find_tree_block
(
root
,
blocknr
);
radix_tree_tag_set
(
&
root
->
fs_info
->
cache_radix
,
blocknr
,
CTREE_EXTENT_PENDING_DEL
);
pin_down_block
(
root
,
blocknr
,
CTREE_EXTENT_PENDING_DEL
);
return
0
;
}
ret
=
__free_extent
(
trans
,
root
,
blocknr
,
num_blocks
,
pin
);
pending_ret
=
run_pending
(
trans
,
root
->
fs_info
->
extent_root
);
if
(
pin
)
{
ret
=
pin_down_block
(
root
,
blocknr
,
CTREE_EXTENT_PINNED
);
BUG_ON
(
ret
);
}
ret
=
__free_extent
(
trans
,
root
,
blocknr
,
num_blocks
);
pending_ret
=
del_pending_extents
(
trans
,
root
->
fs_info
->
extent_root
);
return
ret
?
ret
:
pending_ret
;
}
...
...
@@ -296,14 +298,16 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
int
ret
;
u64
hole_size
=
0
;
int
slot
=
0
;
u64
last_block
;
u64
last_block
=
0
;
u64
test_block
;
int
start_found
;
struct
btrfs_leaf
*
l
;
struct
btrfs_root
*
root
=
orig_root
->
fs_info
->
extent_root
;
int
total_needed
=
num_blocks
;
int
level
;
total_needed
+=
(
btrfs_header_level
(
&
root
->
node
->
node
.
header
)
+
1
)
*
3
;
level
=
btrfs_header_level
(
btrfs_buffer_header
(
root
->
node
));
total_needed
+=
(
level
+
1
)
*
3
;
if
(
root
->
fs_info
->
last_insert
.
objectid
>
search_start
)
search_start
=
root
->
fs_info
->
last_insert
.
objectid
;
...
...
@@ -323,7 +327,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
path
.
slots
[
0
]
--
;
while
(
1
)
{
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
slot
=
path
.
slots
[
0
];
if
(
slot
>=
btrfs_header_nritems
(
&
l
->
header
))
{
ret
=
btrfs_next_leaf
(
root
,
&
path
);
...
...
@@ -429,7 +433,7 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
sizeof
(
extent_item
));
finish_current_insert
(
trans
,
extent_root
);
pending_ret
=
run_pending
(
trans
,
extent_root
);
pending_ret
=
del_pending_extents
(
trans
,
extent_root
);
if
(
ret
)
return
ret
;
if
(
pending_ret
)
...
...
@@ -441,16 +445,15 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
* helper function to allocate a block for a given tree
* returns the tree buffer or NULL.
*/
struct
b
trfs_buffer
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
b
uffer_head
*
btrfs_alloc_free_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
struct
btrfs_key
ins
;
int
ret
;
struct
b
trfs_buffer
*
buf
;
struct
b
uffer_head
*
buf
;
ret
=
alloc_extent
(
trans
,
root
,
1
,
0
,
(
unsigned
long
)
-
1
,
btrfs_header_parentid
(
&
root
->
node
->
node
.
header
),
&
ins
);
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)),
&
ins
);
if
(
ret
)
{
BUG
();
return
NULL
;
...
...
@@ -467,13 +470,13 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
static
int
walk_down_tree
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
*
level
)
{
struct
b
trfs_buffer
*
next
;
struct
b
trfs_buffer
*
cur
;
struct
b
uffer_head
*
next
;
struct
b
uffer_head
*
cur
;
u64
blocknr
;
int
ret
;
u32
refs
;
ret
=
lookup_block_ref
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
blocknr
,
ret
=
lookup_block_ref
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
b
_b
locknr
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
>
1
)
...
...
@@ -484,9 +487,10 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
while
(
*
level
>
0
)
{
cur
=
path
->
nodes
[
*
level
];
if
(
path
->
slots
[
*
level
]
>=
btrfs_header_nritems
(
&
cur
->
node
.
header
))
btrfs_header_nritems
(
btrfs_buffer_header
(
cur
)
))
break
;
blocknr
=
btrfs_node_blockptr
(
&
cur
->
node
,
path
->
slots
[
*
level
]);
blocknr
=
btrfs_node_blockptr
(
btrfs_buffer_node
(
cur
),
path
->
slots
[
*
level
]);
ret
=
lookup_block_ref
(
trans
,
root
,
blocknr
,
&
refs
);
if
(
refs
!=
1
||
*
level
==
1
)
{
path
->
slots
[
*
level
]
++
;
...
...
@@ -499,12 +503,12 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
path
->
nodes
[
*
level
-
1
])
btrfs_block_release
(
root
,
path
->
nodes
[
*
level
-
1
]);
path
->
nodes
[
*
level
-
1
]
=
next
;
*
level
=
btrfs_header_level
(
&
next
->
node
.
header
);
*
level
=
btrfs_header_level
(
btrfs_buffer_header
(
next
)
);
path
->
slots
[
*
level
]
=
0
;
}
out:
ret
=
btrfs_free_extent
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
b
locknr
,
1
,
1
);
ret
=
btrfs_free_extent
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
b
_blocknr
,
1
,
1
);
btrfs_block_release
(
root
,
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
*
level
+=
1
;
...
...
@@ -525,14 +529,14 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
int
ret
;
for
(
i
=
*
level
;
i
<
BTRFS_MAX_LEVEL
-
1
&&
path
->
nodes
[
i
];
i
++
)
{
slot
=
path
->
slots
[
i
];
if
(
slot
<
btrfs_
header_nritems
(
&
path
->
nodes
[
i
]
->
node
.
header
)
-
1
)
{
if
(
slot
<
btrfs_header_nritems
(
btrfs_
buffer_header
(
path
->
nodes
[
i
]))
-
1
)
{
path
->
slots
[
i
]
++
;
*
level
=
i
;
return
0
;
}
else
{
ret
=
btrfs_free_extent
(
trans
,
root
,
path
->
nodes
[
*
level
]
->
blocknr
,
path
->
nodes
[
*
level
]
->
b
_b
locknr
,
1
,
1
);
btrfs_block_release
(
root
,
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
...
...
@@ -549,7 +553,7 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
* decremented.
*/
int
btrfs_drop_snapshot
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
snap
)
*
root
,
struct
b
uffer_head
*
snap
)
{
int
ret
=
0
;
int
wret
;
...
...
@@ -560,7 +564,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_init_path
(
&
path
);
level
=
btrfs_header_level
(
&
snap
->
node
.
header
);
level
=
btrfs_header_level
(
btrfs_buffer_header
(
snap
)
);
orig_level
=
level
;
path
.
nodes
[
level
]
=
snap
;
path
.
slots
[
level
]
=
0
;
...
...
fs/btrfs/hash.c
View file @
e20d96d6
...
...
@@ -10,6 +10,7 @@
* License.
*/
#include <linux/types.h>
#define DELTA 0x9E3779B9
static
void
TEA_transform
(
__u32
buf
[
2
],
__u32
const
in
[])
...
...
@@ -63,6 +64,14 @@ int btrfs_name_hash(const char *name, int len, u64 *hash_result)
const
char
*
p
;
__u32
in
[
8
],
buf
[
2
];
if
(
len
==
1
&&
*
name
==
'.'
)
{
*
hash_result
=
1
;
return
0
;
}
else
if
(
len
==
2
&&
name
[
0
]
==
'.'
&&
name
[
1
]
==
'.'
)
{
*
hash_result
=
2
;
return
0
;
}
/* Initialize the default seed for the hash checksum functions */
buf
[
0
]
=
0x67452301
;
buf
[
1
]
=
0xefcdab89
;
...
...
fs/btrfs/inode-map.c
View file @
e20d96d6
...
...
@@ -15,7 +15,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
int
ret
;
u64
hole_size
=
0
;
int
slot
=
0
;
u64
last_ino
;
u64
last_ino
=
0
;
int
start_found
;
struct
btrfs_leaf
*
l
;
struct
btrfs_root
*
root
=
fs_root
->
fs_info
->
inode_root
;
...
...
@@ -40,7 +40,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
path
.
slots
[
0
]
--
;
while
(
1
)
{
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
slot
=
path
.
slots
[
0
];
if
(
slot
>=
btrfs_header_nritems
(
&
l
->
header
))
{
ret
=
btrfs_next_leaf
(
root
,
&
path
);
...
...
@@ -105,8 +105,8 @@ int btrfs_insert_inode_map(struct btrfs_trans_handle *trans,
if
(
ret
)
goto
out
;
inode_item
=
btrfs_item_ptr
(
&
path
.
nodes
[
0
]
->
leaf
,
path
.
slots
[
0
]
,
struct
btrfs_inode_map_item
);
inode_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
,
path
.
slots
[
0
],
struct
btrfs_inode_map_item
);
btrfs_cpu_key_to_disk
(
&
inode_item
->
key
,
location
);
out:
btrfs_release_path
(
inode_root
,
&
path
);
...
...
fs/btrfs/print-tree.c
View file @
e20d96d6
...
...
@@ -17,7 +17,6 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
printk
(
"leaf %Lu total ptrs %d free space %d
\n
"
,
btrfs_header_blocknr
(
&
l
->
header
),
nr
,
btrfs_leaf_free_space
(
root
,
l
));
fflush
(
stdout
);
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
item
=
l
->
items
+
i
;
type
=
btrfs_disk_key_type
(
&
item
->
key
);
...
...
@@ -67,10 +66,10 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
btrfs_leaf_data
(
l
)
+
btrfs_item_offset
(
item
));
break
;
};
fflush
(
stdout
);
}
}
void
btrfs_print_tree
(
struct
btrfs_root
*
root
,
struct
btrfs_buffer
*
t
)
void
btrfs_print_tree
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
t
)
{
int
i
;
u32
nr
;
...
...
@@ -78,16 +77,16 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t)
if
(
!
t
)
return
;
c
=
&
t
->
node
;
c
=
btrfs_buffer_node
(
t
)
;
nr
=
btrfs_header_nritems
(
&
c
->
header
);
if
(
btrfs_is_leaf
(
c
))
{
btrfs_print_leaf
(
root
,
(
struct
btrfs_leaf
*
)
c
);
return
;
}
printk
(
"node %Lu level %d total ptrs %d free spc %u
\n
"
,
t
->
blocknr
,
btrfs_header_level
(
&
c
->
header
),
nr
,
(
u32
)
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
-
nr
);
fflush
(
stdout
);
printk
(
"node %Lu level %d total ptrs %d free spc %u
\n
"
,
btrfs_header_blocknr
(
&
c
->
header
)
,
btrfs_header_level
(
&
c
->
header
),
nr
,
(
u32
)
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
-
nr
);
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
printk
(
"
\t
key %d (%Lu %u %Lu) block %Lu
\n
"
,
i
,
...
...
@@ -95,12 +94,11 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t)
c
->
ptrs
[
i
].
key
.
flags
,
c
->
ptrs
[
i
].
key
.
offset
,
btrfs_node_blockptr
(
c
,
i
));
fflush
(
stdout
);
}
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
struct
b
trfs_buffer
*
next_buf
=
read_tree_block
(
root
,
struct
b
uffer_head
*
next_buf
=
read_tree_block
(
root
,
btrfs_node_blockptr
(
c
,
i
));
struct
btrfs_node
*
next
=
&
next_buf
->
node
;
struct
btrfs_node
*
next
=
btrfs_buffer_node
(
next_buf
)
;
if
(
btrfs_is_leaf
(
next
)
&&
btrfs_header_level
(
&
c
->
header
)
!=
1
)
BUG
();
...
...
fs/btrfs/print-tree.h
View file @
e20d96d6
#ifndef __PRINT_TREE_
#define __PRINT_TREE_
void
btrfs_print_leaf
(
struct
btrfs_root
*
root
,
struct
btrfs_leaf
*
l
);
void
btrfs_print_tree
(
struct
btrfs_root
*
root
,
struct
b
trfs_buffer
*
t
);
void
btrfs_print_tree
(
struct
btrfs_root
*
root
,
struct
b
uffer_head
*
t
);
#endif
fs/btrfs/root-tree.c
View file @
e20d96d6
...
...
@@ -21,7 +21,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
if
(
ret
<
0
)
goto
out
;
BUG_ON
(
ret
==
0
);
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
BUG_ON
(
path
.
slots
[
0
]
==
0
);
slot
=
path
.
slots
[
0
]
-
1
;
if
(
btrfs_disk_key_objectid
(
&
l
->
items
[
slot
].
key
)
!=
objectid
)
{
...
...
@@ -51,7 +51,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
ret
<
0
)
goto
out
;
BUG_ON
(
ret
!=
0
);
l
=
&
path
.
nodes
[
0
]
->
leaf
;
l
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
])
;
slot
=
path
.
slots
[
0
];
memcpy
(
btrfs_item_ptr
(
l
,
slot
,
struct
btrfs_root_item
),
item
,
sizeof
(
*
item
));
...
...
fs/btrfs/super.c
View file @
e20d96d6
#include <linux/module.h>
#include <linux/buffer_head.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
...
...
@@ -8,13 +9,18 @@
#include <linux/smp_lock.h>
#include <linux/backing-dev.h>
#include "ctree.h"
#include "disk-io.h"
#define BTRFS_SUPER_MAGIC 0x9123682E
static
struct
inode_operations
btrfs_dir_inode_operations
;
static
struct
super_operations
btrfs_super_ops
;
static
struct
file_operations
btrfs_dir_file_operations
;
#if 0
/* some random number */
static struct super_operations ramfs_ops;
static struct inode_operations ramfs_dir_inode_operations;
static struct backing_dev_info ramfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
...
...
@@ -129,46 +135,243 @@ static struct inode_operations ramfs_dir_inode_operations = {
};
#endif
st
ruct
inode
*
btrfs_get_inode
(
struct
super_block
*
sb
,
int
mode
,
dev_t
dev
)
st
atic
void
btrfs_read_locked_inode
(
struct
inode
*
inode
)
{
struct
inode
*
inode
=
new_inode
(
sb
);
struct
btrfs_path
path
;
struct
btrfs_inode_item
*
inode_item
;
struct
btrfs_root
*
root
=
btrfs_sb
(
inode
->
i_sb
);
int
ret
;
printk
(
"read locked inode %lu
\n
"
,
inode
->
i_ino
);
btrfs_init_path
(
&
path
);
ret
=
btrfs_lookup_inode
(
NULL
,
root
,
&
path
,
inode
->
i_ino
,
0
);
if
(
ret
)
{
make_bad_inode
(
inode
);
return
;
}
inode_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
]),
path
.
slots
[
0
],
struct
btrfs_inode_item
);
if
(
inode
)
{
inode
->
i_mode
=
mode
;
inode
->
i_uid
=
current
->
fsuid
;
inode
->
i_gid
=
current
->
fsgid
;
inode
->
i_blocks
=
0
;
inode
->
i_atime
=
inode
->
i_mtime
=
inode
->
i_ctime
=
CURRENT_TIME
;
printk
(
"found locked inode %lu
\n
"
,
inode
->
i_ino
);
inode
->
i_mode
=
btrfs_inode_mode
(
inode_item
);
inode
->
i_nlink
=
btrfs_inode_nlink
(
inode_item
);
inode
->
i_uid
=
btrfs_inode_uid
(
inode_item
);
inode
->
i_gid
=
btrfs_inode_gid
(
inode_item
);
inode
->
i_size
=
btrfs_inode_size
(
inode_item
);
inode
->
i_atime
.
tv_sec
=
btrfs_timespec_sec
(
&
inode_item
->
atime
);
inode
->
i_atime
.
tv_nsec
=
btrfs_timespec_nsec
(
&
inode_item
->
atime
);
inode
->
i_mtime
.
tv_sec
=
btrfs_timespec_sec
(
&
inode_item
->
mtime
);
inode
->
i_mtime
.
tv_nsec
=
btrfs_timespec_nsec
(
&
inode_item
->
mtime
);
inode
->
i_ctime
.
tv_sec
=
btrfs_timespec_sec
(
&
inode_item
->
ctime
);
inode
->
i_ctime
.
tv_nsec
=
btrfs_timespec_nsec
(
&
inode_item
->
ctime
);
inode
->
i_blocks
=
btrfs_inode_nblocks
(
inode_item
);
inode
->
i_generation
=
btrfs_inode_generation
(
inode_item
);
printk
(
"about to release
\n
"
);
btrfs_release_path
(
root
,
&
path
);
switch
(
inode
->
i_mode
&
S_IFMT
)
{
#if 0
default:
init_special_inode(inode, inode->i_mode,
btrfs_inode_rdev(inode_item));
break;
#endif
case
S_IFREG
:
printk
(
"inode %lu now a file
\n
"
,
inode
->
i_ino
);
break
;
case
S_IFDIR
:
printk
(
"inode %lu now a directory
\n
"
,
inode
->
i_ino
);
inode
->
i_op
=
&
btrfs_dir_inode_operations
;
inode
->
i_fop
=
&
btrfs_dir_file_operations
;
break
;
case
S_IFLNK
:
printk
(
"inode %lu now a link
\n
"
,
inode
->
i_ino
);
// inode->i_op = &page_symlink_inode_operations;
break
;
}
return
inode
;
printk
(
"returning!
\n
"
);
return
;
}
static
struct
super_operations
btrfs_ops
=
{
.
statfs
=
simple_statfs
,
.
drop_inode
=
generic_delete_inode
,
};
static
int
btrfs_inode_by_name
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
ino_t
*
ino
)
{
const
char
*
name
=
dentry
->
d_name
.
name
;
int
namelen
=
dentry
->
d_name
.
len
;
struct
btrfs_dir_item
*
di
;
struct
btrfs_path
path
;
struct
btrfs_root
*
root
=
btrfs_sb
(
dir
->
i_sb
);
int
ret
;
btrfs_init_path
(
&
path
);
ret
=
btrfs_lookup_dir_item
(
NULL
,
root
,
&
path
,
dir
->
i_ino
,
name
,
namelen
,
0
);
if
(
ret
)
{
*
ino
=
0
;
goto
out
;
}
di
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
.
nodes
[
0
]),
path
.
slots
[
0
],
struct
btrfs_dir_item
);
*
ino
=
btrfs_dir_objectid
(
di
);
out:
btrfs_release_path
(
root
,
&
path
);
return
ret
;
}
static
struct
dentry
*
btrfs_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
struct
inode
*
inode
;
ino_t
ino
;
int
ret
;
if
(
dentry
->
d_name
.
len
>
BTRFS_NAME_LEN
)
return
ERR_PTR
(
-
ENAMETOOLONG
);
ret
=
btrfs_inode_by_name
(
dir
,
dentry
,
&
ino
);
if
(
ret
<
0
)
return
ERR_PTR
(
ret
);
inode
=
NULL
;
if
(
ino
)
{
printk
(
"lookup on %.*s returns %lu
\n
"
,
dentry
->
d_name
.
len
,
dentry
->
d_name
.
name
,
ino
);
inode
=
iget
(
dir
->
i_sb
,
ino
);
if
(
!
inode
)
return
ERR_PTR
(
-
EACCES
);
}
return
d_splice_alias
(
inode
,
dentry
);
}
static
int
btrfs_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
{
struct
inode
*
inode
=
filp
->
f_path
.
dentry
->
d_inode
;
struct
btrfs_root
*
root
=
btrfs_sb
(
inode
->
i_sb
);
struct
btrfs_item
*
item
;
struct
btrfs_dir_item
*
di
;
struct
btrfs_key
key
;
struct
btrfs_path
path
;
int
ret
;
u32
nritems
;
struct
btrfs_leaf
*
leaf
;
int
slot
;
int
advance
;
unsigned
char
d_type
=
DT_UNKNOWN
;
int
over
;
key
.
objectid
=
inode
->
i_ino
;
printk
(
"readdir on dir %Lu pos %Lu
\n
"
,
key
.
objectid
,
filp
->
f_pos
);
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_DIR_ITEM_KEY
);
key
.
offset
=
filp
->
f_pos
;
btrfs_init_path
(
&
path
);
ret
=
btrfs_search_slot
(
NULL
,
root
,
&
key
,
&
path
,
0
,
0
);
if
(
ret
<
0
)
{
goto
err
;
}
printk
(
"first ret %d
\n
"
,
ret
);
advance
=
filp
->
f_pos
>
0
&&
ret
!=
0
;
while
(
1
)
{
leaf
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
]);
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
slot
=
path
.
slots
[
0
];
printk
(
"leaf %Lu nritems %lu slot %d
\n
"
,
path
.
nodes
[
0
]
->
b_blocknr
,
nritems
,
slot
);
if
(
advance
)
{
printk
(
"advancing!
\n
"
);
if
(
slot
==
nritems
-
1
)
{
ret
=
btrfs_next_leaf
(
root
,
&
path
);
if
(
ret
)
break
;
leaf
=
btrfs_buffer_leaf
(
path
.
nodes
[
0
]);
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
slot
=
path
.
slots
[
0
];
printk
(
"2leaf %Lu nritems %lu slot %d
\n
"
,
path
.
nodes
[
0
]
->
b_blocknr
,
nritems
,
slot
);
}
else
{
slot
++
;
path
.
slots
[
0
]
++
;
}
}
advance
=
1
;
item
=
leaf
->
items
+
slot
;
printk
(
"item key %Lu %u %Lu
\n
"
,
btrfs_disk_key_objectid
(
&
item
->
key
),
btrfs_disk_key_flags
(
&
item
->
key
),
btrfs_disk_key_offset
(
&
item
->
key
));
if
(
btrfs_disk_key_objectid
(
&
item
->
key
)
!=
key
.
objectid
)
break
;
if
(
btrfs_disk_key_type
(
&
item
->
key
)
!=
BTRFS_DIR_ITEM_KEY
)
continue
;
di
=
btrfs_item_ptr
(
leaf
,
slot
,
struct
btrfs_dir_item
);
printk
(
"filldir name %.*s, objectid %Lu
\n
"
,
btrfs_dir_name_len
(
di
),
(
const
char
*
)(
di
+
1
),
btrfs_dir_objectid
(
di
));
over
=
filldir
(
dirent
,
(
const
char
*
)(
di
+
1
),
btrfs_dir_name_len
(
di
),
btrfs_disk_key_offset
(
&
item
->
key
),
btrfs_dir_objectid
(
di
),
d_type
);
if
(
over
)
break
;
filp
->
f_pos
=
btrfs_disk_key_offset
(
&
item
->
key
)
+
1
;
}
printk
(
"filldir all done
\n
"
);
ret
=
0
;
err:
btrfs_release_path
(
root
,
&
path
);
return
ret
;
}
static
void
btrfs_put_super
(
struct
super_block
*
sb
)
{
struct
btrfs_root
*
root
=
btrfs_sb
(
sb
);
int
ret
;
ret
=
close_ctree
(
root
);
if
(
ret
)
{
printk
(
"close ctree returns %d
\n
"
,
ret
);
}
sb
->
s_fs_info
=
NULL
;
}
static
int
btrfs_fill_super
(
struct
super_block
*
sb
,
void
*
data
,
int
silent
)
{
struct
inode
*
inode
;
struct
dentry
*
root
;
struct
dentry
*
root_dentry
;
struct
btrfs_super_block
*
disk_super
;
struct
buffer_head
*
bh
;
struct
btrfs_root
*
root
;
sb
->
s_maxbytes
=
MAX_LFS_FILESIZE
;
sb
->
s_blocksize
=
PAGE_CACHE_SIZE
;
sb
->
s_blocksize_bits
=
PAGE_CACHE_SHIFT
;
sb
->
s_magic
=
BTRFS_SUPER_MAGIC
;
sb
->
s_op
=
&
btrfs_ops
;
sb
->
s_op
=
&
btrfs_
super_
ops
;
sb
->
s_time_gran
=
1
;
inode
=
btrfs_get_inode
(
sb
,
S_IFDIR
|
0755
,
0
);
bh
=
sb_bread
(
sb
,
BTRFS_SUPER_INFO_OFFSET
/
sb
->
s_blocksize
);
if
(
!
bh
)
{
printk
(
"btrfs: unable to read on disk super
\n
"
);
return
-
EIO
;
}
disk_super
=
(
struct
btrfs_super_block
*
)
bh
->
b_data
;
root
=
open_ctree
(
sb
,
bh
,
disk_super
);
sb
->
s_fs_info
=
root
;
if
(
!
root
)
{
printk
(
"btrfs: open_ctree failed
\n
"
);
return
-
EIO
;
}
printk
(
"read in super total blocks %Lu root %Lu
\n
"
,
btrfs_super_total_blocks
(
disk_super
),
btrfs_super_root_dir
(
disk_super
));
inode
=
iget_locked
(
sb
,
btrfs_super_root_dir
(
disk_super
));
if
(
!
inode
)
return
-
ENOMEM
;
if
(
inode
->
i_state
&
I_NEW
)
{
btrfs_read_locked_inode
(
inode
);
unlock_new_inode
(
inode
);
}
root
=
d_alloc_root
(
inode
);
if
(
!
root
)
{
root
_dentry
=
d_alloc_root
(
inode
);
if
(
!
root
_dentry
)
{
iput
(
inode
);
return
-
ENOMEM
;
}
sb
->
s_root
=
root
;
sb
->
s_root
=
root_dentry
;
return
0
;
}
...
...
@@ -187,6 +390,24 @@ static struct file_system_type btrfs_fs_type = {
.
fs_flags
=
FS_REQUIRES_DEV
,
};
static
struct
super_operations
btrfs_super_ops
=
{
.
statfs
=
simple_statfs
,
.
drop_inode
=
generic_delete_inode
,
.
put_super
=
btrfs_put_super
,
.
read_inode
=
btrfs_read_locked_inode
,
};
static
struct
inode_operations
btrfs_dir_inode_operations
=
{
.
lookup
=
btrfs_lookup
,
};
static
struct
file_operations
btrfs_dir_file_operations
=
{
.
llseek
=
generic_file_llseek
,
.
read
=
generic_read_dir
,
.
readdir
=
btrfs_readdir
,
};
static
int
__init
init_btrfs_fs
(
void
)
{
printk
(
"btrfs loaded!
\n
"
);
...
...
fs/btrfs/transaction.h
View file @
e20d96d6
...
...
@@ -10,7 +10,7 @@ struct btrfs_trans_handle {
static
inline
struct
btrfs_trans_handle
*
btrfs_start_transaction
(
struct
btrfs_root
*
root
,
int
num_blocks
)
{
struct
btrfs_trans_handle
*
h
=
malloc
(
sizeof
(
*
h
)
);
struct
btrfs_trans_handle
*
h
=
kmalloc
(
sizeof
(
*
h
),
GFP_NOFS
);
h
->
transid
=
root
->
root_key
.
offset
;
h
->
blocks_reserved
=
num_blocks
;
h
->
blocks_used
=
0
;
...
...
@@ -21,7 +21,7 @@ static inline void btrfs_free_transaction(struct btrfs_root *root,
struct
btrfs_trans_handle
*
handle
)
{
memset
(
handle
,
0
,
sizeof
(
*
handle
));
free
(
handle
);
k
free
(
handle
);
}
#endif
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