All of lore.kernel.org
 help / color / mirror / Atom feed
From: Damien Le Moal <dlemoal@kernel.org>
To: Jens Axboe <axboe@kernel.dk>,
	linux-block@vger.kernel.org, Christoph Hellwig <hch@lst.de>,
	linux-scsi@vger.kernel.org,
	"Martin K . Petersen" <martin.petersen@oracle.com>
Subject: [PATCH v7 05/10] zloop: avoid potential wp_lock deadlocks
Date: Wed, 14 Oct 2026 14:33:31 +0900	[thread overview]
Message-ID: <20261014053337.2328544-6-dlemoal@kernel.org> (raw)
In-Reply-To: <20261014053337.2328544-1-dlemoal@kernel.org>

zloop_queue_rq() maybe called from softirq context with interrupts
disabled. However, zloop_queue_rq() may call
zloop_set_zone_append_sector() which takes a zone wp_lock using a simple
spin_lock(). This can cause deadlocks with competing contexts that have
already taken that lock. Avoid this by using the irq disabling/enabling
variants of spin_lock/unlock. While at it, zloop_report_zones() is also
modified to take the wp_lock around both the write pointer and the zone
condition reporting to ensure that both values are consistent for a
report.

Fixes: fcc6eaa3a03a ("zloop: introduce the ordered_zone_append configuration parameter")
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <mkp@kernel.org>
---
 drivers/block/zloop.c | 37 ++++++++++++++++++++++---------------
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c
index 8f485ef51557..cbe199c135b0 100644
--- a/drivers/block/zloop.c
+++ b/drivers/block/zloop.c
@@ -312,6 +312,7 @@ static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no)
 	struct zloop_zone *zone = &zlo->zones[zone_no];
 	struct kstat stat;
 	sector_t file_sectors;
+	unsigned long flags;
 	int ret;
 
 	lockdep_assert_held(&zone->lock);
@@ -337,7 +338,7 @@ static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no)
 		return -EINVAL;
 	}
 
-	spin_lock(&zone->wp_lock);
+	spin_lock_irqsave(&zone->wp_lock, flags);
 	if (!file_sectors) {
 		zloop_mark_empty(zlo, zone);
 	} else if (file_sectors == zlo->zone_capacity) {
@@ -348,7 +349,7 @@ static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no)
 			zone->cond = BLK_ZONE_COND_CLOSED;
 		zone->wp = zone->start + file_sectors;
 	}
-	spin_unlock(&zone->wp_lock);
+	spin_unlock_irqrestore(&zone->wp_lock, flags);
 
 	return 0;
 }
@@ -381,6 +382,7 @@ static int zloop_open_zone(struct zloop_device *zlo, unsigned int zone_no)
 static int zloop_close_zone(struct zloop_device *zlo, unsigned int zone_no)
 {
 	struct zloop_zone *zone = &zlo->zones[zone_no];
+	unsigned long flags;
 	int ret = 0;
 
 	if (test_bit(ZLOOP_ZONE_CONV, &zone->flags))
@@ -399,13 +401,13 @@ static int zloop_close_zone(struct zloop_device *zlo, unsigned int zone_no)
 		break;
 	case BLK_ZONE_COND_IMP_OPEN:
 	case BLK_ZONE_COND_EXP_OPEN:
-		spin_lock(&zone->wp_lock);
+		spin_lock_irqsave(&zone->wp_lock, flags);
 		zloop_lru_remove_open_zone(zlo, zone);
 		if (zone->wp == zone->start)
 			zone->cond = BLK_ZONE_COND_EMPTY;
 		else
 			zone->cond = BLK_ZONE_COND_CLOSED;
-		spin_unlock(&zone->wp_lock);
+		spin_unlock_irqrestore(&zone->wp_lock, flags);
 		break;
 	case BLK_ZONE_COND_EMPTY:
 	case BLK_ZONE_COND_FULL:
@@ -423,6 +425,7 @@ static int zloop_close_zone(struct zloop_device *zlo, unsigned int zone_no)
 static int zloop_reset_zone(struct zloop_device *zlo, unsigned int zone_no)
 {
 	struct zloop_zone *zone = &zlo->zones[zone_no];
+	unsigned long flags;
 	int ret = 0;
 
 	if (test_bit(ZLOOP_ZONE_CONV, &zone->flags))
@@ -440,10 +443,10 @@ static int zloop_reset_zone(struct zloop_device *zlo, unsigned int zone_no)
 		goto unlock;
 	}
 
-	spin_lock(&zone->wp_lock);
+	spin_lock_irqsave(&zone->wp_lock, flags);
 	zloop_mark_empty(zlo, zone);
 	clear_bit(ZLOOP_ZONE_SEQ_ERROR, &zone->flags);
-	spin_unlock(&zone->wp_lock);
+	spin_unlock_irqrestore(&zone->wp_lock, flags);
 
 unlock:
 	mutex_unlock(&zone->lock);
@@ -468,6 +471,7 @@ static int zloop_reset_all_zones(struct zloop_device *zlo)
 static int zloop_finish_zone(struct zloop_device *zlo, unsigned int zone_no)
 {
 	struct zloop_zone *zone = &zlo->zones[zone_no];
+	unsigned long flags;
 	int ret = 0;
 
 	if (test_bit(ZLOOP_ZONE_CONV, &zone->flags))
@@ -486,10 +490,10 @@ static int zloop_finish_zone(struct zloop_device *zlo, unsigned int zone_no)
 		goto unlock;
 	}
 
-	spin_lock(&zone->wp_lock);
+	spin_lock_irqsave(&zone->wp_lock, flags);
 	zloop_mark_full(zlo, zone);
 	clear_bit(ZLOOP_ZONE_SEQ_ERROR, &zone->flags);
-	spin_unlock(&zone->wp_lock);
+	spin_unlock_irqrestore(&zone->wp_lock, flags);
 
  unlock:
 	mutex_unlock(&zone->lock);
@@ -579,9 +583,10 @@ static int zloop_seq_write_prep(struct zloop_cmd *cmd)
 	bool is_append = req_op(rq) == REQ_OP_ZONE_APPEND;
 	struct zloop_zone *zone = &zlo->zones[zone_no];
 	sector_t zone_end = zone->start + zlo->zone_capacity;
+	unsigned long flags;
 	int ret = 0;
 
-	spin_lock(&zone->wp_lock);
+	spin_lock_irqsave(&zone->wp_lock, flags);
 
 	/*
 	 * Zone append operations always go at the current write pointer, but
@@ -632,7 +637,7 @@ static int zloop_seq_write_prep(struct zloop_cmd *cmd)
 			zloop_mark_full(zlo, zone);
 	}
 out_unlock:
-	spin_unlock(&zone->wp_lock);
+	spin_unlock_irqrestore(&zone->wp_lock, flags);
 	return ret;
 }
 
@@ -887,12 +892,13 @@ static bool zloop_set_zone_append_sector(struct request *rq)
 	struct zloop_zone *zone = &zlo->zones[zone_no];
 	sector_t zone_end = zone->start + zlo->zone_capacity;
 	sector_t nr_sectors = blk_rq_sectors(rq);
+	unsigned long flags;
 
-	spin_lock(&zone->wp_lock);
+	spin_lock_irqsave(&zone->wp_lock, flags);
 
 	if (zone->cond == BLK_ZONE_COND_FULL ||
 	    zone->wp + nr_sectors > zone_end) {
-		spin_unlock(&zone->wp_lock);
+		spin_unlock_irqrestore(&zone->wp_lock, flags);
 		return false;
 	}
 
@@ -901,7 +907,7 @@ static bool zloop_set_zone_append_sector(struct request *rq)
 	if (zone->wp >= zone_end)
 		zloop_mark_full(zlo, zone);
 
-	spin_unlock(&zone->wp_lock);
+	spin_unlock_irqrestore(&zone->wp_lock, flags);
 
 	return true;
 }
@@ -962,6 +968,7 @@ static int zloop_report_zones(struct gendisk *disk, sector_t sector,
 	struct zloop_device *zlo = disk->private_data;
 	struct blk_zone blkz = {};
 	unsigned int first, i;
+	unsigned long flags;
 	int ret;
 
 	first = disk_zone_no(disk, sector);
@@ -985,10 +992,10 @@ static int zloop_report_zones(struct gendisk *disk, sector_t sector,
 
 		blkz.start = zone->start;
 		blkz.len = zlo->zone_size;
-		spin_lock(&zone->wp_lock);
+		spin_lock_irqsave(&zone->wp_lock, flags);
 		blkz.wp = zone->wp;
-		spin_unlock(&zone->wp_lock);
 		blkz.cond = zone->cond;
+		spin_unlock_irqrestore(&zone->wp_lock, flags);
 		if (test_bit(ZLOOP_ZONE_CONV, &zone->flags)) {
 			blkz.type = BLK_ZONE_TYPE_CONVENTIONAL;
 			blkz.capacity = zlo->zone_size;
-- 
2.55.0


  parent reply	other threads:[~2026-10-14  5:33 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-14  5:33 [PATCH v7 00/10] Add support for storage element depopulation Damien Le Moal
2026-10-14  5:33 ` [PATCH v7 01/10] block: introduce disk_zone_is_offline() Damien Le Moal
2026-10-14  5:33 ` [PATCH v7 02/10] block: refactor blk_revalidate_disk_zones() Damien Le Moal
2026-10-14  5:33 ` [PATCH v7 03/10] block: introduce storage element management Damien Le Moal
2026-10-14  5:33 ` [PATCH v7 04/10] block: add storage element management ioctls Damien Le Moal
2026-10-14  5:33 ` Damien Le Moal [this message]
2026-10-14  5:33 ` [PATCH v7 06/10] zloop: add storage element emulation Damien Le Moal
2026-10-14  5:33 ` [PATCH v7 07/10] zloop: add degrade_element control command Damien Le Moal
2026-10-14  5:33 ` [PATCH v7 08/10] scsi: sd: fail read commands to offline zones early Damien Le Moal
2026-10-14  5:33 ` [PATCH v7 09/10] scsi: sd_zbc: always revalidate zones for disks supporting head depopulation Damien Le Moal
2026-10-14  5:33 ` [PATCH v7 10/10] scsi: sd_zbc: define storage element management operations Damien Le Moal
2026-10-14  7:18 ` [PATCH v7 00/10] Add support for storage element depopulation shinichiro.kawasaki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261014053337.2328544-6-dlemoal@kernel.org \
    --to=dlemoal@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=hch@lst.de \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.