aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-01-22 16:47:59 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:59 -0400
commit5f56406aabdf5444d040c5955effc665b1d0dbaf (patch)
tree59c82cc7f5d5de3b65b6eba24b505684eb7941d6 /fs/btrfs/file.c
parentc1e32da616a17813f11b701a7a87775d35c12e3a (diff)
Btrfs: Fix hole insertion corner cases
There were a few places that could cause duplicate extent insertion, this adjusts the code that creates holes to avoid it. lookup_extent_map is changed to correctly return all of the extents in a range, even when there are none matching at the start of the range. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 897242e87fa7..1cd8c908811e 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -278,7 +278,7 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans,
278 u64 hole_size; 278 u64 hole_size;
279 u64 mask = root->sectorsize - 1; 279 u64 mask = root->sectorsize - 1;
280 last_pos_in_file = (isize + mask) & ~mask; 280 last_pos_in_file = (isize + mask) & ~mask;
281 hole_size = (start_pos - last_pos_in_file + mask) & ~mask; 281 hole_size = (end_pos - last_pos_in_file + mask) & ~mask;
282 282
283 if (last_pos_in_file < start_pos) { 283 if (last_pos_in_file < start_pos) {
284 err = btrfs_drop_extents(trans, root, inode, 284 err = btrfs_drop_extents(trans, root, inode,
@@ -293,6 +293,7 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans,
293 inode->i_ino, 293 inode->i_ino,
294 last_pos_in_file, 294 last_pos_in_file,
295 0, 0, hole_size); 295 0, 0, hole_size);
296 btrfs_check_file(root, inode);
296 } 297 }
297 if (err) 298 if (err)
298 goto failed; 299 goto failed;
@@ -378,6 +379,80 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
378 return 0; 379 return 0;
379} 380}
380 381
382int btrfs_check_file(struct btrfs_root *root, struct inode *inode)
383{
384 return 0;
385#if 0
386 struct btrfs_path *path;
387 struct btrfs_key found_key;
388 struct extent_buffer *leaf;
389 struct btrfs_file_extent_item *extent;
390 u64 last_offset = 0;
391 int nritems;
392 int slot;
393 int found_type;
394 int ret;
395 int err = 0;
396 u64 extent_end = 0;
397
398 path = btrfs_alloc_path();
399 ret = btrfs_lookup_file_extent(NULL, root, path, inode->i_ino,
400 last_offset, 0);
401 while(1) {
402 nritems = btrfs_header_nritems(path->nodes[0]);
403 if (path->slots[0] >= nritems) {
404 ret = btrfs_next_leaf(root, path);
405 if (ret)
406 goto out;
407 nritems = btrfs_header_nritems(path->nodes[0]);
408 }
409 slot = path->slots[0];
410 leaf = path->nodes[0];
411 btrfs_item_key_to_cpu(leaf, &found_key, slot);
412 if (found_key.objectid != inode->i_ino)
413 break;
414 if (found_key.type != BTRFS_EXTENT_DATA_KEY)
415 goto out;
416
417 if (found_key.offset != last_offset) {
418 WARN_ON(1);
419 btrfs_print_leaf(root, leaf);
420 printk("inode %lu found offset %Lu expected %Lu\n",
421 inode->i_ino, found_key.offset, last_offset);
422 err = 1;
423 goto out;
424 }
425 extent = btrfs_item_ptr(leaf, slot,
426 struct btrfs_file_extent_item);
427 found_type = btrfs_file_extent_type(leaf, extent);
428 if (found_type == BTRFS_FILE_EXTENT_REG) {
429 extent_end = found_key.offset +
430 btrfs_file_extent_num_bytes(leaf, extent);
431 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
432 struct btrfs_item *item;
433 item = btrfs_item_nr(leaf, slot);
434 extent_end = found_key.offset +
435 btrfs_file_extent_inline_len(leaf, item);
436 extent_end = (extent_end + root->sectorsize - 1) &
437 ~((u64)root->sectorsize -1 );
438 }
439 last_offset = extent_end;
440 path->slots[0]++;
441 }
442 if (last_offset < inode->i_size) {
443 WARN_ON(1);
444 btrfs_print_leaf(root, leaf);
445 printk("inode %lu found offset %Lu size %Lu\n", inode->i_ino,
446 last_offset, inode->i_size);
447 err = 1;
448
449 }
450out:
451 btrfs_free_path(path);
452 return err;
453#endif
454}
455
381/* 456/*
382 * this is very complex, but the basic idea is to drop all extents 457 * this is very complex, but the basic idea is to drop all extents
383 * in the range start - end. hint_block is filled in with a block number 458 * in the range start - end. hint_block is filled in with a block number
@@ -436,6 +511,7 @@ next_slot:
436 slot = path->slots[0]; 511 slot = path->slots[0];
437 ret = 0; 512 ret = 0;
438 btrfs_item_key_to_cpu(leaf, &key, slot); 513 btrfs_item_key_to_cpu(leaf, &key, slot);
514
439 if (key.offset >= end || key.objectid != inode->i_ino) { 515 if (key.offset >= end || key.objectid != inode->i_ino) {
440 goto out; 516 goto out;
441 } 517 }