Commit dcba6e48 authored by Naohiro Aota's avatar Naohiro Aota Committed by David Sterba

btrfs: zoned: reset zones of unused block groups

We must reset the zones of a deleted unused block group to rewind the
zones' write pointers to the zones' start.

To do this, we can use the DISCARD_SYNC code to do the reset when the
filesystem is running on zoned devices.
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarAnand Jain <anand.jain@oracle.com>
Signed-off-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 011b41bf
...@@ -1408,8 +1408,12 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) ...@@ -1408,8 +1408,12 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
if (!async_trim_enabled && btrfs_test_opt(fs_info, DISCARD_ASYNC)) if (!async_trim_enabled && btrfs_test_opt(fs_info, DISCARD_ASYNC))
goto flip_async; goto flip_async;
/* DISCARD can flip during remount */ /*
trimming = btrfs_test_opt(fs_info, DISCARD_SYNC); * DISCARD can flip during remount. On zoned filesystems, we
* need to reset sequential-required zones.
*/
trimming = btrfs_test_opt(fs_info, DISCARD_SYNC) ||
btrfs_is_zoned(fs_info);
/* Implicit trim during transaction commit. */ /* Implicit trim during transaction commit. */
if (trimming) if (trimming)
......
...@@ -1298,6 +1298,9 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, ...@@ -1298,6 +1298,9 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
stripe = bbio->stripes; stripe = bbio->stripes;
for (i = 0; i < bbio->num_stripes; i++, stripe++) { for (i = 0; i < bbio->num_stripes; i++, stripe++) {
struct btrfs_device *dev = stripe->dev;
u64 physical = stripe->physical;
u64 length = stripe->length;
u64 bytes; u64 bytes;
struct request_queue *req_q; struct request_queue *req_q;
...@@ -1305,14 +1308,18 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, ...@@ -1305,14 +1308,18 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
ASSERT(btrfs_test_opt(fs_info, DEGRADED)); ASSERT(btrfs_test_opt(fs_info, DEGRADED));
continue; continue;
} }
req_q = bdev_get_queue(stripe->dev->bdev); req_q = bdev_get_queue(stripe->dev->bdev);
if (!blk_queue_discard(req_q)) /* Zone reset on zoned filesystems */
if (btrfs_can_zone_reset(dev, physical, length))
ret = btrfs_reset_device_zone(dev, physical,
length, &bytes);
else if (blk_queue_discard(req_q))
ret = btrfs_issue_discard(dev->bdev, physical,
length, &bytes);
else
continue; continue;
ret = btrfs_issue_discard(stripe->dev->bdev,
stripe->physical,
stripe->length,
&bytes);
if (!ret) { if (!ret) {
discarded_bytes += bytes; discarded_bytes += bytes;
} else if (ret != -EOPNOTSUPP) { } else if (ret != -EOPNOTSUPP) {
......
...@@ -209,4 +209,19 @@ static inline bool btrfs_check_super_location(struct btrfs_device *device, u64 p ...@@ -209,4 +209,19 @@ static inline bool btrfs_check_super_location(struct btrfs_device *device, u64 p
return device->zone_info == NULL || !btrfs_dev_is_sequential(device, pos); return device->zone_info == NULL || !btrfs_dev_is_sequential(device, pos);
} }
static inline bool btrfs_can_zone_reset(struct btrfs_device *device,
u64 physical, u64 length)
{
u64 zone_size;
if (!btrfs_dev_is_sequential(device, physical))
return false;
zone_size = device->zone_info->zone_size;
if (!IS_ALIGNED(physical, zone_size) || !IS_ALIGNED(length, zone_size))
return false;
return true;
}
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment