diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-26 16:00:06 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-26 16:00:06 -0400 |
commit | dee26a9f7aab7ffe1193cd1415b23a69426acc9f (patch) | |
tree | 7271c85340349817b92647d8882247478192d1bb /fs | |
parent | 4730a4bc5bf3861d2cb40999374b3ac0ee2a1e0d (diff) |
btrfs_get_block, file read/write
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/TODO | 1 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 26 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 4 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 52 | ||||
-rw-r--r-- | fs/btrfs/super.c | 188 |
5 files changed, 230 insertions, 41 deletions
diff --git a/fs/btrfs/TODO b/fs/btrfs/TODO index 454028b6bd46..2ca301b289a6 100644 --- a/fs/btrfs/TODO +++ b/fs/btrfs/TODO | |||
@@ -8,6 +8,7 @@ | |||
8 | * Add block mapping tree (simple dm layer) | 8 | * Add block mapping tree (simple dm layer) |
9 | * Add simple tree locking (semaphore per tree) | 9 | * Add simple tree locking (semaphore per tree) |
10 | * Make allocator smarter | 10 | * Make allocator smarter |
11 | * Make directory hashing work on 32 bit | ||
11 | * Do actual block accounting | 12 | * Do actual block accounting |
12 | * Check compat and incompat flags on the inode | 13 | * Check compat and incompat flags on the inode |
13 | * Add virtual filesystems, mountable snapshots | 14 | * Add virtual filesystems, mountable snapshots |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 0aa1052d9f67..7b7120d3ab42 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -198,7 +198,7 @@ struct btrfs_file_extent_item { | |||
198 | __le64 disk_blocknr; | 198 | __le64 disk_blocknr; |
199 | __le64 disk_num_blocks; | 199 | __le64 disk_num_blocks; |
200 | /* | 200 | /* |
201 | * the logical offset in file bytes (no csums) | 201 | * the logical offset in file blocks (no csums) |
202 | * this extent record is for. This allows a file extent to point | 202 | * this extent record is for. This allows a file extent to point |
203 | * into the middle of an existing extent on disk, sharing it | 203 | * into the middle of an existing extent on disk, sharing it |
204 | * between two snapshots (useful if some bytes in the middle of the | 204 | * between two snapshots (useful if some bytes in the middle of the |
@@ -812,12 +812,19 @@ static inline struct btrfs_root *btrfs_sb(struct super_block *sb) | |||
812 | ((type *)(btrfs_leaf_data(leaf) + \ | 812 | ((type *)(btrfs_leaf_data(leaf) + \ |
813 | btrfs_item_offset((leaf)->items + (slot)))) | 813 | btrfs_item_offset((leaf)->items + (slot)))) |
814 | 814 | ||
815 | /* extent-item.c */ | ||
815 | struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 816 | struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
816 | struct btrfs_root *root); | 817 | struct btrfs_root *root); |
818 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root | ||
819 | *root, u64 num_blocks, u64 search_start, u64 | ||
820 | search_end, u64 owner, struct btrfs_key *ins); | ||
817 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 821 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
818 | struct buffer_head *buf); | 822 | struct buffer_head *buf); |
819 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 823 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
820 | *root, u64 blocknr, u64 num_blocks, int pin); | 824 | *root, u64 blocknr, u64 num_blocks, int pin); |
825 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | ||
826 | btrfs_root *root); | ||
827 | /* ctree.c */ | ||
821 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | 828 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root |
822 | *root, struct btrfs_key *key, struct btrfs_path *p, int | 829 | *root, struct btrfs_key *key, struct btrfs_path *p, int |
823 | ins_len, int cow); | 830 | ins_len, int cow); |
@@ -834,8 +841,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); | |||
834 | int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf); | 841 | int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf); |
835 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | 842 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root |
836 | *root, struct buffer_head *snap); | 843 | *root, struct buffer_head *snap); |
837 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | 844 | /* root-item.c */ |
838 | btrfs_root *root); | ||
839 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 845 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
840 | struct btrfs_key *key); | 846 | struct btrfs_key *key); |
841 | int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root | 847 | int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root |
@@ -846,6 +852,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
846 | *item); | 852 | *item); |
847 | int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct | 853 | int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct |
848 | btrfs_root_item *item, struct btrfs_key *key); | 854 | btrfs_root_item *item, struct btrfs_key *key); |
855 | /* dir-item.c */ | ||
849 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 856 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
850 | *root, const char *name, int name_len, u64 dir, u64 | 857 | *root, const char *name, int name_len, u64 dir, u64 |
851 | objectid, u8 type); | 858 | objectid, u8 type); |
@@ -854,6 +861,7 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
854 | const char *name, int name_len, int mod); | 861 | const char *name, int name_len, int mod); |
855 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | 862 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, |
856 | const char *name, int name_len); | 863 | const char *name, int name_len); |
864 | /* inode-map.c */ | ||
857 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | 865 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, |
858 | struct btrfs_root *fs_root, | 866 | struct btrfs_root *fs_root, |
859 | u64 dirid, u64 *objectid); | 867 | u64 dirid, u64 *objectid); |
@@ -863,9 +871,21 @@ int btrfs_insert_inode_map(struct btrfs_trans_handle *trans, | |||
863 | int btrfs_lookup_inode_map(struct btrfs_trans_handle *trans, | 871 | int btrfs_lookup_inode_map(struct btrfs_trans_handle *trans, |
864 | struct btrfs_root *root, struct btrfs_path *path, | 872 | struct btrfs_root *root, struct btrfs_path *path, |
865 | u64 objectid, int mod); | 873 | u64 objectid, int mod); |
874 | /* inode-item.c */ | ||
866 | int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root | 875 | int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root |
867 | *root, u64 objectid, struct btrfs_inode_item | 876 | *root, u64 objectid, struct btrfs_inode_item |
868 | *inode_item); | 877 | *inode_item); |
869 | int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root | 878 | int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root |
870 | *root, struct btrfs_path *path, u64 objectid, int mod); | 879 | *root, struct btrfs_path *path, u64 objectid, int mod); |
880 | |||
881 | /* file-item.c */ | ||
882 | int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, | ||
883 | struct btrfs_root *root, | ||
884 | u64 objectid, u64 offset, | ||
885 | u64 num_blocks, u64 hint_block, | ||
886 | u64 *result); | ||
887 | int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | ||
888 | struct btrfs_root *root, | ||
889 | struct btrfs_path *path, u64 objectid, | ||
890 | u64 blocknr, u64 num_blocks, int mod); | ||
871 | #endif | 891 | #endif |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b14104276eea..82f6e9eed1d0 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -403,7 +403,7 @@ error: | |||
403 | * | 403 | * |
404 | * returns 0 if everything worked, non-zero otherwise. | 404 | * returns 0 if everything worked, non-zero otherwise. |
405 | */ | 405 | */ |
406 | static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 406 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
407 | *root, u64 num_blocks, u64 search_start, u64 | 407 | *root, u64 num_blocks, u64 search_start, u64 |
408 | search_end, u64 owner, struct btrfs_key *ins) | 408 | search_end, u64 owner, struct btrfs_key *ins) |
409 | { | 409 | { |
@@ -458,7 +458,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
458 | int ret; | 458 | int ret; |
459 | struct buffer_head *buf; | 459 | struct buffer_head *buf; |
460 | 460 | ||
461 | ret = alloc_extent(trans, root, 1, 0, (unsigned long)-1, | 461 | ret = btrfs_alloc_extent(trans, root, 1, 0, (unsigned long)-1, |
462 | btrfs_header_parentid(btrfs_buffer_header(root->node)), &ins); | 462 | btrfs_header_parentid(btrfs_buffer_header(root->node)), &ins); |
463 | if (ret) { | 463 | if (ret) { |
464 | BUG(); | 464 | BUG(); |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 8e1e5b4ccfaf..4a0367d702b7 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -1,9 +1,57 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include "ctree.h" | 2 | #include "ctree.h" |
3 | #include "disk-io.h" | ||
3 | #include "transaction.h" | 4 | #include "transaction.h" |
4 | 5 | ||
5 | int btrfs_create_file(struct btrfs_trans_handle *trans, | 6 | int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, |
6 | struct btrfs_root *root, u64 dirid, u64 *objectid) | 7 | struct btrfs_root *root, |
8 | u64 objectid, u64 offset, | ||
9 | u64 num_blocks, u64 hint_block, | ||
10 | u64 *result) | ||
7 | { | 11 | { |
12 | struct btrfs_key ins; | ||
13 | int ret = 0; | ||
14 | struct btrfs_file_extent_item *item; | ||
15 | struct btrfs_key file_key; | ||
16 | struct btrfs_path path; | ||
17 | |||
18 | btrfs_init_path(&path); | ||
19 | ret = btrfs_alloc_extent(trans, root, num_blocks, hint_block, | ||
20 | (u64)-1, objectid, &ins); | ||
21 | BUG_ON(ret); | ||
22 | file_key.objectid = objectid; | ||
23 | file_key.offset = offset; | ||
24 | file_key.flags = 0; | ||
25 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); | ||
26 | |||
27 | ret = btrfs_insert_empty_item(trans, root, &path, &file_key, | ||
28 | sizeof(*item)); | ||
29 | item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], | ||
30 | struct btrfs_file_extent_item); | ||
31 | btrfs_set_file_extent_disk_blocknr(item, ins.objectid); | ||
32 | btrfs_set_file_extent_disk_num_blocks(item, ins.offset); | ||
33 | btrfs_set_file_extent_offset(item, 0); | ||
34 | btrfs_set_file_extent_num_blocks(item, ins.offset); | ||
35 | mark_buffer_dirty(path.nodes[0]); | ||
36 | *result = ins.objectid; | ||
37 | btrfs_release_path(root, &path); | ||
8 | return 0; | 38 | return 0; |
9 | } | 39 | } |
40 | |||
41 | int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | ||
42 | struct btrfs_root *root, | ||
43 | struct btrfs_path *path, u64 objectid, | ||
44 | u64 blocknr, u64 num_blocks, int mod) | ||
45 | { | ||
46 | int ret; | ||
47 | struct btrfs_key file_key; | ||
48 | int ins_len = mod < 0 ? -1 : 0; | ||
49 | int cow = mod != 0; | ||
50 | |||
51 | file_key.objectid = objectid; | ||
52 | file_key.offset = blocknr; | ||
53 | file_key.flags = 0; | ||
54 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); | ||
55 | ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); | ||
56 | return ret; | ||
57 | } | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 905b093a85fe..2c2883f2856d 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/string.h> | 8 | #include <linux/string.h> |
9 | #include <linux/smp_lock.h> | 9 | #include <linux/smp_lock.h> |
10 | #include <linux/backing-dev.h> | 10 | #include <linux/backing-dev.h> |
11 | #include <linux/mpage.h> | ||
11 | #include "ctree.h" | 12 | #include "ctree.h" |
12 | #include "disk-io.h" | 13 | #include "disk-io.h" |
13 | #include "transaction.h" | 14 | #include "transaction.h" |
@@ -17,6 +18,9 @@ | |||
17 | static struct inode_operations btrfs_dir_inode_operations; | 18 | static struct inode_operations btrfs_dir_inode_operations; |
18 | static struct super_operations btrfs_super_ops; | 19 | static struct super_operations btrfs_super_ops; |
19 | static struct file_operations btrfs_dir_file_operations; | 20 | static struct file_operations btrfs_dir_file_operations; |
21 | static struct inode_operations btrfs_file_inode_operations; | ||
22 | static struct address_space_operations btrfs_aops; | ||
23 | static struct file_operations btrfs_file_operations; | ||
20 | 24 | ||
21 | static void btrfs_read_locked_inode(struct inode *inode) | 25 | static void btrfs_read_locked_inode(struct inode *inode) |
22 | { | 26 | { |
@@ -57,6 +61,9 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
57 | break; | 61 | break; |
58 | #endif | 62 | #endif |
59 | case S_IFREG: | 63 | case S_IFREG: |
64 | inode->i_mapping->a_ops = &btrfs_aops; | ||
65 | inode->i_fop = &btrfs_file_operations; | ||
66 | inode->i_op = &btrfs_file_inode_operations; | ||
60 | break; | 67 | break; |
61 | case S_IFDIR: | 68 | case S_IFDIR: |
62 | inode->i_op = &btrfs_dir_inode_operations; | 69 | inode->i_op = &btrfs_dir_inode_operations; |
@@ -214,35 +221,6 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
214 | return d_splice_alias(inode, dentry); | 221 | return d_splice_alias(inode, dentry); |
215 | } | 222 | } |
216 | 223 | ||
217 | static void reada_leaves(struct btrfs_root *root, struct btrfs_path *path) | ||
218 | { | ||
219 | struct buffer_head *bh; | ||
220 | struct btrfs_node *node; | ||
221 | int i; | ||
222 | int nritems; | ||
223 | u64 objectid; | ||
224 | u64 item_objectid; | ||
225 | u64 blocknr; | ||
226 | int slot; | ||
227 | |||
228 | if (!path->nodes[1]) | ||
229 | return; | ||
230 | node = btrfs_buffer_node(path->nodes[1]); | ||
231 | slot = path->slots[1]; | ||
232 | objectid = btrfs_disk_key_objectid(&node->ptrs[slot].key); | ||
233 | nritems = btrfs_header_nritems(&node->header); | ||
234 | for (i = slot; i < nritems; i++) { | ||
235 | item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key); | ||
236 | if (item_objectid != objectid) | ||
237 | break; | ||
238 | blocknr = btrfs_node_blockptr(node, i); | ||
239 | bh = sb_getblk(root->fs_info->sb, blocknr); | ||
240 | ll_rw_block(READ, 1, &bh); | ||
241 | brelse(bh); | ||
242 | } | ||
243 | |||
244 | } | ||
245 | |||
246 | static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 224 | static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
247 | { | 225 | { |
248 | struct inode *inode = filp->f_path.dentry->d_inode; | 226 | struct inode *inode = filp->f_path.dentry->d_inode; |
@@ -269,21 +247,18 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
269 | goto err; | 247 | goto err; |
270 | } | 248 | } |
271 | advance = 0; | 249 | advance = 0; |
272 | reada_leaves(root, &path); | ||
273 | while(1) { | 250 | while(1) { |
274 | leaf = btrfs_buffer_leaf(path.nodes[0]); | 251 | leaf = btrfs_buffer_leaf(path.nodes[0]); |
275 | nritems = btrfs_header_nritems(&leaf->header); | 252 | nritems = btrfs_header_nritems(&leaf->header); |
276 | slot = path.slots[0]; | 253 | slot = path.slots[0]; |
277 | if (advance) { | 254 | if (advance || slot >= nritems) { |
278 | if (slot == nritems -1) { | 255 | if (slot >= nritems -1) { |
279 | ret = btrfs_next_leaf(root, &path); | 256 | ret = btrfs_next_leaf(root, &path); |
280 | if (ret) | 257 | if (ret) |
281 | break; | 258 | break; |
282 | leaf = btrfs_buffer_leaf(path.nodes[0]); | 259 | leaf = btrfs_buffer_leaf(path.nodes[0]); |
283 | nritems = btrfs_header_nritems(&leaf->header); | 260 | nritems = btrfs_header_nritems(&leaf->header); |
284 | slot = path.slots[0]; | 261 | slot = path.slots[0]; |
285 | if (path.nodes[1] && path.slots[1] == 0) | ||
286 | reada_leaves(root, &path); | ||
287 | } else { | 262 | } else { |
288 | slot++; | 263 | slot++; |
289 | path.slots[0]++; | 264 | path.slots[0]++; |
@@ -297,6 +272,8 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
297 | continue; | 272 | continue; |
298 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) | 273 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) |
299 | continue; | 274 | continue; |
275 | |||
276 | advance = 1; | ||
300 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | 277 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); |
301 | over = filldir(dirent, (const char *)(di + 1), | 278 | over = filldir(dirent, (const char *)(di + 1), |
302 | btrfs_dir_name_len(di), | 279 | btrfs_dir_name_len(di), |
@@ -524,6 +501,11 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
524 | err = btrfs_add_nondir(trans, dentry, inode); | 501 | err = btrfs_add_nondir(trans, dentry, inode); |
525 | if (err) | 502 | if (err) |
526 | drop_inode = 1; | 503 | drop_inode = 1; |
504 | else { | ||
505 | inode->i_mapping->a_ops = &btrfs_aops; | ||
506 | inode->i_fop = &btrfs_file_operations; | ||
507 | inode->i_op = &btrfs_file_inode_operations; | ||
508 | } | ||
527 | dir->i_sb->s_dirt = 1; | 509 | dir->i_sb->s_dirt = 1; |
528 | btrfs_end_transaction(trans, root); | 510 | btrfs_end_transaction(trans, root); |
529 | out_unlock: | 511 | out_unlock: |
@@ -623,11 +605,124 @@ printk("btrfs sync_fs\n"); | |||
623 | return 0; | 605 | return 0; |
624 | } | 606 | } |
625 | 607 | ||
608 | static int btrfs_get_block(struct inode *inode, sector_t iblock, | ||
609 | struct buffer_head *result, int create) | ||
610 | { | ||
611 | int ret; | ||
612 | int err = 0; | ||
613 | u64 blocknr; | ||
614 | u64 extent_start = 0; | ||
615 | u64 extent_end = 0; | ||
616 | u64 objectid = inode->i_ino; | ||
617 | struct btrfs_path path; | ||
618 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | ||
619 | struct btrfs_trans_handle *trans = NULL; | ||
620 | struct btrfs_file_extent_item *item; | ||
621 | struct btrfs_leaf *leaf; | ||
622 | struct btrfs_disk_key *found_key; | ||
623 | |||
624 | btrfs_init_path(&path); | ||
625 | mutex_lock(&root->fs_info->fs_mutex); | ||
626 | if (create) | ||
627 | trans = btrfs_start_transaction(root, 1); | ||
628 | |||
629 | |||
630 | ret = btrfs_lookup_file_extent(trans, root, &path, | ||
631 | inode->i_ino, iblock, 1, 0); | ||
632 | if (ret < 0) { | ||
633 | btrfs_release_path(root, &path); | ||
634 | err = ret; | ||
635 | goto out; | ||
636 | } | ||
637 | |||
638 | if (ret != 0) { | ||
639 | if (path.slots[0] == 0) { | ||
640 | btrfs_release_path(root, &path); | ||
641 | goto allocate; | ||
642 | } | ||
643 | path.slots[0]--; | ||
644 | } | ||
645 | |||
646 | item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], | ||
647 | struct btrfs_file_extent_item); | ||
648 | leaf = btrfs_buffer_leaf(path.nodes[0]); | ||
649 | blocknr = btrfs_file_extent_disk_blocknr(item); | ||
650 | blocknr += btrfs_file_extent_offset(item); | ||
651 | |||
652 | /* exact match found, use it */ | ||
653 | if (ret == 0) { | ||
654 | err = 0; | ||
655 | map_bh(result, inode->i_sb, blocknr); | ||
656 | btrfs_release_path(root, &path); | ||
657 | goto out; | ||
658 | } | ||
659 | |||
660 | /* are we inside the extent that was found? */ | ||
661 | found_key = &leaf->items[path.slots[0]].key; | ||
662 | if (btrfs_disk_key_objectid(found_key) != objectid || | ||
663 | btrfs_disk_key_type(found_key) != BTRFS_EXTENT_DATA_KEY) { | ||
664 | extent_end = 0; | ||
665 | extent_start = 0; | ||
666 | btrfs_release_path(root, &path); | ||
667 | goto allocate; | ||
668 | } | ||
669 | |||
670 | extent_start = btrfs_disk_key_offset(&leaf->items[path.slots[0]].key); | ||
671 | extent_start += btrfs_file_extent_offset(item); | ||
672 | extent_end = extent_start + btrfs_file_extent_num_blocks(item); | ||
673 | btrfs_release_path(root, &path); | ||
674 | if (iblock >= extent_start && iblock < extent_end) { | ||
675 | err = 0; | ||
676 | map_bh(result, inode->i_sb, blocknr + iblock - extent_start); | ||
677 | goto out; | ||
678 | } | ||
679 | allocate: | ||
680 | /* ok, create a new extent */ | ||
681 | if (!create) { | ||
682 | err = 0; | ||
683 | goto out; | ||
684 | } | ||
685 | ret = btrfs_alloc_file_extent(trans, root, objectid, iblock, | ||
686 | 1, extent_end, &blocknr); | ||
687 | if (ret) { | ||
688 | err = ret; | ||
689 | goto out; | ||
690 | } | ||
691 | map_bh(result, inode->i_sb, blocknr); | ||
692 | |||
693 | out: | ||
694 | if (trans) | ||
695 | btrfs_end_transaction(trans, root); | ||
696 | mutex_unlock(&root->fs_info->fs_mutex); | ||
697 | return err; | ||
698 | } | ||
699 | |||
700 | static int btrfs_prepare_write(struct file *file, struct page *page, | ||
701 | unsigned from, unsigned to) | ||
702 | { | ||
703 | return block_prepare_write(page, from, to, btrfs_get_block); | ||
704 | } | ||
705 | |||
626 | static void btrfs_write_super(struct super_block *sb) | 706 | static void btrfs_write_super(struct super_block *sb) |
627 | { | 707 | { |
628 | btrfs_sync_fs(sb, 1); | 708 | btrfs_sync_fs(sb, 1); |
629 | } | 709 | } |
630 | 710 | ||
711 | static int btrfs_readpage(struct file *file, struct page *page) | ||
712 | { | ||
713 | return mpage_readpage(page, btrfs_get_block); | ||
714 | } | ||
715 | |||
716 | static int btrfs_readpages(struct file *file, struct address_space *mapping, | ||
717 | struct list_head *pages, unsigned nr_pages) | ||
718 | { | ||
719 | return mpage_readpages(mapping, pages, nr_pages, btrfs_get_block); | ||
720 | } | ||
721 | |||
722 | static int btrfs_writepage(struct page *page, struct writeback_control *wbc) | ||
723 | { | ||
724 | return block_write_full_page(page, btrfs_get_block, wbc); | ||
725 | } | ||
631 | 726 | ||
632 | static int btrfs_get_sb(struct file_system_type *fs_type, | 727 | static int btrfs_get_sb(struct file_system_type *fs_type, |
633 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 728 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
@@ -667,6 +762,31 @@ static struct file_operations btrfs_dir_file_operations = { | |||
667 | .readdir = btrfs_readdir, | 762 | .readdir = btrfs_readdir, |
668 | }; | 763 | }; |
669 | 764 | ||
765 | static struct address_space_operations btrfs_aops = { | ||
766 | .readpage = btrfs_readpage, | ||
767 | .readpages = btrfs_readpages, | ||
768 | .writepage = btrfs_writepage, | ||
769 | .sync_page = block_sync_page, | ||
770 | .prepare_write = btrfs_prepare_write, | ||
771 | .commit_write = generic_commit_write, | ||
772 | }; | ||
773 | |||
774 | static struct inode_operations btrfs_file_inode_operations = { | ||
775 | .truncate = NULL, | ||
776 | }; | ||
777 | |||
778 | static struct file_operations btrfs_file_operations = { | ||
779 | .llseek = generic_file_llseek, | ||
780 | .read = do_sync_read, | ||
781 | .write = do_sync_write, | ||
782 | .aio_read = generic_file_aio_read, | ||
783 | .aio_write = generic_file_aio_write, | ||
784 | .mmap = generic_file_mmap, | ||
785 | .open = generic_file_open, | ||
786 | .sendfile = generic_file_sendfile, | ||
787 | .splice_read = generic_file_splice_read, | ||
788 | .splice_write = generic_file_splice_write, | ||
789 | }; | ||
670 | 790 | ||
671 | static int __init init_btrfs_fs(void) | 791 | static int __init init_btrfs_fs(void) |
672 | { | 792 | { |