diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 354 |
1 files changed, 170 insertions, 184 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index d81cda2e077c..20794290256b 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -78,104 +78,6 @@ static int link_to_fixup_dir(struct btrfs_trans_handle *trans, | |||
| 78 | */ | 78 | */ |
| 79 | 79 | ||
| 80 | /* | 80 | /* |
| 81 | * btrfs_add_log_tree adds a new per-subvolume log tree into the | ||
| 82 | * tree of log tree roots. This must be called with a tree log transaction | ||
| 83 | * running (see start_log_trans). | ||
| 84 | */ | ||
| 85 | static int btrfs_add_log_tree(struct btrfs_trans_handle *trans, | ||
| 86 | struct btrfs_root *root) | ||
| 87 | { | ||
| 88 | struct btrfs_key key; | ||
| 89 | struct btrfs_root_item root_item; | ||
| 90 | struct btrfs_inode_item *inode_item; | ||
| 91 | struct extent_buffer *leaf; | ||
| 92 | struct btrfs_root *new_root = root; | ||
| 93 | int ret; | ||
| 94 | u64 objectid = root->root_key.objectid; | ||
| 95 | |||
| 96 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0, | ||
| 97 | BTRFS_TREE_LOG_OBJECTID, | ||
| 98 | trans->transid, 0, 0, 0); | ||
| 99 | if (IS_ERR(leaf)) { | ||
| 100 | ret = PTR_ERR(leaf); | ||
| 101 | return ret; | ||
| 102 | } | ||
| 103 | |||
| 104 | btrfs_set_header_nritems(leaf, 0); | ||
| 105 | btrfs_set_header_level(leaf, 0); | ||
| 106 | btrfs_set_header_bytenr(leaf, leaf->start); | ||
| 107 | btrfs_set_header_generation(leaf, trans->transid); | ||
| 108 | btrfs_set_header_owner(leaf, BTRFS_TREE_LOG_OBJECTID); | ||
| 109 | |||
| 110 | write_extent_buffer(leaf, root->fs_info->fsid, | ||
| 111 | (unsigned long)btrfs_header_fsid(leaf), | ||
| 112 | BTRFS_FSID_SIZE); | ||
| 113 | btrfs_mark_buffer_dirty(leaf); | ||
| 114 | |||
| 115 | inode_item = &root_item.inode; | ||
| 116 | memset(inode_item, 0, sizeof(*inode_item)); | ||
| 117 | inode_item->generation = cpu_to_le64(1); | ||
| 118 | inode_item->size = cpu_to_le64(3); | ||
| 119 | inode_item->nlink = cpu_to_le32(1); | ||
| 120 | inode_item->nbytes = cpu_to_le64(root->leafsize); | ||
| 121 | inode_item->mode = cpu_to_le32(S_IFDIR | 0755); | ||
| 122 | |||
| 123 | btrfs_set_root_bytenr(&root_item, leaf->start); | ||
| 124 | btrfs_set_root_generation(&root_item, trans->transid); | ||
| 125 | btrfs_set_root_level(&root_item, 0); | ||
| 126 | btrfs_set_root_refs(&root_item, 0); | ||
| 127 | btrfs_set_root_used(&root_item, 0); | ||
| 128 | |||
| 129 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); | ||
| 130 | root_item.drop_level = 0; | ||
| 131 | |||
| 132 | btrfs_tree_unlock(leaf); | ||
| 133 | free_extent_buffer(leaf); | ||
| 134 | leaf = NULL; | ||
| 135 | |||
| 136 | btrfs_set_root_dirid(&root_item, 0); | ||
| 137 | |||
| 138 | key.objectid = BTRFS_TREE_LOG_OBJECTID; | ||
| 139 | key.offset = objectid; | ||
| 140 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | ||
| 141 | ret = btrfs_insert_root(trans, root->fs_info->log_root_tree, &key, | ||
| 142 | &root_item); | ||
| 143 | if (ret) | ||
| 144 | goto fail; | ||
| 145 | |||
| 146 | new_root = btrfs_read_fs_root_no_radix(root->fs_info->log_root_tree, | ||
| 147 | &key); | ||
| 148 | BUG_ON(!new_root); | ||
| 149 | |||
| 150 | WARN_ON(root->log_root); | ||
| 151 | root->log_root = new_root; | ||
| 152 | |||
| 153 | /* | ||
| 154 | * log trees do not get reference counted because they go away | ||
| 155 | * before a real commit is actually done. They do store pointers | ||
| 156 | * to file data extents, and those reference counts still get | ||
| 157 | * updated (along with back refs to the log tree). | ||
| 158 | */ | ||
| 159 | new_root->ref_cows = 0; | ||
| 160 | new_root->last_trans = trans->transid; | ||
| 161 | |||
| 162 | /* | ||
| 163 | * we need to make sure the root block for this new tree | ||
| 164 | * is marked as dirty in the dirty_log_pages tree. This | ||
| 165 | * is how it gets flushed down to disk at tree log commit time. | ||
| 166 | * | ||
| 167 | * the tree logging mutex keeps others from coming in and changing | ||
| 168 | * the new_root->node, so we can safely access it here | ||
| 169 | */ | ||
| 170 | set_extent_dirty(&new_root->dirty_log_pages, new_root->node->start, | ||
| 171 | new_root->node->start + new_root->node->len - 1, | ||
| 172 | GFP_NOFS); | ||
| 173 | |||
| 174 | fail: | ||
| 175 | return ret; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* | ||
| 179 | * start a sub transaction and setup the log tree | 81 | * start a sub transaction and setup the log tree |
| 180 | * this increments the log tree writer count to make the people | 82 | * this increments the log tree writer count to make the people |
| 181 | * syncing the tree wait for us to finish | 83 | * syncing the tree wait for us to finish |
| @@ -184,6 +86,14 @@ static int start_log_trans(struct btrfs_trans_handle *trans, | |||
| 184 | struct btrfs_root *root) | 86 | struct btrfs_root *root) |
| 185 | { | 87 | { |
| 186 | int ret; | 88 | int ret; |
| 89 | |||
| 90 | mutex_lock(&root->log_mutex); | ||
| 91 | if (root->log_root) { | ||
| 92 | root->log_batch++; | ||
| 93 | atomic_inc(&root->log_writers); | ||
| 94 | mutex_unlock(&root->log_mutex); | ||
| 95 | return 0; | ||
| 96 | } | ||
| 187 | mutex_lock(&root->fs_info->tree_log_mutex); | 97 | mutex_lock(&root->fs_info->tree_log_mutex); |
| 188 | if (!root->fs_info->log_root_tree) { | 98 | if (!root->fs_info->log_root_tree) { |
| 189 | ret = btrfs_init_log_root_tree(trans, root->fs_info); | 99 | ret = btrfs_init_log_root_tree(trans, root->fs_info); |
| @@ -193,9 +103,10 @@ static int start_log_trans(struct btrfs_trans_handle *trans, | |||
| 193 | ret = btrfs_add_log_tree(trans, root); | 103 | ret = btrfs_add_log_tree(trans, root); |
| 194 | BUG_ON(ret); | 104 | BUG_ON(ret); |
| 195 | } | 105 | } |
| 196 | atomic_inc(&root->fs_info->tree_log_writers); | ||
| 197 | root->fs_info->tree_log_batch++; | ||
| 198 | mutex_unlock(&root->fs_info->tree_log_mutex); | 106 | mutex_unlock(&root->fs_info->tree_log_mutex); |
| 107 | root->log_batch++; | ||
| 108 | atomic_inc(&root->log_writers); | ||
| 109 | mutex_unlock(&root->log_mutex); | ||
| 199 | return 0; | 110 | return 0; |
| 200 | } | 111 | } |
| 201 | 112 | ||
| @@ -212,13 +123,12 @@ static int join_running_log_trans(struct btrfs_root *root) | |||
| 212 | if (!root->log_root) | 123 | if (!root->log_root) |
| 213 | return -ENOENT; | 124 | return -ENOENT; |
| 214 | 125 | ||
| 215 | mutex_lock(&root->fs_info->tree_log_mutex); | 126 | mutex_lock(&root->log_mutex); |
| 216 | if (root->log_root) { | 127 | if (root->log_root) { |
| 217 | ret = 0; | 128 | ret = 0; |
| 218 | atomic_inc(&root->fs_info->tree_log_writers); | 129 | atomic_inc(&root->log_writers); |
| 219 | root->fs_info->tree_log_batch++; | ||
| 220 | } | 130 | } |
| 221 | mutex_unlock(&root->fs_info->tree_log_mutex); | 131 | mutex_unlock(&root->log_mutex); |
| 222 | return ret; | 132 | return ret; |
| 223 | } | 133 | } |
| 224 | 134 | ||
| @@ -228,10 +138,11 @@ static int join_running_log_trans(struct btrfs_root *root) | |||
| 228 | */ | 138 | */ |
| 229 | static int end_log_trans(struct btrfs_root *root) | 139 | static int end_log_trans(struct btrfs_root *root) |
| 230 | { | 140 | { |
| 231 | atomic_dec(&root->fs_info->tree_log_writers); | 141 | if (atomic_dec_and_test(&root->log_writers)) { |
| 232 | smp_mb(); | 142 | smp_mb(); |
| 233 | if (waitqueue_active(&root->fs_info->tree_log_wait)) | 143 | if (waitqueue_active(&root->log_writer_wait)) |
| 234 | wake_up(&root->fs_info->tree_log_wait); | 144 | wake_up(&root->log_writer_wait); |
| 145 | } | ||
| 235 | return 0; | 146 | return 0; |
| 236 | } | 147 | } |
| 237 | 148 | ||
| @@ -1704,6 +1615,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
| 1704 | 1615 | ||
| 1705 | btrfs_tree_lock(next); | 1616 | btrfs_tree_lock(next); |
| 1706 | clean_tree_block(trans, root, next); | 1617 | clean_tree_block(trans, root, next); |
| 1618 | btrfs_set_lock_blocking(next); | ||
| 1707 | btrfs_wait_tree_block_writeback(next); | 1619 | btrfs_wait_tree_block_writeback(next); |
| 1708 | btrfs_tree_unlock(next); | 1620 | btrfs_tree_unlock(next); |
| 1709 | 1621 | ||
| @@ -1750,6 +1662,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, | |||
| 1750 | next = path->nodes[*level]; | 1662 | next = path->nodes[*level]; |
| 1751 | btrfs_tree_lock(next); | 1663 | btrfs_tree_lock(next); |
| 1752 | clean_tree_block(trans, root, next); | 1664 | clean_tree_block(trans, root, next); |
| 1665 | btrfs_set_lock_blocking(next); | ||
| 1753 | btrfs_wait_tree_block_writeback(next); | 1666 | btrfs_wait_tree_block_writeback(next); |
| 1754 | btrfs_tree_unlock(next); | 1667 | btrfs_tree_unlock(next); |
| 1755 | 1668 | ||
| @@ -1807,6 +1720,7 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, | |||
| 1807 | 1720 | ||
| 1808 | btrfs_tree_lock(next); | 1721 | btrfs_tree_lock(next); |
| 1809 | clean_tree_block(trans, root, next); | 1722 | clean_tree_block(trans, root, next); |
| 1723 | btrfs_set_lock_blocking(next); | ||
| 1810 | btrfs_wait_tree_block_writeback(next); | 1724 | btrfs_wait_tree_block_writeback(next); |
| 1811 | btrfs_tree_unlock(next); | 1725 | btrfs_tree_unlock(next); |
| 1812 | 1726 | ||
| @@ -1879,6 +1793,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, | |||
| 1879 | 1793 | ||
| 1880 | btrfs_tree_lock(next); | 1794 | btrfs_tree_lock(next); |
| 1881 | clean_tree_block(trans, log, next); | 1795 | clean_tree_block(trans, log, next); |
| 1796 | btrfs_set_lock_blocking(next); | ||
| 1882 | btrfs_wait_tree_block_writeback(next); | 1797 | btrfs_wait_tree_block_writeback(next); |
| 1883 | btrfs_tree_unlock(next); | 1798 | btrfs_tree_unlock(next); |
| 1884 | 1799 | ||
| @@ -1902,26 +1817,65 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, | |||
| 1902 | } | 1817 | } |
| 1903 | } | 1818 | } |
| 1904 | btrfs_free_path(path); | 1819 | btrfs_free_path(path); |
| 1905 | if (wc->free) | ||
| 1906 | free_extent_buffer(log->node); | ||
| 1907 | return ret; | 1820 | return ret; |
| 1908 | } | 1821 | } |
| 1909 | 1822 | ||
| 1910 | static int wait_log_commit(struct btrfs_root *log) | 1823 | /* |
| 1824 | * helper function to update the item for a given subvolumes log root | ||
| 1825 | * in the tree of log roots | ||
| 1826 | */ | ||
| 1827 | static int update_log_root(struct btrfs_trans_handle *trans, | ||
| 1828 | struct btrfs_root *log) | ||
| 1829 | { | ||
| 1830 | int ret; | ||
| 1831 | |||
| 1832 | if (log->log_transid == 1) { | ||
| 1833 | /* insert root item on the first sync */ | ||
| 1834 | ret = btrfs_insert_root(trans, log->fs_info->log_root_tree, | ||
| 1835 | &log->root_key, &log->root_item); | ||
| 1836 | } else { | ||
| 1837 | ret = btrfs_update_root(trans, log->fs_info->log_root_tree, | ||
| 1838 | &log->root_key, &log->root_item); | ||
| 1839 | } | ||
| 1840 | return ret; | ||
| 1841 | } | ||
| 1842 | |||
| 1843 | static int wait_log_commit(struct btrfs_root *root, unsigned long transid) | ||
| 1911 | { | 1844 | { |
| 1912 | DEFINE_WAIT(wait); | 1845 | DEFINE_WAIT(wait); |
| 1913 | u64 transid = log->fs_info->tree_log_transid; | 1846 | int index = transid % 2; |
| 1914 | 1847 | ||
| 1848 | /* | ||
| 1849 | * we only allow two pending log transactions at a time, | ||
| 1850 | * so we know that if ours is more than 2 older than the | ||
| 1851 | * current transaction, we're done | ||
| 1852 | */ | ||
| 1915 | do { | 1853 | do { |
| 1916 | prepare_to_wait(&log->fs_info->tree_log_wait, &wait, | 1854 | prepare_to_wait(&root->log_commit_wait[index], |
| 1917 | TASK_UNINTERRUPTIBLE); | 1855 | &wait, TASK_UNINTERRUPTIBLE); |
| 1918 | mutex_unlock(&log->fs_info->tree_log_mutex); | 1856 | mutex_unlock(&root->log_mutex); |
| 1919 | if (atomic_read(&log->fs_info->tree_log_commit)) | 1857 | if (root->log_transid < transid + 2 && |
| 1858 | atomic_read(&root->log_commit[index])) | ||
| 1920 | schedule(); | 1859 | schedule(); |
| 1921 | finish_wait(&log->fs_info->tree_log_wait, &wait); | 1860 | finish_wait(&root->log_commit_wait[index], &wait); |
| 1922 | mutex_lock(&log->fs_info->tree_log_mutex); | 1861 | mutex_lock(&root->log_mutex); |
| 1923 | } while (transid == log->fs_info->tree_log_transid && | 1862 | } while (root->log_transid < transid + 2 && |
| 1924 | atomic_read(&log->fs_info->tree_log_commit)); | 1863 | atomic_read(&root->log_commit[index])); |
| 1864 | return 0; | ||
| 1865 | } | ||
| 1866 | |||
| 1867 | static int wait_for_writer(struct btrfs_root *root) | ||
| 1868 | { | ||
| 1869 | DEFINE_WAIT(wait); | ||
| 1870 | while (atomic_read(&root->log_writers)) { | ||
| 1871 | prepare_to_wait(&root->log_writer_wait, | ||
| 1872 | &wait, TASK_UNINTERRUPTIBLE); | ||
| 1873 | mutex_unlock(&root->log_mutex); | ||
| 1874 | if (atomic_read(&root->log_writers)) | ||
| 1875 | schedule(); | ||
| 1876 | mutex_lock(&root->log_mutex); | ||
| 1877 | finish_wait(&root->log_writer_wait, &wait); | ||
| 1878 | } | ||
| 1925 | return 0; | 1879 | return 0; |
| 1926 | } | 1880 | } |
| 1927 | 1881 | ||
| @@ -1933,57 +1887,114 @@ static int wait_log_commit(struct btrfs_root *log) | |||
| 1933 | int btrfs_sync_log(struct btrfs_trans_handle *trans, | 1887 | int btrfs_sync_log(struct btrfs_trans_handle *trans, |
| 1934 | struct btrfs_root *root) | 1888 | struct btrfs_root *root) |
| 1935 | { | 1889 | { |
| 1890 | int index1; | ||
| 1891 | int index2; | ||
| 1936 | int ret; | 1892 | int ret; |
| 1937 | unsigned long batch; | ||
| 1938 | struct btrfs_root *log = root->log_root; | 1893 | struct btrfs_root *log = root->log_root; |
| 1894 | struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; | ||
| 1939 | 1895 | ||
| 1940 | mutex_lock(&log->fs_info->tree_log_mutex); | 1896 | mutex_lock(&root->log_mutex); |
| 1941 | if (atomic_read(&log->fs_info->tree_log_commit)) { | 1897 | index1 = root->log_transid % 2; |
| 1942 | wait_log_commit(log); | 1898 | if (atomic_read(&root->log_commit[index1])) { |
| 1943 | goto out; | 1899 | wait_log_commit(root, root->log_transid); |
| 1900 | mutex_unlock(&root->log_mutex); | ||
| 1901 | return 0; | ||
| 1944 | } | 1902 | } |
| 1945 | atomic_set(&log->fs_info->tree_log_commit, 1); | 1903 | atomic_set(&root->log_commit[index1], 1); |
| 1904 | |||
| 1905 | /* wait for previous tree log sync to complete */ | ||
| 1906 | if (atomic_read(&root->log_commit[(index1 + 1) % 2])) | ||
| 1907 | wait_log_commit(root, root->log_transid - 1); | ||
| 1946 | 1908 | ||
| 1947 | while (1) { | 1909 | while (1) { |
| 1948 | batch = log->fs_info->tree_log_batch; | 1910 | unsigned long batch = root->log_batch; |
| 1949 | mutex_unlock(&log->fs_info->tree_log_mutex); | 1911 | mutex_unlock(&root->log_mutex); |
| 1950 | schedule_timeout_uninterruptible(1); | 1912 | schedule_timeout_uninterruptible(1); |
| 1951 | mutex_lock(&log->fs_info->tree_log_mutex); | 1913 | mutex_lock(&root->log_mutex); |
| 1952 | 1914 | wait_for_writer(root); | |
| 1953 | while (atomic_read(&log->fs_info->tree_log_writers)) { | 1915 | if (batch == root->log_batch) |
| 1954 | DEFINE_WAIT(wait); | ||
| 1955 | prepare_to_wait(&log->fs_info->tree_log_wait, &wait, | ||
| 1956 | TASK_UNINTERRUPTIBLE); | ||
| 1957 | mutex_unlock(&log->fs_info->tree_log_mutex); | ||
| 1958 | if (atomic_read(&log->fs_info->tree_log_writers)) | ||
| 1959 | schedule(); | ||
| 1960 | mutex_lock(&log->fs_info->tree_log_mutex); | ||
| 1961 | finish_wait(&log->fs_info->tree_log_wait, &wait); | ||
| 1962 | } | ||
| 1963 | if (batch == log->fs_info->tree_log_batch) | ||
| 1964 | break; | 1916 | break; |
| 1965 | } | 1917 | } |
| 1966 | 1918 | ||
| 1967 | ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages); | 1919 | ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages); |
| 1968 | BUG_ON(ret); | 1920 | BUG_ON(ret); |
| 1969 | ret = btrfs_write_and_wait_marked_extents(root->fs_info->log_root_tree, | 1921 | |
| 1970 | &root->fs_info->log_root_tree->dirty_log_pages); | 1922 | btrfs_set_root_bytenr(&log->root_item, log->node->start); |
| 1923 | btrfs_set_root_generation(&log->root_item, trans->transid); | ||
| 1924 | btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node)); | ||
| 1925 | |||
| 1926 | root->log_batch = 0; | ||
| 1927 | root->log_transid++; | ||
| 1928 | log->log_transid = root->log_transid; | ||
| 1929 | smp_mb(); | ||
| 1930 | /* | ||
| 1931 | * log tree has been flushed to disk, new modifications of | ||
| 1932 | * the log will be written to new positions. so it's safe to | ||
| 1933 | * allow log writers to go in. | ||
| 1934 | */ | ||
| 1935 | mutex_unlock(&root->log_mutex); | ||
| 1936 | |||
| 1937 | mutex_lock(&log_root_tree->log_mutex); | ||
| 1938 | log_root_tree->log_batch++; | ||
| 1939 | atomic_inc(&log_root_tree->log_writers); | ||
| 1940 | mutex_unlock(&log_root_tree->log_mutex); | ||
| 1941 | |||
| 1942 | ret = update_log_root(trans, log); | ||
| 1943 | BUG_ON(ret); | ||
| 1944 | |||
| 1945 | mutex_lock(&log_root_tree->log_mutex); | ||
| 1946 | if (atomic_dec_and_test(&log_root_tree->log_writers)) { | ||
| 1947 | smp_mb(); | ||
| 1948 | if (waitqueue_active(&log_root_tree->log_writer_wait)) | ||
| 1949 | wake_up(&log_root_tree->log_writer_wait); | ||
| 1950 | } | ||
| 1951 | |||
| 1952 | index2 = log_root_tree->log_transid % 2; | ||
| 1953 | if (atomic_read(&log_root_tree->log_commit[index2])) { | ||
| 1954 | wait_log_commit(log_root_tree, log_root_tree->log_transid); | ||
| 1955 | mutex_unlock(&log_root_tree->log_mutex); | ||
| 1956 | goto out; | ||
| 1957 | } | ||
| 1958 | atomic_set(&log_root_tree->log_commit[index2], 1); | ||
| 1959 | |||
| 1960 | if (atomic_read(&log_root_tree->log_commit[(index2 + 1) % 2])) | ||
| 1961 | wait_log_commit(log_root_tree, log_root_tree->log_transid - 1); | ||
| 1962 | |||
| 1963 | wait_for_writer(log_root_tree); | ||
| 1964 | |||
| 1965 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, | ||
| 1966 | &log_root_tree->dirty_log_pages); | ||
| 1971 | BUG_ON(ret); | 1967 | BUG_ON(ret); |
| 1972 | 1968 | ||
| 1973 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, | 1969 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, |
| 1974 | log->fs_info->log_root_tree->node->start); | 1970 | log_root_tree->node->start); |
| 1975 | btrfs_set_super_log_root_level(&root->fs_info->super_for_commit, | 1971 | btrfs_set_super_log_root_level(&root->fs_info->super_for_commit, |
| 1976 | btrfs_header_level(log->fs_info->log_root_tree->node)); | 1972 | btrfs_header_level(log_root_tree->node)); |
| 1973 | |||
| 1974 | log_root_tree->log_batch = 0; | ||
| 1975 | log_root_tree->log_transid++; | ||
| 1976 | smp_mb(); | ||
| 1977 | |||
| 1978 | mutex_unlock(&log_root_tree->log_mutex); | ||
| 1979 | |||
| 1980 | /* | ||
| 1981 | * nobody else is going to jump in and write the the ctree | ||
| 1982 | * super here because the log_commit atomic below is protecting | ||
| 1983 | * us. We must be called with a transaction handle pinning | ||
| 1984 | * the running transaction open, so a full commit can't hop | ||
| 1985 | * in and cause problems either. | ||
| 1986 | */ | ||
| 1987 | write_ctree_super(trans, root->fs_info->tree_root, 2); | ||
| 1977 | 1988 | ||
| 1978 | write_ctree_super(trans, log->fs_info->tree_root, 2); | 1989 | atomic_set(&log_root_tree->log_commit[index2], 0); |
| 1979 | log->fs_info->tree_log_transid++; | ||
| 1980 | log->fs_info->tree_log_batch = 0; | ||
| 1981 | atomic_set(&log->fs_info->tree_log_commit, 0); | ||
| 1982 | smp_mb(); | 1990 | smp_mb(); |
| 1983 | if (waitqueue_active(&log->fs_info->tree_log_wait)) | 1991 | if (waitqueue_active(&log_root_tree->log_commit_wait[index2])) |
| 1984 | wake_up(&log->fs_info->tree_log_wait); | 1992 | wake_up(&log_root_tree->log_commit_wait[index2]); |
| 1985 | out: | 1993 | out: |
| 1986 | mutex_unlock(&log->fs_info->tree_log_mutex); | 1994 | atomic_set(&root->log_commit[index1], 0); |
| 1995 | smp_mb(); | ||
| 1996 | if (waitqueue_active(&root->log_commit_wait[index1])) | ||
| 1997 | wake_up(&root->log_commit_wait[index1]); | ||
| 1987 | return 0; | 1998 | return 0; |
| 1988 | } | 1999 | } |
| 1989 | 2000 | ||
| @@ -2019,38 +2030,18 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | |||
| 2019 | start, end, GFP_NOFS); | 2030 | start, end, GFP_NOFS); |
| 2020 | } | 2031 | } |
| 2021 | 2032 | ||
| 2022 | log = root->log_root; | 2033 | if (log->log_transid > 0) { |
| 2023 | ret = btrfs_del_root(trans, root->fs_info->log_root_tree, | 2034 | ret = btrfs_del_root(trans, root->fs_info->log_root_tree, |
| 2024 | &log->root_key); | 2035 | &log->root_key); |
| 2025 | BUG_ON(ret); | 2036 | BUG_ON(ret); |
| 2037 | } | ||
| 2026 | root->log_root = NULL; | 2038 | root->log_root = NULL; |
| 2027 | kfree(root->log_root); | 2039 | free_extent_buffer(log->node); |
| 2040 | kfree(log); | ||
| 2028 | return 0; | 2041 | return 0; |
| 2029 | } | 2042 | } |
| 2030 | 2043 | ||
| 2031 | /* | 2044 | /* |
| 2032 | * helper function to update the item for a given subvolumes log root | ||
| 2033 | * in the tree of log roots | ||
| 2034 | */ | ||
| 2035 | static int update_log_root(struct btrfs_trans_handle *trans, | ||
| 2036 | struct btrfs_root *log) | ||
| 2037 | { | ||
| 2038 | u64 bytenr = btrfs_root_bytenr(&log->root_item); | ||
| 2039 | int ret; | ||
| 2040 | |||
| 2041 | if (log->node->start == bytenr) | ||
| 2042 | return 0; | ||
| 2043 | |||
| 2044 | btrfs_set_root_bytenr(&log->root_item, log->node->start); | ||
| 2045 | btrfs_set_root_generation(&log->root_item, trans->transid); | ||
| 2046 | btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node)); | ||
| 2047 | ret = btrfs_update_root(trans, log->fs_info->log_root_tree, | ||
| 2048 | &log->root_key, &log->root_item); | ||
| 2049 | BUG_ON(ret); | ||
| 2050 | return ret; | ||
| 2051 | } | ||
| 2052 | |||
| 2053 | /* | ||
| 2054 | * If both a file and directory are logged, and unlinks or renames are | 2045 | * If both a file and directory are logged, and unlinks or renames are |
| 2055 | * mixed in, we have a few interesting corners: | 2046 | * mixed in, we have a few interesting corners: |
| 2056 | * | 2047 | * |
| @@ -2711,11 +2702,6 @@ next_slot: | |||
| 2711 | 2702 | ||
| 2712 | btrfs_free_path(path); | 2703 | btrfs_free_path(path); |
| 2713 | btrfs_free_path(dst_path); | 2704 | btrfs_free_path(dst_path); |
| 2714 | |||
| 2715 | mutex_lock(&root->fs_info->tree_log_mutex); | ||
| 2716 | ret = update_log_root(trans, log); | ||
| 2717 | BUG_ON(ret); | ||
| 2718 | mutex_unlock(&root->fs_info->tree_log_mutex); | ||
| 2719 | out: | 2705 | out: |
| 2720 | return 0; | 2706 | return 0; |
| 2721 | } | 2707 | } |
