aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c71
1 files changed, 61 insertions, 10 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index ff60d8978ae2..79f057c0619a 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -93,7 +93,8 @@
93 */ 93 */
94#define LOG_WALK_PIN_ONLY 0 94#define LOG_WALK_PIN_ONLY 0
95#define LOG_WALK_REPLAY_INODES 1 95#define LOG_WALK_REPLAY_INODES 1
96#define LOG_WALK_REPLAY_ALL 2 96#define LOG_WALK_REPLAY_DIR_INDEX 2
97#define LOG_WALK_REPLAY_ALL 3
97 98
98static int btrfs_log_inode(struct btrfs_trans_handle *trans, 99static int btrfs_log_inode(struct btrfs_trans_handle *trans,
99 struct btrfs_root *root, struct inode *inode, 100 struct btrfs_root *root, struct inode *inode,
@@ -393,6 +394,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
393 if (inode_item) { 394 if (inode_item) {
394 struct btrfs_inode_item *item; 395 struct btrfs_inode_item *item;
395 u64 nbytes; 396 u64 nbytes;
397 u32 mode;
396 398
397 item = btrfs_item_ptr(path->nodes[0], path->slots[0], 399 item = btrfs_item_ptr(path->nodes[0], path->slots[0],
398 struct btrfs_inode_item); 400 struct btrfs_inode_item);
@@ -400,9 +402,19 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
400 item = btrfs_item_ptr(eb, slot, 402 item = btrfs_item_ptr(eb, slot,
401 struct btrfs_inode_item); 403 struct btrfs_inode_item);
402 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);
403 } 414 }
404 } else if (inode_item) { 415 } else if (inode_item) {
405 struct btrfs_inode_item *item; 416 struct btrfs_inode_item *item;
417 u32 mode;
406 418
407 /* 419 /*
408 * 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
@@ -410,6 +422,15 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
410 */ 422 */
411 item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item); 423 item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
412 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);
413 } 434 }
414insert: 435insert:
415 btrfs_release_path(path); 436 btrfs_release_path(path);
@@ -747,7 +768,8 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans,
747 ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len); 768 ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len);
748 if (ret) 769 if (ret)
749 goto out; 770 goto out;
750 btrfs_run_delayed_items(trans, root); 771 else
772 ret = btrfs_run_delayed_items(trans, root);
751out: 773out:
752 kfree(name); 774 kfree(name);
753 iput(inode); 775 iput(inode);
@@ -923,7 +945,9 @@ again:
923 kfree(victim_name); 945 kfree(victim_name);
924 if (ret) 946 if (ret)
925 return ret; 947 return ret;
926 btrfs_run_delayed_items(trans, root); 948 ret = btrfs_run_delayed_items(trans, root);
949 if (ret)
950 return ret;
927 *search_done = 1; 951 *search_done = 1;
928 goto again; 952 goto again;
929 } 953 }
@@ -990,7 +1014,9 @@ again:
990 inode, 1014 inode,
991 victim_name, 1015 victim_name,
992 victim_name_len); 1016 victim_name_len);
993 btrfs_run_delayed_items(trans, root); 1017 if (!ret)
1018 ret = btrfs_run_delayed_items(
1019 trans, root);
994 } 1020 }
995 iput(victim_parent); 1021 iput(victim_parent);
996 kfree(victim_name); 1022 kfree(victim_name);
@@ -1491,6 +1517,7 @@ static noinline int insert_one_name(struct btrfs_trans_handle *trans,
1491 iput(inode); 1517 iput(inode);
1492 return -EIO; 1518 return -EIO;
1493 } 1519 }
1520
1494 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);
1495 1522
1496 /* FIXME, put inode into FIXUP list */ 1523 /* FIXME, put inode into FIXUP list */
@@ -1529,6 +1556,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
1529 u8 log_type; 1556 u8 log_type;
1530 int exists; 1557 int exists;
1531 int ret = 0; 1558 int ret = 0;
1559 bool update_size = (key->type == BTRFS_DIR_INDEX_KEY);
1532 1560
1533 dir = read_one_inode(root, key->objectid); 1561 dir = read_one_inode(root, key->objectid);
1534 if (!dir) 1562 if (!dir)
@@ -1536,8 +1564,10 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
1536 1564
1537 name_len = btrfs_dir_name_len(eb, di); 1565 name_len = btrfs_dir_name_len(eb, di);
1538 name = kmalloc(name_len, GFP_NOFS); 1566 name = kmalloc(name_len, GFP_NOFS);
1539 if (!name) 1567 if (!name) {
1540 return -ENOMEM; 1568 ret = -ENOMEM;
1569 goto out;
1570 }
1541 1571
1542 log_type = btrfs_dir_type(eb, di); 1572 log_type = btrfs_dir_type(eb, di);
1543 read_extent_buffer(eb, name, (unsigned long)(di + 1), 1573 read_extent_buffer(eb, name, (unsigned long)(di + 1),
@@ -1597,6 +1627,10 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
1597 goto insert; 1627 goto insert;
1598out: 1628out:
1599 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 }
1600 kfree(name); 1634 kfree(name);
1601 iput(dir); 1635 iput(dir);
1602 return ret; 1636 return ret;
@@ -1607,6 +1641,7 @@ insert:
1607 name, name_len, log_type, &log_key); 1641 name, name_len, log_type, &log_key);
1608 if (ret && ret != -ENOENT) 1642 if (ret && ret != -ENOENT)
1609 goto out; 1643 goto out;
1644 update_size = false;
1610 ret = 0; 1645 ret = 0;
1611 goto out; 1646 goto out;
1612} 1647}
@@ -1810,7 +1845,7 @@ again:
1810 ret = btrfs_unlink_inode(trans, root, dir, inode, 1845 ret = btrfs_unlink_inode(trans, root, dir, inode,
1811 name, name_len); 1846 name, name_len);
1812 if (!ret) 1847 if (!ret)
1813 btrfs_run_delayed_items(trans, root); 1848 ret = btrfs_run_delayed_items(trans, root);
1814 kfree(name); 1849 kfree(name);
1815 iput(inode); 1850 iput(inode);
1816 if (ret) 1851 if (ret)
@@ -2020,6 +2055,15 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
2020 if (ret) 2055 if (ret)
2021 break; 2056 break;
2022 } 2057 }
2058
2059 if (key.type == BTRFS_DIR_INDEX_KEY &&
2060 wc->stage == LOG_WALK_REPLAY_DIR_INDEX) {
2061 ret = replay_one_dir_item(wc->trans, root, path,
2062 eb, i, &key);
2063 if (ret)
2064 break;
2065 }
2066
2023 if (wc->stage < LOG_WALK_REPLAY_ALL) 2067 if (wc->stage < LOG_WALK_REPLAY_ALL)
2024 continue; 2068 continue;
2025 2069
@@ -2041,8 +2085,7 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
2041 eb, i, &key); 2085 eb, i, &key);
2042 if (ret) 2086 if (ret)
2043 break; 2087 break;
2044 } else if (key.type == BTRFS_DIR_ITEM_KEY || 2088 } else if (key.type == BTRFS_DIR_ITEM_KEY) {
2045 key.type == BTRFS_DIR_INDEX_KEY) {
2046 ret = replay_one_dir_item(wc->trans, root, path, 2089 ret = replay_one_dir_item(wc->trans, root, path,
2047 eb, i, &key); 2090 eb, i, &key);
2048 if (ret) 2091 if (ret)
@@ -3798,6 +3841,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
3798 int ret = 0; 3841 int ret = 0;
3799 struct btrfs_root *root; 3842 struct btrfs_root *root;
3800 struct dentry *old_parent = NULL; 3843 struct dentry *old_parent = NULL;
3844 struct inode *orig_inode = inode;
3801 3845
3802 /* 3846 /*
3803 * for regular files, if its inode is already on disk, we don't 3847 * for regular files, if its inode is already on disk, we don't
@@ -3817,7 +3861,14 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
3817 } 3861 }
3818 3862
3819 while (1) { 3863 while (1) {
3820 BTRFS_I(inode)->logged_trans = trans->transid; 3864 /*
3865 * If we are logging a directory then we start with our inode,
3866 * not our parents inode, so we need to skipp setting the
3867 * logged_trans so that further down in the log code we don't
3868 * think this inode has already been logged.
3869 */
3870 if (inode != orig_inode)
3871 BTRFS_I(inode)->logged_trans = trans->transid;
3821 smp_mb(); 3872 smp_mb();
3822 3873
3823 if (BTRFS_I(inode)->last_unlink_trans > last_committed) { 3874 if (BTRFS_I(inode)->last_unlink_trans > last_committed) {