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
8a4b83cc
Commit
8a4b83cc
authored
Mar 24, 2008
by
Chris Mason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: Add support for device scanning and detection ioctls
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
239b14b3
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
333 additions
and
44 deletions
+333
-44
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+19
-2
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+15
-9
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+3
-1
fs/btrfs/ioctl.h
fs/btrfs/ioctl.h
+5
-1
fs/btrfs/super.c
fs/btrfs/super.c
+44
-17
fs/btrfs/volumes.c
fs/btrfs/volumes.c
+222
-14
fs/btrfs/volumes.h
fs/btrfs/volumes.h
+25
-0
No files found.
fs/btrfs/ctree.h
View file @
8a4b83cc
...
...
@@ -37,7 +37,7 @@ extern struct kmem_cache *btrfs_transaction_cachep;
extern
struct
kmem_cache
*
btrfs_bit_radix_cachep
;
extern
struct
kmem_cache
*
btrfs_path_cachep
;
#define BTRFS_MAGIC "_B
4
RfS_M"
#define BTRFS_MAGIC "_B
5
RfS_M"
#define BTRFS_MAX_LEVEL 8
...
...
@@ -238,6 +238,7 @@ struct btrfs_super_block {
__le64
total_bytes
;
__le64
bytes_used
;
__le64
root_dir_objectid
;
__le64
num_devices
;
__le32
sectorsize
;
__le32
nodesize
;
__le32
leafsize
;
...
...
@@ -440,6 +441,7 @@ struct btrfs_block_group_cache {
};
struct
btrfs_device
;
struct
btrfs_fs_devices
;
struct
btrfs_fs_info
{
u8
fsid
[
BTRFS_FSID_SIZE
];
struct
btrfs_root
*
extent_root
;
...
...
@@ -489,7 +491,7 @@ struct btrfs_fs_info {
u64
total_pinned
;
struct
list_head
dirty_cowonly_roots
;
struct
list_head
devices
;
struct
btrfs_fs_devices
*
fs_
devices
;
struct
list_head
space_info
;
spinlock_t
delalloc_lock
;
spinlock_t
new_trans_lock
;
...
...
@@ -677,6 +679,19 @@ BTRFS_SETGET_FUNCS(device_io_width, struct btrfs_dev_item, io_width, 32);
BTRFS_SETGET_FUNCS
(
device_sector_size
,
struct
btrfs_dev_item
,
sector_size
,
32
);
BTRFS_SETGET_FUNCS
(
device_id
,
struct
btrfs_dev_item
,
devid
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
stack_device_type
,
struct
btrfs_dev_item
,
type
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
stack_device_total_bytes
,
struct
btrfs_dev_item
,
total_bytes
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
stack_device_bytes_used
,
struct
btrfs_dev_item
,
bytes_used
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
stack_device_io_align
,
struct
btrfs_dev_item
,
io_align
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
stack_device_io_width
,
struct
btrfs_dev_item
,
io_width
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
stack_device_sector_size
,
struct
btrfs_dev_item
,
sector_size
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
stack_device_id
,
struct
btrfs_dev_item
,
devid
,
64
);
static
inline
char
*
btrfs_device_uuid
(
struct
btrfs_dev_item
*
d
)
{
return
(
char
*
)
d
+
offsetof
(
struct
btrfs_dev_item
,
uuid
);
...
...
@@ -1106,6 +1121,8 @@ BTRFS_SETGET_STACK_FUNCS(super_stripesize, struct btrfs_super_block,
stripesize
,
32
);
BTRFS_SETGET_STACK_FUNCS
(
super_root_dir
,
struct
btrfs_super_block
,
root_dir_objectid
,
64
);
BTRFS_SETGET_STACK_FUNCS
(
super_num_devices
,
struct
btrfs_super_block
,
num_devices
,
64
);
static
inline
unsigned
long
btrfs_leaf_data
(
struct
extent_buffer
*
l
)
{
...
...
fs/btrfs/disk-io.c
View file @
8a4b83cc
...
...
@@ -365,12 +365,12 @@ static int close_all_devices(struct btrfs_fs_info *fs_info)
struct
list_head
*
next
;
struct
btrfs_device
*
device
;
list
=
&
fs_info
->
devices
;
while
(
!
list_empty
(
list
))
{
next
=
list
->
next
;
list_del
(
next
);
list
=
&
fs_info
->
fs_devices
->
devices
;
list_for_each
(
next
,
list
)
{
device
=
list_entry
(
next
,
struct
btrfs_device
,
dev_list
);
kfree
(
device
);
if
(
device
->
bdev
&&
device
->
bdev
!=
fs_info
->
sb
->
s_bdev
)
close_bdev_excl
(
device
->
bdev
);
device
->
bdev
=
NULL
;
}
return
0
;
}
...
...
@@ -655,7 +655,8 @@ static int add_hasher(struct btrfs_fs_info *info, char *type) {
return 0;
}
#endif
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
)
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
,
struct
btrfs_fs_devices
*
fs_devices
)
{
u32
sectorsize
;
u32
nodesize
;
...
...
@@ -697,8 +698,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
fs_info
->
extent_root
=
extent_root
;
fs_info
->
chunk_root
=
chunk_root
;
fs_info
->
dev_root
=
dev_root
;
fs_info
->
fs_devices
=
fs_devices
;
INIT_LIST_HEAD
(
&
fs_info
->
dirty_cowonly_roots
);
INIT_LIST_HEAD
(
&
fs_info
->
devices
);
INIT_LIST_HEAD
(
&
fs_info
->
space_info
);
btrfs_mapping_init
(
&
fs_info
->
mapping_tree
);
fs_info
->
sb
=
sb
;
...
...
@@ -779,6 +780,12 @@ struct btrfs_root *open_ctree(struct super_block *sb)
if
(
!
btrfs_super_root
(
disk_super
))
goto
fail_sb_buffer
;
if
(
btrfs_super_num_devices
(
disk_super
)
!=
fs_devices
->
num_devices
)
{
printk
(
"Btrfs: wanted %llu devices, but found %llu
\n
"
,
(
unsigned
long
long
)
btrfs_super_num_devices
(
disk_super
),
(
unsigned
long
long
)
fs_devices
->
num_devices
);
goto
fail_sb_buffer
;
}
nodesize
=
btrfs_super_nodesize
(
disk_super
);
leafsize
=
btrfs_super_leafsize
(
disk_super
);
sectorsize
=
btrfs_super_sectorsize
(
disk_super
);
...
...
@@ -799,8 +806,6 @@ struct btrfs_root *open_ctree(struct super_block *sb)
}
mutex_lock
(
&
fs_info
->
fs_mutex
);
ret
=
btrfs_read_super_device
(
tree_root
,
fs_info
->
sb_buffer
);
BUG_ON
(
ret
);
ret
=
btrfs_read_sys_array
(
tree_root
);
BUG_ON
(
ret
);
...
...
@@ -859,6 +864,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
fail_iput:
iput
(
fs_info
->
btree_inode
);
fail:
close_all_devices
(
fs_info
);
kfree
(
extent_root
);
kfree
(
tree_root
);
kfree
(
fs_info
);
...
...
fs/btrfs/disk-io.h
View file @
8a4b83cc
...
...
@@ -21,6 +21,7 @@
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
struct
btrfs_device
;
struct
btrfs_fs_devices
;
struct
extent_buffer
*
read_tree_block
(
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
);
...
...
@@ -29,7 +30,8 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
u64
bytenr
,
u32
blocksize
);
int
clean_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
);
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
);
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
,
struct
btrfs_fs_devices
*
fs_devices
);
int
close_ctree
(
struct
btrfs_root
*
root
);
int
write_ctree_super
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
...
...
fs/btrfs/ioctl.h
View file @
8a4b83cc
...
...
@@ -22,8 +22,10 @@
#define BTRFS_IOCTL_MAGIC 0x94
#define BTRFS_VOL_NAME_MAX 255
#define BTRFS_PATH_NAME_MAX 4095
struct
btrfs_ioctl_vol_args
{
char
name
[
BTRFS_
VOL
_NAME_MAX
+
1
];
char
name
[
BTRFS_
PATH
_NAME_MAX
+
1
];
};
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
...
...
@@ -32,4 +34,6 @@ struct btrfs_ioctl_vol_args {
struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_RESIZE _IOW(BTRFS_IOCTL_MAGIC, 3, \
struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \
struct btrfs_ioctl_vol_args)
#endif
fs/btrfs/super.c
View file @
8a4b83cc
...
...
@@ -44,6 +44,7 @@
#include "ioctl.h"
#include "print-tree.h"
#include "xattr.h"
#include "volumes.h"
#define BTRFS_SUPER_MAGIC 0x9123683E
...
...
@@ -216,7 +217,9 @@ static int parse_options (char * options,
return
1
;
}
static
int
btrfs_fill_super
(
struct
super_block
*
sb
,
void
*
data
,
int
silent
)
static
int
btrfs_fill_super
(
struct
super_block
*
sb
,
struct
btrfs_fs_devices
*
fs_devices
,
void
*
data
,
int
silent
)
{
struct
inode
*
inode
;
struct
dentry
*
root_dentry
;
...
...
@@ -231,7 +234,7 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
sb
->
s_xattr
=
btrfs_xattr_handlers
;
sb
->
s_time_gran
=
1
;
tree_root
=
open_ctree
(
sb
);
tree_root
=
open_ctree
(
sb
,
fs_devices
);
if
(
!
tree_root
||
IS_ERR
(
tree_root
))
{
printk
(
"btrfs: open_ctree failed
\n
"
);
...
...
@@ -334,18 +337,23 @@ static int test_bdev_super(struct super_block *s, void *data)
int
btrfs_get_sb_bdev
(
struct
file_system_type
*
fs_type
,
int
flags
,
const
char
*
dev_name
,
void
*
data
,
int
(
*
fill_super
)(
struct
super_block
*
,
void
*
,
int
),
struct
vfsmount
*
mnt
,
const
char
*
subvol
)
{
struct
block_device
*
bdev
=
NULL
;
struct
super_block
*
s
;
struct
dentry
*
root
;
struct
btrfs_fs_devices
*
fs_devices
=
NULL
;
int
error
=
0
;
bdev
=
open_bdev_excl
(
dev_name
,
flags
,
fs_type
);
if
(
IS_ERR
(
bdev
)
)
return
PTR_ERR
(
bdev
)
;
error
=
btrfs_scan_one_device
(
dev_name
,
flags
,
fs_type
,
&
fs_devices
);
if
(
error
)
return
error
;
error
=
btrfs_open_devices
(
fs_devices
,
flags
,
fs_type
);
if
(
error
)
return
error
;
bdev
=
fs_devices
->
lowest_bdev
;
/*
* once the super is inserted into the list by sget, s_umount
* will protect the lockfs code from trying to start a snapshot
...
...
@@ -372,7 +380,8 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type,
s
->
s_flags
=
flags
;
strlcpy
(
s
->
s_id
,
bdevname
(
bdev
,
b
),
sizeof
(
s
->
s_id
));
sb_set_blocksize
(
s
,
block_size
(
bdev
));
error
=
fill_super
(
s
,
data
,
flags
&
MS_SILENT
?
1
:
0
);
error
=
btrfs_fill_super
(
s
,
fs_devices
,
data
,
flags
&
MS_SILENT
?
1
:
0
);
if
(
error
)
{
up_write
(
&
s
->
s_umount
);
deactivate_super
(
s
);
...
...
@@ -408,7 +417,7 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type,
error_s:
error
=
PTR_ERR
(
s
);
error_bdev:
close_bdev_excl
(
bdev
);
btrfs_close_devices
(
fs_devices
);
error:
return
error
;
}
...
...
@@ -421,8 +430,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type,
char
*
subvol_name
=
NULL
;
parse_options
((
char
*
)
data
,
NULL
,
&
subvol_name
);
ret
=
btrfs_get_sb_bdev
(
fs_type
,
flags
,
dev_name
,
data
,
btrfs_fill_super
,
mnt
,
ret
=
btrfs_get_sb_bdev
(
fs_type
,
flags
,
dev_name
,
data
,
mnt
,
subvol_name
?
subvol_name
:
"default"
);
if
(
subvol_name
)
kfree
(
subvol_name
);
...
...
@@ -445,13 +453,6 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
return
0
;
}
static
long
btrfs_control_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
printk
(
"btrfs control ioctl %d
\n
"
,
cmd
);
return
0
;
}
static
struct
file_system_type
btrfs_fs_type
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"btrfs"
,
...
...
@@ -460,6 +461,31 @@ static struct file_system_type btrfs_fs_type = {
.
fs_flags
=
FS_REQUIRES_DEV
,
};
static
long
btrfs_control_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
btrfs_ioctl_vol_args
*
vol
;
struct
btrfs_fs_devices
*
fs_devices
;
int
ret
;
int
len
;
vol
=
kmalloc
(
sizeof
(
*
vol
),
GFP_KERNEL
);
if
(
copy_from_user
(
vol
,
(
void
__user
*
)
arg
,
sizeof
(
*
vol
)))
{
ret
=
-
EFAULT
;
goto
out
;
}
len
=
strnlen
(
vol
->
name
,
BTRFS_PATH_NAME_MAX
);
switch
(
cmd
)
{
case
BTRFS_IOC_SCAN_DEV
:
ret
=
btrfs_scan_one_device
(
vol
->
name
,
MS_RDONLY
,
&
btrfs_fs_type
,
&
fs_devices
);
break
;
}
out:
kfree
(
vol
);
return
0
;
}
static
void
btrfs_write_super_lockfs
(
struct
super_block
*
sb
)
{
struct
btrfs_root
*
root
=
btrfs_sb
(
sb
);
...
...
@@ -567,6 +593,7 @@ static void __exit exit_btrfs_fs(void)
btrfs_interface_exit
();
unregister_filesystem
(
&
btrfs_fs_type
);
btrfs_exit_sysfs
();
btrfs_cleanup_fs_uuids
();
}
module_init
(
init_btrfs_fs
)
...
...
fs/btrfs/volumes.c
View file @
8a4b83cc
...
...
@@ -17,6 +17,7 @@
*/
#include <linux/sched.h>
#include <linux/bio.h>
#include <linux/buffer_head.h>
#include "ctree.h"
#include "extent_map.h"
#include "disk-io.h"
...
...
@@ -28,6 +29,215 @@ struct map_lookup {
struct
btrfs_device
*
dev
;
u64
physical
;
};
static
DEFINE_MUTEX
(
uuid_mutex
);
static
LIST_HEAD
(
fs_uuids
);
int
btrfs_cleanup_fs_uuids
(
void
)
{
struct
btrfs_fs_devices
*
fs_devices
;
struct
list_head
*
uuid_cur
;
struct
list_head
*
devices_cur
;
struct
btrfs_device
*
dev
;
list_for_each
(
uuid_cur
,
&
fs_uuids
)
{
fs_devices
=
list_entry
(
uuid_cur
,
struct
btrfs_fs_devices
,
list
);
while
(
!
list_empty
(
&
fs_devices
->
devices
))
{
devices_cur
=
fs_devices
->
devices
.
next
;
dev
=
list_entry
(
devices_cur
,
struct
btrfs_device
,
dev_list
);
printk
(
"uuid cleanup finds %s
\n
"
,
dev
->
name
);
if
(
dev
->
bdev
)
{
printk
(
"closing
\n
"
);
close_bdev_excl
(
dev
->
bdev
);
}
list_del
(
&
dev
->
dev_list
);
kfree
(
dev
);
}
}
return
0
;
}
static
struct
btrfs_device
*
__find_device
(
struct
list_head
*
head
,
u64
devid
)
{
struct
btrfs_device
*
dev
;
struct
list_head
*
cur
;
list_for_each
(
cur
,
head
)
{
dev
=
list_entry
(
cur
,
struct
btrfs_device
,
dev_list
);
if
(
dev
->
devid
==
devid
)
return
dev
;
}
return
NULL
;
}
static
struct
btrfs_fs_devices
*
find_fsid
(
u8
*
fsid
)
{
struct
list_head
*
cur
;
struct
btrfs_fs_devices
*
fs_devices
;
list_for_each
(
cur
,
&
fs_uuids
)
{
fs_devices
=
list_entry
(
cur
,
struct
btrfs_fs_devices
,
list
);
if
(
memcmp
(
fsid
,
fs_devices
->
fsid
,
BTRFS_FSID_SIZE
)
==
0
)
return
fs_devices
;
}
return
NULL
;
}
static
int
device_list_add
(
const
char
*
path
,
struct
btrfs_super_block
*
disk_super
,
u64
devid
,
struct
btrfs_fs_devices
**
fs_devices_ret
)
{
struct
btrfs_device
*
device
;
struct
btrfs_fs_devices
*
fs_devices
;
u64
found_transid
=
btrfs_super_generation
(
disk_super
);
fs_devices
=
find_fsid
(
disk_super
->
fsid
);
if
(
!
fs_devices
)
{
fs_devices
=
kmalloc
(
sizeof
(
*
fs_devices
),
GFP_NOFS
);
if
(
!
fs_devices
)
return
-
ENOMEM
;
INIT_LIST_HEAD
(
&
fs_devices
->
devices
);
list_add
(
&
fs_devices
->
list
,
&
fs_uuids
);
memcpy
(
fs_devices
->
fsid
,
disk_super
->
fsid
,
BTRFS_FSID_SIZE
);
fs_devices
->
latest_devid
=
devid
;
fs_devices
->
latest_trans
=
found_transid
;
fs_devices
->
lowest_devid
=
(
u64
)
-
1
;
fs_devices
->
num_devices
=
0
;
device
=
NULL
;
}
else
{
device
=
__find_device
(
&
fs_devices
->
devices
,
devid
);
}
if
(
!
device
)
{
device
=
kzalloc
(
sizeof
(
*
device
),
GFP_NOFS
);
if
(
!
device
)
{
/* we can safely leave the fs_devices entry around */
return
-
ENOMEM
;
}
device
->
devid
=
devid
;
device
->
name
=
kstrdup
(
path
,
GFP_NOFS
);
if
(
!
device
->
name
)
{
kfree
(
device
);
return
-
ENOMEM
;
}
list_add
(
&
device
->
dev_list
,
&
fs_devices
->
devices
);
fs_devices
->
num_devices
++
;
}
if
(
found_transid
>
fs_devices
->
latest_trans
)
{
fs_devices
->
latest_devid
=
devid
;
fs_devices
->
latest_trans
=
found_transid
;
}
if
(
fs_devices
->
lowest_devid
>
devid
)
{
fs_devices
->
lowest_devid
=
devid
;
printk
(
"lowest devid now %Lu
\n
"
,
devid
);
}
*
fs_devices_ret
=
fs_devices
;
return
0
;
}
int
btrfs_close_devices
(
struct
btrfs_fs_devices
*
fs_devices
)
{
struct
list_head
*
head
=
&
fs_devices
->
devices
;
struct
list_head
*
cur
;
struct
btrfs_device
*
device
;
mutex_lock
(
&
uuid_mutex
);
list_for_each
(
cur
,
head
)
{
device
=
list_entry
(
cur
,
struct
btrfs_device
,
dev_list
);
if
(
device
->
bdev
)
{
close_bdev_excl
(
device
->
bdev
);
printk
(
"close devices closes %s
\n
"
,
device
->
name
);
}
device
->
bdev
=
NULL
;
}
mutex_unlock
(
&
uuid_mutex
);
return
0
;
}
int
btrfs_open_devices
(
struct
btrfs_fs_devices
*
fs_devices
,
int
flags
,
void
*
holder
)
{
struct
block_device
*
bdev
;
struct
list_head
*
head
=
&
fs_devices
->
devices
;
struct
list_head
*
cur
;
struct
btrfs_device
*
device
;
int
ret
;
mutex_lock
(
&
uuid_mutex
);
list_for_each
(
cur
,
head
)
{
device
=
list_entry
(
cur
,
struct
btrfs_device
,
dev_list
);
bdev
=
open_bdev_excl
(
device
->
name
,
flags
,
holder
);
printk
(
"opening %s devid %Lu
\n
"
,
device
->
name
,
device
->
devid
);
if
(
IS_ERR
(
bdev
))
{
printk
(
"open %s failed
\n
"
,
device
->
name
);
ret
=
PTR_ERR
(
bdev
);
goto
fail
;
}
if
(
device
->
devid
==
fs_devices
->
latest_devid
)
fs_devices
->
latest_bdev
=
bdev
;
if
(
device
->
devid
==
fs_devices
->
lowest_devid
)
{
fs_devices
->
lowest_bdev
=
bdev
;
printk
(
"lowest bdev %s
\n
"
,
device
->
name
);
}
device
->
bdev
=
bdev
;
}
mutex_unlock
(
&
uuid_mutex
);
return
0
;
fail:
mutex_unlock
(
&
uuid_mutex
);
btrfs_close_devices
(
fs_devices
);
return
ret
;
}
int
btrfs_scan_one_device
(
const
char
*
path
,
int
flags
,
void
*
holder
,
struct
btrfs_fs_devices
**
fs_devices_ret
)
{
struct
btrfs_super_block
*
disk_super
;
struct
block_device
*
bdev
;
struct
buffer_head
*
bh
;
int
ret
;
u64
devid
;
mutex_lock
(
&
uuid_mutex
);
printk
(
"scan one opens %s
\n
"
,
path
);
bdev
=
open_bdev_excl
(
path
,
flags
,
holder
);
if
(
IS_ERR
(
bdev
))
{
printk
(
"open failed
\n
"
);
ret
=
PTR_ERR
(
bdev
);
goto
error
;
}
ret
=
set_blocksize
(
bdev
,
4096
);
if
(
ret
)
goto
error_close
;
bh
=
__bread
(
bdev
,
BTRFS_SUPER_INFO_OFFSET
/
4096
,
4096
);
if
(
!
bh
)
{
ret
=
-
EIO
;
goto
error_close
;
}
disk_super
=
(
struct
btrfs_super_block
*
)
bh
->
b_data
;
if
(
strncmp
((
char
*
)(
&
disk_super
->
magic
),
BTRFS_MAGIC
,
sizeof
(
disk_super
->
magic
)))
{
printk
(
"no btrfs found on %s
\n
"
,
path
);
ret
=
-
ENOENT
;
goto
error_brelse
;
}
devid
=
le64_to_cpu
(
disk_super
->
dev_item
.
devid
);
printk
(
"found device %Lu on %s
\n
"
,
devid
,
path
);
ret
=
device_list_add
(
path
,
disk_super
,
devid
,
fs_devices_ret
);
error_brelse:
brelse
(
bh
);
error_close:
close_bdev_excl
(
bdev
);
printk
(
"scan one closes bdev %s
\n
"
,
path
);
error:
mutex_unlock
(
&
uuid_mutex
);
return
ret
;
}
/*
* this uses a pretty simple search, the expectation is that it is
...
...
@@ -56,6 +266,10 @@ static int find_free_dev_extent(struct btrfs_trans_handle *trans,
/* FIXME use last free of some kind */
/* we don't want to overwrite the superblock on the drive,
* so we make sure to start at an offset of at least 1MB
*/
search_start
=
max
((
u64
)
1024
*
1024
,
search_start
);
key
.
objectid
=
device
->
devid
;
key
.
offset
=
search_start
;
key
.
type
=
BTRFS_DEV_EXTENT_KEY
;
...
...
@@ -285,6 +499,7 @@ int btrfs_add_device(struct btrfs_trans_handle *trans,
leaf
=
path
->
nodes
[
0
];
dev_item
=
btrfs_item_ptr
(
leaf
,
path
->
slots
[
0
],
struct
btrfs_dev_item
);
device
->
devid
=
free_devid
;
btrfs_set_device_id
(
leaf
,
dev_item
,
device
->
devid
);
btrfs_set_device_type
(
leaf
,
dev_item
,
device
->
type
);
btrfs_set_device_io_align
(
leaf
,
dev_item
,
device
->
io_align
);
...
...
@@ -382,7 +597,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
struct
btrfs_device
*
device
=
NULL
;
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
->
fs_devices
->
devices
;
struct
list_head
*
cur
;
struct
extent_map_tree
*
em_tree
;
struct
map_lookup
*
map
;
...
...
@@ -449,7 +664,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
key
.
objectid
,
calc_size
,
&
dev_offset
);
BUG_ON
(
ret
);
printk
(
"alloc chunk size %Lu from dev %Lu
\n
"
,
calc_size
,
device
->
devid
);
device
->
bytes_used
+=
calc_size
;
ret
=
btrfs_update_device
(
trans
,
device
);
BUG_ON
(
ret
);
...
...
@@ -592,17 +807,9 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio)
struct
btrfs_device
*
btrfs_find_device
(
struct
btrfs_root
*
root
,
u64
devid
)
{
struct
btrfs_device
*
dev
;
struct
list_head
*
cur
=
root
->
fs_info
->
devices
.
next
;
struct
list_head
*
head
=
&
root
->
fs_info
->
devices
;
struct
list_head
*
head
=
&
root
->
fs_info
->
fs_devices
->
devices
;
while
(
cur
!=
head
)
{
dev
=
list_entry
(
cur
,
struct
btrfs_device
,
dev_list
);
if
(
dev
->
devid
==
devid
)
return
dev
;
cur
=
cur
->
next
;
}
return
NULL
;
return
__find_device
(
head
,
devid
);
}
static
int
read_one_chunk
(
struct
btrfs_root
*
root
,
struct
btrfs_key
*
key
,
...
...
@@ -699,15 +906,16 @@ static int read_one_dev(struct btrfs_root *root,
devid
=
btrfs_device_id
(
leaf
,
dev_item
);
device
=
btrfs_find_device
(
root
,
devid
);
if
(
!
device
)
{
printk
(
"warning devid %Lu not found already
\n
"
,
devid
);
device
=
kmalloc
(
sizeof
(
*
device
),
GFP_NOFS
);
if
(
!
device
)
return
-
ENOMEM
;
list_add
(
&
device
->
dev_list
,
&
root
->
fs_info
->
devices
);
list_add
(
&
device
->
dev_list
,
&
root
->
fs_info
->
fs_devices
->
devices
);
}
fill_device_from_item
(
leaf
,
dev_item
,
device
);
device
->
dev_root
=
root
->
fs_info
->
dev_root
;
device
->
bdev
=
root
->
fs_info
->
sb
->
s_bdev
;
ret
=
0
;
#if 0
ret = btrfs_open_device(device);
...
...
fs/btrfs/volumes.h
View file @
8a4b83cc
...
...
@@ -24,6 +24,8 @@ struct btrfs_device {
struct
block_device
*
bdev
;
char
*
name
;
/* the internal btrfs device id */
u64
devid
;
...
...
@@ -49,6 +51,20 @@ struct btrfs_device {
u8
uuid
[
BTRFS_DEV_UUID_SIZE
];
};
struct
btrfs_fs_devices
{
u8
fsid
[
BTRFS_FSID_SIZE
];
/* FS specific uuid */
/* the device with this id has the most recent coyp of the super */
u64
latest_devid
;
u64
latest_trans
;
u64
lowest_devid
;
u64
num_devices
;
struct
block_device
*
latest_bdev
;
struct
block_device
*
lowest_bdev
;
struct
list_head
devices
;
struct
list_head
list
;
};
int
btrfs_alloc_dev_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_device
*
device
,
u64
owner
,
u64
num_bytes
,
u64
*
start
);
...
...
@@ -67,4 +83,13 @@ int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf);
int
btrfs_map_block
(
struct
btrfs_mapping_tree
*
map_tree
,
u64
logical
,
u64
*
phys
,
u64
*
length
,
struct
btrfs_device
**
dev
);
int
btrfs_open_devices
(
struct
btrfs_fs_devices
*
fs_devices
,
int
flags
,
void
*
holder
);
int
btrfs_scan_one_device
(
const
char
*
path
,
int
flags
,
void
*
holder
,
struct
btrfs_fs_devices
**
fs_devices_ret
);
int
btrfs_close_devices
(
struct
btrfs_fs_devices
*
fs_devices
);
int
btrfs_add_device
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_device
*
device
);
int
btrfs_cleanup_fs_uuids
(
void
);
#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