aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-09-11 14:17:00 -0400
committerChris Mason <chris.mason@fusionio.com>2013-09-21 11:05:25 -0400
commitd555438b6e1dad139d26ab807f0af68a1fa47a86 (patch)
tree5d9282ac3f56598c504815774b47d96241335959 /fs
parentdd8e721773fdab5ccc7fde44ec57e30b563243b2 (diff)
Btrfs: drop dir i_size when adding new names on replay
So if we have dir_index items in the log that means we also have the inode item as well, which means that the inode's i_size is correct. However when we process dir_index'es we call btrfs_add_link() which will increase the directory's i_size for the new entry. To fix this we need to just set the dir items i_size to 0, and then as we find dir_index items we adjust the i_size. btrfs_add_link() will do it for new entries, and if the entry already exists we can just add the name_len to the i_size ourselves. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/tree-log.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index c91309dea8da..79f057c0619a 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -394,6 +394,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
394 if (inode_item) { 394 if (inode_item) {
395 struct btrfs_inode_item *item; 395 struct btrfs_inode_item *item;
396 u64 nbytes; 396 u64 nbytes;
397 u32 mode;
397 398
398 item = btrfs_item_ptr(path->nodes[0], path->slots[0], 399 item = btrfs_item_ptr(path->nodes[0], path->slots[0],
399 struct btrfs_inode_item); 400 struct btrfs_inode_item);
@@ -401,9 +402,19 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
401 item = btrfs_item_ptr(eb, slot, 402 item = btrfs_item_ptr(eb, slot,
402 struct btrfs_inode_item); 403 struct btrfs_inode_item);
403 btrfs_set_inode_nbytes(eb, item, nbytes); 404 btrfs_set_inode_nbytes(eb, item, nbytes);
405
406 /*
407 * If this is a directory we need to reset the i_size to
408 * 0 so that we can set it up properly when replaying
409 * the rest of the items in this log.
410 */
411 mode = btrfs_inode_mode(eb, item);
412 if (S_ISDIR(mode))
413 btrfs_set_inode_size(eb, item, 0);
404 } 414 }
405 } else if (inode_item) { 415 } else if (inode_item) {
406 struct btrfs_inode_item *item; 416 struct btrfs_inode_item *item;
417 u32 mode;
407 418
408 /* 419 /*
409 * New inode, set nbytes to 0 so that the nbytes comes out 420 * New inode, set nbytes to 0 so that the nbytes comes out
@@ -411,6 +422,15 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
411 */ 422 */
412 item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item); 423 item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
413 btrfs_set_inode_nbytes(eb, item, 0); 424 btrfs_set_inode_nbytes(eb, item, 0);
425
426 /*
427 * If this is a directory we need to reset the i_size to 0 so
428 * that we can set it up properly when replaying the rest of
429 * the items in this log.
430 */
431 mode = btrfs_inode_mode(eb, item);
432 if (S_ISDIR(mode))
433 btrfs_set_inode_size(eb, item, 0);
414 } 434 }
415insert: 435insert:
416 btrfs_release_path(path); 436 btrfs_release_path(path);
@@ -1497,6 +1517,7 @@ static noinline int insert_one_name(struct btrfs_trans_handle *trans,
1497 iput(inode); 1517 iput(inode);
1498 return -EIO; 1518 return -EIO;
1499 } 1519 }
1520
1500 ret = btrfs_add_link(trans, dir, inode, name, name_len, 1, index); 1521 ret = btrfs_add_link(trans, dir, inode, name, name_len, 1, index);
1501 1522
1502 /* FIXME, put inode into FIXUP list */ 1523 /* FIXME, put inode into FIXUP list */
@@ -1535,6 +1556,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
1535 u8 log_type; 1556 u8 log_type;
1536 int exists; 1557 int exists;
1537 int ret = 0; 1558 int ret = 0;
1559 bool update_size = (key->type == BTRFS_DIR_INDEX_KEY);
1538 1560
1539 dir = read_one_inode(root, key->objectid); 1561 dir = read_one_inode(root, key->objectid);
1540 if (!dir) 1562 if (!dir)
@@ -1605,6 +1627,10 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
1605 goto insert; 1627 goto insert;
1606out: 1628out:
1607 btrfs_release_path(path); 1629 btrfs_release_path(path);
1630 if (!ret && update_size) {
1631 btrfs_i_size_write(dir, dir->i_size + name_len * 2);
1632 ret = btrfs_update_inode(trans, root, dir);
1633 }
1608 kfree(name); 1634 kfree(name);
1609 iput(dir); 1635 iput(dir);
1610 return ret; 1636 return ret;
@@ -1615,6 +1641,7 @@ insert:
1615 name, name_len, log_type, &log_key); 1641 name, name_len, log_type, &log_key);
1616 if (ret && ret != -ENOENT) 1642 if (ret && ret != -ENOENT)
1617 goto out; 1643 goto out;
1644 update_size = false;
1618 ret = 0; 1645 ret = 0;
1619 goto out; 1646 goto out;
1620} 1647}