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
a28ec197
Commit
a28ec197
authored
Mar 06, 2007
by
Chris Mason
Committed by
David Woodhouse
Mar 06, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: Fixup reference counting on cows
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
02217ed2
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
267 additions
and
127 deletions
+267
-127
fs/btrfs/Makefile
fs/btrfs/Makefile
+1
-1
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+4
-5
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+4
-0
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+26
-5
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+2
-2
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+204
-87
fs/btrfs/print-tree.c
fs/btrfs/print-tree.c
+4
-2
fs/btrfs/quick-test.c
fs/btrfs/quick-test.c
+15
-11
fs/btrfs/random-test.c
fs/btrfs/random-test.c
+7
-14
No files found.
fs/btrfs/Makefile
View file @
a28ec197
CC
=
gcc
CFLAGS
=
-g
-Wall
headers
=
radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h
headers
=
radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h
list.h
objects
=
ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o
# if you don't have sparse installed, use ls instead
...
...
fs/btrfs/ctree.c
View file @
a28ec197
...
...
@@ -50,16 +50,17 @@ int btrfs_cow_block(struct ctree_root *root,
memcpy
(
&
cow
->
node
,
&
buf
->
node
,
sizeof
(
buf
->
node
));
cow
->
node
.
header
.
blocknr
=
cow
->
blocknr
;
*
cow_ret
=
cow
;
btrfs_inc_ref
(
root
,
buf
);
if
(
buf
==
root
->
node
)
{
root
->
node
=
cow
;
cow
->
count
++
;
if
(
buf
!=
root
->
commit_root
)
free_extent
(
root
,
buf
->
blocknr
,
1
);
tree_block_release
(
root
,
buf
);
}
else
{
parent
->
node
.
blockptrs
[
parent_slot
]
=
cow
->
blocknr
;
BUG_ON
(
list_empty
(
&
parent
->
dirty
));
}
if
(
0
&&
root
!=
root
->
extent_root
&&
!
is_leaf
(
cow
->
node
.
header
.
flags
))
{
btrfs_inc_ref
(
root
,
cow
);
free_extent
(
root
,
buf
->
blocknr
,
1
);
}
tree_block_release
(
root
,
buf
);
return
0
;
...
...
@@ -1018,7 +1019,6 @@ static int split_leaf(struct ctree_root *root, struct ctree_path *path,
slot
=
path
->
slots
[
0
];
nritems
=
l
->
header
.
nritems
;
mid
=
(
nritems
+
1
)
/
2
;
right_buffer
=
alloc_free_block
(
root
);
BUG_ON
(
!
right_buffer
);
BUG_ON
(
mid
==
nritems
);
...
...
@@ -1170,7 +1170,6 @@ static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level,
node
=
&
parent
->
node
;
nritems
=
node
->
header
.
nritems
;
if
(
slot
!=
nritems
-
1
)
{
memmove
(
node
->
keys
+
slot
,
node
->
keys
+
slot
+
1
,
sizeof
(
struct
key
)
*
(
nritems
-
slot
-
1
));
...
...
fs/btrfs/ctree.h
View file @
a28ec197
...
...
@@ -51,10 +51,12 @@ struct tree_buffer;
*/
struct
ctree_root
{
struct
tree_buffer
*
node
;
struct
tree_buffer
*
commit_root
;
struct
ctree_root
*
extent_root
;
struct
key
current_insert
;
int
fp
;
struct
radix_tree_root
cache_radix
;
struct
radix_tree_root
pinned_radix
;
struct
list_head
trans
;
struct
list_head
cache
;
int
cache_size
;
...
...
@@ -151,4 +153,6 @@ int del_item(struct ctree_root *root, struct ctree_path *path);
int
insert_item
(
struct
ctree_root
*
root
,
struct
key
*
key
,
void
*
data
,
int
data_size
);
int
next_leaf
(
struct
ctree_root
*
root
,
struct
ctree_path
*
path
);
int
leaf_free_space
(
struct
leaf
*
leaf
);
int
btrfs_drop_snapshot
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
snap
);
int
btrfs_finish_extent_commit
(
struct
ctree_root
*
root
);
#endif
fs/btrfs/disk-io.c
View file @
a28ec197
...
...
@@ -153,13 +153,24 @@ static int __commit_transaction(struct ctree_root *root)
return
ret
;
}
int
commit_transaction
(
struct
ctree_root
*
root
)
int
commit_transaction
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
)
{
int
ret
;
int
ret
=
0
;
ret
=
__commit_transaction
(
root
);
if
(
!
ret
&&
root
!=
root
->
extent_root
)
ret
=
__commit_transaction
(
root
->
extent_root
);
BUG_ON
(
ret
);
if
(
root
->
commit_root
!=
root
->
node
)
{
struct
tree_buffer
*
snap
=
root
->
commit_root
;
root
->
commit_root
=
root
->
node
;
root
->
node
->
count
++
;
ret
=
btrfs_drop_snapshot
(
root
,
snap
);
BUG_ON
(
ret
);
tree_block_release
(
root
,
snap
);
}
write_ctree_super
(
root
,
s
);
btrfs_finish_extent_commit
(
root
);
return
ret
;
}
...
...
@@ -168,10 +179,13 @@ static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
{
INIT_LIST_HEAD
(
&
root
->
trans
);
INIT_LIST_HEAD
(
&
root
->
cache
);
root
->
cache_size
=
0
;
root
->
fp
=
fp
;
root
->
node
=
NULL
;
root
->
node
=
read_tree_block
(
root
,
info
->
tree_root
);
root
->
extent_root
=
extent_root
;
root
->
commit_root
=
NULL
;
root
->
node
=
read_tree_block
(
root
,
info
->
tree_root
);
memset
(
&
root
->
current_insert
,
0
,
sizeof
(
root
->
current_insert
));
return
0
;
}
...
...
@@ -188,6 +202,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
return
NULL
;
}
INIT_RADIX_TREE
(
&
root
->
cache_radix
,
GFP_KERNEL
);
INIT_RADIX_TREE
(
&
root
->
pinned_radix
,
GFP_KERNEL
);
INIT_RADIX_TREE
(
&
extent_root
->
pinned_radix
,
GFP_KERNEL
);
INIT_RADIX_TREE
(
&
extent_root
->
cache_radix
,
GFP_KERNEL
);
ret
=
pread
(
fp
,
super
,
sizeof
(
struct
ctree_super_block
),
CTREE_SUPER_INFO_OFFSET
(
CTREE_BLOCKSIZE
));
...
...
@@ -204,6 +220,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
BUG_ON
(
ret
<
0
);
__setup_root
(
root
,
extent_root
,
&
super
->
root_info
,
fp
);
__setup_root
(
extent_root
,
extent_root
,
&
super
->
extent_info
,
fp
);
root
->
commit_root
=
root
->
node
;
root
->
node
->
count
++
;
return
root
;
}
...
...
@@ -236,9 +254,11 @@ static int drop_cache(struct ctree_root *root)
}
return
0
;
}
int
close_ctree
(
struct
ctree_root
*
root
)
int
close_ctree
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
)
{
commit_transaction
(
root
);
commit_transaction
(
root
,
s
);
__commit_transaction
(
root
->
extent_root
);
write_ctree_super
(
root
,
s
);
drop_cache
(
root
->
extent_root
);
drop_cache
(
root
);
BUG_ON
(
!
list_empty
(
&
root
->
trans
));
...
...
@@ -249,6 +269,7 @@ int close_ctree(struct ctree_root *root)
tree_block_release
(
root
,
root
->
node
);
if
(
root
->
extent_root
->
node
)
tree_block_release
(
root
->
extent_root
,
root
->
extent_root
->
node
);
tree_block_release
(
root
,
root
->
commit_root
);
free
(
root
);
printf
(
"on close %d blocks are allocated
\n
"
,
allocated_blocks
);
return
0
;
...
...
fs/btrfs/disk-io.h
View file @
a28ec197
...
...
@@ -18,9 +18,9 @@ struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr);
int
write_tree_block
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
);
int
dirty_tree_block
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
);
int
clean_tree_block
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
);
int
commit_transaction
(
struct
ctree_root
*
root
);
int
commit_transaction
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
);
struct
ctree_root
*
open_ctree
(
char
*
filename
,
struct
ctree_super_block
*
s
);
int
close_ctree
(
struct
ctree_root
*
root
);
int
close_ctree
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
);
void
tree_block_release
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
);
int
write_ctree_super
(
struct
ctree_root
*
root
,
struct
ctree_super_block
*
s
);
int
mkfs
(
int
fd
);
...
...
fs/btrfs/extent-tree.c
View file @
a28ec197
...
...
@@ -13,7 +13,8 @@
* other allocations are done. The pending tag is also used in the same
* manner for deletes.
*/
#define CTREE_EXTENT_PENDING 0
#define CTREE_EXTENT_PENDING_ADD 0
#define CTREE_EXTENT_PENDING_DEL 1
static
int
inc_block_ref
(
struct
ctree_root
*
root
,
u64
blocknr
)
{
...
...
@@ -27,20 +28,51 @@ static int inc_block_ref(struct ctree_root *root, u64 blocknr)
key
.
flags
=
0
;
key
.
offset
=
1
;
ret
=
search_slot
(
root
->
extent_root
,
&
key
,
&
path
,
0
,
1
);
if
(
ret
!=
0
)
BUG
();
BUG_ON
(
ret
!=
0
);
l
=
&
path
.
nodes
[
0
]
->
leaf
;
item
=
(
struct
extent_item
*
)(
l
->
data
+
l
->
items
[
path
.
slots
[
0
]].
offset
);
item
->
refs
++
;
BUG_ON
(
list_empty
(
&
path
.
nodes
[
0
]
->
dirty
));
release_path
(
root
->
extent_root
,
&
path
);
return
0
;
}
static
int
lookup_block_ref
(
struct
ctree_root
*
root
,
u64
blocknr
,
int
*
refs
)
{
struct
ctree_path
path
;
int
ret
;
struct
key
key
;
struct
leaf
*
l
;
struct
extent_item
*
item
;
init_path
(
&
path
);
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
1
;
ret
=
search_slot
(
root
->
extent_root
,
&
key
,
&
path
,
0
,
0
);
if
(
ret
!=
0
)
BUG
();
l
=
&
path
.
nodes
[
0
]
->
leaf
;
item
=
(
struct
extent_item
*
)(
l
->
data
+
l
->
items
[
path
.
slots
[
0
]].
offset
);
*
refs
=
item
->
refs
;
release_path
(
root
->
extent_root
,
&
path
);
return
0
;
}
int
btrfs_inc_ref
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
buf
)
{
u64
blocknr
;
int
i
;
if
(
root
==
root
->
extent_root
)
return
0
;
if
(
is_leaf
(
buf
->
node
.
header
.
flags
))
return
0
;
for
(
i
=
0
;
i
<
buf
->
node
.
header
.
nritems
;
i
++
)
{
blocknr
=
buf
->
node
.
blockptrs
[
i
];
inc_block_ref
(
root
,
blocknr
);
...
...
@@ -48,85 +80,187 @@ int btrfs_inc_ref(struct ctree_root *root, struct tree_buffer *buf)
return
0
;
}
int
btrfs_finish_extent_commit
(
struct
ctree_root
*
root
)
{
struct
ctree_root
*
extent_root
=
root
->
extent_root
;
unsigned
long
gang
[
8
];
int
ret
;
int
i
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup
(
&
extent_root
->
pinned_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
));
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
radix_tree_delete
(
&
extent_root
->
pinned_radix
,
gang
[
i
]);
}
return
0
;
}
/*
* find all the blocks marked as pending in the radix tree and remove
* them from the extent map
* remove an extent from the root, returns 0 on success
*/
static
int
del_pending_extents
(
struct
ctree_root
*
extent_root
)
int
__free_extent
(
struct
ctree_root
*
root
,
u64
blocknr
,
u64
num_blocks
)
{
struct
ctree_path
path
;
struct
key
key
;
struct
ctree_root
*
extent_root
=
root
->
extent_root
;
int
ret
;
struct
item
*
item
;
struct
extent_item
*
ei
;
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
num_blocks
;
init_path
(
&
path
);
ret
=
search_slot
(
extent_root
,
&
key
,
&
path
,
-
1
,
1
);
if
(
ret
)
{
printf
(
"failed to find %Lu
\n
"
,
key
.
objectid
);
print_tree
(
extent_root
,
extent_root
->
node
);
printf
(
"failed to find %Lu
\n
"
,
key
.
objectid
);
BUG
();
}
item
=
path
.
nodes
[
0
]
->
leaf
.
items
+
path
.
slots
[
0
];
ei
=
(
struct
extent_item
*
)(
path
.
nodes
[
0
]
->
leaf
.
data
+
item
->
offset
);
BUG_ON
(
ei
->
refs
==
0
);
ei
->
refs
--
;
if
(
ei
->
refs
==
0
)
{
if
(
root
==
extent_root
)
{
int
err
;
radix_tree_preload
(
GFP_KERNEL
);
err
=
radix_tree_insert
(
&
extent_root
->
pinned_radix
,
blocknr
,
(
void
*
)
blocknr
);
BUG_ON
(
err
);
radix_tree_preload_end
();
}
ret
=
del_item
(
extent_root
,
&
path
);
if
(
ret
)
BUG
();
}
release_path
(
extent_root
,
&
path
);
return
ret
;
}
/*
* insert all of the pending extents reserved during the original
* allocation. (CTREE_EXTENT_PENDING). Returns zero if it all worked out
*/
static
int
insert_pending_extents
(
struct
ctree_root
*
extent_root
)
{
int
ret
;
struct
key
key
;
struct
extent_item
item
;
struct
tree_buffer
*
gang
[
4
];
int
i
;
struct
ctree_path
path
;
// FIXME -ENOSPC
item
.
owner
=
extent_root
->
node
->
node
.
header
.
parentid
;
item
.
refs
=
1
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
extent_root
->
cache_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PENDING
);
CTREE_EXTENT_PENDING
_ADD
);
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
key
.
objectid
=
gang
[
i
]
->
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
1
;
init_path
(
&
path
);
ret
=
search_slot
(
extent_root
,
&
key
,
&
path
,
-
1
,
1
);
ret
=
insert_item
(
extent_root
,
&
key
,
&
item
,
sizeof
(
item
)
);
if
(
ret
)
{
printf
(
"%Lu already in tree
\n
"
,
key
.
objectid
);
print_tree
(
extent_root
,
extent_root
->
node
);
printf
(
"unable to find %Lu
\n
"
,
key
.
objectid
);
BUG
();
// FIXME undo it and return sane
return
ret
;
}
ret
=
del_item
(
extent_root
,
&
path
);
if
(
ret
)
{
BUG
();
return
ret
;
}
release_path
(
extent_root
,
&
path
);
radix_tree_tag_clear
(
&
extent_root
->
cache_radix
,
gang
[
i
]
->
blocknr
,
CTREE_EXTENT_PENDING_ADD
);
tree_block_release
(
extent_root
,
gang
[
i
]);
}
}
return
0
;
}
/*
* find all the blocks marked as pending in the radix tree and remove
* them from the extent map
*/
static
int
del_pending_extents
(
struct
ctree_root
*
extent_root
)
{
int
ret
;
struct
tree_buffer
*
gang
[
4
];
int
i
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
extent_root
->
cache_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PENDING_DEL
);
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
ret
=
__free_extent
(
extent_root
,
gang
[
i
]
->
blocknr
,
1
);
radix_tree_tag_clear
(
&
extent_root
->
cache_radix
,
gang
[
i
]
->
blocknr
,
CTREE_EXTENT_PENDING
);
CTREE_EXTENT_PENDING
_DEL
);
tree_block_release
(
extent_root
,
gang
[
i
]);
}
}
return
0
;
}
static
int
run_pending
(
struct
ctree_root
*
extent_root
)
{
while
(
radix_tree_tagged
(
&
extent_root
->
cache_radix
,
CTREE_EXTENT_PENDING_DEL
)
||
radix_tree_tagged
(
&
extent_root
->
cache_radix
,
CTREE_EXTENT_PENDING_ADD
))
{
insert_pending_extents
(
extent_root
);
del_pending_extents
(
extent_root
);
}
return
0
;
}
/*
* remove an extent from the root, returns 0 on success
*/
int
free_extent
(
struct
ctree_root
*
root
,
u64
blocknr
,
u64
num_blocks
)
{
struct
ctree_path
path
;
struct
key
key
;
struct
ctree_root
*
extent_root
=
root
->
extent_root
;
struct
tree_buffer
*
t
;
int
pending_ret
;
int
ret
;
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
num_blocks
;
if
(
root
==
extent_root
)
{
t
=
read_tree_block
(
root
,
key
.
objectid
);
radix_tree_tag_set
(
&
root
->
cache_radix
,
key
.
objectid
,
CTREE_EXTENT_PENDING
);
t
=
find_tree_block
(
root
,
blocknr
);
if
(
radix_tree_tag_get
(
&
root
->
cache_radix
,
blocknr
,
CTREE_EXTENT_PENDING_ADD
))
{
radix_tree_tag_clear
(
&
root
->
cache_radix
,
blocknr
,
CTREE_EXTENT_PENDING_ADD
);
/* once for us */
tree_block_release
(
root
,
t
);
/* once for the pending add */
tree_block_release
(
root
,
t
);
}
else
{
radix_tree_tag_set
(
&
root
->
cache_radix
,
blocknr
,
CTREE_EXTENT_PENDING_DEL
);
}
return
0
;
}
init_path
(
&
path
);
ret
=
search_slot
(
extent_root
,
&
key
,
&
path
,
-
1
,
1
);
if
(
ret
)
{
print_tree
(
extent_root
,
extent_root
->
node
);
printf
(
"failed to find %Lu
\n
"
,
key
.
objectid
);
BUG
();
}
ret
=
del_item
(
extent_root
,
&
path
);
if
(
ret
)
BUG
();
release_path
(
extent_root
,
&
path
);
pending_ret
=
del_pending_extents
(
root
->
extent_root
);
key
.
objectid
=
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
num_blocks
;
ret
=
__free_extent
(
root
,
blocknr
,
num_blocks
);
pending_ret
=
run_pending
(
root
->
extent_root
);
return
ret
?
ret
:
pending_ret
;
}
...
...
@@ -203,7 +337,7 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
*/
release_path
(
root
,
&
path
);
BUG_ON
(
ins
->
objectid
<
search_start
);
if
(
orig_root
->
extent_root
==
orig_root
)
{
if
(
1
||
orig_root
->
extent_root
==
orig_root
)
{
BUG_ON
(
num_blocks
!=
1
);
if
((
root
->
current_insert
.
objectid
<=
ins
->
objectid
&&
root
->
current_insert
.
objectid
+
...
...
@@ -211,8 +345,9 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
(
root
->
current_insert
.
objectid
>
ins
->
objectid
&&
root
->
current_insert
.
objectid
<=
ins
->
objectid
+
ins
->
offset
)
||
radix_tree_lookup
(
&
root
->
pinned_radix
,
ins
->
objectid
)
||
radix_tree_tag_get
(
&
root
->
cache_radix
,
ins
->
objectid
,
CTREE_EXTENT_PENDING
))
{
CTREE_EXTENT_PENDING
_ADD
))
{
search_start
=
ins
->
objectid
+
1
;
goto
check_failed
;
}
...
...
@@ -225,51 +360,6 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
return
ret
;
}
/*
* insert all of the pending extents reserved during the original
* allocation. (CTREE_EXTENT_PENDING). Returns zero if it all worked out
*/
static
int
insert_pending_extents
(
struct
ctree_root
*
extent_root
)
{
int
ret
;
struct
key
key
;
struct
extent_item
item
;
struct
tree_buffer
*
gang
[
4
];
int
i
;
// FIXME -ENOSPC
item
.
refs
=
1
;
item
.
owner
=
extent_root
->
node
->
node
.
header
.
parentid
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
&
extent_root
->
cache_radix
,
(
void
**
)
gang
,
0
,
ARRAY_SIZE
(
gang
),
CTREE_EXTENT_PENDING
);
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
key
.
objectid
=
gang
[
i
]
->
blocknr
;
key
.
flags
=
0
;
key
.
offset
=
1
;
ret
=
insert_item
(
extent_root
,
&
key
,
&
item
,
sizeof
(
item
));
if
(
ret
)
{
printf
(
"%Lu already in tree
\n
"
,
key
.
objectid
);
print_tree
(
extent_root
,
extent_root
->
node
);
BUG
();
// FIXME undo it and return sane
return
ret
;
}
radix_tree_tag_clear
(
&
extent_root
->
cache_radix
,
gang
[
i
]
->
blocknr
,
CTREE_EXTENT_PENDING
);
printf
(
"%Lu is not pending
\n
"
,
gang
[
i
]
->
blocknr
);
tree_block_release
(
extent_root
,
gang
[
i
]);
}
}
return
0
;
}
/*
* finds a free extent and does all the dirty work required for allocation
* returns the key for the extent through ins, and a tree buffer for
...
...
@@ -296,7 +386,7 @@ int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start,
sizeof
(
extent_item
));
memset
(
&
root
->
extent_root
->
current_insert
,
0
,
sizeof
(
struct
key
));
pending_ret
=
insert_pending_extents
(
root
->
extent_root
);
pending_ret
=
run_pending
(
root
->
extent_root
);
if
(
ret
)
return
ret
;
if
(
pending_ret
)
...
...
@@ -309,9 +399,8 @@ int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start,
BUG_ON
(
ins
->
offset
!=
1
);
*
buf
=
find_tree_block
(
root
,
ins
->
objectid
);
BUG_ON
(
!*
buf
);
printf
(
"%Lu is pending
\n
"
,
ins
->
objectid
);
radix_tree_tag_set
(
&
root
->
cache_radix
,
ins
->
objectid
,
CTREE_EXTENT_PENDING
);
CTREE_EXTENT_PENDING
_ADD
);
(
*
buf
)
->
count
++
;
dirty_tree_block
(
root
,
*
buf
);
return
0
;
...
...
@@ -331,13 +420,41 @@ struct tree_buffer *alloc_free_block(struct ctree_root *root)
ret
=
alloc_extent
(
root
,
1
,
0
,
(
unsigned
long
)
-
1
,
root
->
node
->
node
.
header
.
parentid
,
&
ins
,
&
buf
);
if
(
ret
)
{
BUG
();
return
NULL
;
}
if
(
root
!=
root
->
extent_root
)
BUG_ON
(
radix_tree_tag_get
(
&
root
->
extent_root
->
cache_radix
,
buf
->
blocknr
,
CTREE_EXTENT_PENDING
));
buf
->
blocknr
,
CTREE_EXTENT_PENDING_ADD
));
return
buf
;
}
int
btrfs_drop_snapshot
(
struct
ctree_root
*
root
,
struct
tree_buffer
*
snap
)
{
int
ret
;
int
level
;
int
refs
;
u64
blocknr
=
snap
->
blocknr
;
level
=
node_level
(
snap
->
node
.
header
.
flags
);
ret
=
lookup_block_ref
(
root
,
snap
->
blocknr
,
&
refs
);
BUG_ON
(
ret
);
if
(
refs
==
1
&&
level
!=
0
)
{
struct
node
*
n
=
&
snap
->
node
;
struct
tree_buffer
*
b
;
int
i
;
for
(
i
=
0
;
i
<
n
->
header
.
nritems
;
i
++
)
{
b
=
read_tree_block
(
root
,
n
->
blockptrs
[
i
]);
/* FIXME, don't recurse here */
ret
=
btrfs_drop_snapshot
(
root
,
b
);
BUG_ON
(
ret
);
tree_block_release
(
root
,
b
);
}
}
ret
=
free_extent
(
root
,
blocknr
,
1
);
BUG_ON
(
ret
);
return
0
;
}
fs/btrfs/print-tree.c
View file @
a28ec197
...
...
@@ -21,9 +21,11 @@ void print_leaf(struct leaf *l)
item
->
key
.
objectid
,
item
->
key
.
flags
,
item
->
key
.
offset
,
item
->
offset
,
item
->
size
);
fflush
(
stdout
);
printf
(
"
\t\t
item data %.*s
\n
"
,
item
->
size
,
l
->
data
+
item
->
offset
);
printf
(
"
\t\t
item data %.*s
\n
"
,
item
->
size
,
l
->
data
+
item
->
offset
);
ei
=
(
struct
extent_item
*
)(
l
->
data
+
item
->
offset
);
printf
(
"
\t\t
extent data %u %Lu
\n
"
,
ei
->
refs
,
ei
->
owner
);
printf
(
"
\t\t
extent data refs %u owner %Lu
\n
"
,
ei
->
refs
,
ei
->
owner
);
fflush
(
stdout
);
}
}
...
...
fs/btrfs/quick-test.c
View file @
a28ec197
...
...
@@ -19,7 +19,7 @@ int main(int ac, char **av) {
int
i
;
int
num
;
int
ret
;
int
run_size
=
10
24
;
int
run_size
=
10
0000
;
int
max_key
=
100000000
;
int
tree_size
=
0
;
struct
ctree_path
path
;
...
...
@@ -44,9 +44,9 @@ int main(int ac, char **av) {
if
(
!
ret
)
tree_size
++
;
free
(
buf
);
}
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
printf
(
"starting search
\n
"
);
...
...
@@ -65,8 +65,7 @@ int main(int ac, char **av) {
}
release_path
(
root
,
&
path
);
}
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
printf
(
"node %p level %d total ptrs %d free spc %lu
\n
"
,
root
->
node
,
node_level
(
root
->
node
->
node
.
header
.
flags
),
...
...
@@ -90,8 +89,7 @@ int main(int ac, char **av) {
}
release_path
(
root
,
&
path
);
}
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
srand
(
128
);
for
(
i
=
0
;
i
<
run_size
;
i
++
)
{
...
...
@@ -106,8 +104,7 @@ int main(int ac, char **av) {
tree_size
++
;
free
(
buf
);
}
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
srand
(
128
);
printf
(
"starting search2
\n
"
);
...
...
@@ -156,10 +153,17 @@ int main(int ac, char **av) {
}
release_path
(
root
,
&
path
);
}
/*
printf("previous tree:\n");
print_tree(root, root->commit_root);
printf("map before commit\n");
print_tree(root->extent_root, root->extent_root->node);
*/
commit_transaction
(
root
,
&
super
);
printf
(
"tree size is now %d
\n
"
,
tree_size
);
printf
(
"root %p commit root %p
\n
"
,
root
->
node
,
root
->
commit_root
);
printf
(
"map tree
\n
"
);
print_tree
(
root
->
extent_root
,
root
->
extent_root
->
node
);
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
return
0
;
}
fs/btrfs/random-test.c
View file @
a28ec197
...
...
@@ -8,6 +8,7 @@
#include "print-tree.h"
int
keep_running
=
1
;
struct
ctree_super_block
super
;
static
int
setup_key
(
struct
radix_tree_root
*
root
,
struct
key
*
key
,
int
exists
)
{
...
...
@@ -59,11 +60,6 @@ static int ins_one(struct ctree_root *root, struct radix_tree_root *radix)
return
-
1
;
}
static
int
run_commit
(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
{
return
commit_transaction
(
root
);
}
static
int
insert_dup
(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
{
struct
ctree_path
path
;
...
...
@@ -210,7 +206,7 @@ static int fill_tree(struct ctree_root *root, struct radix_tree_root *radix,
goto
out
;
}
if
(
i
%
1000
==
0
)
{
ret
=
commit_transaction
(
root
);
ret
=
commit_transaction
(
root
,
&
super
);
if
(
ret
)
{
fprintf
(
stderr
,
"fill commit failed
\n
"
);
return
ret
;
...
...
@@ -229,7 +225,7 @@ static int fill_tree(struct ctree_root *root, struct radix_tree_root *radix,
static
int
bulk_op
(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
{
int
ret
;
int
nr
=
rand
()
%
20
000
;
int
nr
=
rand
()
%
5
000
;
static
int
run_nr
=
0
;
/* do the bulk op much less frequently */
...
...
@@ -247,7 +243,7 @@ static int bulk_op(struct ctree_root *root, struct radix_tree_root *radix)
int
(
*
ops
[])(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
=
{
ins_one
,
insert_dup
,
del_one
,
lookup_item
,
lookup_enoent
,
bulk_op
,
run_commit
};
lookup_enoent
,
bulk_op
};
static
int
fill_radix
(
struct
ctree_root
*
root
,
struct
radix_tree_root
*
radix
)
{
...
...
@@ -314,7 +310,6 @@ int print_usage(void)
int
main
(
int
ac
,
char
**
av
)
{
RADIX_TREE
(
radix
,
GFP_KERNEL
);
struct
ctree_super_block
super
;
struct
ctree_root
*
root
;
int
i
;
int
ret
;
...
...
@@ -365,8 +360,7 @@ int main(int ac, char **av)
printf
(
"open & close, root level %d nritems %d
\n
"
,
node_level
(
root
->
node
->
node
.
header
.
flags
),
root
->
node
->
node
.
header
.
nritems
);
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
root
=
open_ctree
(
"dbfile"
,
&
super
);
}
while
(
count
--
)
{
...
...
@@ -380,7 +374,7 @@ int main(int ac, char **av)
err
=
ret
;
goto
out
;
}
if
(
ops
[
op
]
==
bulk_op
||
ops
[
op
]
==
run_commit
)
if
(
ops
[
op
]
==
bulk_op
)
break
;
if
(
keep_running
==
0
)
{
err
=
0
;
...
...
@@ -389,8 +383,7 @@ int main(int ac, char **av)
}
}
out:
write_ctree_super
(
root
,
&
super
);
close_ctree
(
root
);
close_ctree
(
root
,
&
super
);
return
err
;
}
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