diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 86 |
1 files changed, 46 insertions, 40 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 741666a7676a..4a9434b622ec 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -542,8 +542,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
542 | 542 | ||
543 | saved_nbytes = inode_get_bytes(inode); | 543 | saved_nbytes = inode_get_bytes(inode); |
544 | /* drop any overlapping extents */ | 544 | /* drop any overlapping extents */ |
545 | ret = btrfs_drop_extents(trans, root, inode, | 545 | ret = btrfs_drop_extents(trans, inode, start, extent_end, |
546 | start, extent_end, extent_end, start, &alloc_hint, 1); | 546 | &alloc_hint, 1); |
547 | BUG_ON(ret); | 547 | BUG_ON(ret); |
548 | 548 | ||
549 | if (found_type == BTRFS_FILE_EXTENT_REG || | 549 | if (found_type == BTRFS_FILE_EXTENT_REG || |
@@ -930,6 +930,17 @@ out_nowrite: | |||
930 | return 0; | 930 | return 0; |
931 | } | 931 | } |
932 | 932 | ||
933 | static int insert_orphan_item(struct btrfs_trans_handle *trans, | ||
934 | struct btrfs_root *root, u64 offset) | ||
935 | { | ||
936 | int ret; | ||
937 | ret = btrfs_find_orphan_item(root, offset); | ||
938 | if (ret > 0) | ||
939 | ret = btrfs_insert_orphan_item(trans, root, offset); | ||
940 | return ret; | ||
941 | } | ||
942 | |||
943 | |||
933 | /* | 944 | /* |
934 | * There are a few corners where the link count of the file can't | 945 | * There are a few corners where the link count of the file can't |
935 | * be properly maintained during replay. So, instead of adding | 946 | * be properly maintained during replay. So, instead of adding |
@@ -997,9 +1008,13 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, | |||
997 | } | 1008 | } |
998 | BTRFS_I(inode)->index_cnt = (u64)-1; | 1009 | BTRFS_I(inode)->index_cnt = (u64)-1; |
999 | 1010 | ||
1000 | if (inode->i_nlink == 0 && S_ISDIR(inode->i_mode)) { | 1011 | if (inode->i_nlink == 0) { |
1001 | ret = replay_dir_deletes(trans, root, NULL, path, | 1012 | if (S_ISDIR(inode->i_mode)) { |
1002 | inode->i_ino, 1); | 1013 | ret = replay_dir_deletes(trans, root, NULL, path, |
1014 | inode->i_ino, 1); | ||
1015 | BUG_ON(ret); | ||
1016 | } | ||
1017 | ret = insert_orphan_item(trans, root, inode->i_ino); | ||
1003 | BUG_ON(ret); | 1018 | BUG_ON(ret); |
1004 | } | 1019 | } |
1005 | btrfs_free_path(path); | 1020 | btrfs_free_path(path); |
@@ -1587,7 +1602,6 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1587 | /* inode keys are done during the first stage */ | 1602 | /* inode keys are done during the first stage */ |
1588 | if (key.type == BTRFS_INODE_ITEM_KEY && | 1603 | if (key.type == BTRFS_INODE_ITEM_KEY && |
1589 | wc->stage == LOG_WALK_REPLAY_INODES) { | 1604 | wc->stage == LOG_WALK_REPLAY_INODES) { |
1590 | struct inode *inode; | ||
1591 | struct btrfs_inode_item *inode_item; | 1605 | struct btrfs_inode_item *inode_item; |
1592 | u32 mode; | 1606 | u32 mode; |
1593 | 1607 | ||
@@ -1603,31 +1617,16 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1603 | eb, i, &key); | 1617 | eb, i, &key); |
1604 | BUG_ON(ret); | 1618 | BUG_ON(ret); |
1605 | 1619 | ||
1606 | /* for regular files, truncate away | 1620 | /* for regular files, make sure corresponding |
1607 | * extents past the new EOF | 1621 | * orhpan item exist. extents past the new EOF |
1622 | * will be truncated later by orphan cleanup. | ||
1608 | */ | 1623 | */ |
1609 | if (S_ISREG(mode)) { | 1624 | if (S_ISREG(mode)) { |
1610 | inode = read_one_inode(root, | 1625 | ret = insert_orphan_item(wc->trans, root, |
1611 | key.objectid); | 1626 | key.objectid); |
1612 | BUG_ON(!inode); | ||
1613 | |||
1614 | ret = btrfs_truncate_inode_items(wc->trans, | ||
1615 | root, inode, inode->i_size, | ||
1616 | BTRFS_EXTENT_DATA_KEY); | ||
1617 | BUG_ON(ret); | 1627 | BUG_ON(ret); |
1618 | |||
1619 | /* if the nlink count is zero here, the iput | ||
1620 | * will free the inode. We bump it to make | ||
1621 | * sure it doesn't get freed until the link | ||
1622 | * count fixup is done | ||
1623 | */ | ||
1624 | if (inode->i_nlink == 0) { | ||
1625 | btrfs_inc_nlink(inode); | ||
1626 | btrfs_update_inode(wc->trans, | ||
1627 | root, inode); | ||
1628 | } | ||
1629 | iput(inode); | ||
1630 | } | 1628 | } |
1629 | |||
1631 | ret = link_to_fixup_dir(wc->trans, root, | 1630 | ret = link_to_fixup_dir(wc->trans, root, |
1632 | path, key.objectid); | 1631 | path, key.objectid); |
1633 | BUG_ON(ret); | 1632 | BUG_ON(ret); |
@@ -1977,10 +1976,11 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
1977 | { | 1976 | { |
1978 | int index1; | 1977 | int index1; |
1979 | int index2; | 1978 | int index2; |
1979 | int mark; | ||
1980 | int ret; | 1980 | int ret; |
1981 | struct btrfs_root *log = root->log_root; | 1981 | struct btrfs_root *log = root->log_root; |
1982 | struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; | 1982 | struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; |
1983 | u64 log_transid = 0; | 1983 | unsigned long log_transid = 0; |
1984 | 1984 | ||
1985 | mutex_lock(&root->log_mutex); | 1985 | mutex_lock(&root->log_mutex); |
1986 | index1 = root->log_transid % 2; | 1986 | index1 = root->log_transid % 2; |
@@ -2014,24 +2014,29 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2014 | goto out; | 2014 | goto out; |
2015 | } | 2015 | } |
2016 | 2016 | ||
2017 | log_transid = root->log_transid; | ||
2018 | if (log_transid % 2 == 0) | ||
2019 | mark = EXTENT_DIRTY; | ||
2020 | else | ||
2021 | mark = EXTENT_NEW; | ||
2022 | |||
2017 | /* we start IO on all the marked extents here, but we don't actually | 2023 | /* we start IO on all the marked extents here, but we don't actually |
2018 | * wait for them until later. | 2024 | * wait for them until later. |
2019 | */ | 2025 | */ |
2020 | ret = btrfs_write_marked_extents(log, &log->dirty_log_pages); | 2026 | ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark); |
2021 | BUG_ON(ret); | 2027 | BUG_ON(ret); |
2022 | 2028 | ||
2023 | btrfs_set_root_node(&log->root_item, log->node); | 2029 | btrfs_set_root_node(&log->root_item, log->node); |
2024 | 2030 | ||
2025 | root->log_batch = 0; | 2031 | root->log_batch = 0; |
2026 | log_transid = root->log_transid; | ||
2027 | root->log_transid++; | 2032 | root->log_transid++; |
2028 | log->log_transid = root->log_transid; | 2033 | log->log_transid = root->log_transid; |
2029 | root->log_start_pid = 0; | 2034 | root->log_start_pid = 0; |
2030 | smp_mb(); | 2035 | smp_mb(); |
2031 | /* | 2036 | /* |
2032 | * log tree has been flushed to disk, new modifications of | 2037 | * IO has been started, blocks of the log tree have WRITTEN flag set |
2033 | * the log will be written to new positions. so it's safe to | 2038 | * in their headers. new modifications of the log will be written to |
2034 | * allow log writers to go in. | 2039 | * new positions. so it's safe to allow log writers to go in. |
2035 | */ | 2040 | */ |
2036 | mutex_unlock(&root->log_mutex); | 2041 | mutex_unlock(&root->log_mutex); |
2037 | 2042 | ||
@@ -2052,7 +2057,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2052 | 2057 | ||
2053 | index2 = log_root_tree->log_transid % 2; | 2058 | index2 = log_root_tree->log_transid % 2; |
2054 | if (atomic_read(&log_root_tree->log_commit[index2])) { | 2059 | if (atomic_read(&log_root_tree->log_commit[index2])) { |
2055 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | 2060 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2056 | wait_log_commit(trans, log_root_tree, | 2061 | wait_log_commit(trans, log_root_tree, |
2057 | log_root_tree->log_transid); | 2062 | log_root_tree->log_transid); |
2058 | mutex_unlock(&log_root_tree->log_mutex); | 2063 | mutex_unlock(&log_root_tree->log_mutex); |
@@ -2072,16 +2077,17 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2072 | * check the full commit flag again | 2077 | * check the full commit flag again |
2073 | */ | 2078 | */ |
2074 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { | 2079 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { |
2075 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | 2080 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2076 | mutex_unlock(&log_root_tree->log_mutex); | 2081 | mutex_unlock(&log_root_tree->log_mutex); |
2077 | ret = -EAGAIN; | 2082 | ret = -EAGAIN; |
2078 | goto out_wake_log_root; | 2083 | goto out_wake_log_root; |
2079 | } | 2084 | } |
2080 | 2085 | ||
2081 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, | 2086 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, |
2082 | &log_root_tree->dirty_log_pages); | 2087 | &log_root_tree->dirty_log_pages, |
2088 | EXTENT_DIRTY | EXTENT_NEW); | ||
2083 | BUG_ON(ret); | 2089 | BUG_ON(ret); |
2084 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | 2090 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2085 | 2091 | ||
2086 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, | 2092 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, |
2087 | log_root_tree->node->start); | 2093 | log_root_tree->node->start); |
@@ -2147,12 +2153,12 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | |||
2147 | 2153 | ||
2148 | while (1) { | 2154 | while (1) { |
2149 | ret = find_first_extent_bit(&log->dirty_log_pages, | 2155 | ret = find_first_extent_bit(&log->dirty_log_pages, |
2150 | 0, &start, &end, EXTENT_DIRTY); | 2156 | 0, &start, &end, EXTENT_DIRTY | EXTENT_NEW); |
2151 | if (ret) | 2157 | if (ret) |
2152 | break; | 2158 | break; |
2153 | 2159 | ||
2154 | clear_extent_dirty(&log->dirty_log_pages, | 2160 | clear_extent_bits(&log->dirty_log_pages, start, end, |
2155 | start, end, GFP_NOFS); | 2161 | EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS); |
2156 | } | 2162 | } |
2157 | 2163 | ||
2158 | if (log->log_transid > 0) { | 2164 | if (log->log_transid > 0) { |