Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
5eda7b5e
Commit
5eda7b5e
authored
Jun 22, 2007
by
Chris Mason
Committed by
David Woodhouse
Jun 22, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: Add the ability to find and remove dead roots after a crash.
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
54aa1f4d
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
164 additions
and
32 deletions
+164
-32
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+15
-2
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+30
-14
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+3
-0
fs/btrfs/inode.c
fs/btrfs/inode.c
+2
-0
fs/btrfs/root-tree.c
fs/btrfs/root-tree.c
+66
-9
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+47
-7
fs/btrfs/transaction.h
fs/btrfs/transaction.h
+1
-0
No files found.
fs/btrfs/ctree.h
View file @
5eda7b5e
...
...
@@ -122,12 +122,12 @@ struct btrfs_super_block {
u8
fsid
[
16
];
/* FS specific uuid */
__le64
blocknr
;
/* this block number */
__le64
magic
;
__le32
blocksize
;
__le64
generation
;
__le64
root
;
__le64
total_blocks
;
__le64
blocks_used
;
__le64
root_dir_objectid
;
__le32
blocksize
;
}
__attribute__
((
__packed__
));
/*
...
...
@@ -226,10 +226,12 @@ struct btrfs_root_item {
struct
btrfs_inode_item
inode
;
__le64
root_dirid
;
__le64
blocknr
;
__le32
flags
;
__le64
block_limit
;
__le64
blocks_used
;
__le32
flags
;
__le32
refs
;
struct
btrfs_disk_key
drop_progress
;
u8
drop_level
;
}
__attribute__
((
__packed__
));
#define BTRFS_FILE_EXTENT_REG 0
...
...
@@ -800,6 +802,16 @@ static inline void btrfs_set_root_refs(struct btrfs_root_item *item, u32 val)
item
->
refs
=
cpu_to_le32
(
val
);
}
static
inline
u32
btrfs_root_flags
(
struct
btrfs_root_item
*
item
)
{
return
le32_to_cpu
(
item
->
flags
);
}
static
inline
void
btrfs_set_root_flags
(
struct
btrfs_root_item
*
item
,
u32
val
)
{
item
->
flags
=
cpu_to_le32
(
val
);
}
static
inline
u64
btrfs_super_blocknr
(
struct
btrfs_super_block
*
s
)
{
return
le64_to_cpu
(
s
->
blocknr
);
...
...
@@ -1076,6 +1088,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
*
item
);
int
btrfs_find_last_root
(
struct
btrfs_root
*
root
,
u64
objectid
,
struct
btrfs_root_item
*
item
,
struct
btrfs_key
*
key
);
int
btrfs_find_dead_roots
(
struct
btrfs_root
*
root
);
/* dir-item.c */
int
btrfs_insert_dir_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
const
char
*
name
,
int
name_len
,
u64
dir
,
...
...
fs/btrfs/disk-io.c
View file @
5eda7b5e
...
...
@@ -326,7 +326,7 @@ static int find_and_setup_root(int blocksize,
return
0
;
}
struct
btrfs_root
*
btrfs_read_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_root
*
btrfs_read_fs_root
_no_radix
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_key
*
location
)
{
struct
btrfs_root
*
root
;
...
...
@@ -336,11 +336,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
u64
highest_inode
;
int
ret
=
0
;
root
=
radix_tree_lookup
(
&
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
location
->
objectid
);
if
(
root
)
return
root
;
root
=
kmalloc
(
sizeof
(
*
root
),
GFP_NOFS
);
root
=
kzalloc
(
sizeof
(
*
root
),
GFP_NOFS
);
if
(
!
root
)
return
ERR_PTR
(
-
ENOMEM
);
if
(
location
->
offset
==
(
u64
)
-
1
)
{
...
...
@@ -383,6 +379,28 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
BUG_ON
(
!
root
->
node
);
insert:
root
->
ref_cows
=
1
;
ret
=
btrfs_find_highest_inode
(
root
,
&
highest_inode
);
if
(
ret
==
0
)
{
root
->
highest_inode
=
highest_inode
;
root
->
last_inode_alloc
=
highest_inode
;
}
return
root
;
}
struct
btrfs_root
*
btrfs_read_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_key
*
location
)
{
struct
btrfs_root
*
root
;
int
ret
;
root
=
radix_tree_lookup
(
&
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
location
->
objectid
);
if
(
root
)
return
root
;
root
=
btrfs_read_fs_root_no_radix
(
fs_info
,
location
);
if
(
IS_ERR
(
root
))
return
root
;
ret
=
radix_tree_insert
(
&
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
root
->
root_key
.
objectid
,
root
);
...
...
@@ -391,11 +409,6 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
kfree
(
root
);
return
ERR_PTR
(
ret
);
}
ret
=
btrfs_find_highest_inode
(
root
,
&
highest_inode
);
if
(
ret
==
0
)
{
root
->
highest_inode
=
highest_inode
;
root
->
last_inode_alloc
=
highest_inode
;
}
return
root
;
}
...
...
@@ -489,6 +502,9 @@ struct btrfs_root *open_ctree(struct super_block *sb)
btrfs_read_block_groups
(
extent_root
);
fs_info
->
generation
=
btrfs_super_generation
(
disk_super
)
+
1
;
ret
=
btrfs_find_dead_roots
(
tree_root
);
if
(
ret
)
goto
fail_tree_root
;
mutex_unlock
(
&
fs_info
->
fs_mutex
);
return
tree_root
;
...
...
@@ -538,7 +554,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
return
0
;
}
static
int
free_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_root
*
root
)
int
btrfs_
free_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_root
*
root
)
{
radix_tree_delete
(
&
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
root
->
root_key
.
objectid
);
...
...
@@ -565,7 +581,7 @@ static int del_fs_roots(struct btrfs_fs_info *fs_info)
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
free_fs_root
(
fs_info
,
gang
[
i
]);
btrfs_
free_fs_root
(
fs_info
,
gang
[
i
]);
}
return
0
;
}
...
...
fs/btrfs/disk-io.h
View file @
5eda7b5e
...
...
@@ -65,6 +65,8 @@ int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len,
char
*
result
);
struct
btrfs_root
*
btrfs_read_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_key
*
location
);
struct
btrfs_root
*
btrfs_read_fs_root_no_radix
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_key
*
location
);
u64
bh_blocknr
(
struct
buffer_head
*
bh
);
int
btrfs_insert_dev_radix
(
struct
btrfs_root
*
root
,
struct
block_device
*
bdev
,
...
...
@@ -75,4 +77,5 @@ int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh,
u64
logical
);
int
btrfs_releasepage
(
struct
page
*
page
,
gfp_t
flags
);
void
btrfs_btree_balance_dirty
(
struct
btrfs_root
*
root
);
int
btrfs_free_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_root
*
root
);
#endif
fs/btrfs/inode.c
View file @
5eda7b5e
...
...
@@ -2028,6 +2028,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
btrfs_set_root_blocknr
(
&
root_item
,
bh_blocknr
(
subvol
));
btrfs_set_root_refs
(
&
root_item
,
1
);
memset
(
&
root_item
.
drop_progress
,
0
,
sizeof
(
root_item
.
drop_progress
));
root_item
.
drop_level
=
0
;
brelse
(
subvol
);
subvol
=
NULL
;
...
...
fs/btrfs/root-tree.c
View file @
5eda7b5e
...
...
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include "ctree.h"
#include "transaction.h"
#include "disk-io.h"
#include "print-tree.h"
...
...
@@ -32,7 +33,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
search_key
.
objectid
=
objectid
;
search_key
.
flags
=
(
u32
)
-
1
;
search_key
.
offset
=
(
u
32
)
-
1
;
search_key
.
offset
=
(
u
64
)
-
1
;
path
=
btrfs_alloc_path
();
BUG_ON
(
!
path
);
...
...
@@ -50,6 +51,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
memcpy
(
item
,
btrfs_item_ptr
(
l
,
slot
,
struct
btrfs_root_item
),
sizeof
(
*
item
));
btrfs_disk_key_to_cpu
(
key
,
&
l
->
items
[
slot
].
key
);
printk
(
"find last finds key %Lu %u %Lu slot %d search for obj %Lu
\n
"
,
key
->
objectid
,
key
->
flags
,
key
->
offset
,
slot
,
objectid
);
ret
=
0
;
out:
btrfs_release_path
(
root
,
path
);
...
...
@@ -93,6 +95,67 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
return
ret
;
}
int
btrfs_find_dead_roots
(
struct
btrfs_root
*
root
)
{
struct
btrfs_root
*
dead_root
;
struct
btrfs_item
*
item
;
struct
btrfs_root_item
*
ri
;
struct
btrfs_key
key
;
struct
btrfs_path
*
path
;
int
ret
;
u32
nritems
;
struct
btrfs_leaf
*
leaf
;
int
slot
;
key
.
objectid
=
0
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_ROOT_ITEM_KEY
);
key
.
offset
=
0
;
path
=
btrfs_alloc_path
();
if
(
!
path
)
return
-
ENOMEM
;
ret
=
btrfs_search_slot
(
NULL
,
root
,
&
key
,
path
,
0
,
0
);
if
(
ret
<
0
)
goto
err
;
while
(
1
)
{
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
slot
=
path
->
slots
[
0
];
if
(
slot
>=
nritems
)
{
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
];
}
item
=
leaf
->
items
+
slot
;
btrfs_disk_key_to_cpu
(
&
key
,
&
item
->
key
);
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_ROOT_ITEM_KEY
)
goto
next
;
ri
=
btrfs_item_ptr
(
leaf
,
slot
,
struct
btrfs_root_item
);
if
(
btrfs_root_refs
(
ri
)
!=
0
)
goto
next
;
dead_root
=
btrfs_read_fs_root_no_radix
(
root
->
fs_info
,
&
key
);
if
(
IS_ERR
(
root
))
{
ret
=
PTR_ERR
(
root
);
goto
err
;
}
printk
(
"found dead root %Lu %u %Lu
\n
"
,
key
.
objectid
,
key
.
flags
,
key
.
offset
);
ret
=
btrfs_add_dead_root
(
dead_root
,
&
root
->
fs_info
->
dead_roots
);
if
(
ret
)
goto
err
;
next:
slot
++
;
path
->
slots
[
0
]
++
;
}
ret
=
0
;
err:
btrfs_free_path
(
path
);
return
ret
;
}
int
btrfs_del_root
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_key
*
key
)
{
...
...
@@ -111,14 +174,8 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
path
->
slots
[
0
],
struct
btrfs_root_item
);
refs
=
btrfs_root_refs
(
ri
);
BUG_ON
(
refs
==
0
);
if
(
refs
==
1
)
{
BUG_ON
(
refs
!=
0
);
ret
=
btrfs_del_item
(
trans
,
root
,
path
);
}
else
{
btrfs_set_root_refs
(
ri
,
refs
-
1
);
WARN_ON
(
1
);
mark_buffer_dirty
(
path
->
nodes
[
0
]);
}
out:
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
...
...
fs/btrfs/transaction.c
View file @
5eda7b5e
...
...
@@ -85,11 +85,15 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
if
(
root
!=
root
->
fs_info
->
tree_root
&&
root
->
last_trans
<
running_trans_id
)
{
if
(
root
->
root_item
.
refs
!=
0
)
{
radix_tree_tag_set
(
&
root
->
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
root
->
root_key
.
objectid
,
BTRFS_ROOT_TRANS_TAG
);
root
->
commit_root
=
root
->
node
;
get_bh
(
root
->
node
);
}
else
{
WARN_ON
(
1
);
}
}
root
->
last_trans
=
running_trans_id
;
h
->
transid
=
running_trans_id
;
...
...
@@ -208,8 +212,24 @@ struct dirty_root {
struct
btrfs_key
snap_key
;
struct
buffer_head
*
commit_root
;
struct
btrfs_root
*
root
;
int
free_on_drop
;
};
int
btrfs_add_dead_root
(
struct
btrfs_root
*
root
,
struct
list_head
*
dead_list
)
{
struct
dirty_root
*
dirty
;
dirty
=
kmalloc
(
sizeof
(
*
dirty
),
GFP_NOFS
);
if
(
!
dirty
)
return
-
ENOMEM
;
memcpy
(
&
dirty
->
snap_key
,
&
root
->
root_key
,
sizeof
(
root
->
root_key
));
dirty
->
commit_root
=
root
->
node
;
dirty
->
root
=
root
;
dirty
->
free_on_drop
=
1
;
list_add
(
&
dirty
->
list
,
dead_list
);
return
0
;
}
static
int
add_dirty_roots
(
struct
btrfs_trans_handle
*
trans
,
struct
radix_tree_root
*
radix
,
struct
list_head
*
list
)
...
...
@@ -217,9 +237,11 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
struct
dirty_root
*
dirty
;
struct
btrfs_root
*
gang
[
8
];
struct
btrfs_root
*
root
;
struct
btrfs_root_item
tmp_item
;
int
i
;
int
ret
;
int
err
=
0
;
u32
refs
;
while
(
1
)
{
ret
=
radix_tree_gang_lookup_tag
(
radix
,
(
void
**
)
gang
,
0
,
...
...
@@ -246,6 +268,9 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
dirty
->
commit_root
=
root
->
commit_root
;
root
->
commit_root
=
NULL
;
dirty
->
root
=
root
;
dirty
->
free_on_drop
=
0
;
memcpy
(
&
tmp_item
,
&
root
->
root_item
,
sizeof
(
tmp_item
));
root
->
root_key
.
offset
=
root
->
fs_info
->
generation
;
btrfs_set_root_blocknr
(
&
root
->
root_item
,
bh_blocknr
(
root
->
node
));
...
...
@@ -254,7 +279,18 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
&
root
->
root_item
);
if
(
err
)
break
;
refs
=
btrfs_root_refs
(
&
tmp_item
);
btrfs_set_root_refs
(
&
tmp_item
,
refs
-
1
);
err
=
btrfs_update_root
(
trans
,
root
->
fs_info
->
tree_root
,
&
dirty
->
snap_key
,
&
tmp_item
);
BUG_ON
(
err
);
if
(
refs
==
1
)
list_add
(
&
dirty
->
list
,
list
);
else
kfree
(
dirty
);
}
}
return
err
;
...
...
@@ -270,16 +306,20 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
mutex_lock
(
&
tree_root
->
fs_info
->
fs_mutex
);
dirty
=
list_entry
(
list
->
next
,
struct
dirty_root
,
list
);
list_del_init
(
&
dirty
->
list
);
trans
=
btrfs_start_transaction
(
tree_root
,
1
);
printk
(
"deleting root %Lu %u %Lu
\n
"
,
dirty
->
snap_key
.
objectid
,
dirty
->
snap_key
.
flags
,
dirty
->
snap_key
.
offset
);
ret
=
btrfs_drop_snapshot
(
trans
,
dirty
->
root
,
dirty
->
commit_root
);
BUG_ON
(
ret
);
ret
=
btrfs_del_root
(
trans
,
tree_root
,
&
dirty
->
snap_key
);
if
(
ret
)
break
;
ret
=
btrfs_end_transaction
(
trans
,
tree_root
);
BUG_ON
(
ret
);
if
(
dirty
->
free_on_drop
)
kfree
(
dirty
->
root
);
kfree
(
dirty
);
mutex_unlock
(
&
tree_root
->
fs_info
->
fs_mutex
);
btrfs_btree_balance_dirty
(
tree_root
);
...
...
fs/btrfs/transaction.h
View file @
5eda7b5e
...
...
@@ -69,5 +69,6 @@ void btrfs_transaction_flush_work(struct btrfs_root *root);
void
btrfs_transaction_queue_work
(
struct
btrfs_root
*
root
,
int
delay
);
void
btrfs_init_transaction_sys
(
void
);
void
btrfs_exit_transaction_sys
(
void
);
int
btrfs_add_dead_root
(
struct
btrfs_root
*
root
,
struct
list_head
*
dead_list
);
#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