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) { |
