diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-17 13:26:50 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-17 13:26:50 -0400 |
commit | b18c6685810af8e6763760711aece31ccc7a8ea8 (patch) | |
tree | db7220ed6fb418fbdc069ac422fc8b1c1598e92f /fs/btrfs | |
parent | 6567e837df07e43bffc08ac40858af8133a007bf (diff) |
Btrfs: progress on file_write
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 57 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 21 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 20 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 61 | ||||
-rw-r--r-- | fs/btrfs/super.c | 284 |
5 files changed, 394 insertions, 49 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 6b76fd967153..43d4779abdd1 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1249,6 +1249,63 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1249 | return ret; | 1249 | return ret; |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | int btrfs_truncate_item(struct btrfs_trans_handle *trans, | ||
1253 | struct btrfs_root *root, | ||
1254 | struct btrfs_path *path, | ||
1255 | u32 new_size) | ||
1256 | { | ||
1257 | int ret = 0; | ||
1258 | int slot; | ||
1259 | int slot_orig; | ||
1260 | struct btrfs_leaf *leaf; | ||
1261 | struct buffer_head *leaf_buf; | ||
1262 | u32 nritems; | ||
1263 | unsigned int data_end; | ||
1264 | unsigned int old_data_start; | ||
1265 | unsigned int old_size; | ||
1266 | unsigned int size_diff; | ||
1267 | int i; | ||
1268 | |||
1269 | slot_orig = path->slots[0]; | ||
1270 | leaf_buf = path->nodes[0]; | ||
1271 | leaf = btrfs_buffer_leaf(leaf_buf); | ||
1272 | |||
1273 | nritems = btrfs_header_nritems(&leaf->header); | ||
1274 | data_end = leaf_data_end(root, leaf); | ||
1275 | |||
1276 | slot = path->slots[0]; | ||
1277 | old_data_start = btrfs_item_offset(leaf->items + slot); | ||
1278 | old_size = btrfs_item_size(leaf->items + slot); | ||
1279 | BUG_ON(old_size <= new_size); | ||
1280 | size_diff = old_size - new_size; | ||
1281 | |||
1282 | BUG_ON(slot < 0); | ||
1283 | BUG_ON(slot >= nritems); | ||
1284 | |||
1285 | /* | ||
1286 | * item0..itemN ... dataN.offset..dataN.size .. data0.size | ||
1287 | */ | ||
1288 | /* first correct the data pointers */ | ||
1289 | for (i = slot; i < nritems; i++) { | ||
1290 | u32 ioff = btrfs_item_offset(leaf->items + i); | ||
1291 | btrfs_set_item_offset(leaf->items + i, | ||
1292 | ioff + size_diff); | ||
1293 | } | ||
1294 | /* shift the data */ | ||
1295 | printk("truncate item, new_size %u old_size %u, diff %u, bufp %p, dst, %p, num %u, old_data_start %u, data_end %u\n", new_size, old_size, size_diff, leaf, btrfs_leaf_data(leaf) + data_end + size_diff, old_data_start-data_end, old_data_start, data_end); | ||
1296 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + | ||
1297 | data_end + size_diff, btrfs_leaf_data(leaf) + | ||
1298 | data_end, old_data_start + new_size - data_end); | ||
1299 | btrfs_set_item_size(leaf->items + slot, new_size); | ||
1300 | btrfs_mark_buffer_dirty(leaf_buf); | ||
1301 | |||
1302 | ret = 0; | ||
1303 | if (btrfs_leaf_free_space(root, leaf) < 0) | ||
1304 | BUG(); | ||
1305 | check_leaf(root, path, 0); | ||
1306 | return ret; | ||
1307 | } | ||
1308 | |||
1252 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | 1309 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root |
1253 | *root, struct btrfs_path *path, u32 data_size) | 1310 | *root, struct btrfs_path *path, u32 data_size) |
1254 | { | 1311 | { |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 796f19d03ab5..ca3ab160f460 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -999,7 +999,7 @@ static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh) | |||
999 | ((type *)(btrfs_leaf_data(leaf) + \ | 999 | ((type *)(btrfs_leaf_data(leaf) + \ |
1000 | btrfs_item_offset((leaf)->items + (slot)))) | 1000 | btrfs_item_offset((leaf)->items + (slot)))) |
1001 | 1001 | ||
1002 | /* extent-item.c */ | 1002 | /* extent-tree.c */ |
1003 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | 1003 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, |
1004 | struct btrfs_root *root); | 1004 | struct btrfs_root *root); |
1005 | struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 1005 | struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
@@ -1013,9 +1013,16 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1013 | *root, u64 blocknr, u64 num_blocks, int pin); | 1013 | *root, u64 blocknr, u64 num_blocks, int pin); |
1014 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | 1014 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct |
1015 | btrfs_root *root); | 1015 | btrfs_root *root); |
1016 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | ||
1017 | struct btrfs_root *root, | ||
1018 | u64 blocknr, u64 num_blocks); | ||
1016 | /* ctree.c */ | 1019 | /* ctree.c */ |
1017 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | 1020 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root |
1018 | *root, struct btrfs_path *path, u32 data_size); | 1021 | *root, struct btrfs_path *path, u32 data_size); |
1022 | int btrfs_truncate_item(struct btrfs_trans_handle *trans, | ||
1023 | struct btrfs_root *root, | ||
1024 | struct btrfs_path *path, | ||
1025 | u32 new_size); | ||
1019 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | 1026 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root |
1020 | *root, struct btrfs_key *key, struct btrfs_path *p, int | 1027 | *root, struct btrfs_key *key, struct btrfs_path *p, int |
1021 | ins_len, int cow); | 1028 | ins_len, int cow); |
@@ -1073,11 +1080,10 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1073 | struct btrfs_key *location, int mod); | 1080 | struct btrfs_key *location, int mod); |
1074 | 1081 | ||
1075 | /* file-item.c */ | 1082 | /* file-item.c */ |
1076 | int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, | 1083 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, |
1077 | struct btrfs_root *root, | 1084 | struct btrfs_root *root, |
1078 | u64 objectid, u64 offset, | 1085 | u64 objectid, u64 pos, u64 offset, |
1079 | u64 num_blocks, u64 hint_block, | 1086 | u64 num_blocks); |
1080 | u64 *result); | ||
1081 | int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | 1087 | int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, |
1082 | struct btrfs_root *root, | 1088 | struct btrfs_root *root, |
1083 | struct btrfs_path *path, u64 objectid, | 1089 | struct btrfs_path *path, u64 objectid, |
@@ -1090,6 +1096,11 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
1090 | int btrfs_csum_verify_file_block(struct btrfs_root *root, | 1096 | int btrfs_csum_verify_file_block(struct btrfs_root *root, |
1091 | u64 objectid, u64 offset, | 1097 | u64 objectid, u64 offset, |
1092 | char *data, size_t len); | 1098 | char *data, size_t len); |
1099 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | ||
1100 | struct btrfs_root *root, | ||
1101 | struct btrfs_path *path, | ||
1102 | u64 objectid, u64 offset, | ||
1103 | int cow); | ||
1093 | /* super.c */ | 1104 | /* super.c */ |
1094 | extern struct subsystem btrfs_subsys; | 1105 | extern struct subsystem btrfs_subsys; |
1095 | 1106 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index d560831c10a7..2cee9df001f6 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -12,8 +12,9 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
12 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct | 12 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
13 | btrfs_root *extent_root); | 13 | btrfs_root *extent_root); |
14 | 14 | ||
15 | static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | 15 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, |
16 | *root, u64 blocknr, u64 num_blocks) | 16 | struct btrfs_root *root, |
17 | u64 blocknr, u64 num_blocks) | ||
17 | { | 18 | { |
18 | struct btrfs_path *path; | 19 | struct btrfs_path *path; |
19 | int ret; | 20 | int ret; |
@@ -50,8 +51,9 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
50 | return 0; | 51 | return 0; |
51 | } | 52 | } |
52 | 53 | ||
53 | static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | 54 | static int lookup_extent_ref(struct btrfs_trans_handle *trans, |
54 | *root, u64 blocknr, u64 num_blocks, u32 *refs) | 55 | struct btrfs_root *root, u64 blocknr, |
56 | u64 num_blocks, u32 *refs) | ||
55 | { | 57 | { |
56 | struct btrfs_path *path; | 58 | struct btrfs_path *path; |
57 | int ret; | 59 | int ret; |
@@ -80,7 +82,7 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
80 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | 82 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, |
81 | struct btrfs_root *root) | 83 | struct btrfs_root *root) |
82 | { | 84 | { |
83 | return inc_block_ref(trans, root, bh_blocknr(root->node), 1); | 85 | return btrfs_inc_extent_ref(trans, root, bh_blocknr(root->node), 1); |
84 | } | 86 | } |
85 | 87 | ||
86 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 88 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
@@ -107,13 +109,13 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
107 | continue; | 109 | continue; |
108 | fi = btrfs_item_ptr(buf_leaf, i, | 110 | fi = btrfs_item_ptr(buf_leaf, i, |
109 | struct btrfs_file_extent_item); | 111 | struct btrfs_file_extent_item); |
110 | ret = inc_block_ref(trans, root, | 112 | ret = btrfs_inc_extent_ref(trans, root, |
111 | btrfs_file_extent_disk_blocknr(fi), | 113 | btrfs_file_extent_disk_blocknr(fi), |
112 | btrfs_file_extent_disk_num_blocks(fi)); | 114 | btrfs_file_extent_disk_num_blocks(fi)); |
113 | BUG_ON(ret); | 115 | BUG_ON(ret); |
114 | } else { | 116 | } else { |
115 | blocknr = btrfs_node_blockptr(buf_node, i); | 117 | blocknr = btrfs_node_blockptr(buf_node, i); |
116 | ret = inc_block_ref(trans, root, blocknr, 1); | 118 | ret = btrfs_inc_extent_ref(trans, root, blocknr, 1); |
117 | BUG_ON(ret); | 119 | BUG_ON(ret); |
118 | } | 120 | } |
119 | } | 121 | } |
@@ -563,7 +565,7 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
563 | 565 | ||
564 | WARN_ON(*level < 0); | 566 | WARN_ON(*level < 0); |
565 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 567 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
566 | ret = lookup_block_ref(trans, root, bh_blocknr(path->nodes[*level]), | 568 | ret = lookup_extent_ref(trans, root, bh_blocknr(path->nodes[*level]), |
567 | 1, &refs); | 569 | 1, &refs); |
568 | BUG_ON(ret); | 570 | BUG_ON(ret); |
569 | if (refs > 1) | 571 | if (refs > 1) |
@@ -587,7 +589,7 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
587 | } | 589 | } |
588 | blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur), | 590 | blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur), |
589 | path->slots[*level]); | 591 | path->slots[*level]); |
590 | ret = lookup_block_ref(trans, root, blocknr, 1, &refs); | 592 | ret = lookup_extent_ref(trans, root, blocknr, 1, &refs); |
591 | BUG_ON(ret); | 593 | BUG_ON(ret); |
592 | if (refs != 1) { | 594 | if (refs != 1) { |
593 | path->slots[*level]++; | 595 | path->slots[*level]++; |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 93d42d650820..f49968ad0a07 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -6,13 +6,11 @@ | |||
6 | #define MAX_CSUM_ITEMS(r) ((((BTRFS_LEAF_DATA_SIZE(r) - \ | 6 | #define MAX_CSUM_ITEMS(r) ((((BTRFS_LEAF_DATA_SIZE(r) - \ |
7 | sizeof(struct btrfs_item)) / \ | 7 | sizeof(struct btrfs_item)) / \ |
8 | sizeof(struct btrfs_csum_item)) - 1)) | 8 | sizeof(struct btrfs_csum_item)) - 1)) |
9 | int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, | 9 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, |
10 | struct btrfs_root *root, | 10 | struct btrfs_root *root, |
11 | u64 objectid, u64 offset, | 11 | u64 objectid, u64 pos, |
12 | u64 num_blocks, u64 hint_block, | 12 | u64 offset, u64 num_blocks) |
13 | u64 *result) | ||
14 | { | 13 | { |
15 | struct btrfs_key ins; | ||
16 | int ret = 0; | 14 | int ret = 0; |
17 | struct btrfs_file_extent_item *item; | 15 | struct btrfs_file_extent_item *item; |
18 | struct btrfs_key file_key; | 16 | struct btrfs_key file_key; |
@@ -21,11 +19,13 @@ int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, | |||
21 | path = btrfs_alloc_path(); | 19 | path = btrfs_alloc_path(); |
22 | BUG_ON(!path); | 20 | BUG_ON(!path); |
23 | btrfs_init_path(path); | 21 | btrfs_init_path(path); |
22 | /* | ||
24 | ret = btrfs_alloc_extent(trans, root, num_blocks, hint_block, | 23 | ret = btrfs_alloc_extent(trans, root, num_blocks, hint_block, |
25 | (u64)-1, &ins); | 24 | (u64)-1, &ins); |
25 | */ | ||
26 | BUG_ON(ret); | 26 | BUG_ON(ret); |
27 | file_key.objectid = objectid; | 27 | file_key.objectid = objectid; |
28 | file_key.offset = offset; | 28 | file_key.offset = pos; |
29 | file_key.flags = 0; | 29 | file_key.flags = 0; |
30 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); | 30 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); |
31 | 31 | ||
@@ -34,21 +34,22 @@ int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, | |||
34 | BUG_ON(ret); | 34 | BUG_ON(ret); |
35 | item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 35 | item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], |
36 | struct btrfs_file_extent_item); | 36 | struct btrfs_file_extent_item); |
37 | btrfs_set_file_extent_disk_blocknr(item, ins.objectid); | 37 | btrfs_set_file_extent_disk_blocknr(item, offset); |
38 | btrfs_set_file_extent_disk_num_blocks(item, ins.offset); | 38 | btrfs_set_file_extent_disk_num_blocks(item, num_blocks); |
39 | btrfs_set_file_extent_offset(item, 0); | 39 | btrfs_set_file_extent_offset(item, 0); |
40 | btrfs_set_file_extent_num_blocks(item, ins.offset); | 40 | btrfs_set_file_extent_num_blocks(item, num_blocks); |
41 | btrfs_set_file_extent_generation(item, trans->transid); | 41 | btrfs_set_file_extent_generation(item, trans->transid); |
42 | btrfs_mark_buffer_dirty(path->nodes[0]); | 42 | btrfs_mark_buffer_dirty(path->nodes[0]); |
43 | *result = ins.objectid; | ||
44 | btrfs_release_path(root, path); | 43 | btrfs_release_path(root, path); |
45 | btrfs_free_path(path); | 44 | btrfs_free_path(path); |
46 | return 0; | 45 | return 0; |
47 | } | 46 | } |
48 | 47 | ||
49 | static struct btrfs_csum_item *__lookup_csum_item(struct btrfs_root *root, | 48 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, |
50 | struct btrfs_path *path, | 49 | struct btrfs_root *root, |
51 | u64 objectid, u64 offset) | 50 | struct btrfs_path *path, |
51 | u64 objectid, u64 offset, | ||
52 | int cow) | ||
52 | { | 53 | { |
53 | int ret; | 54 | int ret; |
54 | struct btrfs_key file_key; | 55 | struct btrfs_key file_key; |
@@ -61,19 +62,23 @@ static struct btrfs_csum_item *__lookup_csum_item(struct btrfs_root *root, | |||
61 | file_key.offset = offset; | 62 | file_key.offset = offset; |
62 | file_key.flags = 0; | 63 | file_key.flags = 0; |
63 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 64 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); |
64 | ret = btrfs_search_slot(NULL, root, &file_key, path, 0, 0); | 65 | printk("__lookup for %Lu\n", offset); |
66 | ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); | ||
65 | if (ret < 0) | 67 | if (ret < 0) |
66 | goto fail; | 68 | goto fail; |
67 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 69 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
68 | if (ret > 0) { | 70 | if (ret > 0) { |
69 | ret = 1; | 71 | ret = 1; |
70 | if (path->slots[0] == 0) | 72 | if (path->slots[0] == 0) { |
73 | printk("fail1\n"); | ||
71 | goto fail; | 74 | goto fail; |
75 | } | ||
72 | path->slots[0]--; | 76 | path->slots[0]--; |
73 | btrfs_disk_key_to_cpu(&found_key, | 77 | btrfs_disk_key_to_cpu(&found_key, |
74 | &leaf->items[path->slots[0]].key); | 78 | &leaf->items[path->slots[0]].key); |
75 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || | 79 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || |
76 | found_key.objectid != objectid) { | 80 | found_key.objectid != objectid) { |
81 | printk("fail2 type %u %Lu %Lu\n", btrfs_key_type(&found_key), found_key.objectid, objectid); | ||
77 | goto fail; | 82 | goto fail; |
78 | } | 83 | } |
79 | csum_offset = (offset - found_key.offset) >> | 84 | csum_offset = (offset - found_key.offset) >> |
@@ -81,6 +86,7 @@ static struct btrfs_csum_item *__lookup_csum_item(struct btrfs_root *root, | |||
81 | if (csum_offset >= | 86 | if (csum_offset >= |
82 | btrfs_item_size(leaf->items + path->slots[0]) / | 87 | btrfs_item_size(leaf->items + path->slots[0]) / |
83 | sizeof(struct btrfs_csum_item)) { | 88 | sizeof(struct btrfs_csum_item)) { |
89 | printk("fail3, csum offset %lu size %u\n", csum_offset, btrfs_item_size(leaf->items + path->slots[0]) / sizeof(struct btrfs_csum_item)); | ||
84 | goto fail; | 90 | goto fail; |
85 | } | 91 | } |
86 | } | 92 | } |
@@ -89,7 +95,7 @@ static struct btrfs_csum_item *__lookup_csum_item(struct btrfs_root *root, | |||
89 | return item; | 95 | return item; |
90 | fail: | 96 | fail: |
91 | if (ret > 0) | 97 | if (ret > 0) |
92 | ret = -EIO; | 98 | ret = -ENOENT; |
93 | return ERR_PTR(ret); | 99 | return ERR_PTR(ret); |
94 | } | 100 | } |
95 | 101 | ||
@@ -105,7 +111,7 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
105 | int cow = mod != 0; | 111 | int cow = mod != 0; |
106 | struct btrfs_csum_item *csum_item; | 112 | struct btrfs_csum_item *csum_item; |
107 | 113 | ||
108 | csum_item = __lookup_csum_item(root, path, objectid, offset); | 114 | csum_item = btrfs_lookup_csum(trans, root, path, objectid, offset, 0); |
109 | if (IS_ERR(csum_item)) | 115 | if (IS_ERR(csum_item)) |
110 | return PTR_ERR(csum_item); | 116 | return PTR_ERR(csum_item); |
111 | file_key.objectid = objectid; | 117 | file_key.objectid = objectid; |
@@ -113,7 +119,9 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
113 | file_key.flags = 0; | 119 | file_key.flags = 0; |
114 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); | 120 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); |
115 | btrfs_release_path(root, path); | 121 | btrfs_release_path(root, path); |
122 | printk("lookup file extent searches for %Lu\n", file_key.offset); | ||
116 | ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); | 123 | ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); |
124 | printk("ret is %d\n", ret); | ||
117 | return ret; | 125 | return ret; |
118 | } | 126 | } |
119 | 127 | ||
@@ -134,17 +142,23 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
134 | path = btrfs_alloc_path(); | 142 | path = btrfs_alloc_path(); |
135 | BUG_ON(!path); | 143 | BUG_ON(!path); |
136 | btrfs_init_path(path); | 144 | btrfs_init_path(path); |
145 | |||
146 | item = btrfs_lookup_csum(trans, root, path, objectid, offset, 0); | ||
147 | if (!IS_ERR(item)) | ||
148 | goto found; | ||
149 | btrfs_release_path(root, path); | ||
137 | file_key.objectid = objectid; | 150 | file_key.objectid = objectid; |
138 | file_key.offset = offset; | 151 | file_key.offset = offset; |
139 | file_key.flags = 0; | 152 | file_key.flags = 0; |
140 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 153 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); |
154 | printk("searching for csum %Lu %Lu\n", objectid, offset); | ||
141 | ret = btrfs_search_slot(trans, root, &file_key, path, | 155 | ret = btrfs_search_slot(trans, root, &file_key, path, |
142 | sizeof(struct btrfs_csum_item), 1); | 156 | sizeof(struct btrfs_csum_item), 1); |
157 | printk("ret %d\n", ret); | ||
143 | if (ret < 0) | 158 | if (ret < 0) |
144 | goto fail; | 159 | goto fail; |
145 | if (ret == 0) { | 160 | if (ret == 0) { |
146 | csum_offset = 0; | 161 | BUG(); |
147 | goto csum; | ||
148 | } | 162 | } |
149 | if (path->slots[0] == 0) { | 163 | if (path->slots[0] == 0) { |
150 | btrfs_release_path(root, path); | 164 | btrfs_release_path(root, path); |
@@ -153,12 +167,15 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
153 | path->slots[0]--; | 167 | path->slots[0]--; |
154 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 168 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
155 | btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key); | 169 | btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key); |
170 | printk("found key %Lu %Lu %u\n", found_key.objectid, found_key.offset, found_key.flags); | ||
156 | csum_offset = (offset - found_key.offset) >> | 171 | csum_offset = (offset - found_key.offset) >> |
157 | root->fs_info->sb->s_blocksize_bits; | 172 | root->fs_info->sb->s_blocksize_bits; |
173 | printk("csum_offset %Lu\n", csum_offset); | ||
158 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || | 174 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || |
159 | found_key.objectid != objectid || | 175 | found_key.objectid != objectid || |
160 | csum_offset >= MAX_CSUM_ITEMS(root)) { | 176 | csum_offset >= MAX_CSUM_ITEMS(root)) { |
161 | btrfs_release_path(root, path); | 177 | btrfs_release_path(root, path); |
178 | printk("insert1\n"); | ||
162 | goto insert; | 179 | goto insert; |
163 | } | 180 | } |
164 | if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) / | 181 | if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) / |
@@ -166,11 +183,13 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
166 | ret = btrfs_extend_item(trans, root, path, | 183 | ret = btrfs_extend_item(trans, root, path, |
167 | sizeof(struct btrfs_csum_item)); | 184 | sizeof(struct btrfs_csum_item)); |
168 | BUG_ON(ret); | 185 | BUG_ON(ret); |
186 | printk("item extended\n"); | ||
169 | goto csum; | 187 | goto csum; |
170 | } | 188 | } |
171 | 189 | ||
172 | insert: | 190 | insert: |
173 | csum_offset = 0; | 191 | csum_offset = 0; |
192 | printk("inserting item %Lu %Lu %u\n", file_key.objectid, file_key.offset, file_key.flags); | ||
174 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, | 193 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, |
175 | sizeof(struct btrfs_csum_item)); | 194 | sizeof(struct btrfs_csum_item)); |
176 | if (ret != 0 && ret != -EEXIST) | 195 | if (ret != 0 && ret != -EEXIST) |
@@ -180,12 +199,14 @@ csum: | |||
180 | struct btrfs_csum_item); | 199 | struct btrfs_csum_item); |
181 | ret = 0; | 200 | ret = 0; |
182 | item += csum_offset; | 201 | item += csum_offset; |
202 | found: | ||
183 | ret = btrfs_csum_data(root, data, len, item->csum); | 203 | ret = btrfs_csum_data(root, data, len, item->csum); |
184 | btrfs_set_csum_extent_offset(item, extent_offset); | 204 | btrfs_set_csum_extent_offset(item, extent_offset); |
185 | btrfs_mark_buffer_dirty(path->nodes[0]); | 205 | btrfs_mark_buffer_dirty(path->nodes[0]); |
186 | fail: | 206 | fail: |
187 | btrfs_release_path(root, path); | 207 | btrfs_release_path(root, path); |
188 | btrfs_free_path(path); | 208 | btrfs_free_path(path); |
209 | printk("return ret %d\n", ret); | ||
189 | return ret; | 210 | return ret; |
190 | } | 211 | } |
191 | 212 | ||
@@ -208,7 +229,7 @@ int btrfs_csum_verify_file_block(struct btrfs_root *root, | |||
208 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 229 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); |
209 | mutex_lock(&root->fs_info->fs_mutex); | 230 | mutex_lock(&root->fs_info->fs_mutex); |
210 | 231 | ||
211 | item = __lookup_csum_item(root, path, objectid, offset); | 232 | item = btrfs_lookup_csum(NULL, root, path, objectid, offset, 0); |
212 | if (IS_ERR(item)) { | 233 | if (IS_ERR(item)) { |
213 | ret = PTR_ERR(item); | 234 | ret = PTR_ERR(item); |
214 | goto fail; | 235 | goto fail; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index ec689992fdf4..6a56416147e6 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1089,7 +1089,6 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
1089 | 1089 | ||
1090 | extent_start = btrfs_disk_key_offset(&leaf->items[path->slots[0]].key); | 1090 | extent_start = btrfs_disk_key_offset(&leaf->items[path->slots[0]].key); |
1091 | extent_start = extent_start >> inode->i_blkbits; | 1091 | extent_start = extent_start >> inode->i_blkbits; |
1092 | extent_start += btrfs_file_extent_offset(item); | ||
1093 | extent_end = extent_start + btrfs_file_extent_num_blocks(item); | 1092 | extent_end = extent_start + btrfs_file_extent_num_blocks(item); |
1094 | if (iblock >= extent_start && iblock < extent_end) { | 1093 | if (iblock >= extent_start && iblock < extent_end) { |
1095 | err = 0; | 1094 | err = 0; |
@@ -1103,6 +1102,7 @@ allocate: | |||
1103 | err = 0; | 1102 | err = 0; |
1104 | goto out; | 1103 | goto out; |
1105 | } | 1104 | } |
1105 | #if 0 | ||
1106 | ret = btrfs_alloc_file_extent(trans, root, objectid, | 1106 | ret = btrfs_alloc_file_extent(trans, root, objectid, |
1107 | iblock << inode->i_blkbits, | 1107 | iblock << inode->i_blkbits, |
1108 | 1, extent_end, &blocknr); | 1108 | 1, extent_end, &blocknr); |
@@ -1115,9 +1115,11 @@ allocate: | |||
1115 | map_bh(result, inode->i_sb, blocknr); | 1115 | map_bh(result, inode->i_sb, blocknr); |
1116 | 1116 | ||
1117 | btrfs_map_bh_to_logical(root, result, blocknr); | 1117 | btrfs_map_bh_to_logical(root, result, blocknr); |
1118 | #endif | ||
1118 | out: | 1119 | out: |
1119 | btrfs_release_path(root, path); | 1120 | btrfs_release_path(root, path); |
1120 | btrfs_free_path(path); | 1121 | btrfs_free_path(path); |
1122 | printk("mapping iblock %lu to %lu\n", iblock, result->b_blocknr); | ||
1121 | if (trans) | 1123 | if (trans) |
1122 | btrfs_end_transaction(trans, root); | 1124 | btrfs_end_transaction(trans, root); |
1123 | return err; | 1125 | return err; |
@@ -1273,8 +1275,244 @@ failed: | |||
1273 | return err; | 1275 | return err; |
1274 | } | 1276 | } |
1275 | 1277 | ||
1276 | static int prepare_pages(struct btrfs_trans_handle *trans, | 1278 | static int drop_csums(struct btrfs_trans_handle *trans, |
1277 | struct btrfs_root *root, | 1279 | struct btrfs_root *root, |
1280 | struct inode *inode, | ||
1281 | u64 start, u64 end) | ||
1282 | { | ||
1283 | struct btrfs_path *path; | ||
1284 | struct btrfs_leaf *leaf; | ||
1285 | struct btrfs_key key; | ||
1286 | int slot; | ||
1287 | struct btrfs_csum_item *item; | ||
1288 | char *old_block = NULL; | ||
1289 | u64 cur = start; | ||
1290 | u64 found_end; | ||
1291 | u64 num_csums; | ||
1292 | u64 item_size; | ||
1293 | int ret; | ||
1294 | |||
1295 | path = btrfs_alloc_path(); | ||
1296 | if (!path) | ||
1297 | return -ENOMEM; | ||
1298 | while(cur < end) { | ||
1299 | item = btrfs_lookup_csum(trans, root, path, | ||
1300 | inode->i_ino, cur, 1); | ||
1301 | if (IS_ERR(item)) { | ||
1302 | cur += root->blocksize; | ||
1303 | continue; | ||
1304 | } | ||
1305 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
1306 | slot = path->slots[0]; | ||
1307 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | ||
1308 | item_size = btrfs_item_size(leaf->items + slot); | ||
1309 | num_csums = item_size / sizeof(struct btrfs_csum_item); | ||
1310 | found_end = key.offset + (num_csums << inode->i_blkbits); | ||
1311 | cur = found_end; | ||
1312 | |||
1313 | if (found_end > end) { | ||
1314 | char *src; | ||
1315 | old_block = kmalloc(root->blocksize, GFP_NOFS); | ||
1316 | src = btrfs_item_ptr(leaf, slot, char); | ||
1317 | memcpy(old_block, src, item_size); | ||
1318 | } | ||
1319 | if (key.offset < start) { | ||
1320 | u64 new_size = (start - key.offset) >> | ||
1321 | inode->i_blkbits; | ||
1322 | new_size *= sizeof(struct btrfs_csum_item); | ||
1323 | ret = btrfs_truncate_item(trans, root, path, new_size); | ||
1324 | BUG_ON(ret); | ||
1325 | } else { | ||
1326 | btrfs_del_item(trans, root, path); | ||
1327 | } | ||
1328 | btrfs_release_path(root, path); | ||
1329 | if (found_end > end) { | ||
1330 | char *dst; | ||
1331 | int i; | ||
1332 | int new_size; | ||
1333 | |||
1334 | num_csums = (found_end - end) >> inode->i_blkbits; | ||
1335 | new_size = num_csums * sizeof(struct btrfs_csum_item); | ||
1336 | key.offset = end; | ||
1337 | ret = btrfs_insert_empty_item(trans, root, path, | ||
1338 | &key, new_size); | ||
1339 | BUG_ON(ret); | ||
1340 | dst = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
1341 | path->slots[0], char); | ||
1342 | memcpy(dst, old_block + item_size - new_size, | ||
1343 | new_size); | ||
1344 | item = (struct btrfs_csum_item *)dst; | ||
1345 | for (i = 0; i < num_csums; i++) { | ||
1346 | btrfs_set_csum_extent_offset(item, end); | ||
1347 | item++; | ||
1348 | } | ||
1349 | mark_buffer_dirty(path->nodes[0]); | ||
1350 | kfree(old_block); | ||
1351 | break; | ||
1352 | } | ||
1353 | } | ||
1354 | btrfs_free_path(path); | ||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1358 | static int drop_extents(struct btrfs_trans_handle *trans, | ||
1359 | struct btrfs_root *root, | ||
1360 | struct inode *inode, | ||
1361 | u64 start, u64 end) | ||
1362 | { | ||
1363 | int ret; | ||
1364 | struct btrfs_key key; | ||
1365 | struct btrfs_leaf *leaf; | ||
1366 | int slot; | ||
1367 | struct btrfs_file_extent_item *extent; | ||
1368 | u64 extent_end; | ||
1369 | int keep; | ||
1370 | struct btrfs_file_extent_item old; | ||
1371 | struct btrfs_path *path; | ||
1372 | u64 search_start = start; | ||
1373 | int bookend; | ||
1374 | |||
1375 | path = btrfs_alloc_path(); | ||
1376 | if (!path) | ||
1377 | return -ENOMEM; | ||
1378 | search_again: | ||
1379 | printk("drop extent inode %lu start %Lu end %Lu\n", inode->i_ino, start, end); | ||
1380 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, | ||
1381 | search_start, -1); | ||
1382 | if (ret != 0) { | ||
1383 | printk("lookup failed\n"); | ||
1384 | goto out; | ||
1385 | } | ||
1386 | while(1) { | ||
1387 | keep = 0; | ||
1388 | bookend = 0; | ||
1389 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
1390 | slot = path->slots[0]; | ||
1391 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | ||
1392 | |||
1393 | printk("found key %Lu %Lu %u\n", key.objectid, key.offset, key.flags); | ||
1394 | |||
1395 | extent = btrfs_item_ptr(leaf, slot, | ||
1396 | struct btrfs_file_extent_item); | ||
1397 | extent_end = key.offset + | ||
1398 | (btrfs_file_extent_num_blocks(extent) << | ||
1399 | inode->i_blkbits); | ||
1400 | printk("extent end is %Lu\n", extent_end); | ||
1401 | if (key.offset >= end || key.objectid != inode->i_ino) { | ||
1402 | ret = 0; | ||
1403 | goto out; | ||
1404 | } | ||
1405 | if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) | ||
1406 | goto next_leaf; | ||
1407 | |||
1408 | if (end < extent_end && end >= key.offset) { | ||
1409 | memcpy(&old, extent, sizeof(old)); | ||
1410 | ret = btrfs_inc_extent_ref(trans, root, | ||
1411 | btrfs_file_extent_disk_blocknr(&old), | ||
1412 | btrfs_file_extent_disk_num_blocks(&old)); | ||
1413 | BUG_ON(ret); | ||
1414 | bookend = 1; | ||
1415 | } | ||
1416 | |||
1417 | if (start > key.offset) { | ||
1418 | u64 new_num; | ||
1419 | /* truncate existing extent */ | ||
1420 | keep = 1; | ||
1421 | WARN_ON(start & (root->blocksize - 1)); | ||
1422 | new_num = (start - key.offset) >> inode->i_blkbits; | ||
1423 | printk("truncating existing extent, was %Lu ", btrfs_file_extent_num_blocks(extent)); | ||
1424 | btrfs_set_file_extent_num_blocks(extent, new_num); | ||
1425 | printk("now %Lu\n", btrfs_file_extent_num_blocks(extent)); | ||
1426 | |||
1427 | mark_buffer_dirty(path->nodes[0]); | ||
1428 | } | ||
1429 | if (!keep) { | ||
1430 | u64 disk_blocknr; | ||
1431 | u64 disk_num_blocks; | ||
1432 | printk("del old\n"); | ||
1433 | disk_blocknr = btrfs_file_extent_disk_blocknr(extent); | ||
1434 | disk_num_blocks = | ||
1435 | btrfs_file_extent_disk_num_blocks(extent); | ||
1436 | search_start = key.offset + | ||
1437 | (btrfs_file_extent_num_blocks(extent) << | ||
1438 | inode->i_blkbits); | ||
1439 | ret = btrfs_del_item(trans, root, path); | ||
1440 | BUG_ON(ret); | ||
1441 | btrfs_release_path(root, path); | ||
1442 | |||
1443 | ret = btrfs_free_extent(trans, root, disk_blocknr, | ||
1444 | disk_num_blocks, 0); | ||
1445 | |||
1446 | BUG_ON(ret); | ||
1447 | if (!bookend && search_start >= end) { | ||
1448 | ret = 0; | ||
1449 | goto out; | ||
1450 | } | ||
1451 | if (!bookend) | ||
1452 | goto search_again; | ||
1453 | } | ||
1454 | if (bookend) { | ||
1455 | /* create bookend */ | ||
1456 | struct btrfs_key ins; | ||
1457 | printk("bookend! extent end %Lu\n", extent_end); | ||
1458 | ins.objectid = inode->i_ino; | ||
1459 | ins.offset = end; | ||
1460 | ins.flags = 0; | ||
1461 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); | ||
1462 | |||
1463 | btrfs_release_path(root, path); | ||
1464 | ret = drop_csums(trans, root, inode, start, end); | ||
1465 | BUG_ON(ret); | ||
1466 | ret = btrfs_insert_empty_item(trans, root, path, &ins, | ||
1467 | sizeof(*extent)); | ||
1468 | BUG_ON(ret); | ||
1469 | extent = btrfs_item_ptr( | ||
1470 | btrfs_buffer_leaf(path->nodes[0]), | ||
1471 | path->slots[0], | ||
1472 | struct btrfs_file_extent_item); | ||
1473 | btrfs_set_file_extent_disk_blocknr(extent, | ||
1474 | btrfs_file_extent_disk_blocknr(&old)); | ||
1475 | btrfs_set_file_extent_disk_num_blocks(extent, | ||
1476 | btrfs_file_extent_disk_num_blocks(&old)); | ||
1477 | |||
1478 | btrfs_set_file_extent_offset(extent, | ||
1479 | btrfs_file_extent_offset(&old) + | ||
1480 | ((end - key.offset) >> inode->i_blkbits)); | ||
1481 | WARN_ON(btrfs_file_extent_num_blocks(&old) < | ||
1482 | (end - key.offset) >> inode->i_blkbits); | ||
1483 | btrfs_set_file_extent_num_blocks(extent, | ||
1484 | btrfs_file_extent_num_blocks(&old) - | ||
1485 | ((end - key.offset) >> inode->i_blkbits)); | ||
1486 | |||
1487 | btrfs_set_file_extent_generation(extent, | ||
1488 | btrfs_file_extent_generation(&old)); | ||
1489 | printk("new bookend at offset %Lu, file_extent_offset %Lu, file_extent_num_blocks %Lu\n", end, btrfs_file_extent_offset(extent), btrfs_file_extent_num_blocks(extent)); | ||
1490 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
1491 | ret = 0; | ||
1492 | goto out_nocsum; | ||
1493 | } | ||
1494 | next_leaf: | ||
1495 | if (slot >= btrfs_header_nritems(&leaf->header) - 1) { | ||
1496 | ret = btrfs_next_leaf(root, path); | ||
1497 | if (ret) { | ||
1498 | ret = 0; | ||
1499 | goto out; | ||
1500 | } | ||
1501 | } else { | ||
1502 | path->slots[0]++; | ||
1503 | } | ||
1504 | } | ||
1505 | |||
1506 | out: | ||
1507 | ret = drop_csums(trans, root, inode, start, end); | ||
1508 | BUG_ON(ret); | ||
1509 | |||
1510 | out_nocsum: | ||
1511 | btrfs_free_path(path); | ||
1512 | return ret; | ||
1513 | } | ||
1514 | |||
1515 | static int prepare_pages(struct btrfs_root *root, | ||
1278 | struct file *file, | 1516 | struct file *file, |
1279 | struct page **pages, | 1517 | struct page **pages, |
1280 | size_t num_pages, | 1518 | size_t num_pages, |
@@ -1289,7 +1527,6 @@ static int prepare_pages(struct btrfs_trans_handle *trans, | |||
1289 | struct inode *inode = file->f_path.dentry->d_inode; | 1527 | struct inode *inode = file->f_path.dentry->d_inode; |
1290 | int offset; | 1528 | int offset; |
1291 | int err = 0; | 1529 | int err = 0; |
1292 | int ret; | ||
1293 | int this_write; | 1530 | int this_write; |
1294 | struct buffer_head *bh; | 1531 | struct buffer_head *bh; |
1295 | struct buffer_head *head; | 1532 | struct buffer_head *head; |
@@ -1305,18 +1542,21 @@ static int prepare_pages(struct btrfs_trans_handle *trans, | |||
1305 | } | 1542 | } |
1306 | offset = pos & (PAGE_CACHE_SIZE -1); | 1543 | offset = pos & (PAGE_CACHE_SIZE -1); |
1307 | this_write = min(PAGE_CACHE_SIZE - offset, write_bytes); | 1544 | this_write = min(PAGE_CACHE_SIZE - offset, write_bytes); |
1308 | if (!PageUptodate(pages[i]) && | 1545 | #if 0 |
1309 | (pages[i]->index == first_index || | 1546 | if ((pages[i]->index == first_index || |
1310 | pages[i]->index == last_index) && pos < isize) { | 1547 | pages[i]->index == last_index) && pos < isize && |
1548 | !PageUptodate(pages[i])) { | ||
1311 | ret = mpage_readpage(pages[i], btrfs_get_block); | 1549 | ret = mpage_readpage(pages[i], btrfs_get_block); |
1312 | BUG_ON(ret); | 1550 | BUG_ON(ret); |
1313 | lock_page(pages[i]); | 1551 | lock_page(pages[i]); |
1314 | } | 1552 | } |
1553 | #endif | ||
1315 | create_empty_buffers(pages[i], root->fs_info->sb->s_blocksize, | 1554 | create_empty_buffers(pages[i], root->fs_info->sb->s_blocksize, |
1316 | (1 << BH_Uptodate)); | 1555 | (1 << BH_Uptodate)); |
1317 | head = page_buffers(pages[i]); | 1556 | head = page_buffers(pages[i]); |
1318 | bh = head; | 1557 | bh = head; |
1319 | do { | 1558 | do { |
1559 | printk("mapping page %lu to block %Lu\n", pages[i]->index, alloc_extent_start); | ||
1320 | err = btrfs_map_bh_to_logical(root, bh, | 1560 | err = btrfs_map_bh_to_logical(root, bh, |
1321 | alloc_extent_start); | 1561 | alloc_extent_start); |
1322 | BUG_ON(err); | 1562 | BUG_ON(err); |
@@ -1351,7 +1591,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1351 | int ret = 0; | 1591 | int ret = 0; |
1352 | struct inode *inode = file->f_path.dentry->d_inode; | 1592 | struct inode *inode = file->f_path.dentry->d_inode; |
1353 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1593 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1354 | struct page *pages[1]; | 1594 | struct page *pages[8]; |
1355 | unsigned long first_index; | 1595 | unsigned long first_index; |
1356 | unsigned long last_index; | 1596 | unsigned long last_index; |
1357 | u64 start_pos; | 1597 | u64 start_pos; |
@@ -1359,6 +1599,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1359 | u64 alloc_extent_start; | 1599 | u64 alloc_extent_start; |
1360 | u64 orig_extent_start; | 1600 | u64 orig_extent_start; |
1361 | struct btrfs_trans_handle *trans; | 1601 | struct btrfs_trans_handle *trans; |
1602 | struct btrfs_key ins; | ||
1362 | 1603 | ||
1363 | if (file->f_flags & O_DIRECT) | 1604 | if (file->f_flags & O_DIRECT) |
1364 | return -EINVAL; | 1605 | return -EINVAL; |
@@ -1390,16 +1631,24 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1390 | trans = btrfs_start_transaction(root, 1); | 1631 | trans = btrfs_start_transaction(root, 1); |
1391 | if (!trans) { | 1632 | if (!trans) { |
1392 | err = -ENOMEM; | 1633 | err = -ENOMEM; |
1634 | mutex_unlock(&root->fs_info->fs_mutex); | ||
1393 | goto out_unlock; | 1635 | goto out_unlock; |
1394 | } | 1636 | } |
1395 | ret = btrfs_alloc_file_extent(trans, root, inode->i_ino, | 1637 | if (start_pos < inode->i_size) { |
1396 | start_pos, num_blocks, 1, | 1638 | ret = drop_extents(trans, root, inode, |
1397 | &alloc_extent_start); | 1639 | start_pos, |
1398 | BUG_ON(ret); | 1640 | (pos + count + root->blocksize -1) & |
1399 | 1641 | ~(root->blocksize - 1)); | |
1642 | } | ||
1400 | orig_extent_start = start_pos; | 1643 | orig_extent_start = start_pos; |
1401 | ret = btrfs_end_transaction(trans, root); | 1644 | ret = btrfs_alloc_extent(trans, root, num_blocks, 1, |
1645 | (u64)-1, &ins); | ||
1646 | BUG_ON(ret); | ||
1647 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, | ||
1648 | start_pos, ins.objectid, ins.offset); | ||
1402 | BUG_ON(ret); | 1649 | BUG_ON(ret); |
1650 | alloc_extent_start = ins.objectid; | ||
1651 | ret = btrfs_end_transaction(trans, root); | ||
1403 | mutex_unlock(&root->fs_info->fs_mutex); | 1652 | mutex_unlock(&root->fs_info->fs_mutex); |
1404 | 1653 | ||
1405 | while(count > 0) { | 1654 | while(count > 0) { |
@@ -1407,16 +1656,21 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1407 | size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); | 1656 | size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); |
1408 | size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> | 1657 | size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> |
1409 | PAGE_CACHE_SHIFT; | 1658 | PAGE_CACHE_SHIFT; |
1410 | ret = prepare_pages(NULL, root, file, pages, num_pages, | 1659 | printk("num_pages is %lu\n", num_pages); |
1660 | |||
1661 | memset(pages, 0, sizeof(pages)); | ||
1662 | ret = prepare_pages(root, file, pages, num_pages, | ||
1411 | pos, first_index, last_index, | 1663 | pos, first_index, last_index, |
1412 | write_bytes, alloc_extent_start); | 1664 | write_bytes, alloc_extent_start); |
1413 | BUG_ON(ret); | 1665 | BUG_ON(ret); |
1666 | |||
1414 | /* FIXME blocks != pagesize */ | 1667 | /* FIXME blocks != pagesize */ |
1415 | alloc_extent_start += num_pages; | 1668 | alloc_extent_start += num_pages; |
1416 | ret = btrfs_copy_from_user(pos, num_pages, | 1669 | ret = btrfs_copy_from_user(pos, num_pages, |
1417 | write_bytes, pages, buf); | 1670 | write_bytes, pages, buf); |
1418 | BUG_ON(ret); | 1671 | BUG_ON(ret); |
1419 | 1672 | ||
1673 | printk("2num_pages is %lu\n", num_pages); | ||
1420 | ret = dirty_and_release_pages(NULL, root, file, pages, | 1674 | ret = dirty_and_release_pages(NULL, root, file, pages, |
1421 | num_pages, orig_extent_start, | 1675 | num_pages, orig_extent_start, |
1422 | pos, write_bytes); | 1676 | pos, write_bytes); |