Skip to content

Commit

Permalink
btrfs: zoned: reset zones of unused block groups
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Naohiro Aota authored and David Sterba committed Feb 9, 2021
1 parent 011b41b commit dcba6e4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 deletions.
8 changes: 6 additions & 2 deletions fs/btrfs/block-group.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
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. */
if (trimming)
Expand Down
17 changes: 12 additions & 5 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1298,21 +1298,28 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,

stripe = bbio->stripes;
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;
struct request_queue *req_q;

if (!stripe->dev->bdev) {
ASSERT(btrfs_test_opt(fs_info, DEGRADED));
continue;
}

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;

ret = btrfs_issue_discard(stripe->dev->bdev,
stripe->physical,
stripe->length,
&bytes);
if (!ret) {
discarded_bytes += bytes;
} else if (ret != -EOPNOTSUPP) {
Expand Down
15 changes: 15 additions & 0 deletions fs/btrfs/zoned.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

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

0 comments on commit dcba6e4

Please sign in to comment.