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
8352d8a4
Commit
8352d8a4
authored
Apr 12, 2007
by
Chris Mason
Committed by
David Woodhouse
Apr 12, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: add disk ioctl, mostly working
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
7eccb903
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
221 additions
and
17 deletions
+221
-17
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+121
-7
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+6
-0
fs/btrfs/ioctl.h
fs/btrfs/ioctl.h
+2
-0
fs/btrfs/super.c
fs/btrfs/super.c
+86
-10
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+6
-0
No files found.
fs/btrfs/disk-io.c
View file @
8352d8a4
...
...
@@ -16,6 +16,28 @@ struct dev_lookup {
struct
block_device
*
bdev
;
};
int
btrfs_insert_dev_radix
(
struct
btrfs_root
*
root
,
struct
block_device
*
bdev
,
u64
block_start
,
u64
num_blocks
)
{
struct
dev_lookup
*
lookup
;
char
b
[
BDEVNAME_SIZE
];
int
ret
;
lookup
=
kmalloc
(
sizeof
(
*
lookup
),
GFP_NOFS
);
if
(
!
lookup
)
return
-
ENOMEM
;
lookup
->
block_start
=
block_start
;
lookup
->
num_blocks
=
num_blocks
;
lookup
->
bdev
=
bdev
;
printk
(
"inserting %s into dev radix %Lu %Lu
\n
"
,
bdevname
(
bdev
,
b
),
block_start
,
num_blocks
);
ret
=
radix_tree_insert
(
&
root
->
fs_info
->
dev_radix
,
block_start
+
num_blocks
-
1
,
lookup
);
return
ret
;
}
u64
bh_blocknr
(
struct
buffer_head
*
bh
)
{
int
blkbits
=
bh
->
b_page
->
mapping
->
host
->
i_blkbits
;
...
...
@@ -34,6 +56,8 @@ static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf)
{
struct
btrfs_node
*
node
=
btrfs_buffer_node
(
buf
);
if
(
bh_blocknr
(
buf
)
!=
btrfs_header_blocknr
(
&
node
->
header
))
{
printk
(
KERN_CRIT
"bh_blocknr(buf) is %Lu, header is %Lu
\n
"
,
bh_blocknr
(
buf
),
btrfs_header_blocknr
(
&
node
->
header
));
BUG
();
}
return
0
;
...
...
@@ -76,11 +100,10 @@ struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr)
return
ret
;
}
static
int
map_bh_to_logical
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
bh
,
int
btrfs_
map_bh_to_logical
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
bh
,
u64
logical
)
{
struct
dev_lookup
*
lookup
[
2
];
char
b
[
BDEVNAME_SIZE
];
int
ret
;
...
...
@@ -96,7 +119,6 @@ static int map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh,
}
bh
->
b_bdev
=
lookup
[
0
]
->
bdev
;
bh
->
b_blocknr
=
logical
-
lookup
[
0
]
->
block_start
;
printk
(
"logical mapping %Lu to %lu bdev %s
\n
"
,
logical
,
bh
->
b_blocknr
,
bdevname
(
bh
->
b_bdev
,
b
));
set_buffer_mapped
(
bh
);
ret
=
0
;
out:
...
...
@@ -126,7 +148,7 @@ struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root,
bh
=
head
;
do
{
if
(
!
buffer_mapped
(
bh
))
{
err
=
map_bh_to_logical
(
root
,
bh
,
first_block
);
err
=
btrfs_
map_bh_to_logical
(
root
,
bh
,
first_block
);
BUG_ON
(
err
);
}
if
(
bh_blocknr
(
bh
)
==
blocknr
)
{
...
...
@@ -150,7 +172,7 @@ static int btree_get_block(struct inode *inode, sector_t iblock,
{
int
err
;
struct
btrfs_root
*
root
=
BTRFS_I
(
bh
->
b_page
->
mapping
->
host
)
->
root
;
err
=
map_bh_to_logical
(
root
,
bh
,
iblock
);
err
=
btrfs_
map_bh_to_logical
(
root
,
bh
,
iblock
);
return
err
;
}
...
...
@@ -396,6 +418,89 @@ printk("all worked\n");
return
root
;
}
int
btrfs_open_disk
(
struct
btrfs_root
*
root
,
u64
block_start
,
u64
num_blocks
,
char
*
filename
,
int
name_len
)
{
char
*
null_filename
;
struct
block_device
*
bdev
;
int
ret
;
if
(
block_start
==
0
)
{
printk
(
"skipping disk with block_start == 0
\n
"
);
return
0
;
}
null_filename
=
kmalloc
(
name_len
+
1
,
GFP_NOFS
);
if
(
!
null_filename
)
return
-
ENOMEM
;
memcpy
(
null_filename
,
filename
,
name_len
);
null_filename
[
name_len
]
=
'\0'
;
bdev
=
open_bdev_excl
(
null_filename
,
O_RDWR
,
root
->
fs_info
->
sb
);
if
(
IS_ERR
(
bdev
))
{
ret
=
PTR_ERR
(
bdev
);
goto
out
;
}
set_blocksize
(
bdev
,
root
->
fs_info
->
sb
->
s_blocksize
);
ret
=
btrfs_insert_dev_radix
(
root
,
bdev
,
block_start
,
num_blocks
);
BUG_ON
(
ret
);
ret
=
0
;
out:
kfree
(
null_filename
);
return
ret
;
}
static
int
read_device_info
(
struct
btrfs_root
*
root
)
{
struct
btrfs_path
*
path
;
int
ret
;
struct
btrfs_key
key
;
struct
btrfs_leaf
*
leaf
;
struct
btrfs_device_item
*
dev_item
;
int
nritems
;
int
slot
;
root
=
root
->
fs_info
->
dev_root
;
path
=
btrfs_alloc_path
();
if
(
!
path
)
return
-
ENOMEM
;
key
.
objectid
=
0
;
key
.
offset
=
0
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_DEV_ITEM_KEY
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
ret
=
btrfs_search_slot
(
NULL
,
root
,
&
key
,
path
,
0
,
0
);
leaf
=
btrfs_buffer_leaf
(
path
->
nodes
[
0
]);
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
while
(
1
)
{
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
];
}
btrfs_disk_key_to_cpu
(
&
key
,
&
leaf
->
items
[
slot
].
key
);
if
(
btrfs_key_type
(
&
key
)
!=
BTRFS_DEV_ITEM_KEY
)
{
path
->
slots
[
0
]
++
;
continue
;
}
dev_item
=
btrfs_item_ptr
(
leaf
,
slot
,
struct
btrfs_device_item
);
printk
(
"found key %Lu %Lu
\n
"
,
key
.
objectid
,
key
.
offset
);
ret
=
btrfs_open_disk
(
root
,
key
.
objectid
,
key
.
offset
,
(
char
*
)(
dev_item
+
1
),
btrfs_device_pathlen
(
dev_item
));
BUG_ON
(
ret
);
path
->
slots
[
0
]
++
;
}
btrfs_free_path
(
path
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
return
0
;
}
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
)
{
struct
btrfs_root
*
extent_root
=
kmalloc
(
sizeof
(
struct
btrfs_root
),
...
...
@@ -463,17 +568,26 @@ struct btrfs_root *open_ctree(struct super_block *sb)
if
(
!
btrfs_super_root
(
disk_super
))
return
NULL
;
i_size_write
(
fs_info
->
btree_inode
,
btrfs_super_total_blocks
(
disk_super
)
<<
fs_info
->
btree_inode
->
i_blkbits
);
radix_tree_delete
(
&
fs_info
->
dev_radix
,
(
u32
)
-
2
);
dev_lookup
->
block_start
=
btrfs_super_device_block_start
(
disk_super
);
dev_lookup
->
num_blocks
=
btrfs_super_device_num_blocks
(
disk_super
);
ret
=
radix_tree_insert
(
&
fs_info
->
dev_radix
,
dev_lookup
->
block_start
+
dev_lookup
->
num_blocks
,
dev_lookup
);
dev_lookup
->
num_blocks
-
1
,
dev_lookup
);
BUG_ON
(
ret
);
fs_info
->
disk_super
=
disk_super
;
dev_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_device_root
(
disk_super
));
ret
=
read_device_info
(
dev_root
);
BUG_ON
(
ret
);
tree_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_root
(
disk_super
));
BUG_ON
(
!
tree_root
->
node
);
...
...
@@ -562,7 +676,7 @@ static int free_dev_radix(struct btrfs_fs_info *fs_info)
close_bdev_excl
(
lookup
[
i
]
->
bdev
);
radix_tree_delete
(
&
fs_info
->
dev_radix
,
lookup
[
i
]
->
block_start
+
lookup
[
i
]
->
num_blocks
);
lookup
[
i
]
->
num_blocks
-
1
);
kfree
(
lookup
[
i
]);
}
}
...
...
fs/btrfs/disk-io.h
View file @
8352d8a4
...
...
@@ -42,4 +42,10 @@ int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len,
struct
btrfs_root
*
btrfs_read_fs_root
(
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
,
u64
block_start
,
u64
num_blocks
);
int
btrfs_map_bh_to_logical
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
bh
,
u64
logical
);
#endif
fs/btrfs/ioctl.h
View file @
8352d8a4
...
...
@@ -10,4 +10,6 @@ struct btrfs_ioctl_vol_args {
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_ADD_DISK _IOW(BTRFS_IOCTL_MAGIC, 2, \
struct btrfs_ioctl_vol_args)
#endif
fs/btrfs/super.c
View file @
8352d8a4
...
...
@@ -1073,6 +1073,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
}
map_bh
(
result
,
inode
->
i_sb
,
blocknr
);
btrfs_map_bh_to_logical
(
root
,
result
,
blocknr
);
goto
out
;
}
...
...
@@ -1092,7 +1093,8 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
extent_end
=
extent_start
+
btrfs_file_extent_num_blocks
(
item
);
if
(
iblock
>=
extent_start
&&
iblock
<
extent_end
)
{
err
=
0
;
map_bh
(
result
,
inode
->
i_sb
,
blocknr
+
iblock
-
extent_start
);
btrfs_map_bh_to_logical
(
root
,
result
,
blocknr
+
iblock
-
extent_start
);
goto
out
;
}
allocate:
...
...
@@ -1112,6 +1114,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
set_buffer_new
(
result
);
map_bh
(
result
,
inode
->
i_sb
,
blocknr
);
btrfs_map_bh_to_logical
(
root
,
result
,
blocknr
);
out:
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
...
...
@@ -1153,12 +1156,6 @@ static int btrfs_readpage(struct file *file, struct page *page)
return
mpage_readpage
(
page
,
btrfs_get_block
);
}
static
int
btrfs_readpages
(
struct
file
*
file
,
struct
address_space
*
mapping
,
struct
list_head
*
pages
,
unsigned
nr_pages
)
{
return
mpage_readpages
(
mapping
,
pages
,
nr_pages
,
btrfs_get_block
);
}
static
int
btrfs_writepage
(
struct
page
*
page
,
struct
writeback_control
*
wbc
)
{
return
nobh_writepage
(
page
,
btrfs_get_block
,
wbc
);
...
...
@@ -1831,12 +1828,81 @@ printk("adding snapshot name %.*s root %Lu %Lu %u\n", namelen, name, key.objecti
return
0
;
}
static
int
add_disk
(
struct
btrfs_root
*
root
,
char
*
name
,
int
namelen
)
{
struct
block_device
*
bdev
;
struct
btrfs_path
*
path
;
struct
super_block
*
sb
=
root
->
fs_info
->
sb
;
struct
btrfs_root
*
dev_root
=
root
->
fs_info
->
dev_root
;
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_device_item
*
dev_item
;
struct
btrfs_key
key
;
u16
item_size
;
u64
num_blocks
;
u64
new_blocks
;
int
ret
;
printk
(
"adding disk %s
\n
"
,
name
);
path
=
btrfs_alloc_path
();
if
(
!
path
)
return
-
ENOMEM
;
num_blocks
=
btrfs_super_total_blocks
(
root
->
fs_info
->
disk_super
);
bdev
=
open_bdev_excl
(
name
,
O_RDWR
,
sb
);
if
(
IS_ERR
(
bdev
))
{
ret
=
PTR_ERR
(
bdev
);
printk
(
"open bdev excl failed ret %d
\n
"
,
ret
);
goto
out_nolock
;
}
set_blocksize
(
bdev
,
sb
->
s_blocksize
);
new_blocks
=
bdev
->
bd_inode
->
i_size
>>
sb
->
s_blocksize_bits
;
key
.
objectid
=
num_blocks
;
key
.
offset
=
new_blocks
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_DEV_ITEM_KEY
);
mutex_lock
(
&
dev_root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
dev_root
,
1
);
item_size
=
sizeof
(
*
dev_item
)
+
namelen
;
printk
(
"insert empty on %Lu %Lu %u size %d
\n
"
,
num_blocks
,
new_blocks
,
key
.
flags
,
item_size
);
ret
=
btrfs_insert_empty_item
(
trans
,
dev_root
,
path
,
&
key
,
item_size
);
if
(
ret
)
{
printk
(
"insert failed %d
\n
"
,
ret
);
close_bdev_excl
(
bdev
);
if
(
ret
>
0
)
ret
=
-
EEXIST
;
goto
out
;
}
dev_item
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_device_item
);
btrfs_set_device_pathlen
(
dev_item
,
namelen
);
memcpy
(
dev_item
+
1
,
name
,
namelen
);
mark_buffer_dirty
(
path
->
nodes
[
0
]);
ret
=
btrfs_insert_dev_radix
(
root
,
bdev
,
num_blocks
,
new_blocks
);
if
(
!
ret
)
{
btrfs_set_super_total_blocks
(
root
->
fs_info
->
disk_super
,
num_blocks
+
new_blocks
);
i_size_write
(
root
->
fs_info
->
btree_inode
,
(
num_blocks
+
new_blocks
)
<<
root
->
fs_info
->
btree_inode
->
i_blkbits
);
}
out:
ret
=
btrfs_commit_transaction
(
trans
,
dev_root
);
BUG_ON
(
ret
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
out_nolock:
btrfs_free_path
(
path
);
return
ret
;
}
static
int
btrfs_ioctl
(
struct
inode
*
inode
,
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
struct
btrfs_ioctl_vol_args
vol_args
;
int
ret
;
int
ret
=
0
;
int
namelen
;
struct
btrfs_path
*
path
;
u64
root_dirid
;
...
...
@@ -1869,10 +1935,21 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
ret
=
create_snapshot
(
root
,
vol_args
.
name
,
namelen
);
WARN_ON
(
ret
);
break
;
case
BTRFS_IOC_ADD_DISK
:
if
(
copy_from_user
(
&
vol_args
,
(
struct
btrfs_ioctl_vol_args
__user
*
)
arg
,
sizeof
(
vol_args
)))
return
-
EFAULT
;
namelen
=
strlen
(
vol_args
.
name
);
if
(
namelen
>
BTRFS_VOL_NAME_MAX
)
return
-
EINVAL
;
vol_args
.
name
[
namelen
]
=
'\0'
;
ret
=
add_disk
(
root
,
vol_args
.
name
,
namelen
);
break
;
default:
return
-
ENOTTY
;
}
return
0
;
return
ret
;
}
static
struct
kmem_cache
*
btrfs_inode_cachep
;
...
...
@@ -2004,7 +2081,6 @@ static struct file_operations btrfs_dir_file_operations = {
static
struct
address_space_operations
btrfs_aops
=
{
.
readpage
=
btrfs_readpage
,
.
readpages
=
btrfs_readpages
,
.
writepage
=
btrfs_writepage
,
.
sync_page
=
block_sync_page
,
.
prepare_write
=
btrfs_prepare_write
,
...
...
fs/btrfs/transaction.c
View file @
8352d8a4
...
...
@@ -116,7 +116,13 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
struct
btrfs_fs_info
*
fs_info
=
root
->
fs_info
;
struct
btrfs_root
*
tree_root
=
fs_info
->
tree_root
;
struct
btrfs_root
*
extent_root
=
fs_info
->
extent_root
;
struct
btrfs_root
*
dev_root
=
fs_info
->
dev_root
;
if
(
btrfs_super_device_root
(
fs_info
->
disk_super
)
!=
bh_blocknr
(
dev_root
->
node
))
{
btrfs_set_super_device_root
(
fs_info
->
disk_super
,
bh_blocknr
(
dev_root
->
node
));
}
while
(
1
)
{
old_extent_block
=
btrfs_root_blocknr
(
&
extent_root
->
root_item
);
if
(
old_extent_block
==
bh_blocknr
(
extent_root
->
node
))
...
...
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