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: Josef Bacik <josef@toxicpanda.com> Reviewed-by: Anand Jain <anand.jain@oracle.com> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
committed by
David Sterba
parent
011b41bffa
commit
dcba6e48b5
@@ -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,
|
|||||||
|
|
||||||
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,
|
|||||||
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
|
|||||||
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
|
||||||
|
|||||||
Reference in New Issue
Block a user