Improve handling of offline and read-only zones - #1224
Open
blktests-ci-kpd[bot] wants to merge 16 commits into
Open
Improve handling of offline and read-only zones#1224blktests-ci-kpd[bot] wants to merge 16 commits into
blktests-ci-kpd[bot] wants to merge 16 commits into
Conversation
Author
|
Upstream branch: bc35965 |
blktests-ci-kpd
Bot
force-pushed
the
linus-master_base
branch
from
September 7, 2026 02:54
8242bf1 to
5b28f57
Compare
Author
|
Upstream branch: df29080 |
blktests-ci-kpd
Bot
force-pushed
the
series/1144041=>linus-master
branch
from
September 7, 2026 04:30
078677d to
544e176
Compare
Author
|
Upstream branch: 28924df |
blktests-ci-kpd
Bot
force-pushed
the
series/1144041=>linus-master
branch
from
September 8, 2026 15:45
544e176 to
25f5386
Compare
blktests-ci-kpd
Bot
force-pushed
the
linus-master_base
branch
from
September 9, 2026 07:40
4ddd216 to
00cc4ca
Compare
Author
|
Upstream branch: 893e117 |
blktests-ci-kpd
Bot
force-pushed
the
series/1144041=>linus-master
branch
from
September 9, 2026 08:05
25f5386 to
2a36d0e
Compare
Author
|
Upstream branch: 893e117 |
blktests-ci-kpd
Bot
force-pushed
the
series/1144041=>linus-master
branch
from
September 9, 2026 09:34
2a36d0e to
002371c
Compare
In the rare event when revalidating the zones of a zoned block device fails, the device capacity will be dropped to 0. In such case, the zoned block device will either be rescanned and restored or will be dropped entirely and its gendisk will be destroyed. So calling disk_free_zone_resources() from blk_revalidate_disk_zones() in case of an error does not make much sense. We can keep the zone resources in case the device is rescanned and restored and simply free all resources in disk_release_zone_resources() when the gendisk is destroyed. Remove the call to disk_free_zone_resources() from blk_revalidate_disk_zones() and squash disk_free_zone_resources() inside disk_release_zone_resources(). With this change, the conditional creation of the zone write plugs work queue is not necessary anymore as the workqueue will keep existing together with all other resources until the disk is released. This simplifies disk_alloc_zone_resources(). Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
While executing blk_revalidate_disk_zones(), a disk capacity is looked at using get_capacity() several times: on entry to blk_revalidate_disk_zones(), when allocating zone revalidation arguments in disk_revalidate_zone_resources(), while validating zones in blk_revalidate_zone_cb() and one last time at the end of blk_revalidate_disk_zones() to check that all zones have been inspected. Since this is all done while passthrough commands can be issued, it is possible that a capacity change operation (e.g. the removal of a storage element on a SCSI or SATA disk) is concurrently executed, potentially resulting in an inconsistent or conflicting revalidation with potentially out-of-bound accesses to the zone condition array. Prevent issues by using get_capacity() once on entry to blk_revalidate_disk_zones(), remembering this capacity as a field of struct blk_revalidate_zone_args and using that field while revalidating zones. A final second call to get_capacity() is done at the end of blk_revalidate_disk_zones() to ensure that the disk capacity has not changed, thus revalidating the capacity (and number of zones) itself. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
The function disk_revalidate_zone_resources() is misnamed as it does not revalidate anything but rather allocates the revalidation arguments and then calls disk_alloc_zone_resources() to initialize the disk zone resources if they are needed and not already allocated. Make this function less confusing by renaming it disk_init_revalidate_args() and moving the call to disk_alloc_zone_resources() into blk_revalidate_disk_zones(). As before, this function is only called if the zone resources are needed and not yet allocated. The initialization of the atomic nr_zone_wplugs is also moved to the function disk_init_zone_resources() so that this is done once and not on all revalidation. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Since the function disk_update_zone_resources() does a lot of checks beside updating a zoned disk limits and resources, rename this function to disk_revalidate_zone_resources(). To keep all the checks together, move the capacity checks (including the check on the end sector of the last zone of the disk) in blk_revalidate_disk_zones() to this function. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
Currently, bdev_zone_is_seq() identifies a sequential zone by looking at the zone condition, assuming that any zone that does not have the condition BLK_ZONE_COND_NOT_WP is a sequential write required zone. That is correct only as long as the target zoned device does not support storage element depopulation (aka HDD head depopulation), which is a feature that can transition conventional zones to the read-only or offline condition. For such device, we cannot distinguish anymore between conventional and sequential zones using the zone condition as both zone types can have the same conditions. Prepare for fully supporting storage element depopulation and restoration by caching the type of a zone in addition to its condition. This is implemented by reformating the zones_cond array using a more compact zone condition representation with the new enum blk_zstate. This zone condition representation only uses the lower 4 bits of a byte for the condition values, thus leaving the high order 4 bits of each byte entry of the array for flags. The flag BLK_ZFLAG_CONV is defined to indicate conventional zones. The helper functions blk_zstate_to_zone_cond() and blk_zone_cond_to_zstate() are implemented using lookup tables to convert between enum blk_zone_condition values and enum blk_zstate zone condition values. The helper blk_zstate_set() can be used to set a zones_state entry with a zone condition and zone type flags, safely in accordance to the size of the zone state array being accessed. This helper is used in disk_zone_set_cond() to update a zone condition. bdev_zone_is_seq() is modified to use the flags of the zones_state array entries to identify sequential zones. The zones_state array initialization and revalidation is unchanged from the former zones_cond array. Overall, any zone condition that is being considered outside of the zones_state array always uses the enum blk_zone_condition values as before, thus minimizing the number of changes. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Define the helper function disk_zone_is_seq() and use it to refactor bdev_zone_is_seq(). disk_zone_is_seq() is also used in blk_zone_wplug_handle_write(). Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
Add a zone state array bound check to ensure that like disk_zone_get_state(), we never attempt to access the zone state array beyond its size. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
Introduce the helper function disk_for_all_zone_wplugs() to allow executing an actor function on all hashed zone write plugs. This helper is used to simplify the implementation of blk_zone_reset_all_bio_endio() and queue_zone_wplugs_show(). Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
The zone related fields of struct gendisk can be modified by blk_revalidate_disk_zones() either on the first scan of the disk, or during user triggered scans or device revalidation, if some characteristics of the disk has changed (e.g. the disk capacity). Changes to these fields are always done with the disk request queue frozen so that BIO processing does not see any inconsistent state of the zones. This implies a contract that reading these zone related fields must always be done while holding a usage count on the request queue of the disk. However, increasing the usage count of the disk request queue cannot be done from the context of blk_revalidate_disk_zones() itself, as that would prevent freezing the disk queue and result in a deadlock. This prevents blk_revalidate_disk_zones() from consulting the zone related fields of struct gendisk to detect, for instance, a change in the number of zones of the disk. For such case, we want to detect the change, take appropriate measures and revalidate exclusively revalidate the zones to avoid concurrent revalidation calls to see the same change while corrections are already on-going. A simple solution to avoid this issue is to introduce a mutex to serialize calls to blk_revalidate_disk_zones() and ensure only a single context at a time can modify the zone related fields of a gendisk. In preparation for handling disk capacity revalidation in blk_revalidate_disk_zones(), do so with the mutex zone_revalidate_mutex. This mutex is initialized in disk_init_zone_resources(), destroyed in disk_release_zone_resources() and taken and released only in blk_revalidate_disk_zones() to serialize the execution of this function. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
If during revalidation, we detect a capacity change for a zoned block device, e.g. due to a storage element removal on an HDD, we can assume that the device was reformatted, which implies that all sequential zones are empty. For such case, we can remove and free all zone write plugs in the gendisk hash table by marking them as dead, thus avoiding also to leave zone write plugs for zones that are beyond the new device capacity in the disk hash table. Introduce the function disk_revalidate_capacity() to do this and call this new function at the beginning of blk_revalidate_disk_zones(), so that the zone revalidation process can re-create, if needed, any zone write plug for sequential zones that are not empty. The checks on the capacity and zone size that were in blk_revalidate_disk_zones() are moved to disk_revalidate_capacity() and if true, also trigger dropping all zone write plugs. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
When disk_revalidate_zone_resources() detects a capacity change, -ENODEV is returned, failing the disk revalidation. However, since a capacity change may happen due to a storage element removal being executed concurrently to blk_revalidate_disk_zones(), we can simply retry the revalidation to capture the new zone state with the new capacity without failing the revalidation. Retrying the revalidation is driven by disk_revalidate_zone_resources() returning -EAGAIN when a new valid capacity is detected. And to avoid getting stuck in an infinite loop revalidating zones, retries are limited to 2. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
When revalidating the zones of a zoned block device, or when handling a zone which has a zone write plug flagged with BLK_ZONE_WPLUG_NEED_WP_UPDATE, the function disk_zone_wplug_sync_wp_offset() is used to update the write pointer offset of a zone write plug. However, this does not take into account the condition of the zone, which may have changed to readonly or offline, which in itself will always cause errors. In order to catch such errors, rename disk_zone_wplug_sync_wp_offset() to disk_zone_wplug_sync_state() and in addition to the zone write pointer, also update the zone write plug condition if the zone is readonly or offline. This change also requires changes to how a reset all zones operation (REQ_OP_ZONE_RESET_ALL) is handled so that the offline or read-only condition of zone write plugs is not overwritten with an erroneous empty condition. To do so, introduce the helper function disk_zone_is_offline_or_readonly() to skip updating the condition of zones that are read-only or offline and that do not have a zone write plug. For zones that have a zone write plug, the helper function disk_zone_wplug_is_offline_or_readonly() is used in disk_zone_wplug_set_wp_offset() to not update a zone write plug write pointer and condition for read-only and offline zones. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Since any write BIO targeting an offline or a read-only zone will fail, there is no point in keeping zone write plugs for these zones. So for any offline or read-only zone, the zone write plug should always be treated as dead. Do this by modifying disk_check_zone_wplug_dead() to always mark read-only and offline zones as dead to force a removal of the zone write plug from the disk hash table on BIO submission. blk_zone_wplug_prepare_bio() is also modified to have the same checks to immediately fail a write BIO targeting a read-only or offline zone. With these two changes, any newly issued or unplugged write BIO targeting a read-only or offline zone is immediately failed. Finally, disk_zone_wplug_sync_state() is modified to add a call to disk_mark_zone_wplug_dead() for the zone write plug of any read-only or offline zone found during zone revalidation or a report zones. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Author
|
Upstream branch: 893e117 |
Any zone management operation targeting a zone that is in the read-only or offline condition will fail. So there is no point in issuing such BIO. Modify the check in submit_bio_noacct() to use the new helper function bdev_zone_mgmt_allowed() to check that a zone is sequential (as was checked before) and also that the zone is not offline nor read-only. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
With SCSI and ATA SMR HDDs, the storage element depopulation feature can change the condition of conventional zones to read-only (if a write head is depopulated) or to offline (if a read head is depopulated). However, the function blk_revalidate_zone_cond() currently does not allow these conditions for conventional zones, causing a zone revalidation failure. Remove blk_revalidate_zone_cond() and move the zone condition checks for conventional zones to blk_revalidate_conv_zone(), allowing the regular BLK_ZONE_COND_NOT_WP condition as well as the BLK_ZONE_COND_OFFLINE and BLK_ZONE_COND_READONLY conditions to match the conditions that can be seen from a zoned device with depopulated storage elements. The zone condition checks for sequential write required zones are moved to blk_revalidate_seq_zone() without any change to the conditions allowed. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
disk_zone_set_cond() is used to set a zone condition afer a reset, a finish or a reset all operation. For a single zone reset or finish, we are guaranteed that the target zone is a sequential one that is not offline nor read-only (otherwise, the operation would have failed). For a reset all operation, there is no point in calling this function for offline and read-only zones since the condition checks in disk_zone_set_cond() will result in nothing being done. Simplify all this using disk_zone_is_offline_or_readonly() in blk_zone_reset_all_bio_endio() to skip zones that are offline or read-only. This change allows simplifying disk_zone_set_cond() by removing the zone condition checks. This change is also consistent with the fact that conventional zones can now have the offline or read-only condition. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Hannes Reinecke <hare@kernel.org>
blktests-ci-kpd
Bot
force-pushed
the
series/1144041=>linus-master
branch
from
September 10, 2026 05:42
002371c to
1947c96
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull request for series with
subject: Improve handling of offline and read-only zones
version: 6
url: https://patchwork.kernel.org/project/linux-block/list/?series=1154085