diff options
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 9 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 248 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.c | 57 | ||||
-rw-r--r-- | fs/btrfs/super.c | 13 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 2 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 63 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 3 |
9 files changed, 342 insertions, 58 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index d4042c89d29b..938efe33be80 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -3431,6 +3431,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
3431 | struct btrfs_root *root, u64 group_start, | 3431 | struct btrfs_root *root, u64 group_start, |
3432 | struct extent_map *em); | 3432 | struct extent_map *em); |
3433 | void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info); | 3433 | void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info); |
3434 | void btrfs_get_block_group_trimming(struct btrfs_block_group_cache *cache); | ||
3435 | void btrfs_put_block_group_trimming(struct btrfs_block_group_cache *cache); | ||
3434 | void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, | 3436 | void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, |
3435 | struct btrfs_root *root); | 3437 | struct btrfs_root *root); |
3436 | u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data); | 3438 | u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data); |
@@ -4067,6 +4069,7 @@ __cold | |||
4067 | void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, | 4069 | void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, |
4068 | unsigned int line, int errno, const char *fmt, ...); | 4070 | unsigned int line, int errno, const char *fmt, ...); |
4069 | 4071 | ||
4072 | const char *btrfs_decode_error(int errno); | ||
4070 | 4073 | ||
4071 | __cold | 4074 | __cold |
4072 | void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, | 4075 | void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 230546b45474..cc15514b4a76 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -3761,6 +3761,15 @@ void close_ctree(struct btrfs_root *root) | |||
3761 | cancel_work_sync(&fs_info->async_reclaim_work); | 3761 | cancel_work_sync(&fs_info->async_reclaim_work); |
3762 | 3762 | ||
3763 | if (!(fs_info->sb->s_flags & MS_RDONLY)) { | 3763 | if (!(fs_info->sb->s_flags & MS_RDONLY)) { |
3764 | /* | ||
3765 | * If the cleaner thread is stopped and there are | ||
3766 | * block groups queued for removal, the deletion will be | ||
3767 | * skipped when we quit the cleaner thread. | ||
3768 | */ | ||
3769 | mutex_lock(&root->fs_info->cleaner_mutex); | ||
3770 | btrfs_delete_unused_bgs(root->fs_info); | ||
3771 | mutex_unlock(&root->fs_info->cleaner_mutex); | ||
3772 | |||
3764 | ret = btrfs_commit_super(root); | 3773 | ret = btrfs_commit_super(root); |
3765 | if (ret) | 3774 | if (ret) |
3766 | btrfs_err(fs_info, "commit super ret %d", ret); | 3775 | btrfs_err(fs_info, "commit super ret %d", ret); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 59d59d98bca1..5411f0ab5683 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1882,10 +1882,77 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans, | |||
1882 | return ret; | 1882 | return ret; |
1883 | } | 1883 | } |
1884 | 1884 | ||
1885 | static int btrfs_issue_discard(struct block_device *bdev, | 1885 | #define in_range(b, first, len) ((b) >= (first) && (b) < (first) + (len)) |
1886 | u64 start, u64 len) | 1886 | static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len, |
1887 | u64 *discarded_bytes) | ||
1887 | { | 1888 | { |
1888 | return blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0); | 1889 | int j, ret = 0; |
1890 | u64 bytes_left, end; | ||
1891 | u64 aligned_start = ALIGN(start, 1 << 9); | ||
1892 | |||
1893 | if (WARN_ON(start != aligned_start)) { | ||
1894 | len -= aligned_start - start; | ||
1895 | len = round_down(len, 1 << 9); | ||
1896 | start = aligned_start; | ||
1897 | } | ||
1898 | |||
1899 | *discarded_bytes = 0; | ||
1900 | |||
1901 | if (!len) | ||
1902 | return 0; | ||
1903 | |||
1904 | end = start + len; | ||
1905 | bytes_left = len; | ||
1906 | |||
1907 | /* Skip any superblocks on this device. */ | ||
1908 | for (j = 0; j < BTRFS_SUPER_MIRROR_MAX; j++) { | ||
1909 | u64 sb_start = btrfs_sb_offset(j); | ||
1910 | u64 sb_end = sb_start + BTRFS_SUPER_INFO_SIZE; | ||
1911 | u64 size = sb_start - start; | ||
1912 | |||
1913 | if (!in_range(sb_start, start, bytes_left) && | ||
1914 | !in_range(sb_end, start, bytes_left) && | ||
1915 | !in_range(start, sb_start, BTRFS_SUPER_INFO_SIZE)) | ||
1916 | continue; | ||
1917 | |||
1918 | /* | ||
1919 | * Superblock spans beginning of range. Adjust start and | ||
1920 | * try again. | ||
1921 | */ | ||
1922 | if (sb_start <= start) { | ||
1923 | start += sb_end - start; | ||
1924 | if (start > end) { | ||
1925 | bytes_left = 0; | ||
1926 | break; | ||
1927 | } | ||
1928 | bytes_left = end - start; | ||
1929 | continue; | ||
1930 | } | ||
1931 | |||
1932 | if (size) { | ||
1933 | ret = blkdev_issue_discard(bdev, start >> 9, size >> 9, | ||
1934 | GFP_NOFS, 0); | ||
1935 | if (!ret) | ||
1936 | *discarded_bytes += size; | ||
1937 | else if (ret != -EOPNOTSUPP) | ||
1938 | return ret; | ||
1939 | } | ||
1940 | |||
1941 | start = sb_end; | ||
1942 | if (start > end) { | ||
1943 | bytes_left = 0; | ||
1944 | break; | ||
1945 | } | ||
1946 | bytes_left = end - start; | ||
1947 | } | ||
1948 | |||
1949 | if (bytes_left) { | ||
1950 | ret = blkdev_issue_discard(bdev, start >> 9, bytes_left >> 9, | ||
1951 | GFP_NOFS, 0); | ||
1952 | if (!ret) | ||
1953 | *discarded_bytes += bytes_left; | ||
1954 | } | ||
1955 | return ret; | ||
1889 | } | 1956 | } |
1890 | 1957 | ||
1891 | int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, | 1958 | int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, |
@@ -1906,14 +1973,16 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, | |||
1906 | 1973 | ||
1907 | 1974 | ||
1908 | for (i = 0; i < bbio->num_stripes; i++, stripe++) { | 1975 | for (i = 0; i < bbio->num_stripes; i++, stripe++) { |
1976 | u64 bytes; | ||
1909 | if (!stripe->dev->can_discard) | 1977 | if (!stripe->dev->can_discard) |
1910 | continue; | 1978 | continue; |
1911 | 1979 | ||
1912 | ret = btrfs_issue_discard(stripe->dev->bdev, | 1980 | ret = btrfs_issue_discard(stripe->dev->bdev, |
1913 | stripe->physical, | 1981 | stripe->physical, |
1914 | stripe->length); | 1982 | stripe->length, |
1983 | &bytes); | ||
1915 | if (!ret) | 1984 | if (!ret) |
1916 | discarded_bytes += stripe->length; | 1985 | discarded_bytes += bytes; |
1917 | else if (ret != -EOPNOTSUPP) | 1986 | else if (ret != -EOPNOTSUPP) |
1918 | break; /* Logic errors or -ENOMEM, or -EIO but I don't know how that could happen JDM */ | 1987 | break; /* Logic errors or -ENOMEM, or -EIO but I don't know how that could happen JDM */ |
1919 | 1988 | ||
@@ -6061,20 +6130,19 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
6061 | struct btrfs_root *root) | 6130 | struct btrfs_root *root) |
6062 | { | 6131 | { |
6063 | struct btrfs_fs_info *fs_info = root->fs_info; | 6132 | struct btrfs_fs_info *fs_info = root->fs_info; |
6133 | struct btrfs_block_group_cache *block_group, *tmp; | ||
6134 | struct list_head *deleted_bgs; | ||
6064 | struct extent_io_tree *unpin; | 6135 | struct extent_io_tree *unpin; |
6065 | u64 start; | 6136 | u64 start; |
6066 | u64 end; | 6137 | u64 end; |
6067 | int ret; | 6138 | int ret; |
6068 | 6139 | ||
6069 | if (trans->aborted) | ||
6070 | return 0; | ||
6071 | |||
6072 | if (fs_info->pinned_extents == &fs_info->freed_extents[0]) | 6140 | if (fs_info->pinned_extents == &fs_info->freed_extents[0]) |
6073 | unpin = &fs_info->freed_extents[1]; | 6141 | unpin = &fs_info->freed_extents[1]; |
6074 | else | 6142 | else |
6075 | unpin = &fs_info->freed_extents[0]; | 6143 | unpin = &fs_info->freed_extents[0]; |
6076 | 6144 | ||
6077 | while (1) { | 6145 | while (!trans->aborted) { |
6078 | mutex_lock(&fs_info->unused_bg_unpin_mutex); | 6146 | mutex_lock(&fs_info->unused_bg_unpin_mutex); |
6079 | ret = find_first_extent_bit(unpin, 0, &start, &end, | 6147 | ret = find_first_extent_bit(unpin, 0, &start, &end, |
6080 | EXTENT_DIRTY, NULL); | 6148 | EXTENT_DIRTY, NULL); |
@@ -6093,6 +6161,34 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
6093 | cond_resched(); | 6161 | cond_resched(); |
6094 | } | 6162 | } |
6095 | 6163 | ||
6164 | /* | ||
6165 | * Transaction is finished. We don't need the lock anymore. We | ||
6166 | * do need to clean up the block groups in case of a transaction | ||
6167 | * abort. | ||
6168 | */ | ||
6169 | deleted_bgs = &trans->transaction->deleted_bgs; | ||
6170 | list_for_each_entry_safe(block_group, tmp, deleted_bgs, bg_list) { | ||
6171 | u64 trimmed = 0; | ||
6172 | |||
6173 | ret = -EROFS; | ||
6174 | if (!trans->aborted) | ||
6175 | ret = btrfs_discard_extent(root, | ||
6176 | block_group->key.objectid, | ||
6177 | block_group->key.offset, | ||
6178 | &trimmed); | ||
6179 | |||
6180 | list_del_init(&block_group->bg_list); | ||
6181 | btrfs_put_block_group_trimming(block_group); | ||
6182 | btrfs_put_block_group(block_group); | ||
6183 | |||
6184 | if (ret) { | ||
6185 | const char *errstr = btrfs_decode_error(ret); | ||
6186 | btrfs_warn(fs_info, | ||
6187 | "Discard failed while removing blockgroup: errno=%d %s\n", | ||
6188 | ret, errstr); | ||
6189 | } | ||
6190 | } | ||
6191 | |||
6096 | return 0; | 6192 | return 0; |
6097 | } | 6193 | } |
6098 | 6194 | ||
@@ -9830,6 +9926,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
9830 | * currently running transaction might finish and a new one start, | 9926 | * currently running transaction might finish and a new one start, |
9831 | * allowing for new block groups to be created that can reuse the same | 9927 | * allowing for new block groups to be created that can reuse the same |
9832 | * physical device locations unless we take this special care. | 9928 | * physical device locations unless we take this special care. |
9929 | * | ||
9930 | * There may also be an implicit trim operation if the file system | ||
9931 | * is mounted with -odiscard. The same protections must remain | ||
9932 | * in place until the extents have been discarded completely when | ||
9933 | * the transaction commit has completed. | ||
9833 | */ | 9934 | */ |
9834 | remove_em = (atomic_read(&block_group->trimming) == 0); | 9935 | remove_em = (atomic_read(&block_group->trimming) == 0); |
9835 | /* | 9936 | /* |
@@ -9904,6 +10005,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) | |||
9904 | spin_lock(&fs_info->unused_bgs_lock); | 10005 | spin_lock(&fs_info->unused_bgs_lock); |
9905 | while (!list_empty(&fs_info->unused_bgs)) { | 10006 | while (!list_empty(&fs_info->unused_bgs)) { |
9906 | u64 start, end; | 10007 | u64 start, end; |
10008 | int trimming; | ||
9907 | 10009 | ||
9908 | block_group = list_first_entry(&fs_info->unused_bgs, | 10010 | block_group = list_first_entry(&fs_info->unused_bgs, |
9909 | struct btrfs_block_group_cache, | 10011 | struct btrfs_block_group_cache, |
@@ -10003,12 +10105,39 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) | |||
10003 | spin_unlock(&block_group->lock); | 10105 | spin_unlock(&block_group->lock); |
10004 | spin_unlock(&space_info->lock); | 10106 | spin_unlock(&space_info->lock); |
10005 | 10107 | ||
10108 | /* DISCARD can flip during remount */ | ||
10109 | trimming = btrfs_test_opt(root, DISCARD); | ||
10110 | |||
10111 | /* Implicit trim during transaction commit. */ | ||
10112 | if (trimming) | ||
10113 | btrfs_get_block_group_trimming(block_group); | ||
10114 | |||
10006 | /* | 10115 | /* |
10007 | * Btrfs_remove_chunk will abort the transaction if things go | 10116 | * Btrfs_remove_chunk will abort the transaction if things go |
10008 | * horribly wrong. | 10117 | * horribly wrong. |
10009 | */ | 10118 | */ |
10010 | ret = btrfs_remove_chunk(trans, root, | 10119 | ret = btrfs_remove_chunk(trans, root, |
10011 | block_group->key.objectid); | 10120 | block_group->key.objectid); |
10121 | |||
10122 | if (ret) { | ||
10123 | if (trimming) | ||
10124 | btrfs_put_block_group_trimming(block_group); | ||
10125 | goto end_trans; | ||
10126 | } | ||
10127 | |||
10128 | /* | ||
10129 | * If we're not mounted with -odiscard, we can just forget | ||
10130 | * about this block group. Otherwise we'll need to wait | ||
10131 | * until transaction commit to do the actual discard. | ||
10132 | */ | ||
10133 | if (trimming) { | ||
10134 | WARN_ON(!list_empty(&block_group->bg_list)); | ||
10135 | spin_lock(&trans->transaction->deleted_bgs_lock); | ||
10136 | list_move(&block_group->bg_list, | ||
10137 | &trans->transaction->deleted_bgs); | ||
10138 | spin_unlock(&trans->transaction->deleted_bgs_lock); | ||
10139 | btrfs_get_block_group(block_group); | ||
10140 | } | ||
10012 | end_trans: | 10141 | end_trans: |
10013 | btrfs_end_transaction(trans, root); | 10142 | btrfs_end_transaction(trans, root); |
10014 | next: | 10143 | next: |
@@ -10062,10 +10191,99 @@ int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) | |||
10062 | return unpin_extent_range(root, start, end, false); | 10191 | return unpin_extent_range(root, start, end, false); |
10063 | } | 10192 | } |
10064 | 10193 | ||
10194 | /* | ||
10195 | * It used to be that old block groups would be left around forever. | ||
10196 | * Iterating over them would be enough to trim unused space. Since we | ||
10197 | * now automatically remove them, we also need to iterate over unallocated | ||
10198 | * space. | ||
10199 | * | ||
10200 | * We don't want a transaction for this since the discard may take a | ||
10201 | * substantial amount of time. We don't require that a transaction be | ||
10202 | * running, but we do need to take a running transaction into account | ||
10203 | * to ensure that we're not discarding chunks that were released in | ||
10204 | * the current transaction. | ||
10205 | * | ||
10206 | * Holding the chunks lock will prevent other threads from allocating | ||
10207 | * or releasing chunks, but it won't prevent a running transaction | ||
10208 | * from committing and releasing the memory that the pending chunks | ||
10209 | * list head uses. For that, we need to take a reference to the | ||
10210 | * transaction. | ||
10211 | */ | ||
10212 | static int btrfs_trim_free_extents(struct btrfs_device *device, | ||
10213 | u64 minlen, u64 *trimmed) | ||
10214 | { | ||
10215 | u64 start = 0, len = 0; | ||
10216 | int ret; | ||
10217 | |||
10218 | *trimmed = 0; | ||
10219 | |||
10220 | /* Not writeable = nothing to do. */ | ||
10221 | if (!device->writeable) | ||
10222 | return 0; | ||
10223 | |||
10224 | /* No free space = nothing to do. */ | ||
10225 | if (device->total_bytes <= device->bytes_used) | ||
10226 | return 0; | ||
10227 | |||
10228 | ret = 0; | ||
10229 | |||
10230 | while (1) { | ||
10231 | struct btrfs_fs_info *fs_info = device->dev_root->fs_info; | ||
10232 | struct btrfs_transaction *trans; | ||
10233 | u64 bytes; | ||
10234 | |||
10235 | ret = mutex_lock_interruptible(&fs_info->chunk_mutex); | ||
10236 | if (ret) | ||
10237 | return ret; | ||
10238 | |||
10239 | down_read(&fs_info->commit_root_sem); | ||
10240 | |||
10241 | spin_lock(&fs_info->trans_lock); | ||
10242 | trans = fs_info->running_transaction; | ||
10243 | if (trans) | ||
10244 | atomic_inc(&trans->use_count); | ||
10245 | spin_unlock(&fs_info->trans_lock); | ||
10246 | |||
10247 | ret = find_free_dev_extent_start(trans, device, minlen, start, | ||
10248 | &start, &len); | ||
10249 | if (trans) | ||
10250 | btrfs_put_transaction(trans); | ||
10251 | |||
10252 | if (ret) { | ||
10253 | up_read(&fs_info->commit_root_sem); | ||
10254 | mutex_unlock(&fs_info->chunk_mutex); | ||
10255 | if (ret == -ENOSPC) | ||
10256 | ret = 0; | ||
10257 | break; | ||
10258 | } | ||
10259 | |||
10260 | ret = btrfs_issue_discard(device->bdev, start, len, &bytes); | ||
10261 | up_read(&fs_info->commit_root_sem); | ||
10262 | mutex_unlock(&fs_info->chunk_mutex); | ||
10263 | |||
10264 | if (ret) | ||
10265 | break; | ||
10266 | |||
10267 | start += len; | ||
10268 | *trimmed += bytes; | ||
10269 | |||
10270 | if (fatal_signal_pending(current)) { | ||
10271 | ret = -ERESTARTSYS; | ||
10272 | break; | ||
10273 | } | ||
10274 | |||
10275 | cond_resched(); | ||
10276 | } | ||
10277 | |||
10278 | return ret; | ||
10279 | } | ||
10280 | |||
10065 | int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) | 10281 | int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) |
10066 | { | 10282 | { |
10067 | struct btrfs_fs_info *fs_info = root->fs_info; | 10283 | struct btrfs_fs_info *fs_info = root->fs_info; |
10068 | struct btrfs_block_group_cache *cache = NULL; | 10284 | struct btrfs_block_group_cache *cache = NULL; |
10285 | struct btrfs_device *device; | ||
10286 | struct list_head *devices; | ||
10069 | u64 group_trimmed; | 10287 | u64 group_trimmed; |
10070 | u64 start; | 10288 | u64 start; |
10071 | u64 end; | 10289 | u64 end; |
@@ -10120,6 +10338,18 @@ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) | |||
10120 | cache = next_block_group(fs_info->tree_root, cache); | 10338 | cache = next_block_group(fs_info->tree_root, cache); |
10121 | } | 10339 | } |
10122 | 10340 | ||
10341 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); | ||
10342 | devices = &root->fs_info->fs_devices->alloc_list; | ||
10343 | list_for_each_entry(device, devices, dev_alloc_list) { | ||
10344 | ret = btrfs_trim_free_extents(device, range->minlen, | ||
10345 | &group_trimmed); | ||
10346 | if (ret) | ||
10347 | break; | ||
10348 | |||
10349 | trimmed += group_trimmed; | ||
10350 | } | ||
10351 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); | ||
10352 | |||
10123 | range->len = trimmed; | 10353 | range->len = trimmed; |
10124 | return ret; | 10354 | return ret; |
10125 | } | 10355 | } |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index fb5a6b1c62a6..abe3a66bd3ba 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -3272,35 +3272,23 @@ next: | |||
3272 | return ret; | 3272 | return ret; |
3273 | } | 3273 | } |
3274 | 3274 | ||
3275 | int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group, | 3275 | void btrfs_get_block_group_trimming(struct btrfs_block_group_cache *cache) |
3276 | u64 *trimmed, u64 start, u64 end, u64 minlen) | ||
3277 | { | 3276 | { |
3278 | int ret; | 3277 | atomic_inc(&cache->trimming); |
3278 | } | ||
3279 | 3279 | ||
3280 | *trimmed = 0; | 3280 | void btrfs_put_block_group_trimming(struct btrfs_block_group_cache *block_group) |
3281 | { | ||
3282 | struct extent_map_tree *em_tree; | ||
3283 | struct extent_map *em; | ||
3284 | bool cleanup; | ||
3281 | 3285 | ||
3282 | spin_lock(&block_group->lock); | 3286 | spin_lock(&block_group->lock); |
3283 | if (block_group->removed) { | 3287 | cleanup = (atomic_dec_and_test(&block_group->trimming) && |
3284 | spin_unlock(&block_group->lock); | 3288 | block_group->removed); |
3285 | return 0; | ||
3286 | } | ||
3287 | atomic_inc(&block_group->trimming); | ||
3288 | spin_unlock(&block_group->lock); | 3289 | spin_unlock(&block_group->lock); |
3289 | 3290 | ||
3290 | ret = trim_no_bitmap(block_group, trimmed, start, end, minlen); | 3291 | if (cleanup) { |
3291 | if (ret) | ||
3292 | goto out; | ||
3293 | |||
3294 | ret = trim_bitmaps(block_group, trimmed, start, end, minlen); | ||
3295 | out: | ||
3296 | spin_lock(&block_group->lock); | ||
3297 | if (atomic_dec_and_test(&block_group->trimming) && | ||
3298 | block_group->removed) { | ||
3299 | struct extent_map_tree *em_tree; | ||
3300 | struct extent_map *em; | ||
3301 | |||
3302 | spin_unlock(&block_group->lock); | ||
3303 | |||
3304 | lock_chunks(block_group->fs_info->chunk_root); | 3292 | lock_chunks(block_group->fs_info->chunk_root); |
3305 | em_tree = &block_group->fs_info->mapping_tree.map_tree; | 3293 | em_tree = &block_group->fs_info->mapping_tree.map_tree; |
3306 | write_lock(&em_tree->lock); | 3294 | write_lock(&em_tree->lock); |
@@ -3324,10 +3312,31 @@ out: | |||
3324 | * this block group have left 1 entry each one. Free them. | 3312 | * this block group have left 1 entry each one. Free them. |
3325 | */ | 3313 | */ |
3326 | __btrfs_remove_free_space_cache(block_group->free_space_ctl); | 3314 | __btrfs_remove_free_space_cache(block_group->free_space_ctl); |
3327 | } else { | 3315 | } |
3316 | } | ||
3317 | |||
3318 | int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group, | ||
3319 | u64 *trimmed, u64 start, u64 end, u64 minlen) | ||
3320 | { | ||
3321 | int ret; | ||
3322 | |||
3323 | *trimmed = 0; | ||
3324 | |||
3325 | spin_lock(&block_group->lock); | ||
3326 | if (block_group->removed) { | ||
3328 | spin_unlock(&block_group->lock); | 3327 | spin_unlock(&block_group->lock); |
3328 | return 0; | ||
3329 | } | 3329 | } |
3330 | btrfs_get_block_group_trimming(block_group); | ||
3331 | spin_unlock(&block_group->lock); | ||
3332 | |||
3333 | ret = trim_no_bitmap(block_group, trimmed, start, end, minlen); | ||
3334 | if (ret) | ||
3335 | goto out; | ||
3330 | 3336 | ||
3337 | ret = trim_bitmaps(block_group, trimmed, start, end, minlen); | ||
3338 | out: | ||
3339 | btrfs_put_block_group_trimming(block_group); | ||
3331 | return ret; | 3340 | return ret; |
3332 | } | 3341 | } |
3333 | 3342 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index d366dd4664d0..c389c13f0f38 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -69,7 +69,7 @@ static struct file_system_type btrfs_fs_type; | |||
69 | 69 | ||
70 | static int btrfs_remount(struct super_block *sb, int *flags, char *data); | 70 | static int btrfs_remount(struct super_block *sb, int *flags, char *data); |
71 | 71 | ||
72 | static const char *btrfs_decode_error(int errno) | 72 | const char *btrfs_decode_error(int errno) |
73 | { | 73 | { |
74 | char *errstr = "unknown"; | 74 | char *errstr = "unknown"; |
75 | 75 | ||
@@ -1651,6 +1651,17 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
1651 | 1651 | ||
1652 | sb->s_flags |= MS_RDONLY; | 1652 | sb->s_flags |= MS_RDONLY; |
1653 | 1653 | ||
1654 | /* | ||
1655 | * Setting MS_RDONLY will put the cleaner thread to | ||
1656 | * sleep at the next loop if it's already active. | ||
1657 | * If it's already asleep, we'll leave unused block | ||
1658 | * groups on disk until we're mounted read-write again | ||
1659 | * unless we clean them up here. | ||
1660 | */ | ||
1661 | mutex_lock(&root->fs_info->cleaner_mutex); | ||
1662 | btrfs_delete_unused_bgs(fs_info); | ||
1663 | mutex_unlock(&root->fs_info->cleaner_mutex); | ||
1664 | |||
1654 | btrfs_dev_replace_suspend_for_unmount(fs_info); | 1665 | btrfs_dev_replace_suspend_for_unmount(fs_info); |
1655 | btrfs_scrub_cancel(fs_info); | 1666 | btrfs_scrub_cancel(fs_info); |
1656 | btrfs_pause_balance(fs_info); | 1667 | btrfs_pause_balance(fs_info); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 91f44c9f7ebc..20267d47dbcd 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -258,6 +258,8 @@ loop: | |||
258 | mutex_init(&cur_trans->cache_write_mutex); | 258 | mutex_init(&cur_trans->cache_write_mutex); |
259 | cur_trans->num_dirty_bgs = 0; | 259 | cur_trans->num_dirty_bgs = 0; |
260 | spin_lock_init(&cur_trans->dirty_bgs_lock); | 260 | spin_lock_init(&cur_trans->dirty_bgs_lock); |
261 | INIT_LIST_HEAD(&cur_trans->deleted_bgs); | ||
262 | spin_lock_init(&cur_trans->deleted_bgs_lock); | ||
261 | list_add_tail(&cur_trans->list, &fs_info->trans_list); | 263 | list_add_tail(&cur_trans->list, &fs_info->trans_list); |
262 | extent_io_tree_init(&cur_trans->dirty_pages, | 264 | extent_io_tree_init(&cur_trans->dirty_pages, |
263 | fs_info->btree_inode->i_mapping); | 265 | fs_info->btree_inode->i_mapping); |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index eb09c2067fa8..edc2fbc262d7 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -74,6 +74,8 @@ struct btrfs_transaction { | |||
74 | */ | 74 | */ |
75 | struct mutex cache_write_mutex; | 75 | struct mutex cache_write_mutex; |
76 | spinlock_t dirty_bgs_lock; | 76 | spinlock_t dirty_bgs_lock; |
77 | struct list_head deleted_bgs; | ||
78 | spinlock_t deleted_bgs_lock; | ||
77 | struct btrfs_delayed_ref_root delayed_refs; | 79 | struct btrfs_delayed_ref_root delayed_refs; |
78 | int aborted; | 80 | int aborted; |
79 | int dirty_bg_run; | 81 | int dirty_bg_run; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 88e2fe931bde..7c84a8122c37 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1116,15 +1116,18 @@ out: | |||
1116 | return ret; | 1116 | return ret; |
1117 | } | 1117 | } |
1118 | 1118 | ||
1119 | static int contains_pending_extent(struct btrfs_trans_handle *trans, | 1119 | static int contains_pending_extent(struct btrfs_transaction *transaction, |
1120 | struct btrfs_device *device, | 1120 | struct btrfs_device *device, |
1121 | u64 *start, u64 len) | 1121 | u64 *start, u64 len) |
1122 | { | 1122 | { |
1123 | struct btrfs_fs_info *fs_info = device->dev_root->fs_info; | ||
1123 | struct extent_map *em; | 1124 | struct extent_map *em; |
1124 | struct list_head *search_list = &trans->transaction->pending_chunks; | 1125 | struct list_head *search_list = &fs_info->pinned_chunks; |
1125 | int ret = 0; | 1126 | int ret = 0; |
1126 | u64 physical_start = *start; | 1127 | u64 physical_start = *start; |
1127 | 1128 | ||
1129 | if (transaction) | ||
1130 | search_list = &transaction->pending_chunks; | ||
1128 | again: | 1131 | again: |
1129 | list_for_each_entry(em, search_list, list) { | 1132 | list_for_each_entry(em, search_list, list) { |
1130 | struct map_lookup *map; | 1133 | struct map_lookup *map; |
@@ -1159,8 +1162,8 @@ again: | |||
1159 | } | 1162 | } |
1160 | } | 1163 | } |
1161 | } | 1164 | } |
1162 | if (search_list == &trans->transaction->pending_chunks) { | 1165 | if (search_list != &fs_info->pinned_chunks) { |
1163 | search_list = &trans->root->fs_info->pinned_chunks; | 1166 | search_list = &fs_info->pinned_chunks; |
1164 | goto again; | 1167 | goto again; |
1165 | } | 1168 | } |
1166 | 1169 | ||
@@ -1169,12 +1172,13 @@ again: | |||
1169 | 1172 | ||
1170 | 1173 | ||
1171 | /* | 1174 | /* |
1172 | * find_free_dev_extent - find free space in the specified device | 1175 | * find_free_dev_extent_start - find free space in the specified device |
1173 | * @device: the device which we search the free space in | 1176 | * @device: the device which we search the free space in |
1174 | * @num_bytes: the size of the free space that we need | 1177 | * @num_bytes: the size of the free space that we need |
1175 | * @start: store the start of the free space. | 1178 | * @search_start: the position from which to begin the search |
1176 | * @len: the size of the free space. that we find, or the size of the max | 1179 | * @start: store the start of the free space. |
1177 | * free space if we don't find suitable free space | 1180 | * @len: the size of the free space. that we find, or the size |
1181 | * of the max free space if we don't find suitable free space | ||
1178 | * | 1182 | * |
1179 | * this uses a pretty simple search, the expectation is that it is | 1183 | * this uses a pretty simple search, the expectation is that it is |
1180 | * called very infrequently and that a given device has a small number | 1184 | * called very infrequently and that a given device has a small number |
@@ -1188,9 +1192,9 @@ again: | |||
1188 | * But if we don't find suitable free space, it is used to store the size of | 1192 | * But if we don't find suitable free space, it is used to store the size of |
1189 | * the max free space. | 1193 | * the max free space. |
1190 | */ | 1194 | */ |
1191 | int find_free_dev_extent(struct btrfs_trans_handle *trans, | 1195 | int find_free_dev_extent_start(struct btrfs_transaction *transaction, |
1192 | struct btrfs_device *device, u64 num_bytes, | 1196 | struct btrfs_device *device, u64 num_bytes, |
1193 | u64 *start, u64 *len) | 1197 | u64 search_start, u64 *start, u64 *len) |
1194 | { | 1198 | { |
1195 | struct btrfs_key key; | 1199 | struct btrfs_key key; |
1196 | struct btrfs_root *root = device->dev_root; | 1200 | struct btrfs_root *root = device->dev_root; |
@@ -1200,19 +1204,11 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans, | |||
1200 | u64 max_hole_start; | 1204 | u64 max_hole_start; |
1201 | u64 max_hole_size; | 1205 | u64 max_hole_size; |
1202 | u64 extent_end; | 1206 | u64 extent_end; |
1203 | u64 search_start; | ||
1204 | u64 search_end = device->total_bytes; | 1207 | u64 search_end = device->total_bytes; |
1205 | int ret; | 1208 | int ret; |
1206 | int slot; | 1209 | int slot; |
1207 | struct extent_buffer *l; | 1210 | struct extent_buffer *l; |
1208 | 1211 | ||
1209 | /* FIXME use last free of some kind */ | ||
1210 | |||
1211 | /* we don't want to overwrite the superblock on the drive, | ||
1212 | * so we make sure to start at an offset of at least 1MB | ||
1213 | */ | ||
1214 | search_start = max(root->fs_info->alloc_start, 1024ull * 1024); | ||
1215 | |||
1216 | path = btrfs_alloc_path(); | 1212 | path = btrfs_alloc_path(); |
1217 | if (!path) | 1213 | if (!path) |
1218 | return -ENOMEM; | 1214 | return -ENOMEM; |
@@ -1273,7 +1269,7 @@ again: | |||
1273 | * Have to check before we set max_hole_start, otherwise | 1269 | * Have to check before we set max_hole_start, otherwise |
1274 | * we could end up sending back this offset anyway. | 1270 | * we could end up sending back this offset anyway. |
1275 | */ | 1271 | */ |
1276 | if (contains_pending_extent(trans, device, | 1272 | if (contains_pending_extent(transaction, device, |
1277 | &search_start, | 1273 | &search_start, |
1278 | hole_size)) { | 1274 | hole_size)) { |
1279 | if (key.offset >= search_start) { | 1275 | if (key.offset >= search_start) { |
@@ -1322,7 +1318,7 @@ next: | |||
1322 | if (search_end > search_start) { | 1318 | if (search_end > search_start) { |
1323 | hole_size = search_end - search_start; | 1319 | hole_size = search_end - search_start; |
1324 | 1320 | ||
1325 | if (contains_pending_extent(trans, device, &search_start, | 1321 | if (contains_pending_extent(transaction, device, &search_start, |
1326 | hole_size)) { | 1322 | hole_size)) { |
1327 | btrfs_release_path(path); | 1323 | btrfs_release_path(path); |
1328 | goto again; | 1324 | goto again; |
@@ -1348,6 +1344,24 @@ out: | |||
1348 | return ret; | 1344 | return ret; |
1349 | } | 1345 | } |
1350 | 1346 | ||
1347 | int find_free_dev_extent(struct btrfs_trans_handle *trans, | ||
1348 | struct btrfs_device *device, u64 num_bytes, | ||
1349 | u64 *start, u64 *len) | ||
1350 | { | ||
1351 | struct btrfs_root *root = device->dev_root; | ||
1352 | u64 search_start; | ||
1353 | |||
1354 | /* FIXME use last free of some kind */ | ||
1355 | |||
1356 | /* | ||
1357 | * we don't want to overwrite the superblock on the drive, | ||
1358 | * so we make sure to start at an offset of at least 1MB | ||
1359 | */ | ||
1360 | search_start = max(root->fs_info->alloc_start, 1024ull * 1024); | ||
1361 | return find_free_dev_extent_start(trans->transaction, device, | ||
1362 | num_bytes, search_start, start, len); | ||
1363 | } | ||
1364 | |||
1351 | static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, | 1365 | static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, |
1352 | struct btrfs_device *device, | 1366 | struct btrfs_device *device, |
1353 | u64 start, u64 *dev_extent_len) | 1367 | u64 start, u64 *dev_extent_len) |
@@ -4196,7 +4210,8 @@ again: | |||
4196 | u64 start = new_size; | 4210 | u64 start = new_size; |
4197 | u64 len = old_size - new_size; | 4211 | u64 len = old_size - new_size; |
4198 | 4212 | ||
4199 | if (contains_pending_extent(trans, device, &start, len)) { | 4213 | if (contains_pending_extent(trans->transaction, device, |
4214 | &start, len)) { | ||
4200 | unlock_chunks(root); | 4215 | unlock_chunks(root); |
4201 | checked_pending_chunks = true; | 4216 | checked_pending_chunks = true; |
4202 | failed = 0; | 4217 | failed = 0; |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 95842a909e7f..2ca784a14e84 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -453,6 +453,9 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info); | |||
453 | int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info); | 453 | int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info); |
454 | int btrfs_check_uuid_tree(struct btrfs_fs_info *fs_info); | 454 | int btrfs_check_uuid_tree(struct btrfs_fs_info *fs_info); |
455 | int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); | 455 | int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); |
456 | int find_free_dev_extent_start(struct btrfs_transaction *transaction, | ||
457 | struct btrfs_device *device, u64 num_bytes, | ||
458 | u64 search_start, u64 *start, u64 *max_avail); | ||
456 | int find_free_dev_extent(struct btrfs_trans_handle *trans, | 459 | int find_free_dev_extent(struct btrfs_trans_handle *trans, |
457 | struct btrfs_device *device, u64 num_bytes, | 460 | struct btrfs_device *device, u64 num_bytes, |
458 | u64 *start, u64 *max_avail); | 461 | u64 *start, u64 *max_avail); |