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
6324fbf3
Commit
6324fbf3
authored
Mar 24, 2008
by
Chris Mason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: Dynamic chunk and block group allocation
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
0b86a832
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
263 additions
and
57 deletions
+263
-57
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+11
-1
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+1
-1
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+190
-18
fs/btrfs/inode.c
fs/btrfs/inode.c
+7
-2
fs/btrfs/volumes.c
fs/btrfs/volumes.c
+53
-34
fs/btrfs/volumes.h
fs/btrfs/volumes.h
+1
-1
No files found.
fs/btrfs/ctree.h
View file @
6324fbf3
...
@@ -431,9 +431,19 @@ struct btrfs_block_group_item {
...
@@ -431,9 +431,19 @@ struct btrfs_block_group_item {
__le64
flags
;
__le64
flags
;
}
__attribute__
((
__packed__
));
}
__attribute__
((
__packed__
));
struct
btrfs_space_info
{
u64
flags
;
u64
total_bytes
;
u64
bytes_used
;
u64
bytes_pinned
;
int
full
;
struct
list_head
list
;
};
struct
btrfs_block_group_cache
{
struct
btrfs_block_group_cache
{
struct
btrfs_key
key
;
struct
btrfs_key
key
;
struct
btrfs_block_group_item
item
;
struct
btrfs_block_group_item
item
;
struct
btrfs_space_info
*
space_info
;
u64
pinned
;
u64
pinned
;
u64
flags
;
u64
flags
;
int
cached
;
int
cached
;
...
@@ -490,7 +500,7 @@ struct btrfs_fs_info {
...
@@ -490,7 +500,7 @@ struct btrfs_fs_info {
struct
list_head
dirty_cowonly_roots
;
struct
list_head
dirty_cowonly_roots
;
struct
list_head
devices
;
struct
list_head
devices
;
struct
list_head
*
last_device
;
struct
list_head
space_info
;
spinlock_t
delalloc_lock
;
spinlock_t
delalloc_lock
;
spinlock_t
new_trans_lock
;
spinlock_t
new_trans_lock
;
u64
delalloc_bytes
;
u64
delalloc_bytes
;
...
...
fs/btrfs/disk-io.c
View file @
6324fbf3
...
@@ -700,8 +700,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
...
@@ -700,8 +700,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
fs_info
->
dev_root
=
dev_root
;
fs_info
->
dev_root
=
dev_root
;
INIT_LIST_HEAD
(
&
fs_info
->
dirty_cowonly_roots
);
INIT_LIST_HEAD
(
&
fs_info
->
dirty_cowonly_roots
);
INIT_LIST_HEAD
(
&
fs_info
->
devices
);
INIT_LIST_HEAD
(
&
fs_info
->
devices
);
INIT_LIST_HEAD
(
&
fs_info
->
space_info
);
btrfs_mapping_init
(
&
fs_info
->
mapping_tree
);
btrfs_mapping_init
(
&
fs_info
->
mapping_tree
);
fs_info
->
last_device
=
&
fs_info
->
devices
;
fs_info
->
sb
=
sb
;
fs_info
->
sb
=
sb
;
fs_info
->
throttles
=
0
;
fs_info
->
throttles
=
0
;
fs_info
->
mount_opt
=
0
;
fs_info
->
mount_opt
=
0
;
...
...
fs/btrfs/extent-tree.c
View file @
6324fbf3
...
@@ -36,6 +36,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
...
@@ -36,6 +36,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
btrfs_root
*
extent_root
);
btrfs_root
*
extent_root
);
static
int
del_pending_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
static
int
del_pending_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
);
btrfs_root
*
extent_root
);
int
btrfs_make_block_group
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
bytes_used
,
u64
type
,
u64
chunk_tree
,
u64
chunk_objectid
,
u64
size
);
static
int
cache_block_group
(
struct
btrfs_root
*
root
,
static
int
cache_block_group
(
struct
btrfs_root
*
root
,
...
@@ -168,16 +172,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
...
@@ -168,16 +172,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
static
int
block_group_bits
(
struct
btrfs_block_group_cache
*
cache
,
u64
bits
)
static
int
block_group_bits
(
struct
btrfs_block_group_cache
*
cache
,
u64
bits
)
{
{
if
((
bits
&
BLOCK_GROUP_DATA
)
&&
return
(
cache
->
flags
&
bits
);
(
cache
->
flags
&
BTRFS_BLOCK_GROUP_DATA
))
return
1
;
if
((
bits
&
BLOCK_GROUP_METADATA
)
&&
(
cache
->
flags
&
BTRFS_BLOCK_GROUP_METADATA
))
return
1
;
if
((
bits
&
BLOCK_GROUP_SYSTEM
)
&&
(
cache
->
flags
&
BTRFS_BLOCK_GROUP_SYSTEM
))
return
1
;
return
0
;
}
}
static
int
noinline
find_search_start
(
struct
btrfs_root
*
root
,
static
int
noinline
find_search_start
(
struct
btrfs_root
*
root
,
...
@@ -276,6 +271,18 @@ static u64 div_factor(u64 num, int factor)
...
@@ -276,6 +271,18 @@ static u64 div_factor(u64 num, int factor)
return
num
;
return
num
;
}
}
static
int
block_group_state_bits
(
u64
flags
)
{
int
bits
=
0
;
if
(
flags
&
BTRFS_BLOCK_GROUP_DATA
)
bits
|=
BLOCK_GROUP_DATA
;
if
(
flags
&
BTRFS_BLOCK_GROUP_METADATA
)
bits
|=
BLOCK_GROUP_METADATA
;
if
(
flags
&
BTRFS_BLOCK_GROUP_SYSTEM
)
bits
|=
BLOCK_GROUP_SYSTEM
;
return
bits
;
}
struct
btrfs_block_group_cache
*
btrfs_find_block_group
(
struct
btrfs_root
*
root
,
struct
btrfs_block_group_cache
*
btrfs_find_block_group
(
struct
btrfs_root
*
root
,
struct
btrfs_block_group_cache
struct
btrfs_block_group_cache
*
hint
,
u64
search_start
,
*
hint
,
u64
search_start
,
...
@@ -304,7 +311,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
...
@@ -304,7 +311,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
if
(
!
owner
)
if
(
!
owner
)
factor
=
8
;
factor
=
8
;
bit
=
data
;
bit
=
block_group_state_bits
(
data
)
;
if
(
search_start
&&
search_start
<
total_fs_bytes
)
{
if
(
search_start
&&
search_start
<
total_fs_bytes
)
{
struct
btrfs_block_group_cache
*
shint
;
struct
btrfs_block_group_cache
*
shint
;
...
@@ -358,10 +365,15 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
...
@@ -358,10 +365,15 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
free_check
=
cache
->
key
.
offset
;
free_check
=
cache
->
key
.
offset
;
else
else
free_check
=
div_factor
(
cache
->
key
.
offset
,
factor
);
free_check
=
div_factor
(
cache
->
key
.
offset
,
factor
);
if
(
used
+
cache
->
pinned
<
free_check
)
{
if
(
used
+
cache
->
pinned
<
free_check
)
{
found_group
=
cache
;
found_group
=
cache
;
goto
found
;
goto
found
;
}
}
if
(
full_search
)
{
printk
(
"failed on cache %Lu used %Lu total %Lu
\n
"
,
cache
->
key
.
objectid
,
used
,
cache
->
key
.
offset
);
}
cond_resched
();
cond_resched
();
}
}
if
(
!
full_search
)
{
if
(
!
full_search
)
{
...
@@ -983,6 +995,58 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
...
@@ -983,6 +995,58 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
return
werr
;
return
werr
;
}
}
static
struct
btrfs_space_info
*
__find_space_info
(
struct
btrfs_fs_info
*
info
,
u64
flags
)
{
struct
list_head
*
head
=
&
info
->
space_info
;
struct
list_head
*
cur
;
struct
btrfs_space_info
*
found
;
list_for_each
(
cur
,
head
)
{
found
=
list_entry
(
cur
,
struct
btrfs_space_info
,
list
);
if
(
found
->
flags
==
flags
)
return
found
;
}
return
NULL
;
}
static
int
do_chunk_alloc
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
,
u64
alloc_bytes
,
u64
flags
)
{
struct
btrfs_space_info
*
space_info
;
u64
thresh
;
u64
start
;
u64
num_bytes
;
int
ret
;
space_info
=
__find_space_info
(
extent_root
->
fs_info
,
flags
);
BUG_ON
(
!
space_info
);
if
(
space_info
->
full
)
return
0
;
thresh
=
div_factor
(
space_info
->
total_bytes
,
7
);
if
((
space_info
->
bytes_used
+
space_info
->
bytes_pinned
+
alloc_bytes
)
<
thresh
)
return
0
;
ret
=
btrfs_alloc_chunk
(
trans
,
extent_root
,
&
start
,
&
num_bytes
,
flags
);
if
(
ret
==
-
ENOSPC
)
{
printk
(
"space info full %Lu
\n
"
,
flags
);
space_info
->
full
=
1
;
return
0
;
}
BUG_ON
(
ret
);
ret
=
btrfs_make_block_group
(
trans
,
extent_root
,
0
,
flags
,
extent_root
->
fs_info
->
chunk_root
->
root_key
.
objectid
,
start
,
num_bytes
);
BUG_ON
(
ret
);
return
0
;
}
static
int
update_block_group
(
struct
btrfs_trans_handle
*
trans
,
static
int
update_block_group
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_root
*
root
,
u64
bytenr
,
u64
num_bytes
,
int
alloc
,
u64
bytenr
,
u64
num_bytes
,
int
alloc
,
...
@@ -1012,8 +1076,10 @@ static int update_block_group(struct btrfs_trans_handle *trans,
...
@@ -1012,8 +1076,10 @@ static int update_block_group(struct btrfs_trans_handle *trans,
num_bytes
=
min
(
total
,
cache
->
key
.
offset
-
byte_in_group
);
num_bytes
=
min
(
total
,
cache
->
key
.
offset
-
byte_in_group
);
if
(
alloc
)
{
if
(
alloc
)
{
old_val
+=
num_bytes
;
old_val
+=
num_bytes
;
cache
->
space_info
->
bytes_used
+=
num_bytes
;
}
else
{
}
else
{
old_val
-=
num_bytes
;
old_val
-=
num_bytes
;
cache
->
space_info
->
bytes_used
-=
num_bytes
;
if
(
mark_free
)
{
if
(
mark_free
)
{
set_extent_dirty
(
&
info
->
free_space_cache
,
set_extent_dirty
(
&
info
->
free_space_cache
,
bytenr
,
bytenr
+
num_bytes
-
1
,
bytenr
,
bytenr
+
num_bytes
-
1
,
...
@@ -1026,6 +1092,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
...
@@ -1026,6 +1092,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
}
}
return
0
;
return
0
;
}
}
static
int
update_pinned_extents
(
struct
btrfs_root
*
root
,
static
int
update_pinned_extents
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u64
num
,
int
pin
)
u64
bytenr
,
u64
num
,
int
pin
)
{
{
...
@@ -1047,9 +1114,11 @@ static int update_pinned_extents(struct btrfs_root *root,
...
@@ -1047,9 +1114,11 @@ static int update_pinned_extents(struct btrfs_root *root,
(
bytenr
-
cache
->
key
.
objectid
));
(
bytenr
-
cache
->
key
.
objectid
));
if
(
pin
)
{
if
(
pin
)
{
cache
->
pinned
+=
len
;
cache
->
pinned
+=
len
;
cache
->
space_info
->
bytes_pinned
+=
len
;
fs_info
->
total_pinned
+=
len
;
fs_info
->
total_pinned
+=
len
;
}
else
{
}
else
{
cache
->
pinned
-=
len
;
cache
->
pinned
-=
len
;
cache
->
space_info
->
bytes_pinned
-=
len
;
fs_info
->
total_pinned
-=
len
;
fs_info
->
total_pinned
-=
len
;
}
}
bytenr
+=
len
;
bytenr
+=
len
;
...
@@ -1472,7 +1541,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
...
@@ -1472,7 +1541,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
goto
new_group
;
goto
new_group
;
}
}
if
(
!
(
data
&
BLOCK_GROUP_DATA
))
{
if
(
!
(
data
&
B
TRFS_B
LOCK_GROUP_DATA
))
{
block_group
=
btrfs_lookup_block_group
(
info
,
ins
->
objectid
);
block_group
=
btrfs_lookup_block_group
(
info
,
ins
->
objectid
);
if
(
block_group
)
if
(
block_group
)
trans
->
block_group
=
block_group
;
trans
->
block_group
=
block_group
;
...
@@ -1532,12 +1601,25 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
...
@@ -1532,12 +1601,25 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct
btrfs_path
*
path
;
struct
btrfs_path
*
path
;
struct
btrfs_key
keys
[
2
];
struct
btrfs_key
keys
[
2
];
if
(
data
)
if
(
data
)
{
data
=
BLOCK_GROUP_DATA
;
data
=
BTRFS_BLOCK_GROUP_DATA
;
else
if
(
root
==
root
->
fs_info
->
chunk_root
)
}
else
if
(
root
==
root
->
fs_info
->
chunk_root
)
{
data
=
BLOCK_GROUP_SYSTEM
;
data
=
BTRFS_BLOCK_GROUP_SYSTEM
;
else
}
else
{
data
=
BLOCK_GROUP_METADATA
;
data
=
BTRFS_BLOCK_GROUP_METADATA
;
}
if
(
root
->
ref_cows
)
{
if
(
data
!=
BTRFS_BLOCK_GROUP_METADATA
)
{
ret
=
do_chunk_alloc
(
trans
,
root
->
fs_info
->
extent_root
,
num_bytes
,
BTRFS_BLOCK_GROUP_METADATA
);
BUG_ON
(
ret
);
}
ret
=
do_chunk_alloc
(
trans
,
root
->
fs_info
->
extent_root
,
num_bytes
,
data
);
BUG_ON
(
ret
);
}
new_hint
=
max
(
hint_byte
,
root
->
fs_info
->
alloc_start
);
new_hint
=
max
(
hint_byte
,
root
->
fs_info
->
alloc_start
);
if
(
new_hint
<
btrfs_super_total_bytes
(
&
info
->
super_copy
))
if
(
new_hint
<
btrfs_super_total_bytes
(
&
info
->
super_copy
))
...
@@ -2490,6 +2572,34 @@ int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path,
...
@@ -2490,6 +2572,34 @@ int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path,
return
ret
;
return
ret
;
}
}
static
int
update_space_info
(
struct
btrfs_fs_info
*
info
,
u64
flags
,
u64
total_bytes
,
u64
bytes_used
,
struct
btrfs_space_info
**
space_info
)
{
struct
btrfs_space_info
*
found
;
found
=
__find_space_info
(
info
,
flags
);
if
(
found
)
{
found
->
total_bytes
+=
total_bytes
;
found
->
bytes_used
+=
bytes_used
;
WARN_ON
(
found
->
total_bytes
<
found
->
bytes_used
);
*
space_info
=
found
;
return
0
;
}
found
=
kmalloc
(
sizeof
(
*
found
),
GFP_NOFS
);
if
(
!
found
)
return
-
ENOMEM
;
list_add
(
&
found
->
list
,
&
info
->
space_info
);
found
->
flags
=
flags
;
found
->
total_bytes
=
total_bytes
;
found
->
bytes_used
=
bytes_used
;
found
->
bytes_pinned
=
0
;
found
->
full
=
0
;
*
space_info
=
found
;
return
0
;
}
int
btrfs_read_block_groups
(
struct
btrfs_root
*
root
)
int
btrfs_read_block_groups
(
struct
btrfs_root
*
root
)
{
{
struct
btrfs_path
*
path
;
struct
btrfs_path
*
path
;
...
@@ -2497,6 +2607,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
...
@@ -2497,6 +2607,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
int
bit
;
int
bit
;
struct
btrfs_block_group_cache
*
cache
;
struct
btrfs_block_group_cache
*
cache
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
struct
btrfs_space_info
*
space_info
;
struct
extent_io_tree
*
block_group_cache
;
struct
extent_io_tree
*
block_group_cache
;
struct
btrfs_key
key
;
struct
btrfs_key
key
;
struct
btrfs_key
found_key
;
struct
btrfs_key
found_key
;
...
@@ -2547,6 +2658,12 @@ int btrfs_read_block_groups(struct btrfs_root *root)
...
@@ -2547,6 +2658,12 @@ int btrfs_read_block_groups(struct btrfs_root *root)
bit
=
BLOCK_GROUP_METADATA
;
bit
=
BLOCK_GROUP_METADATA
;
}
}
ret
=
update_space_info
(
info
,
cache
->
flags
,
found_key
.
offset
,
btrfs_block_group_used
(
&
cache
->
item
),
&
space_info
);
BUG_ON
(
ret
);
cache
->
space_info
=
space_info
;
/* use EXTENT_LOCKED to prevent merging */
/* use EXTENT_LOCKED to prevent merging */
set_extent_bits
(
block_group_cache
,
found_key
.
objectid
,
set_extent_bits
(
block_group_cache
,
found_key
.
objectid
,
found_key
.
objectid
+
found_key
.
offset
-
1
,
found_key
.
objectid
+
found_key
.
offset
-
1
,
...
@@ -2563,3 +2680,58 @@ int btrfs_read_block_groups(struct btrfs_root *root)
...
@@ -2563,3 +2680,58 @@ int btrfs_read_block_groups(struct btrfs_root *root)
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
return
ret
;
return
ret
;
}
}
int
btrfs_make_block_group
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
bytes_used
,
u64
type
,
u64
chunk_tree
,
u64
chunk_objectid
,
u64
size
)
{
int
ret
;
int
bit
=
0
;
struct
btrfs_root
*
extent_root
;
struct
btrfs_block_group_cache
*
cache
;
struct
extent_io_tree
*
block_group_cache
;
extent_root
=
root
->
fs_info
->
extent_root
;
block_group_cache
=
&
root
->
fs_info
->
block_group_cache
;
cache
=
kmalloc
(
sizeof
(
*
cache
),
GFP_NOFS
);
BUG_ON
(
!
cache
);
cache
->
key
.
objectid
=
chunk_objectid
;
cache
->
key
.
offset
=
size
;
cache
->
cached
=
0
;
cache
->
pinned
=
0
;
btrfs_set_key_type
(
&
cache
->
key
,
BTRFS_BLOCK_GROUP_ITEM_KEY
);
memset
(
&
cache
->
item
,
0
,
sizeof
(
cache
->
item
));
btrfs_set_block_group_used
(
&
cache
->
item
,
bytes_used
);
btrfs_set_block_group_chunk_tree
(
&
cache
->
item
,
chunk_tree
);
btrfs_set_block_group_chunk_objectid
(
&
cache
->
item
,
chunk_objectid
);
cache
->
flags
=
type
;
btrfs_set_block_group_flags
(
&
cache
->
item
,
type
);
ret
=
update_space_info
(
root
->
fs_info
,
cache
->
flags
,
size
,
bytes_used
,
&
cache
->
space_info
);
BUG_ON
(
ret
);
if
(
type
&
BTRFS_BLOCK_GROUP_DATA
)
{
bit
=
BLOCK_GROUP_DATA
;
}
else
if
(
type
&
BTRFS_BLOCK_GROUP_SYSTEM
)
{
bit
=
BLOCK_GROUP_SYSTEM
;
}
else
if
(
type
&
BTRFS_BLOCK_GROUP_METADATA
)
{
bit
=
BLOCK_GROUP_METADATA
;
}
set_extent_bits
(
block_group_cache
,
chunk_objectid
,
chunk_objectid
+
size
-
1
,
bit
|
EXTENT_LOCKED
,
GFP_NOFS
);
set_state_private
(
block_group_cache
,
chunk_objectid
,
(
unsigned
long
)
cache
);
ret
=
btrfs_insert_item
(
trans
,
extent_root
,
&
cache
->
key
,
&
cache
->
item
,
sizeof
(
cache
->
item
));
BUG_ON
(
ret
);
finish_current_insert
(
trans
,
extent_root
);
ret
=
del_pending_extents
(
trans
,
extent_root
);
BUG_ON
(
ret
);
return
0
;
}
fs/btrfs/inode.c
View file @
6324fbf3
...
@@ -1527,6 +1527,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
...
@@ -1527,6 +1527,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
{
{
struct
inode
*
inode
;
struct
inode
*
inode
;
struct
btrfs_inode_item
*
inode_item
;
struct
btrfs_inode_item
*
inode_item
;
struct
btrfs_block_group_cache
*
new_inode_group
;
struct
btrfs_key
*
location
;
struct
btrfs_key
*
location
;
struct
btrfs_path
*
path
;
struct
btrfs_path
*
path
;
struct
btrfs_inode_ref
*
ref
;
struct
btrfs_inode_ref
*
ref
;
...
@@ -1553,9 +1554,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
...
@@ -1553,9 +1554,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
owner
=
0
;
owner
=
0
;
else
else
owner
=
1
;
owner
=
1
;
group
=
btrfs_find_block_group
(
root
,
group
,
0
,
new_inode_
group
=
btrfs_find_block_group
(
root
,
group
,
0
,
BTRFS_BLOCK_GROUP_METADATA
,
owner
);
BTRFS_BLOCK_GROUP_METADATA
,
owner
);
BTRFS_I
(
inode
)
->
block_group
=
group
;
if
(
!
new_inode_group
)
{
printk
(
"find_block group failed
\n
"
);
new_inode_group
=
group
;
}
BTRFS_I
(
inode
)
->
block_group
=
new_inode_group
;
BTRFS_I
(
inode
)
->
flags
=
0
;
BTRFS_I
(
inode
)
->
flags
=
0
;
key
[
0
].
objectid
=
objectid
;
key
[
0
].
objectid
=
objectid
;
...
...
fs/btrfs/volumes.c
View file @
6324fbf3
...
@@ -131,7 +131,7 @@ static int find_free_dev_extent(struct btrfs_trans_handle *trans,
...
@@ -131,7 +131,7 @@ static int find_free_dev_extent(struct btrfs_trans_handle *trans,
btrfs_release_path
(
root
,
path
);
btrfs_release_path
(
root
,
path
);
BUG_ON
(
*
start
<
search_start
);
BUG_ON
(
*
start
<
search_start
);
if
(
*
start
+
num_bytes
>
=
search_end
)
{
if
(
*
start
+
num_bytes
>
search_end
)
{
ret
=
-
ENOSPC
;
ret
=
-
ENOSPC
;
goto
error
;
goto
error
;
}
}
...
@@ -159,8 +159,9 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
...
@@ -159,8 +159,9 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
return
-
ENOMEM
;
return
-
ENOMEM
;
ret
=
find_free_dev_extent
(
trans
,
device
,
path
,
num_bytes
,
start
);
ret
=
find_free_dev_extent
(
trans
,
device
,
path
,
num_bytes
,
start
);
if
(
ret
)
if
(
ret
)
{
goto
err
;
goto
err
;
}
key
.
objectid
=
device
->
devid
;
key
.
objectid
=
device
->
devid
;
key
.
offset
=
*
start
;
key
.
offset
=
*
start
;
...
@@ -214,22 +215,6 @@ static int find_next_chunk(struct btrfs_root *root, u64 *objectid)
...
@@ -214,22 +215,6 @@ static int find_next_chunk(struct btrfs_root *root, u64 *objectid)
return
ret
;
return
ret
;
}
}
static
struct
btrfs_device
*
next_device
(
struct
list_head
*
head
,
struct
list_head
*
last
)
{
struct
list_head
*
next
=
last
->
next
;
struct
btrfs_device
*
dev
;
if
(
list_empty
(
head
))
return
NULL
;
if
(
next
==
head
)
next
=
next
->
next
;
dev
=
list_entry
(
next
,
struct
btrfs_device
,
dev_list
);
return
dev
;
}
static
int
find_next_devid
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
static
int
find_next_devid
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
*
objectid
)
u64
*
objectid
)
{
{
...
@@ -397,31 +382,63 @@ int btrfs_add_system_chunk(struct btrfs_trans_handle *trans,
...
@@ -397,31 +382,63 @@ int btrfs_add_system_chunk(struct btrfs_trans_handle *trans,
int
btrfs_alloc_chunk
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_alloc_chunk
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
,
u64
*
start
,
struct
btrfs_root
*
extent_root
,
u64
*
start
,
u64
*
num_bytes
,
u
32
type
)
u64
*
num_bytes
,
u
64
type
)
{
{
u64
dev_offset
;
u64
dev_offset
;
struct
btrfs_root
*
chunk_root
=
extent_root
->
fs_info
->
chunk_root
;
struct
btrfs_root
*
chunk_root
=
extent_root
->
fs_info
->
chunk_root
;
struct
btrfs_stripe
*
stripes
;
struct
btrfs_stripe
*
stripes
;
struct
btrfs_device
*
device
=
NULL
;
struct
btrfs_device
*
device
=
NULL
;
struct
btrfs_chunk
*
chunk
;
struct
btrfs_chunk
*
chunk
;
struct
list_head
private_devs
;
struct
list_head
*
dev_list
=
&
extent_root
->
fs_info
->
devices
;
struct
list_head
*
dev_list
=
&
extent_root
->
fs_info
->
devices
;
struct
list_head
*
last_dev
=
extent_root
->
fs_info
->
last_device
;
struct
list_head
*
cur
;
struct
extent_map_tree
*
em_tree
;
struct
extent_map_tree
*
em_tree
;
struct
map_lookup
*
map
;
struct
map_lookup
*
map
;
struct
extent_map
*
em
;
struct
extent_map
*
em
;
u64
physical
;
u64
physical
;
u64
calc_size
=
1024
*
1024
*
1024
;
u64
calc_size
=
1024
*
1024
*
1024
;
int
num_stripes
;
u64
avail
;
u64
max_avail
=
0
;
int
num_stripes
=
1
;
int
looped
=
0
;
int
ret
;
int
ret
;
int
index
=
0
;
int
index
;
struct
btrfs_key
key
;
struct
btrfs_key
key
;
if
(
list_empty
(
dev_list
))
return
-
ENOSPC
;
again:
INIT_LIST_HEAD
(
&
private_devs
);
cur
=
dev_list
->
next
;
index
=
0
;
/* build a private list of devices we will allocate from */
while
(
index
<
num_stripes
)
{
device
=
list_entry
(
cur
,
struct
btrfs_device
,
dev_list
);
avail
=
device
->
total_bytes
-
device
->
bytes_used
;
cur
=
cur
->
next
;
if
(
avail
>
max_avail
)
max_avail
=
avail
;
if
(
avail
>=
calc_size
)
{
list_move_tail
(
&
device
->
dev_list
,
&
private_devs
);
index
++
;
}
if
(
cur
==
dev_list
)
break
;
}
if
(
index
<
num_stripes
)
{
list_splice
(
&
private_devs
,
dev_list
);
if
(
!
looped
&&
max_avail
>
0
)
{
looped
=
1
;
calc_size
=
max_avail
;
goto
again
;
}
return
-
ENOSPC
;
}
ret
=
find_next_chunk
(
chunk_root
,
&
key
.
objectid
);
ret
=
find_next_chunk
(
chunk_root
,
&
key
.
objectid
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
num_stripes
=
1
;
chunk
=
kmalloc
(
btrfs_chunk_item_size
(
num_stripes
),
GFP_NOFS
);
chunk
=
kmalloc
(
btrfs_chunk_item_size
(
num_stripes
),
GFP_NOFS
);
if
(
!
chunk
)
if
(
!
chunk
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -429,11 +446,12 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
...
@@ -429,11 +446,12 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
stripes
=
&
chunk
->
stripe
;
stripes
=
&
chunk
->
stripe
;
*
num_bytes
=
calc_size
;
*
num_bytes
=
calc_size
;
index
=
0
;
while
(
index
<
num_stripes
)
{
while
(
index
<
num_stripes
)
{
device
=
next_device
(
dev_list
,
last_dev
);
BUG_ON
(
list_empty
(
&
private_devs
)
);
BUG_ON
(
!
device
)
;
cur
=
private_devs
.
next
;
last_dev
=
&
device
->
dev_list
;
device
=
list_entry
(
cur
,
struct
btrfs_device
,
dev_list
)
;
extent_root
->
fs_info
->
last_device
=
last_dev
;
list_move_tail
(
&
device
->
dev_list
,
dev_list
)
;
ret
=
btrfs_alloc_dev_extent
(
trans
,
device
,
ret
=
btrfs_alloc_dev_extent
(
trans
,
device
,
key
.
objectid
,
key
.
objectid
,
...
@@ -449,6 +467,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
...
@@ -449,6 +467,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
physical
=
dev_offset
;
physical
=
dev_offset
;
index
++
;
index
++
;
}
}
BUG_ON
(
!
list_empty
(
&
private_devs
));
/* key.objectid was set above */
/* key.objectid was set above */
key
.
offset
=
*
num_bytes
;
key
.
offset
=
*
num_bytes
;
...
@@ -692,17 +711,17 @@ static int read_one_dev(struct btrfs_root *root, struct btrfs_key *key,
...
@@ -692,17 +711,17 @@ static int read_one_dev(struct btrfs_root *root, struct btrfs_key *key,
int
ret
;
int
ret
;
devid
=
btrfs_device_id
(
leaf
,
dev_item
);
devid
=
btrfs_device_id
(
leaf
,
dev_item
);
if
(
btrfs_find_device
(
root
,
devid
))
device
=
btrfs_find_device
(
root
,
devid
);
return
0
;
if
(
!
device
)
{
device
=
kmalloc
(
sizeof
(
*
device
),
GFP_NOFS
);
device
=
kmalloc
(
sizeof
(
*
device
),
GFP_NOFS
);
if
(
!
device
)
if
(
!
device
)
return
-
ENOMEM
;
return
-
ENOMEM
;
list_add
(
&
device
->
dev_list
,
&
root
->
fs_info
->
devices
);
}
fill_device_from_item
(
leaf
,
dev_item
,
device
);
fill_device_from_item
(
leaf
,
dev_item
,
device
);
device
->
dev_root
=
root
->
fs_info
->
dev_root
;
device
->
dev_root
=
root
->
fs_info
->
dev_root
;
device
->
bdev
=
root
->
fs_info
->
sb
->
s_bdev
;
device
->
bdev
=
root
->
fs_info
->
sb
->
s_bdev
;
list_add
(
&
device
->
dev_list
,
&
root
->
fs_info
->
devices
);
memcpy
(
&
device
->
dev_key
,
key
,
sizeof
(
*
key
));
memcpy
(
&
device
->
dev_key
,
key
,
sizeof
(
*
key
));
ret
=
0
;
ret
=
0
;
#if 0
#if 0
...
...
fs/btrfs/volumes.h
View file @
6324fbf3
...
@@ -71,7 +71,7 @@ int btrfs_read_sys_array(struct btrfs_root *root);
...
@@ -71,7 +71,7 @@ int btrfs_read_sys_array(struct btrfs_root *root);
int
btrfs_read_chunk_tree
(
struct
btrfs_root
*
root
);
int
btrfs_read_chunk_tree
(
struct
btrfs_root
*
root
);
int
btrfs_alloc_chunk
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_alloc_chunk
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
extent_root
,
u64
*
start
,
struct
btrfs_root
*
extent_root
,
u64
*
start
,
u64
*
num_bytes
,
u
32
type
);
u64
*
num_bytes
,
u
64
type
);
void
btrfs_mapping_init
(
struct
btrfs_mapping_tree
*
tree
);
void
btrfs_mapping_init
(
struct
btrfs_mapping_tree
*
tree
);
void
btrfs_mapping_tree_free
(
struct
btrfs_mapping_tree
*
tree
);
void
btrfs_mapping_tree_free
(
struct
btrfs_mapping_tree
*
tree
);
int
btrfs_map_bio
(
struct
btrfs_root
*
root
,
int
rw
,
struct
bio
*
bio
);
int
btrfs_map_bio
(
struct
btrfs_root
*
root
,
int
rw
,
struct
bio
*
bio
);
...
...
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