diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-18 16:15:28 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-18 16:15:28 -0400 |
commit | a429e51371eee3c989160c003ee40bc3947c6a76 (patch) | |
tree | 863b55de8823be579264260a51407cd90aac103d /fs/btrfs/file-item.c | |
parent | 70b2befd0c8a4064715d8b340270650cc9d15af8 (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.c | 66 |
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)) |
9 | int btrfs_insert_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, |
@@ -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 | ||
171 | insert: | 191 | insert: |
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 | } | ||
177 | csum: | 201 | csum: |
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; |
182 | found: | 206 | found: |
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]); |
185 | fail: | 210 | fail: |
@@ -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 | ||