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
acbcabd2
Commit
acbcabd2
authored
Jun 14, 2012
by
Chris Mason
Committed by
Chris Mason
Jun 15, 2012
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-chris' of
git://git.jan-o-sch.net/btrfs-unstable
into for-linus
parents
69e380d1
3310c36e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
70 additions
and
35 deletions
+70
-35
fs/btrfs/backref.c
fs/btrfs/backref.c
+5
-12
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+63
-23
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+2
-0
No files found.
fs/btrfs/backref.c
View file @
acbcabd2
...
...
@@ -179,7 +179,8 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id,
static
int
add_all_parents
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
ulist
*
parents
,
int
level
,
struct
btrfs_key
*
key
,
u64
wanted_disk_byte
,
struct
btrfs_key
*
key
,
u64
time_seq
,
u64
wanted_disk_byte
,
const
u64
*
extent_item_pos
)
{
int
ret
;
...
...
@@ -212,7 +213,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
*/
while
(
1
)
{
eie
=
NULL
;
ret
=
btrfs_next_
leaf
(
root
,
path
);
ret
=
btrfs_next_
old_leaf
(
root
,
path
,
time_seq
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
)
...
...
@@ -294,18 +295,10 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
goto
out
;
}
if
(
level
==
0
)
{
if
(
ret
==
1
&&
path
->
slots
[
0
]
>=
btrfs_header_nritems
(
eb
))
{
ret
=
btrfs_next_leaf
(
root
,
path
);
if
(
ret
)
goto
out
;
eb
=
path
->
nodes
[
0
];
}
if
(
level
==
0
)
btrfs_item_key_to_cpu
(
eb
,
&
key
,
path
->
slots
[
0
]);
}
ret
=
add_all_parents
(
root
,
path
,
parents
,
level
,
&
key
,
ret
=
add_all_parents
(
root
,
path
,
parents
,
level
,
&
key
,
time_seq
,
ref
->
wanted_disk_byte
,
extent_item_pos
);
out:
btrfs_free_path
(
path
);
...
...
fs/btrfs/ctree.c
View file @
acbcabd2
...
...
@@ -467,6 +467,15 @@ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info,
return
0
;
}
/*
* This allocates memory and gets a tree modification sequence number when
* needed.
*
* Returns 0 when no sequence number is needed, < 0 on error.
* Returns 1 when a sequence number was added. In this case,
* fs_info->tree_mod_seq_lock was acquired and must be released by the caller
* after inserting into the rb tree.
*/
static
inline
int
tree_mod_alloc
(
struct
btrfs_fs_info
*
fs_info
,
gfp_t
flags
,
struct
tree_mod_elem
**
tm_ret
)
{
...
...
@@ -491,11 +500,11 @@ static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags,
*/
kfree
(
tm
);
seq
=
0
;
spin_unlock
(
&
fs_info
->
tree_mod_seq_lock
);
}
else
{
__get_tree_mod_seq
(
fs_info
,
&
tm
->
elem
);
seq
=
tm
->
elem
.
seq
;
}
spin_unlock
(
&
fs_info
->
tree_mod_seq_lock
);
return
seq
;
}
...
...
@@ -521,7 +530,9 @@ tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info,
tm
->
slot
=
slot
;
tm
->
generation
=
btrfs_node_ptr_generation
(
eb
,
slot
);
return
__tree_mod_log_insert
(
fs_info
,
tm
);
ret
=
__tree_mod_log_insert
(
fs_info
,
tm
);
spin_unlock
(
&
fs_info
->
tree_mod_seq_lock
);
return
ret
;
}
static
noinline
int
...
...
@@ -559,7 +570,9 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
tm
->
move
.
nr_items
=
nr_items
;
tm
->
op
=
MOD_LOG_MOVE_KEYS
;
return
__tree_mod_log_insert
(
fs_info
,
tm
);
ret
=
__tree_mod_log_insert
(
fs_info
,
tm
);
spin_unlock
(
&
fs_info
->
tree_mod_seq_lock
);
return
ret
;
}
static
noinline
int
...
...
@@ -580,7 +593,9 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
tm
->
generation
=
btrfs_header_generation
(
old_root
);
tm
->
op
=
MOD_LOG_ROOT_REPLACE
;
return
__tree_mod_log_insert
(
fs_info
,
tm
);
ret
=
__tree_mod_log_insert
(
fs_info
,
tm
);
spin_unlock
(
&
fs_info
->
tree_mod_seq_lock
);
return
ret
;
}
static
struct
tree_mod_elem
*
...
...
@@ -1023,6 +1038,10 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info,
looped
=
1
;
}
/* if there's no old root to return, return what we found instead */
if
(
!
found
)
found
=
tm
;
return
found
;
}
...
...
@@ -1143,22 +1162,36 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
return
eb_rewin
;
}
/*
* get_old_root() rewinds the state of @root's root node to the given @time_seq
* value. If there are no changes, the current root->root_node is returned. If
* anything changed in between, there's a fresh buffer allocated on which the
* rewind operations are done. In any case, the returned buffer is read locked.
* Returns NULL on error (with no locks held).
*/
static
inline
struct
extent_buffer
*
get_old_root
(
struct
btrfs_root
*
root
,
u64
time_seq
)
{
struct
tree_mod_elem
*
tm
;
struct
extent_buffer
*
eb
;
struct
tree_mod_root
*
old_root
;
struct
tree_mod_root
*
old_root
=
NULL
;
u64
old_generation
;
u64
logical
;
eb
=
btrfs_read_lock_root_node
(
root
);
tm
=
__tree_mod_log_oldest_root
(
root
->
fs_info
,
root
,
time_seq
);
if
(
!
tm
)
return
root
->
node
;
old_root
=
&
tm
->
old_root
;
old_generation
=
tm
->
generation
;
if
(
tm
->
op
==
MOD_LOG_ROOT_REPLACE
)
{
old_root
=
&
tm
->
old_root
;
old_generation
=
tm
->
generation
;
logical
=
old_root
->
logical
;
}
else
{
logical
=
root
->
node
->
start
;
}
tm
=
tree_mod_log_search
(
root
->
fs_info
,
old_root
->
logical
,
time_seq
);
tm
=
tree_mod_log_search
(
root
->
fs_info
,
logical
,
time_seq
);
/*
* there was an item in the log when __tree_mod_log_oldest_root
* returned. this one must not go away, because the time_seq passed to
...
...
@@ -1166,22 +1199,25 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
*/
BUG_ON
(
!
tm
);
if
(
old_root
->
logical
==
root
->
node
->
start
)
{
/* there are logged operations for the current root */
eb
=
btrfs_clone_extent_buffer
(
root
->
node
);
}
else
{
/* there's a root replace operation for the current root */
if
(
old_root
)
eb
=
alloc_dummy_extent_buffer
(
tm
->
index
<<
PAGE_CACHE_SHIFT
,
root
->
nodesize
);
else
eb
=
btrfs_clone_extent_buffer
(
root
->
node
);
btrfs_tree_read_unlock
(
root
->
node
);
free_extent_buffer
(
root
->
node
);
if
(
!
eb
)
return
NULL
;
btrfs_tree_read_lock
(
eb
);
if
(
old_root
)
{
btrfs_set_header_bytenr
(
eb
,
eb
->
start
);
btrfs_set_header_backref_rev
(
eb
,
BTRFS_MIXED_BACKREF_REV
);
btrfs_set_header_owner
(
eb
,
root
->
root_key
.
objectid
);
btrfs_set_header_level
(
eb
,
old_root
->
level
);
btrfs_set_header_generation
(
eb
,
old_generation
);
}
if
(
!
eb
)
return
NULL
;
btrfs_set_header_level
(
eb
,
old_root
->
level
);
btrfs_set_header_generation
(
eb
,
old_generation
);
__tree_mod_log_rewind
(
eb
,
time_seq
,
tm
);
extent_buffer_get
(
eb
);
return
eb
;
}
...
...
@@ -1650,8 +1686,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
/
4
)
return
0
;
btrfs_header_nritems
(
mid
);
left
=
read_node_slot
(
root
,
parent
,
pslot
-
1
);
if
(
left
)
{
btrfs_tree_lock
(
left
);
...
...
@@ -1681,7 +1715,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
wret
=
push_node_left
(
trans
,
root
,
left
,
mid
,
1
);
if
(
wret
<
0
)
ret
=
wret
;
btrfs_header_nritems
(
mid
);
}
/*
...
...
@@ -2615,9 +2648,7 @@ int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key,
again:
b
=
get_old_root
(
root
,
time_seq
);
extent_buffer_get
(
b
);
level
=
btrfs_header_level
(
b
);
btrfs_tree_read_lock
(
b
);
p
->
locks
[
level
]
=
BTRFS_READ_LOCK
;
while
(
b
)
{
...
...
@@ -5000,6 +5031,12 @@ int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
* returns < 0 on io errors.
*/
int
btrfs_next_leaf
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
)
{
return
btrfs_next_old_leaf
(
root
,
path
,
0
);
}
int
btrfs_next_old_leaf
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
time_seq
)
{
int
slot
;
int
level
;
...
...
@@ -5025,7 +5062,10 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
path
->
keep_locks
=
1
;
path
->
leave_spinning
=
1
;
ret
=
btrfs_search_slot
(
NULL
,
root
,
&
key
,
path
,
0
,
0
);
if
(
time_seq
)
ret
=
btrfs_search_old_slot
(
root
,
&
key
,
path
,
time_seq
);
else
ret
=
btrfs_search_slot
(
NULL
,
root
,
&
key
,
path
,
0
,
0
);
path
->
keep_locks
=
0
;
if
(
ret
<
0
)
...
...
fs/btrfs/ctree.h
View file @
acbcabd2
...
...
@@ -2753,6 +2753,8 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
}
int
btrfs_next_leaf
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
);
int
btrfs_next_old_leaf
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
time_seq
);
static
inline
int
btrfs_next_item
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
p
)
{
++
p
->
slots
[
0
];
...
...
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