aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-08-05 13:05:02 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:06 -0400
commit7ea394f1192bee1af67ea4762c88ef4b7b0487a8 (patch)
treee2c593d054d802bc71e86508a5b7523ff80cc1ea /fs/btrfs/inode.c
parent00e4e6b33a0f78aab4b788d6d31c884fd8bf88da (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.c60
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);
206again: 208again:
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; 279not_found:
266 } 280 btrfs_end_transaction(trans, root);
267loop:
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); 284out:
273 loops++; 285 WARN_ON(err);
274 goto again; 286 btrfs_end_transaction(trans, root);
275 287 btrfs_free_path(path);
276not_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
283static int run_delalloc_range(struct inode *inode, u64 start, u64 end) 291static 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);
585nocow:
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