Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
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
Hide 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,8 +326,8 @@ 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_key
*
location
)
struct
btrfs_root
*
btrfs_read_fs_root
_no_radix
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_key
*
location
)
{
struct
btrfs_root
*
root
;
struct
btrfs_root
*
tree_root
=
fs_info
->
tree_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 @@ out:
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 @@ insert:
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
)
{
ret
=
btrfs_del_item
(
trans
,
root
,
path
);
}
else
{
btrfs_set_root_refs
(
ri
,
refs
-
1
);
WARN_ON
(
1
);
mark_buffer_dirty
(
path
->
nodes
[
0
]);
}
BUG_ON
(
refs
!=
0
);
ret
=
btrfs_del_item
(
trans
,
root
,
path
);
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
)
{
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
);
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
;
list_add
(
&
dirty
->
list
,
list
);
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