diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2008-08-05 13:05:02 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:06 -0400 |
commit | 7ea394f1192bee1af67ea4762c88ef4b7b0487a8 (patch) | |
tree | e2c593d054d802bc71e86508a5b7523ff80cc1ea /fs/btrfs/inode.c | |
parent | 00e4e6b33a0f78aab4b788d6d31c884fd8bf88da (diff) |
Btrfs: Fix nodatacow for the new data=ordered mode
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 4d8ffc01931e..c33053ba3816 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -166,7 +166,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
166 | 166 | ||
167 | cur_alloc_size = ins.offset; | 167 | cur_alloc_size = ins.offset; |
168 | ret = btrfs_add_ordered_extent(inode, start, ins.objectid, | 168 | ret = btrfs_add_ordered_extent(inode, start, ins.objectid, |
169 | ins.offset); | 169 | ins.offset, 0); |
170 | BUG_ON(ret); | 170 | BUG_ON(ret); |
171 | if (num_bytes < cur_alloc_size) { | 171 | if (num_bytes < cur_alloc_size) { |
172 | printk("num_bytes %Lu cur_alloc %Lu\n", num_bytes, | 172 | printk("num_bytes %Lu cur_alloc %Lu\n", num_bytes, |
@@ -187,31 +187,32 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end) | |||
187 | u64 extent_start; | 187 | u64 extent_start; |
188 | u64 extent_end; | 188 | u64 extent_end; |
189 | u64 bytenr; | 189 | u64 bytenr; |
190 | u64 cow_end; | ||
191 | u64 loops = 0; | 190 | u64 loops = 0; |
192 | u64 total_fs_bytes; | 191 | u64 total_fs_bytes; |
193 | struct btrfs_root *root = BTRFS_I(inode)->root; | 192 | struct btrfs_root *root = BTRFS_I(inode)->root; |
194 | struct btrfs_block_group_cache *block_group; | 193 | struct btrfs_block_group_cache *block_group; |
194 | struct btrfs_trans_handle *trans; | ||
195 | struct extent_buffer *leaf; | 195 | struct extent_buffer *leaf; |
196 | int found_type; | 196 | int found_type; |
197 | struct btrfs_path *path; | 197 | struct btrfs_path *path; |
198 | struct btrfs_file_extent_item *item; | 198 | struct btrfs_file_extent_item *item; |
199 | int ret; | 199 | int ret; |
200 | int err; | 200 | int err = 0; |
201 | struct btrfs_key found_key; | 201 | struct btrfs_key found_key; |
202 | 202 | ||
203 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | 203 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); |
204 | path = btrfs_alloc_path(); | 204 | path = btrfs_alloc_path(); |
205 | BUG_ON(!path); | 205 | BUG_ON(!path); |
206 | trans = btrfs_join_transaction(root, 1); | ||
207 | BUG_ON(!trans); | ||
206 | again: | 208 | again: |
207 | ret = btrfs_lookup_file_extent(NULL, root, path, | 209 | ret = btrfs_lookup_file_extent(NULL, root, path, |
208 | inode->i_ino, start, 0); | 210 | inode->i_ino, start, 0); |
209 | if (ret < 0) { | 211 | if (ret < 0) { |
210 | btrfs_free_path(path); | 212 | err = ret; |
211 | return ret; | 213 | goto out; |
212 | } | 214 | } |
213 | 215 | ||
214 | cow_end = end; | ||
215 | if (ret != 0) { | 216 | if (ret != 0) { |
216 | if (path->slots[0] == 0) | 217 | if (path->slots[0] == 0) |
217 | goto not_found; | 218 | goto not_found; |
@@ -244,12 +245,11 @@ again: | |||
244 | if (start < extent_start || start >= extent_end) | 245 | if (start < extent_start || start >= extent_end) |
245 | goto not_found; | 246 | goto not_found; |
246 | 247 | ||
247 | cow_end = min(end, extent_end - 1); | ||
248 | bytenr = btrfs_file_extent_disk_bytenr(leaf, item); | 248 | bytenr = btrfs_file_extent_disk_bytenr(leaf, item); |
249 | if (bytenr == 0) | 249 | if (bytenr == 0) |
250 | goto not_found; | 250 | goto not_found; |
251 | 251 | ||
252 | if (btrfs_cross_ref_exists(root, &found_key, bytenr)) | 252 | if (btrfs_cross_ref_exists(trans, root, &found_key, bytenr)) |
253 | goto not_found; | 253 | goto not_found; |
254 | /* | 254 | /* |
255 | * we may be called by the resizer, make sure we're inside | 255 | * we may be called by the resizer, make sure we're inside |
@@ -260,24 +260,32 @@ again: | |||
260 | if (!block_group || block_group->ro) | 260 | if (!block_group || block_group->ro) |
261 | goto not_found; | 261 | goto not_found; |
262 | 262 | ||
263 | bytenr += btrfs_file_extent_offset(leaf, item); | ||
264 | extent_num_bytes = min(end + 1, extent_end) - start; | ||
265 | ret = btrfs_add_ordered_extent(inode, start, bytenr, | ||
266 | extent_num_bytes, 1); | ||
267 | if (ret) { | ||
268 | err = ret; | ||
269 | goto out; | ||
270 | } | ||
271 | |||
272 | btrfs_release_path(root, path); | ||
263 | start = extent_end; | 273 | start = extent_end; |
274 | if (start <= end) { | ||
275 | loops++; | ||
276 | goto again; | ||
277 | } | ||
264 | } else { | 278 | } else { |
265 | goto not_found; | 279 | not_found: |
266 | } | 280 | btrfs_end_transaction(trans, root); |
267 | loop: | ||
268 | if (start > end) { | ||
269 | btrfs_free_path(path); | 281 | btrfs_free_path(path); |
270 | return 0; | 282 | return cow_file_range(inode, start, end); |
271 | } | 283 | } |
272 | btrfs_release_path(root, path); | 284 | out: |
273 | loops++; | 285 | WARN_ON(err); |
274 | goto again; | 286 | btrfs_end_transaction(trans, root); |
275 | 287 | btrfs_free_path(path); | |
276 | not_found: | 288 | return err; |
277 | btrfs_release_path(root, path); | ||
278 | cow_file_range(inode, start, end); | ||
279 | start = end + 1; | ||
280 | goto loop; | ||
281 | } | 289 | } |
282 | 290 | ||
283 | static int run_delalloc_range(struct inode *inode, u64 start, u64 end) | 291 | static int run_delalloc_range(struct inode *inode, u64 start, u64 end) |
@@ -385,6 +393,11 @@ int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
385 | goto mapit; | 393 | goto mapit; |
386 | } | 394 | } |
387 | 395 | ||
396 | if (btrfs_test_opt(root, NODATASUM) || | ||
397 | btrfs_test_flag(inode, NODATASUM)) { | ||
398 | goto mapit; | ||
399 | } | ||
400 | |||
388 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, | 401 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, |
389 | inode, rw, bio, mirror_num, | 402 | inode, rw, bio, mirror_num, |
390 | __btrfs_submit_bio_hook); | 403 | __btrfs_submit_bio_hook); |
@@ -527,6 +540,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
527 | 540 | ||
528 | ordered_extent = btrfs_lookup_ordered_extent(inode, start); | 541 | ordered_extent = btrfs_lookup_ordered_extent(inode, start); |
529 | BUG_ON(!ordered_extent); | 542 | BUG_ON(!ordered_extent); |
543 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) | ||
544 | goto nocow; | ||
530 | 545 | ||
531 | lock_extent(io_tree, ordered_extent->file_offset, | 546 | lock_extent(io_tree, ordered_extent->file_offset, |
532 | ordered_extent->file_offset + ordered_extent->len - 1, | 547 | ordered_extent->file_offset + ordered_extent->len - 1, |
@@ -567,6 +582,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
567 | unlock_extent(io_tree, ordered_extent->file_offset, | 582 | unlock_extent(io_tree, ordered_extent->file_offset, |
568 | ordered_extent->file_offset + ordered_extent->len - 1, | 583 | ordered_extent->file_offset + ordered_extent->len - 1, |
569 | GFP_NOFS); | 584 | GFP_NOFS); |
585 | nocow: | ||
570 | add_pending_csums(trans, inode, ordered_extent->file_offset, | 586 | add_pending_csums(trans, inode, ordered_extent->file_offset, |
571 | &ordered_extent->list); | 587 | &ordered_extent->list); |
572 | 588 | ||