Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions block/blk-zoned.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,28 @@ static void disk_mark_zone_wplug_dead(struct blk_zone_wplug *zwplug)
}
}

static inline bool disk_check_zone_wplug_dead(struct blk_zone_wplug *zwplug)
{
if (!(zwplug->flags & BLK_ZONE_WPLUG_DEAD))
return false;

/*
* If a new write is received right after a zone reset completes and
* while the disk_zone_wplugs_worker() thread has not yet released the
* reference on the zone write plug after processing the last write to
* the zone, then the new write BIO will see the zone write plug marked
* as dead. This case is however a false positive and a perfectly valid
* pattern. In such case, restore the zone write plug to a live one.
*/
if (!zwplug->wp_offset && bio_list_empty(&zwplug->bio_list)) {
zwplug->flags &= ~BLK_ZONE_WPLUG_DEAD;
refcount_inc(&zwplug->ref);
return false;
}

return true;
}

static bool disk_zone_wplug_submit_bio(struct gendisk *disk,
struct blk_zone_wplug *zwplug);

Expand Down Expand Up @@ -1444,12 +1466,12 @@ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
spin_lock_irqsave(&zwplug->lock, flags);

/*
* If we got a zone write plug marked as dead, then the user is issuing
* writes to a full zone, or without synchronizing with zone reset or
* zone finish operations. In such case, fail the BIO to signal this
* invalid usage.
* Check if we got a zone write plug marked as dead. If yes, then the
* user is likely issuing writes to a full zone, or without
* synchronizing with zone reset or zone finish operations. In such
* case, fail the BIO to signal this invalid usage.
*/
if (zwplug->flags & BLK_ZONE_WPLUG_DEAD) {
if (disk_check_zone_wplug_dead(zwplug)) {
spin_unlock_irqrestore(&zwplug->lock, flags);
disk_put_zone_wplug(zwplug);
bio_io_error(bio);
Expand Down