All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2] sd_zbc: Write unlock zone from sd_uninit_cmnd()
@ 2017-08-09  3:00 Damien Le Moal
  2017-08-11  0:36 ` Martin K. Petersen
  0 siblings, 1 reply; 2+ messages in thread
From: Damien Le Moal @ 2017-08-09  3:00 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen; +Cc: Bart Van Assche, Christoph Hellwig

Releasing a zone write lock only when the write commnand that acquired the
lock completes can cause deadlocks due to potential command reordering if the
lock owning request is requeued and not executed. This problem exists only
with the scsi-mq path as, unlike the legacy path, requests are moved out of
the dispatch queue before being prepared and so before locking a zone for a
write command.

Since sd_uninit_cmnd() is now always called when a request is requeued,
call sd_zbc_write_unlock_zone() from that function for write requests
that acquired a zone lock instead of from sd_done(). Acquisition of a zone
lock by a write command is indicated using the new command
flag SCMD_ZONE_WRITE_LOCK.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Bart Van Assche <Bart.VanAssche@wdc.com>
---
Changes from V1:
* Changed WARN_ON to WARN_ON_ONCE as suggested by Bart
* Updated commit message

 drivers/scsi/sd.c        | 3 +++
 drivers/scsi/sd_zbc.c    | 9 +++++----
 include/scsi/scsi_cmnd.h | 1 +
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index bea36adeee17..e2647f2d4430 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1277,6 +1277,9 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt)
 {
 	struct request *rq = SCpnt->request;
 
+	if (SCpnt->flags & SCMD_ZONE_WRITE_LOCK)
+		sd_zbc_write_unlock_zone(SCpnt);
+
 	if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
 		__free_page(rq->special_vec.bv_page);
 
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 96855df9f49d..8aa54779aac1 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -294,6 +294,9 @@ int sd_zbc_write_lock_zone(struct scsi_cmnd *cmd)
 	    test_and_set_bit(zno, sdkp->zones_wlock))
 		return BLKPREP_DEFER;
 
+	WARN_ON_ONCE(cmd->flags & SCMD_ZONE_WRITE_LOCK);
+	cmd->flags |= SCMD_ZONE_WRITE_LOCK;
+
 	return BLKPREP_OK;
 }
 
@@ -302,9 +305,10 @@ void sd_zbc_write_unlock_zone(struct scsi_cmnd *cmd)
 	struct request *rq = cmd->request;
 	struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
 
-	if (sdkp->zones_wlock) {
+	if (sdkp->zones_wlock && cmd->flags & SCMD_ZONE_WRITE_LOCK) {
 		unsigned int zno = sd_zbc_zone_no(sdkp, blk_rq_pos(rq));
 		WARN_ON_ONCE(!test_bit(zno, sdkp->zones_wlock));
+		cmd->flags &= ~SCMD_ZONE_WRITE_LOCK;
 		clear_bit_unlock(zno, sdkp->zones_wlock);
 		smp_mb__after_atomic();
 	}
@@ -335,9 +339,6 @@ void sd_zbc_complete(struct scsi_cmnd *cmd,
 	case REQ_OP_WRITE_ZEROES:
 	case REQ_OP_WRITE_SAME:
 
-		/* Unlock the zone */
-		sd_zbc_write_unlock_zone(cmd);
-
 		if (result &&
 		    sshdr->sense_key == ILLEGAL_REQUEST &&
 		    sshdr->asc == 0x21)
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index a1266d318c85..6af198d8120b 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -57,6 +57,7 @@ struct scsi_pointer {
 /* for scmd->flags */
 #define SCMD_TAGGED		(1 << 0)
 #define SCMD_UNCHECKED_ISA_DMA	(1 << 1)
+#define SCMD_ZONE_WRITE_LOCK	(1 << 2)
 
 struct scsi_cmnd {
 	struct scsi_request req;
-- 
2.13.3

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH V2] sd_zbc: Write unlock zone from sd_uninit_cmnd()
  2017-08-09  3:00 [PATCH V2] sd_zbc: Write unlock zone from sd_uninit_cmnd() Damien Le Moal
@ 2017-08-11  0:36 ` Martin K. Petersen
  0 siblings, 0 replies; 2+ messages in thread
From: Martin K. Petersen @ 2017-08-11  0:36 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: linux-scsi, Martin K . Petersen, Bart Van Assche,
	Christoph Hellwig


Damien,

> Releasing a zone write lock only when the write commnand that acquired
> the lock completes can cause deadlocks due to potential command
> reordering if the lock owning request is requeued and not
> executed. This problem exists only with the scsi-mq path as, unlike
> the legacy path, requests are moved out of the dispatch queue before
> being prepared and so before locking a zone for a write command.
>
> Since sd_uninit_cmnd() is now always called when a request is
> requeued, call sd_zbc_write_unlock_zone() from that function for write
> requests that acquired a zone lock instead of from
> sd_done(). Acquisition of a zone lock by a write command is indicated
> using the new command flag SCMD_ZONE_WRITE_LOCK.

Applied to 4.13/scsi-fixes. Thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-08-11  0:37 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-09  3:00 [PATCH V2] sd_zbc: Write unlock zone from sd_uninit_cmnd() Damien Le Moal
2017-08-11  0:36 ` Martin K. Petersen

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.