aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file-item.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-04-18 16:15:28 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-04-18 16:15:28 -0400
commita429e51371eee3c989160c003ee40bc3947c6a76 (patch)
tree863b55de8823be579264260a51407cd90aac103d /fs/btrfs/file-item.c
parent70b2befd0c8a4064715d8b340270650cc9d15af8 (diff)
Btrfs: working file_write, reorganized key flags
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r--fs/btrfs/file-item.c66
1 files changed, 47 insertions, 19 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index ff8f3339c684..8cc3c1d15412 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -4,7 +4,7 @@
4#include "transaction.h" 4#include "transaction.h"
5 5
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) * 2) / \
8 sizeof(struct btrfs_csum_item)) - 1)) 8 sizeof(struct btrfs_csum_item)) - 1))
9int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, 9int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
10 struct btrfs_root *root, 10 struct btrfs_root *root,
@@ -19,11 +19,6 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
19 path = btrfs_alloc_path(); 19 path = btrfs_alloc_path();
20 BUG_ON(!path); 20 BUG_ON(!path);
21 btrfs_init_path(path); 21 btrfs_init_path(path);
22 /*
23 ret = btrfs_alloc_extent(trans, root, num_blocks, hint_block,
24 (u64)-1, &ins);
25 */
26 BUG_ON(ret);
27 file_key.objectid = objectid; 22 file_key.objectid = objectid;
28 file_key.offset = pos; 23 file_key.offset = pos;
29 file_key.flags = 0; 24 file_key.flags = 0;
@@ -40,6 +35,7 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
40 btrfs_set_file_extent_num_blocks(item, num_blocks); 35 btrfs_set_file_extent_num_blocks(item, num_blocks);
41 btrfs_set_file_extent_generation(item, trans->transid); 36 btrfs_set_file_extent_generation(item, trans->transid);
42 btrfs_mark_buffer_dirty(path->nodes[0]); 37 btrfs_mark_buffer_dirty(path->nodes[0]);
38
43 btrfs_release_path(root, path); 39 btrfs_release_path(root, path);
44 btrfs_free_path(path); 40 btrfs_free_path(path);
45 return 0; 41 return 0;
@@ -57,6 +53,7 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
57 struct btrfs_csum_item *item; 53 struct btrfs_csum_item *item;
58 struct btrfs_leaf *leaf; 54 struct btrfs_leaf *leaf;
59 u64 csum_offset = 0; 55 u64 csum_offset = 0;
56 int csums_in_item;
60 57
61 file_key.objectid = objectid; 58 file_key.objectid = objectid;
62 file_key.offset = offset; 59 file_key.offset = offset;
@@ -79,9 +76,11 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
79 } 76 }
80 csum_offset = (offset - found_key.offset) >> 77 csum_offset = (offset - found_key.offset) >>
81 root->fs_info->sb->s_blocksize_bits; 78 root->fs_info->sb->s_blocksize_bits;
82 if (csum_offset >= 79 csums_in_item = btrfs_item_size(leaf->items + path->slots[0]);
83 btrfs_item_size(leaf->items + path->slots[0]) / 80 csums_in_item /= sizeof(struct btrfs_csum_item);
84 sizeof(struct btrfs_csum_item)) { 81
82 if (csum_offset >= csums_in_item) {
83 ret = -EFBIG;
85 goto fail; 84 goto fail;
86 } 85 }
87 } 86 }
@@ -128,16 +127,36 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
128 127
129 path = btrfs_alloc_path(); 128 path = btrfs_alloc_path();
130 BUG_ON(!path); 129 BUG_ON(!path);
131 btrfs_init_path(path);
132 130
133 item = btrfs_lookup_csum(trans, root, path, objectid, offset, 0);
134 if (!IS_ERR(item))
135 goto found;
136 btrfs_release_path(root, path);
137 file_key.objectid = objectid; 131 file_key.objectid = objectid;
138 file_key.offset = offset; 132 file_key.offset = offset;
139 file_key.flags = 0; 133 file_key.flags = 0;
140 btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); 134 btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
135
136 item = btrfs_lookup_csum(trans, root, path, objectid, offset, 1);
137 if (!IS_ERR(item))
138 goto found;
139 ret = PTR_ERR(item);
140 if (ret == -EFBIG) {
141 u32 item_size;
142 /* we found one, but it isn't big enough yet */
143 leaf = btrfs_buffer_leaf(path->nodes[0]);
144 item_size = btrfs_item_size(leaf->items + path->slots[0]);
145 if ((item_size / sizeof(struct btrfs_csum_item)) >=
146 MAX_CSUM_ITEMS(root)) {
147 /* already at max size, make a new one */
148 goto insert;
149 }
150 } else {
151 /* we didn't find a csum item, insert one */
152 goto insert;
153 }
154
155 /*
156 * at this point, we know the tree has an item, but it isn't big
157 * enough yet to put our csum in. Grow it
158 */
159 btrfs_release_path(root, path);
141 ret = btrfs_search_slot(trans, root, &file_key, path, 160 ret = btrfs_search_slot(trans, root, &file_key, path,
142 sizeof(struct btrfs_csum_item), 1); 161 sizeof(struct btrfs_csum_item), 1);
143 if (ret < 0) 162 if (ret < 0)
@@ -146,7 +165,6 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
146 BUG(); 165 BUG();
147 } 166 }
148 if (path->slots[0] == 0) { 167 if (path->slots[0] == 0) {
149 btrfs_release_path(root, path);
150 goto insert; 168 goto insert;
151 } 169 }
152 path->slots[0]--; 170 path->slots[0]--;
@@ -157,29 +175,36 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
157 if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || 175 if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
158 found_key.objectid != objectid || 176 found_key.objectid != objectid ||
159 csum_offset >= MAX_CSUM_ITEMS(root)) { 177 csum_offset >= MAX_CSUM_ITEMS(root)) {
160 btrfs_release_path(root, path); 178 WARN_ON(1);
161 goto insert; 179 goto insert;
162 } 180 }
163 if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) / 181 if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) /
164 sizeof(struct btrfs_csum_item)) { 182 sizeof(struct btrfs_csum_item)) {
165 ret = btrfs_extend_item(trans, root, path, 183 u32 diff = (csum_offset + 1) * sizeof(struct btrfs_csum_item);
166 sizeof(struct btrfs_csum_item)); 184 diff = diff - btrfs_item_size(leaf->items + path->slots[0]);
185 WARN_ON(diff != sizeof(struct btrfs_csum_item));
186 ret = btrfs_extend_item(trans, root, path, diff);
167 BUG_ON(ret); 187 BUG_ON(ret);
168 goto csum; 188 goto csum;
169 } 189 }
170 190
171insert: 191insert:
192 btrfs_release_path(root, path);
172 csum_offset = 0; 193 csum_offset = 0;
173 ret = btrfs_insert_empty_item(trans, root, path, &file_key, 194 ret = btrfs_insert_empty_item(trans, root, path, &file_key,
174 sizeof(struct btrfs_csum_item)); 195 sizeof(struct btrfs_csum_item));
175 if (ret != 0 && ret != -EEXIST) 196 if (ret != 0) {
197 printk("at insert for %Lu %u %Lu ret is %d\n", file_key.objectid, file_key.flags, file_key.offset, ret);
198 WARN_ON(1);
176 goto fail; 199 goto fail;
200 }
177csum: 201csum:
178 item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], 202 item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
179 struct btrfs_csum_item); 203 struct btrfs_csum_item);
180 ret = 0; 204 ret = 0;
181 item += csum_offset; 205 item += csum_offset;
182found: 206found:
207 btrfs_check_bounds(item->csum, BTRFS_CSUM_SIZE, path->nodes[0]->b_data, root->fs_info->sb->s_blocksize);
183 ret = btrfs_csum_data(root, data, len, item->csum); 208 ret = btrfs_csum_data(root, data, len, item->csum);
184 btrfs_mark_buffer_dirty(path->nodes[0]); 209 btrfs_mark_buffer_dirty(path->nodes[0]);
185fail: 210fail:
@@ -210,6 +235,9 @@ int btrfs_csum_verify_file_block(struct btrfs_root *root,
210 item = btrfs_lookup_csum(NULL, root, path, objectid, offset, 0); 235 item = btrfs_lookup_csum(NULL, root, path, objectid, offset, 0);
211 if (IS_ERR(item)) { 236 if (IS_ERR(item)) {
212 ret = PTR_ERR(item); 237 ret = PTR_ERR(item);
238 /* a csum that isn't present is a preallocated region. */
239 if (ret == -ENOENT || ret == -EFBIG)
240 ret = 1;
213 goto fail; 241 goto fail;
214 } 242 }
215 243