mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
btrfs: zoned: finish superblock zone once no space left for new SB
If there is no more space left for a new superblock in a superblock zone, then it is better to ZONE_FINISH the zone and frees up the active zone count. Since btrfs_advance_sb_log() can now issue REQ_OP_ZONE_FINISH, we also need to convert it to return int for the error case. Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
9658b72ef3
commit
8376d9e1ed
@ -3887,7 +3887,9 @@ static int write_dev_supers(struct btrfs_device *device,
|
|||||||
bio->bi_opf |= REQ_FUA;
|
bio->bi_opf |= REQ_FUA;
|
||||||
|
|
||||||
btrfsic_submit_bio(bio);
|
btrfsic_submit_bio(bio);
|
||||||
btrfs_advance_sb_log(device, i);
|
|
||||||
|
if (btrfs_advance_sb_log(device, i))
|
||||||
|
errors++;
|
||||||
}
|
}
|
||||||
return errors < i ? 0 : -1;
|
return errors < i ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
@ -789,36 +789,56 @@ static inline bool is_sb_log_zone(struct btrfs_zoned_device_info *zinfo,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void btrfs_advance_sb_log(struct btrfs_device *device, int mirror)
|
int btrfs_advance_sb_log(struct btrfs_device *device, int mirror)
|
||||||
{
|
{
|
||||||
struct btrfs_zoned_device_info *zinfo = device->zone_info;
|
struct btrfs_zoned_device_info *zinfo = device->zone_info;
|
||||||
struct blk_zone *zone;
|
struct blk_zone *zone;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!is_sb_log_zone(zinfo, mirror))
|
if (!is_sb_log_zone(zinfo, mirror))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
zone = &zinfo->sb_zones[BTRFS_NR_SB_LOG_ZONES * mirror];
|
zone = &zinfo->sb_zones[BTRFS_NR_SB_LOG_ZONES * mirror];
|
||||||
if (zone->cond != BLK_ZONE_COND_FULL) {
|
for (i = 0; i < BTRFS_NR_SB_LOG_ZONES; i++) {
|
||||||
|
/* Advance the next zone */
|
||||||
|
if (zone->cond == BLK_ZONE_COND_FULL) {
|
||||||
|
zone++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (zone->cond == BLK_ZONE_COND_EMPTY)
|
if (zone->cond == BLK_ZONE_COND_EMPTY)
|
||||||
zone->cond = BLK_ZONE_COND_IMP_OPEN;
|
zone->cond = BLK_ZONE_COND_IMP_OPEN;
|
||||||
|
|
||||||
zone->wp += (BTRFS_SUPER_INFO_SIZE >> SECTOR_SHIFT);
|
zone->wp += SUPER_INFO_SECTORS;
|
||||||
|
|
||||||
if (zone->wp == zone->start + zone->len)
|
if (sb_zone_is_full(zone)) {
|
||||||
|
/*
|
||||||
|
* No room left to write new superblock. Since
|
||||||
|
* superblock is written with REQ_SYNC, it is safe to
|
||||||
|
* finish the zone now.
|
||||||
|
*
|
||||||
|
* If the write pointer is exactly at the capacity,
|
||||||
|
* explicit ZONE_FINISH is not necessary.
|
||||||
|
*/
|
||||||
|
if (zone->wp != zone->start + zone->capacity) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = blkdev_zone_mgmt(device->bdev,
|
||||||
|
REQ_OP_ZONE_FINISH, zone->start,
|
||||||
|
zone->len, GFP_NOFS);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
zone->wp = zone->start + zone->len;
|
||||||
zone->cond = BLK_ZONE_COND_FULL;
|
zone->cond = BLK_ZONE_COND_FULL;
|
||||||
|
}
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
zone++;
|
/* All the zones are FULL. Should not reach here. */
|
||||||
ASSERT(zone->cond != BLK_ZONE_COND_FULL);
|
ASSERT(0);
|
||||||
if (zone->cond == BLK_ZONE_COND_EMPTY)
|
return -EIO;
|
||||||
zone->cond = BLK_ZONE_COND_IMP_OPEN;
|
|
||||||
|
|
||||||
zone->wp += (BTRFS_SUPER_INFO_SIZE >> SECTOR_SHIFT);
|
|
||||||
|
|
||||||
if (zone->wp == zone->start + zone->len)
|
|
||||||
zone->cond = BLK_ZONE_COND_FULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror)
|
int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror)
|
||||||
|
@ -40,7 +40,7 @@ int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw,
|
|||||||
u64 *bytenr_ret);
|
u64 *bytenr_ret);
|
||||||
int btrfs_sb_log_location(struct btrfs_device *device, int mirror, int rw,
|
int btrfs_sb_log_location(struct btrfs_device *device, int mirror, int rw,
|
||||||
u64 *bytenr_ret);
|
u64 *bytenr_ret);
|
||||||
void btrfs_advance_sb_log(struct btrfs_device *device, int mirror);
|
int btrfs_advance_sb_log(struct btrfs_device *device, int mirror);
|
||||||
int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror);
|
int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror);
|
||||||
u64 btrfs_find_allocatable_zones(struct btrfs_device *device, u64 hole_start,
|
u64 btrfs_find_allocatable_zones(struct btrfs_device *device, u64 hole_start,
|
||||||
u64 hole_end, u64 num_bytes);
|
u64 hole_end, u64 num_bytes);
|
||||||
@ -113,8 +113,10 @@ static inline int btrfs_sb_log_location(struct btrfs_device *device, int mirror,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void btrfs_advance_sb_log(struct btrfs_device *device, int mirror)
|
static inline int btrfs_advance_sb_log(struct btrfs_device *device, int mirror)
|
||||||
{ }
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror)
|
static inline int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user