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
19c00ddc
Commit
19c00ddc
authored
Oct 15, 2007
by
Chris Mason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: Add back metadata checksumming
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
0f82731f
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
245 additions
and
81 deletions
+245
-81
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+2
-0
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+155
-60
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+4
-0
fs/btrfs/extent_map.c
fs/btrfs/extent_map.c
+68
-15
fs/btrfs/extent_map.h
fs/btrfs/extent_map.h
+16
-2
fs/btrfs/inode.c
fs/btrfs/inode.c
+0
-4
No files found.
fs/btrfs/ctree.h
View file @
19c00ddc
...
@@ -310,9 +310,11 @@ struct btrfs_fs_info {
...
@@ -310,9 +310,11 @@ struct btrfs_fs_info {
struct
extent_buffer
*
sb_buffer
;
struct
extent_buffer
*
sb_buffer
;
struct
super_block
*
sb
;
struct
super_block
*
sb
;
struct
inode
*
btree_inode
;
struct
inode
*
btree_inode
;
spinlock_t
hash_lock
;
struct
mutex
trans_mutex
;
struct
mutex
trans_mutex
;
struct
mutex
fs_mutex
;
struct
mutex
fs_mutex
;
struct
list_head
trans_list
;
struct
list_head
trans_list
;
struct
list_head
hashers
;
struct
list_head
dead_roots
;
struct
list_head
dead_roots
;
struct
delayed_work
trans_work
;
struct
delayed_work
trans_work
;
struct
kobject
super_kobj
;
struct
kobject
super_kobj
;
...
...
fs/btrfs/disk-io.c
View file @
19c00ddc
...
@@ -60,7 +60,7 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
...
@@ -60,7 +60,7 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
struct
extent_buffer
*
eb
;
struct
extent_buffer
*
eb
;
eb
=
alloc_extent_buffer
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
eb
=
alloc_extent_buffer
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
bytenr
,
blocksize
,
GFP_NOFS
);
bytenr
,
blocksize
,
NULL
,
GFP_NOFS
);
return
eb
;
return
eb
;
}
}
...
@@ -99,10 +99,102 @@ struct extent_map *btree_get_extent(struct inode *inode, struct page *page,
...
@@ -99,10 +99,102 @@ struct extent_map *btree_get_extent(struct inode *inode, struct page *page,
return
em
;
return
em
;
}
}
u32
btrfs_csum_data
(
struct
btrfs_root
*
root
,
char
*
data
,
u32
seed
,
size_t
len
)
{
return
crc32c
(
seed
,
data
,
len
);
}
void
btrfs_csum_final
(
u32
crc
,
char
*
result
)
{
*
(
__le32
*
)
result
=
~
cpu_to_le32
(
crc
);
}
static
int
csum_tree_block
(
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
,
int
verify
)
{
char
result
[
BTRFS_CRC32_SIZE
];
unsigned
long
len
;
unsigned
long
cur_len
;
unsigned
long
offset
=
BTRFS_CSUM_SIZE
;
char
*
map_token
=
NULL
;
char
*
kaddr
;
unsigned
long
map_start
;
unsigned
long
map_len
;
int
err
;
u32
crc
=
~
(
u32
)
0
;
len
=
buf
->
len
-
offset
;
while
(
len
>
0
)
{
err
=
map_private_extent_buffer
(
buf
,
offset
,
32
,
&
map_token
,
&
kaddr
,
&
map_start
,
&
map_len
,
KM_USER0
);
if
(
err
)
{
printk
(
"failed to map extent buffer! %lu
\n
"
,
offset
);
return
1
;
}
cur_len
=
min
(
len
,
map_len
-
(
offset
-
map_start
));
crc
=
btrfs_csum_data
(
root
,
kaddr
+
offset
-
map_start
,
crc
,
cur_len
);
len
-=
cur_len
;
offset
+=
cur_len
;
unmap_extent_buffer
(
buf
,
map_token
,
KM_USER0
);
}
btrfs_csum_final
(
crc
,
result
);
if
(
verify
)
{
if
(
memcmp_extent_buffer
(
buf
,
result
,
0
,
BTRFS_CRC32_SIZE
))
{
printk
(
"btrfs: %s checksum verify failed on %llu
\n
"
,
root
->
fs_info
->
sb
->
s_id
,
buf
->
start
);
return
1
;
}
}
else
{
write_extent_buffer
(
buf
,
result
,
0
,
BTRFS_CRC32_SIZE
);
}
return
0
;
}
int
csum_dirty_buffer
(
struct
btrfs_root
*
root
,
struct
page
*
page
)
{
struct
extent_map_tree
*
tree
;
u64
start
=
page
->
index
<<
PAGE_CACHE_SHIFT
;
u64
found_start
;
int
found_level
;
unsigned
long
len
;
struct
extent_buffer
*
eb
;
tree
=
&
BTRFS_I
(
page
->
mapping
->
host
)
->
extent_tree
;
if
(
page
->
private
==
EXTENT_PAGE_PRIVATE
)
goto
out
;
if
(
!
page
->
private
)
goto
out
;
len
=
page
->
private
>>
2
;
if
(
len
==
0
)
{
WARN_ON
(
1
);
}
eb
=
alloc_extent_buffer
(
tree
,
start
,
len
,
page
,
GFP_NOFS
);
read_extent_buffer_pages
(
tree
,
eb
,
start
+
PAGE_CACHE_SIZE
,
1
);
found_start
=
btrfs_header_bytenr
(
eb
);
if
(
found_start
!=
start
)
{
printk
(
"warning: eb start incorrect %Lu buffer %Lu len %lu
\n
"
,
start
,
found_start
,
len
);
}
found_level
=
btrfs_header_level
(
eb
);
csum_tree_block
(
root
,
eb
,
0
);
free_extent_buffer
(
eb
);
out:
return
0
;
}
static
int
btree_writepage
(
struct
page
*
page
,
struct
writeback_control
*
wbc
)
static
int
btree_writepage
(
struct
page
*
page
,
struct
writeback_control
*
wbc
)
{
{
struct
extent_map_tree
*
tree
;
struct
extent_map_tree
*
tree
;
struct
btrfs_root
*
root
=
BTRFS_I
(
page
->
mapping
->
host
)
->
root
;
tree
=
&
BTRFS_I
(
page
->
mapping
->
host
)
->
extent_tree
;
tree
=
&
BTRFS_I
(
page
->
mapping
->
host
)
->
extent_tree
;
csum_dirty_buffer
(
root
,
page
);
return
extent_write_full_page
(
tree
,
page
,
btree_get_extent
,
wbc
);
return
extent_write_full_page
(
tree
,
page
,
btree_get_extent
,
wbc
);
}
}
int
btree_readpage
(
struct
file
*
file
,
struct
page
*
page
)
int
btree_readpage
(
struct
file
*
file
,
struct
page
*
page
)
...
@@ -117,7 +209,6 @@ static int btree_releasepage(struct page *page, gfp_t unused_gfp_flags)
...
@@ -117,7 +209,6 @@ static int btree_releasepage(struct page *page, gfp_t unused_gfp_flags)
struct
extent_map_tree
*
tree
;
struct
extent_map_tree
*
tree
;
int
ret
;
int
ret
;
BUG_ON
(
page
->
private
!=
1
);
tree
=
&
BTRFS_I
(
page
->
mapping
->
host
)
->
extent_tree
;
tree
=
&
BTRFS_I
(
page
->
mapping
->
host
)
->
extent_tree
;
ret
=
try_release_extent_mapping
(
tree
,
page
);
ret
=
try_release_extent_mapping
(
tree
,
page
);
if
(
ret
==
1
)
{
if
(
ret
==
1
)
{
...
@@ -136,46 +227,6 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
...
@@ -136,46 +227,6 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
btree_releasepage
(
page
,
GFP_NOFS
);
btree_releasepage
(
page
,
GFP_NOFS
);
}
}
int
btrfs_csum_data
(
struct
btrfs_root
*
root
,
char
*
data
,
size_t
len
,
char
*
result
)
{
return
0
;
#if 0
u32 crc;
crc = crc32c(0, data, len);
memcpy(result, &crc, BTRFS_CRC32_SIZE);
return 0;
#endif
}
#if 0
static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
int verify)
{
return 0;
char result[BTRFS_CRC32_SIZE];
int ret;
struct btrfs_node *node;
ret = btrfs_csum_data(root, bh->b_data + BTRFS_CSUM_SIZE,
bh->b_size - BTRFS_CSUM_SIZE, result);
if (ret)
return ret;
if (verify) {
if (memcmp(bh->b_data, result, BTRFS_CRC32_SIZE)) {
printk("btrfs: %s checksum verify failed on %llu\n",
root->fs_info->sb->s_id,
(unsigned long long)bh_blocknr(bh));
return 1;
}
} else {
node = btrfs_buffer_node(bh);
memcpy(node->header.csum, result, BTRFS_CRC32_SIZE);
}
return 0;
}
#endif
#if 0
#if 0
static int btree_writepage(struct page *page, struct writeback_control *wbc)
static int btree_writepage(struct page *page, struct writeback_control *wbc)
{
{
...
@@ -215,7 +266,7 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize)
...
@@ -215,7 +266,7 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize)
if
(
!
buf
)
if
(
!
buf
)
return
0
;
return
0
;
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
,
0
);
buf
,
0
,
0
);
free_extent_buffer
(
buf
);
free_extent_buffer
(
buf
);
return
ret
;
return
ret
;
}
}
...
@@ -225,12 +276,29 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
...
@@ -225,12 +276,29 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
{
{
struct
extent_buffer
*
buf
=
NULL
;
struct
extent_buffer
*
buf
=
NULL
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
extent_map_tree
*
extent_tree
;
int
ret
;
extent_tree
=
&
BTRFS_I
(
btree_inode
)
->
extent_tree
;
buf
=
btrfs_find_create_tree_block
(
root
,
bytenr
,
blocksize
);
buf
=
btrfs_find_create_tree_block
(
root
,
bytenr
,
blocksize
);
if
(
!
buf
)
if
(
!
buf
)
return
NULL
;
return
NULL
;
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
,
1
);
buf
,
0
,
1
);
if
(
buf
->
flags
&
EXTENT_CSUM
)
{
return
buf
;
}
if
(
test_range_bit
(
extent_tree
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
EXTENT_CSUM
,
1
))
{
buf
->
flags
|=
EXTENT_CSUM
;
return
buf
;
}
ret
=
csum_tree_block
(
root
,
buf
,
1
);
set_extent_bits
(
extent_tree
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
EXTENT_CSUM
,
GFP_NOFS
);
buf
->
flags
|=
EXTENT_CSUM
;
return
buf
;
return
buf
;
}
}
...
@@ -251,13 +319,6 @@ int wait_on_tree_block_writeback(struct btrfs_root *root,
...
@@ -251,13 +319,6 @@ int wait_on_tree_block_writeback(struct btrfs_root *root,
return
0
;
return
0
;
}
}
int
set_tree_block_dirty
(
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
)
{
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
set_extent_buffer_dirty
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
);
return
0
;
}
static
int
__setup_root
(
u32
nodesize
,
u32
leafsize
,
u32
sectorsize
,
static
int
__setup_root
(
u32
nodesize
,
u32
leafsize
,
u32
sectorsize
,
struct
btrfs_root
*
root
,
struct
btrfs_root
*
root
,
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_fs_info
*
fs_info
,
...
@@ -416,7 +477,24 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
...
@@ -416,7 +477,24 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
return
root
;
return
root
;
}
}
#if 0
static int add_hasher(struct btrfs_fs_info *info, char *type) {
struct btrfs_hasher *hasher;
hasher = kmalloc(sizeof(*hasher), GFP_NOFS);
if (!hasher)
return -ENOMEM;
hasher->hash_tfm = crypto_alloc_hash(type, 0, CRYPTO_ALG_ASYNC);
if (!hasher->hash_tfm) {
kfree(hasher);
return -EINVAL;
}
spin_lock(&info->hash_lock);
list_add(&hasher->list, &info->hashers);
spin_unlock(&info->hash_lock);
return 0;
}
#endif
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
)
struct
btrfs_root
*
open_ctree
(
struct
super_block
*
sb
)
{
{
u32
sectorsize
;
u32
sectorsize
;
...
@@ -440,6 +518,9 @@ struct btrfs_root *open_ctree(struct super_block *sb)
...
@@ -440,6 +518,9 @@ struct btrfs_root *open_ctree(struct super_block *sb)
INIT_RADIX_TREE
(
&
fs_info
->
fs_roots_radix
,
GFP_NOFS
);
INIT_RADIX_TREE
(
&
fs_info
->
fs_roots_radix
,
GFP_NOFS
);
INIT_LIST_HEAD
(
&
fs_info
->
trans_list
);
INIT_LIST_HEAD
(
&
fs_info
->
trans_list
);
INIT_LIST_HEAD
(
&
fs_info
->
dead_roots
);
INIT_LIST_HEAD
(
&
fs_info
->
dead_roots
);
INIT_LIST_HEAD
(
&
fs_info
->
hashers
);
spin_lock_init
(
&
fs_info
->
hash_lock
);
memset
(
&
fs_info
->
super_kobj
,
0
,
sizeof
(
fs_info
->
super_kobj
));
memset
(
&
fs_info
->
super_kobj
,
0
,
sizeof
(
fs_info
->
super_kobj
));
init_completion
(
&
fs_info
->
kobj_unregister
);
init_completion
(
&
fs_info
->
kobj_unregister
);
sb_set_blocksize
(
sb
,
4096
);
sb_set_blocksize
(
sb
,
4096
);
...
@@ -479,6 +560,14 @@ struct btrfs_root *open_ctree(struct super_block *sb)
...
@@ -479,6 +560,14 @@ struct btrfs_root *open_ctree(struct super_block *sb)
mutex_init
(
&
fs_info
->
trans_mutex
);
mutex_init
(
&
fs_info
->
trans_mutex
);
mutex_init
(
&
fs_info
->
fs_mutex
);
mutex_init
(
&
fs_info
->
fs_mutex
);
#if 0
ret = add_hasher(fs_info, "crc32c");
if (ret) {
printk("btrfs: failed hash setup, modprobe cryptomgr?\n");
err = -ENOMEM;
goto fail_iput;
}
#endif
__setup_root
(
512
,
512
,
512
,
tree_root
,
__setup_root
(
512
,
512
,
512
,
tree_root
,
fs_info
,
BTRFS_ROOT_TREE_OBJECTID
);
fs_info
,
BTRFS_ROOT_TREE_OBJECTID
);
...
@@ -509,25 +598,21 @@ struct btrfs_root *open_ctree(struct super_block *sb)
...
@@ -509,25 +598,21 @@ struct btrfs_root *open_ctree(struct super_block *sb)
i_size_write
(
fs_info
->
btree_inode
,
i_size_write
(
fs_info
->
btree_inode
,
btrfs_super_total_bytes
(
disk_super
));
btrfs_super_total_bytes
(
disk_super
));
if
(
strncmp
((
char
*
)(
&
disk_super
->
magic
),
BTRFS_MAGIC
,
if
(
strncmp
((
char
*
)(
&
disk_super
->
magic
),
BTRFS_MAGIC
,
sizeof
(
disk_super
->
magic
)))
{
sizeof
(
disk_super
->
magic
)))
{
printk
(
"btrfs: valid FS not found on %s
\n
"
,
sb
->
s_id
);
printk
(
"btrfs: valid FS not found on %s
\n
"
,
sb
->
s_id
);
goto
fail_sb_buffer
;
goto
fail_sb_buffer
;
}
}
blocksize
=
btrfs_level_size
(
tree_root
,
blocksize
=
btrfs_level_size
(
tree_root
,
btrfs_super_root_level
(
disk_super
));
btrfs_super_root_level
(
disk_super
));
tree_root
->
node
=
read_tree_block
(
tree_root
,
tree_root
->
node
=
read_tree_block
(
tree_root
,
btrfs_super_root
(
disk_super
),
btrfs_super_root
(
disk_super
),
blocksize
);
blocksize
);
if
(
!
tree_root
->
node
)
if
(
!
tree_root
->
node
)
goto
fail_sb_buffer
;
goto
fail_sb_buffer
;
#if 0
btrfs_print_leaf(tree_root, tree_root->node);
err = -EIO;
goto fail_tree_root;
#endif
mutex_lock
(
&
fs_info
->
fs_mutex
);
mutex_lock
(
&
fs_info
->
fs_mutex
);
ret
=
find_and_setup_root
(
tree_root
,
fs_info
,
ret
=
find_and_setup_root
(
tree_root
,
fs_info
,
...
@@ -634,9 +719,19 @@ int close_ctree(struct btrfs_root *root)
...
@@ -634,9 +719,19 @@ int close_ctree(struct btrfs_root *root)
btrfs_free_block_groups
(
root
->
fs_info
);
btrfs_free_block_groups
(
root
->
fs_info
);
del_fs_roots
(
fs_info
);
del_fs_roots
(
fs_info
);
extent_map_tree_
cleanup
(
&
BTRFS_I
(
fs_info
->
btree_inode
)
->
extent_tree
);
extent_map_tree_
empty_lru
(
&
BTRFS_I
(
fs_info
->
btree_inode
)
->
extent_tree
);
truncate_inode_pages
(
fs_info
->
btree_inode
->
i_mapping
,
0
);
truncate_inode_pages
(
fs_info
->
btree_inode
->
i_mapping
,
0
);
iput
(
fs_info
->
btree_inode
);
iput
(
fs_info
->
btree_inode
);
#if 0
while(!list_empty(&fs_info->hashers)) {
struct btrfs_hasher *hasher;
hasher = list_entry(fs_info->hashers.next, struct btrfs_hasher,
hashers);
list_del(&hasher->hashers);
crypto_free_hash(&fs_info->hash_tfm);
kfree(hasher);
}
#endif
kfree
(
fs_info
->
extent_root
);
kfree
(
fs_info
->
extent_root
);
kfree
(
fs_info
->
tree_root
);
kfree
(
fs_info
->
tree_root
);
return
0
;
return
0
;
...
@@ -733,5 +828,5 @@ int btrfs_read_buffer(struct extent_buffer *buf)
...
@@ -733,5 +828,5 @@ int btrfs_read_buffer(struct extent_buffer *buf)
struct
btrfs_root
*
root
=
BTRFS_I
(
buf
->
first_page
->
mapping
->
host
)
->
root
;
struct
btrfs_root
*
root
=
BTRFS_I
(
buf
->
first_page
->
mapping
->
host
)
->
root
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
return
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
return
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
,
1
);
buf
,
0
,
1
);
}
}
fs/btrfs/extent-tree.c
View file @
19c00ddc
...
@@ -1178,6 +1178,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
...
@@ -1178,6 +1178,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
btrfs_set_buffer_uptodate
(
buf
);
btrfs_set_buffer_uptodate
(
buf
);
set_extent_dirty
(
&
trans
->
transaction
->
dirty_pages
,
buf
->
start
,
set_extent_dirty
(
&
trans
->
transaction
->
dirty_pages
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
GFP_NOFS
);
buf
->
start
+
buf
->
len
-
1
,
GFP_NOFS
);
set_extent_bits
(
&
BTRFS_I
(
root
->
fs_info
->
btree_inode
)
->
extent_tree
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
EXTENT_CSUM
,
GFP_NOFS
);
buf
->
flags
|=
EXTENT_CSUM
;
btrfs_set_buffer_defrag
(
buf
);
btrfs_set_buffer_defrag
(
buf
);
trans
->
blocks_used
++
;
trans
->
blocks_used
++
;
return
buf
;
return
buf
;
...
...
fs/btrfs/extent_map.c
View file @
19c00ddc
...
@@ -81,7 +81,7 @@ void extent_map_tree_init(struct extent_map_tree *tree,
...
@@ -81,7 +81,7 @@ void extent_map_tree_init(struct extent_map_tree *tree,
}
}
EXPORT_SYMBOL
(
extent_map_tree_init
);
EXPORT_SYMBOL
(
extent_map_tree_init
);
void
extent_map_tree_
cleanup
(
struct
extent_map_tree
*
tree
)
void
extent_map_tree_
empty_lru
(
struct
extent_map_tree
*
tree
)
{
{
struct
extent_buffer
*
eb
;
struct
extent_buffer
*
eb
;
while
(
!
list_empty
(
&
tree
->
buffer_lru
))
{
while
(
!
list_empty
(
&
tree
->
buffer_lru
))
{
...
@@ -91,7 +91,7 @@ void extent_map_tree_cleanup(struct extent_map_tree *tree)
...
@@ -91,7 +91,7 @@ void extent_map_tree_cleanup(struct extent_map_tree *tree)
free_extent_buffer
(
eb
);
free_extent_buffer
(
eb
);
}
}
}
}
EXPORT_SYMBOL
(
extent_map_tree_
cleanup
);
EXPORT_SYMBOL
(
extent_map_tree_
empty_lru
);
struct
extent_map
*
alloc_extent_map
(
gfp_t
mask
)
struct
extent_map
*
alloc_extent_map
(
gfp_t
mask
)
{
{
...
@@ -1464,7 +1464,7 @@ void set_page_extent_mapped(struct page *page)
...
@@ -1464,7 +1464,7 @@ void set_page_extent_mapped(struct page *page)
if
(
!
PagePrivate
(
page
))
{
if
(
!
PagePrivate
(
page
))
{
SetPagePrivate
(
page
);
SetPagePrivate
(
page
);
WARN_ON
(
!
page
->
mapping
->
a_ops
->
invalidatepage
);
WARN_ON
(
!
page
->
mapping
->
a_ops
->
invalidatepage
);
set_page_private
(
page
,
1
);
set_page_private
(
page
,
EXTENT_PAGE_PRIVATE
);
page_cache_get
(
page
);
page_cache_get
(
page
);
}
}
}
}
...
@@ -1979,8 +1979,9 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_map_tree *tree,
...
@@ -1979,8 +1979,9 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_map_tree *tree,
spin_lock
(
&
tree
->
lru_lock
);
spin_lock
(
&
tree
->
lru_lock
);
eb
=
find_lru
(
tree
,
start
,
len
);
eb
=
find_lru
(
tree
,
start
,
len
);
if
(
eb
)
if
(
eb
)
{
goto
lru_add
;
goto
lru_add
;
}
spin_unlock
(
&
tree
->
lru_lock
);
spin_unlock
(
&
tree
->
lru_lock
);
if
(
eb
)
{
if
(
eb
)
{
...
@@ -2007,6 +2008,7 @@ static void __free_extent_buffer(struct extent_buffer *eb)
...
@@ -2007,6 +2008,7 @@ static void __free_extent_buffer(struct extent_buffer *eb)
struct
extent_buffer
*
alloc_extent_buffer
(
struct
extent_map_tree
*
tree
,
struct
extent_buffer
*
alloc_extent_buffer
(
struct
extent_map_tree
*
tree
,
u64
start
,
unsigned
long
len
,
u64
start
,
unsigned
long
len
,
struct
page
*
page0
,
gfp_t
mask
)
gfp_t
mask
)
{
{
unsigned
long
num_pages
=
num_extent_pages
(
start
,
len
);
unsigned
long
num_pages
=
num_extent_pages
(
start
,
len
);
...
@@ -2024,7 +2026,18 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
...
@@ -2024,7 +2026,18 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
if
(
eb
->
flags
&
EXTENT_BUFFER_FILLED
)
if
(
eb
->
flags
&
EXTENT_BUFFER_FILLED
)
return
eb
;
return
eb
;
for
(
i
=
0
;
i
<
num_pages
;
i
++
,
index
++
)
{
if
(
page0
)
{
eb
->
first_page
=
page0
;
i
=
1
;
index
++
;
page_cache_get
(
page0
);
set_page_extent_mapped
(
page0
);
set_page_private
(
page0
,
EXTENT_PAGE_PRIVATE_FIRST_PAGE
|
len
<<
2
);
}
else
{
i
=
0
;
}
for
(;
i
<
num_pages
;
i
++
,
index
++
)
{
p
=
find_or_create_page
(
mapping
,
index
,
mask
|
__GFP_HIGHMEM
);
p
=
find_or_create_page
(
mapping
,
index
,
mask
|
__GFP_HIGHMEM
);
if
(
!
p
)
{
if
(
!
p
)
{
WARN_ON
(
1
);
WARN_ON
(
1
);
...
@@ -2036,8 +2049,13 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
...
@@ -2036,8 +2049,13 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
goto
fail
;
goto
fail
;
}
}
set_page_extent_mapped
(
p
);
set_page_extent_mapped
(
p
);
if
(
i
==
0
)
if
(
i
==
0
)
{
eb
->
first_page
=
p
;
eb
->
first_page
=
p
;
set_page_private
(
p
,
EXTENT_PAGE_PRIVATE_FIRST_PAGE
|
len
<<
2
);
}
else
{
set_page_private
(
p
,
EXTENT_PAGE_PRIVATE
);
}
if
(
!
PageUptodate
(
p
))
if
(
!
PageUptodate
(
p
))
uptodate
=
0
;
uptodate
=
0
;
unlock_page
(
p
);
unlock_page
(
p
);
...
@@ -2057,8 +2075,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
...
@@ -2057,8 +2075,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
gfp_t
mask
)
gfp_t
mask
)
{
{
unsigned
long
num_pages
=
num_extent_pages
(
start
,
len
);
unsigned
long
num_pages
=
num_extent_pages
(
start
,
len
);
unsigned
long
i
;
unsigned
long
i
;
unsigned
long
index
=
start
>>
PAGE_CACHE_SHIFT
;
unsigned
long
index
=
start
>>
PAGE_CACHE_SHIFT
;
struct
extent_buffer
*
eb
;
struct
extent_buffer
*
eb
;
struct
page
*
p
;
struct
page
*
p
;
struct
address_space
*
mapping
=
tree
->
mapping
;
struct
address_space
*
mapping
=
tree
->
mapping
;
...
@@ -2082,8 +2099,15 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
...
@@ -2082,8 +2099,15 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
goto
fail
;
goto
fail
;
}
}
set_page_extent_mapped
(
p
);
set_page_extent_mapped
(
p
);
if
(
i
==
0
)
if
(
i
==
0
)
{
eb
->
first_page
=
p
;
eb
->
first_page
=
p
;
set_page_private
(
p
,
EXTENT_PAGE_PRIVATE_FIRST_PAGE
|
len
<<
2
);
}
else
{
set_page_private
(
p
,
EXTENT_PAGE_PRIVATE
);
}
if
(
!
PageUptodate
(
p
))
if
(
!
PageUptodate
(
p
))
uptodate
=
0
;
uptodate
=
0
;
unlock_page
(
p
);
unlock_page
(
p
);
...
@@ -2174,7 +2198,21 @@ int set_extent_buffer_dirty(struct extent_map_tree *tree,
...
@@ -2174,7 +2198,21 @@ int set_extent_buffer_dirty(struct extent_map_tree *tree,
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
struct
page
*
page
=
extent_buffer_page
(
eb
,
i
);
/* writepage may need to do something special for the
* first page, we have to make sure page->private is
* properly set. releasepage may drop page->private
* on us if the page isn't already dirty.
*/
if
(
i
==
0
)
{
lock_page
(
page
);
set_page_private
(
page
,
EXTENT_PAGE_PRIVATE_FIRST_PAGE
|
eb
->
len
<<
2
);
}
__set_page_dirty_nobuffers
(
extent_buffer_page
(
eb
,
i
));
__set_page_dirty_nobuffers
(
extent_buffer_page
(
eb
,
i
));
if
(
i
==
0
)
unlock_page
(
page
);
}
}
return
set_extent_dirty
(
tree
,
eb
->
start
,
return
set_extent_dirty
(
tree
,
eb
->
start
,
eb
->
start
+
eb
->
len
-
1
,
GFP_NOFS
);
eb
->
start
+
eb
->
len
-
1
,
GFP_NOFS
);
...
@@ -2217,9 +2255,12 @@ int extent_buffer_uptodate(struct extent_map_tree *tree,
...
@@ -2217,9 +2255,12 @@ int extent_buffer_uptodate(struct extent_map_tree *tree,
EXPORT_SYMBOL
(
extent_buffer_uptodate
);
EXPORT_SYMBOL
(
extent_buffer_uptodate
);
int
read_extent_buffer_pages
(
struct
extent_map_tree
*
tree
,
int
read_extent_buffer_pages
(
struct
extent_map_tree
*
tree
,
struct
extent_buffer
*
eb
,
int
wait
)
struct
extent_buffer
*
eb
,
u64
start
,
int
wait
)
{
{
unsigned
long
i
;
unsigned
long
i
;
unsigned
long
start_i
;
struct
page
*
page
;
struct
page
*
page
;
int
err
;
int
err
;
int
ret
=
0
;
int
ret
=
0
;
...
@@ -2232,9 +2273,16 @@ int read_extent_buffer_pages(struct extent_map_tree *tree,
...
@@ -2232,9 +2273,16 @@ int read_extent_buffer_pages(struct extent_map_tree *tree,
EXTENT_UPTODATE
,
1
))
{
EXTENT_UPTODATE
,
1
))
{
return
0
;
return
0
;
}
}
if
(
start
)
{
WARN_ON
(
start
<
eb
->
start
);
start_i
=
(
start
>>
PAGE_CACHE_SHIFT
)
-
(
eb
->
start
>>
PAGE_CACHE_SHIFT
);
}
else
{
start_i
=
0
;
}
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
num_pages
=
num_extent_pages
(
eb
->
start
,
eb
->
len
);
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
for
(
i
=
start_i
;
i
<
num_pages
;
i
++
)
{
page
=
extent_buffer_page
(
eb
,
i
);
page
=
extent_buffer_page
(
eb
,
i
);
if
(
PageUptodate
(
page
))
{
if
(
PageUptodate
(
page
))
{
continue
;
continue
;
...
@@ -2260,7 +2308,7 @@ int read_extent_buffer_pages(struct extent_map_tree *tree,
...
@@ -2260,7 +2308,7 @@ int read_extent_buffer_pages(struct extent_map_tree *tree,
return
ret
;
return
ret
;
}
}
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
for
(
i
=
start_i
;
i
<
num_pages
;
i
++
)
{
page
=
extent_buffer_page
(
eb
,
i
);
page
=
extent_buffer_page
(
eb
,
i
);
wait_on_page_locked
(
page
);
wait_on_page_locked
(
page
);
if
(
!
PageUptodate
(
page
))
{
if
(
!
PageUptodate
(
page
))
{
...
@@ -2314,7 +2362,7 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
...
@@ -2314,7 +2362,7 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
}
}
EXPORT_SYMBOL
(
read_extent_buffer
);
EXPORT_SYMBOL
(
read_extent_buffer
);
static
int
__map
_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
int
map_private
_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
*
map_start
,
unsigned
long
*
map_start
,
unsigned
long
*
map_len
,
int
km
)
unsigned
long
*
map_len
,
int
km
)
...
@@ -2337,6 +2385,10 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start,
...
@@ -2337,6 +2385,10 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start,
offset
=
0
;
offset
=
0
;
*
map_start
=
(
i
<<
PAGE_CACHE_SHIFT
)
-
start_offset
;
*
map_start
=
(
i
<<
PAGE_CACHE_SHIFT
)
-
start_offset
;
}
}
if
(
start
+
min_len
>=
eb
->
len
)
{
printk
(
"bad mapping eb start %Lu len %lu, wanted %lu %lu
\n
"
,
eb
->
start
,
eb
->
len
,
start
,
min_len
);
WARN_ON
(
1
);
}
p
=
extent_buffer_page
(
eb
,
i
);
p
=
extent_buffer_page
(
eb
,
i
);
WARN_ON
(
!
PageUptodate
(
p
));
WARN_ON
(
!
PageUptodate
(
p
));
...
@@ -2346,6 +2398,7 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start,
...
@@ -2346,6 +2398,7 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start,
*
map_len
=
PAGE_CACHE_SIZE
-
offset
;
*
map_len
=
PAGE_CACHE_SIZE
-
offset
;
return
0
;
return
0
;
}
}
EXPORT_SYMBOL
(
map_private_extent_buffer
);
int
map_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
int
map_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
start
,
unsigned
long
min_len
,
unsigned
long
min_len
,
...
@@ -2360,7 +2413,7 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
...
@@ -2360,7 +2413,7 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
eb
->
map_token
=
NULL
;
eb
->
map_token
=
NULL
;
save
=
1
;
save
=
1
;
}
}
err
=
__map
_extent_buffer
(
eb
,
start
,
min_len
,
token
,
map
,
err
=
map_private
_extent_buffer
(
eb
,
start
,
min_len
,
token
,
map
,
map_start
,
map_len
,
km
);
map_start
,
map_len
,
km
);
if
(
!
err
&&
save
)
{
if
(
!
err
&&
save
)
{
eb
->
map_token
=
*
token
;
eb
->
map_token
=
*
token
;
...
...
fs/btrfs/extent_map.h
View file @
19c00ddc
...
@@ -17,8 +17,17 @@
...
@@ -17,8 +17,17 @@
#define EXTENT_DEFRAG (1 << 6)
#define EXTENT_DEFRAG (1 << 6)
#define EXTENT_DEFRAG_DONE (1 << 7)
#define EXTENT_DEFRAG_DONE (1 << 7)
#define EXTENT_BUFFER_FILLED (1 << 8)
#define EXTENT_BUFFER_FILLED (1 << 8)
#define EXTENT_CSUM (1 << 9)
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
/*
* page->private values. Every page that is controlled by the extent
* map has page->private set to one.
*/
#define EXTENT_PAGE_PRIVATE 1
#define EXTENT_PAGE_PRIVATE_FIRST_PAGE 3
struct
extent_map_ops
{
struct
extent_map_ops
{
int
(
*
fill_delalloc
)(
struct
inode
*
inode
,
u64
start
,
u64
end
);
int
(
*
fill_delalloc
)(
struct
inode
*
inode
,
u64
start
,
u64
end
);
...
@@ -89,7 +98,7 @@ typedef struct extent_map *(get_extent_t)(struct inode *inode,
...
@@ -89,7 +98,7 @@ typedef struct extent_map *(get_extent_t)(struct inode *inode,
void
extent_map_tree_init
(
struct
extent_map_tree
*
tree
,
void
extent_map_tree_init
(
struct
extent_map_tree
*
tree
,
struct
address_space
*
mapping
,
gfp_t
mask
);
struct
address_space
*
mapping
,
gfp_t
mask
);
void
extent_map_tree_
cleanup
(
struct
extent_map_tree
*
tree
);
void
extent_map_tree_
empty_lru
(
struct
extent_map_tree
*
tree
);
struct
extent_map
*
lookup_extent_mapping
(
struct
extent_map_tree
*
tree
,
struct
extent_map
*
lookup_extent_mapping
(
struct
extent_map_tree
*
tree
,
u64
start
,
u64
end
);
u64
start
,
u64
end
);
int
add_extent_mapping
(
struct
extent_map_tree
*
tree
,
int
add_extent_mapping
(
struct
extent_map_tree
*
tree
,
...
@@ -143,13 +152,14 @@ void set_page_extent_mapped(struct page *page);
...
@@ -143,13 +152,14 @@ void set_page_extent_mapped(struct page *page);
struct
extent_buffer
*
alloc_extent_buffer
(
struct
extent_map_tree
*
tree
,
struct
extent_buffer
*
alloc_extent_buffer
(
struct
extent_map_tree
*
tree
,
u64
start
,
unsigned
long
len
,
u64
start
,
unsigned
long
len
,
struct
page
*
page0
,
gfp_t
mask
);
gfp_t
mask
);
struct
extent_buffer
*
find_extent_buffer
(
struct
extent_map_tree
*
tree
,
struct
extent_buffer
*
find_extent_buffer
(
struct
extent_map_tree
*
tree
,
u64
start
,
unsigned
long
len
,
u64
start
,
unsigned
long
len
,
gfp_t
mask
);
gfp_t
mask
);
void
free_extent_buffer
(
struct
extent_buffer
*
eb
);
void
free_extent_buffer
(
struct
extent_buffer
*
eb
);
int
read_extent_buffer_pages
(
struct
extent_map_tree
*
tree
,
int
read_extent_buffer_pages
(
struct
extent_map_tree
*
tree
,
struct
extent_buffer
*
eb
,
int
wait
);
struct
extent_buffer
*
eb
,
u64
start
,
int
wait
);
static
inline
void
extent_buffer_get
(
struct
extent_buffer
*
eb
)
static
inline
void
extent_buffer_get
(
struct
extent_buffer
*
eb
)
{
{
...
@@ -187,5 +197,9 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long offset,
...
@@ -187,5 +197,9 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long offset,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
*
map_start
,
unsigned
long
*
map_start
,
unsigned
long
*
map_len
,
int
km
);
unsigned
long
*
map_len
,
int
km
);
int
map_private_extent_buffer
(
struct
extent_buffer
*
eb
,
unsigned
long
offset
,
unsigned
long
min_len
,
char
**
token
,
char
**
map
,
unsigned
long
*
map_start
,
unsigned
long
*
map_len
,
int
km
);
void
unmap_extent_buffer
(
struct
extent_buffer
*
eb
,
char
*
token
,
int
km
);
void
unmap_extent_buffer
(
struct
extent_buffer
*
eb
,
char
*
token
,
int
km
);
#endif
#endif
fs/btrfs/inode.c
View file @
19c00ddc
...
@@ -1713,10 +1713,6 @@ static int btrfs_releasepage(struct page *page, gfp_t unused_gfp_flags)
...
@@ -1713,10 +1713,6 @@ static int btrfs_releasepage(struct page *page, gfp_t unused_gfp_flags)
struct
extent_map_tree
*
tree
;
struct
extent_map_tree
*
tree
;
int
ret
;
int
ret
;
if
(
page
->
private
!=
1
)
{
WARN_ON
(
1
);
return
try_to_free_buffers
(
page
);
}
tree
=
&
BTRFS_I
(
page
->
mapping
->
host
)
->
extent_tree
;
tree
=
&
BTRFS_I
(
page
->
mapping
->
host
)
->
extent_tree
;
ret
=
try_release_extent_mapping
(
tree
,
page
);
ret
=
try_release_extent_mapping
(
tree
,
page
);
if
(
ret
==
1
)
{
if
(
ret
==
1
)
{
...
...
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