Linux SCSI subsystem development
 help / color / mirror / Atom feed
* [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD
@ 2026-09-29 19:28 Laurence Oberman
  2026-09-29 19:28 ` [PATCH v4 1/4] scsi: st: Restore changed drive settings after reset also for MTLOAD and MTRETEN Laurence Oberman
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Laurence Oberman @ 2026-09-29 19:28 UTC (permalink / raw)
  To: linux-scsi
  Cc: Martin K . Petersen, James E . J . Bottomley, Kai Makisara,
	John Meneghini, emilne, bgurney

After a device reset st blocks tape access until one of MTREW, MTOFFL,
MTLOAD, MTRETEN, MTERASE, MTSEEK or MTEOM clears the reset condition.
Testing the reset handling on scsi_debug and on IBM LTO drives found that
several settings and parts of the driver state do not survive the reset
or an MTLOAD.

1. Changed block size and density are lost after MTLOAD or MTRETEN

   A reset returns the drive's block size and density to their defaults.
   Commit 7081dc75df79 ("scsi: st: Restore some drive settings after
   reset") re-applies the values set by the user, but only for MTREW,
   MTSEEK and MTEOM.  Because check_tape() reads the drive's block size
   with MODE SENSE on every open, the driver follows the drive back to
   its default after the reset.  An application that set fixed-block
   mode with MTSETBLK and recovers with MTLOAD or MTRETEN keeps writing
   without any error, but in variable-length blocks.

   Patch 1 restores the changed settings for MTLOAD and MTRETEN as well.
   Both may make the drive report a new medium, and the new session
   started by check_tape() clears the "changed" flags and applies the
   mode defaults.  The values are therefore saved before the operation
   and re-applied after check_tape() has run.  scsi_debug reports a new
   medium after MTRETEN and MTLOAD; the IBM drives do not.  The series
   was tested against both behaviours.

2. Tape state is not reset after MTLOAD of an already loaded medium

   A LOAD positions the medium at the beginning of partition 0.
   check_tape() records that only when it starts a new session, which
   requires a new-medium unit attention.  Drives that do not report one
   for an already loaded cartridge (IBM LTO) are left with the state from
   before the load:

   - After a reset, MTIOCGET keeps reporting file/block -1 and no BOT,
     although commit 0b120edb37dc ("scsi: st: Add MTIOCGET and MTLOAD to
     ioctls allowed after device reset") allows MTLOAD because the tape
     location is known after it.
   - After reading to EOD, a read following MTLOAD fails with EIO.
   - If partition 1 was selected, st still records partition 1, so a
     later MTSETPART 1 is not performed and I/O goes to partition 0.

   Patch 2 resets the partition and the state of all partitions after a
   successful load, as the new-session path in check_tape() does:
   partition 0, position at BOT, EOF state cleared and no pending write.
   Resetting all partitions matters: a partition switch done by read()
   or write() (in rw_checks()) leaves the rw state of the partition that
   is left, and a stale ST_WRITING state would make st_flush() write a
   filemark at the beginning of partition 0 when the device is closed.

3. The drive buffering mode is lost after a reset

   A reset also returns the drive's buffered mode to its default, and
   check_tape() reads it back on every open, so a mode set with
   MTSETDRVBUFFER is lost - with every recovery operation, including
   MTREW.  Unlike density and block size there was no "changed" state to
   restore it from.  Patch 3 records the value set with MTSETDRVBUFFER
   and restores it in both restore paths, before density and block size.

4. The door is not locked again after a reset

   With auto-lock, st locks the door at the first read or write.  A reset
   clears the drive's medium removal prevention, but st kept its locked
   state and never locked the door again.  Patch 4 marks the door
   unlocked when a reset is recognized, so the next access locks it.

MTOFFL is deliberately not changed: the medium is unloaded, and a
different one may be loaded next, for which the mode defaults should
apply.

Immediate mode: with MT_ST_NOWAIT, MTRETEN returns before the
retension completes, so patch 1 does not restore the settings there
rather than waiting for the drive.  After MTLOAD and MTRETEN the
settings are only restored when the drive is ready: with an
immediate-mode load and O_NONBLOCK, check_tape() does not wait and the
drive may still be loading.

The SCSI tape driver is currently marked Orphan in MAINTAINERS.

Testing (v7.3-rc2, scsi_debug and IBM LTO drives on FC):

Block size after reset + recovery (patch 1):

                            R04.load       R04.retension  R04.offline
unpatched:
  scsi_debug                discarded      discarded      discarded
  IBM ULTRIUM-TD5 (LTO-5)   discarded      discarded      discarded
  IBM ULT3580-TDA           discarded      discarded      discarded
patched:
  scsi_debug                restored       restored       discarded (*)
  IBM ULTRIUM-TD5 (LTO-5)   restored       restored       discarded (*)
  IBM ULT3580-TDA           restored       restored       discarded (*)

(*) unchanged by design, see above.

State after MTLOAD (patch 2):

  R03.load: position after reset + MTLOAD
    IBM LTO-5 and ULT3580-TDA  unpatched: MTIOCGET -1:-1    v3: ok (0:0)
    scsi_debug                 unpatched and v3: ok (new session)
  B09: read after MTLOAD at EOD, no reset
    IBM ULT3580-TDA            v1: read() fails with EIO    v2, v3: ok
    scsi_debug                 v1, v2, v3: ok (new session)
  X04: MTLOAD while in partition 1, then MTSETPART 1 and read
    IBM ULTRIUM-TD5 (LTO-5)    v2: MTIOCGET still reports partition 1,
                                   MTSETPART 1 not performed, read in
                                   partition 0 fails with EIO
                               v3: ok
    scsi_debug                 v2, v3, v4: ok (new session)
  X05: one open file: write in partition 0, MTSETPART 1, read()
       (switches in rw_checks() without resetting partition 0's state),
       MTLOAD, close; then read partition 0
    IBM ULTRIUM-TD5 (LTO-5)    v3: close wrote a filemark at BOT of
                                   partition 0, the file there is lost
                               v4: ok, partition 0 intact
    scsi_debug                 v4: ok

Drive buffering mode after reset (patch 3), read from the drive with
MODE SENSE through the sg node, mode 0 set with MTSETDRVBUFFER:

  R15: reset + MTREW / MTLOAD / MTRETEN
    IBM ULTRIUM-TD5 (LTO-5)    patches 1-2: drive back in mode 1
                               v3:          mode 0 restored
    scsi_debug                 does not implement buffered mode

Door lock after reset (patch 4), auto-lock on, same open file:

  R16: read (locks), reset, recover, read
    IBM ULTRIUM-TD5 (LTO-5)    patches 1-2: door not locked again
                               v3:          locked again
    scsi_debug                 v3:          locked again

For the position tests, "ok" means that MTIOCPOS returns 0 and the
first block read without repositioning is block 0 of file 0; it is not
based on MTIOCGET alone.  The restore after MTREW/MTSEEK/MTEOM from
7081dc75df79 is unaffected on all devices.  Every test ends with a
byte-exact read-back of the whole tape.

The tests are part of a tape validation harness (reset detection, the
blocked-operation matrix, recovery operations, interrupted I/O, SCSI EH
via scsi_debug error injection); B09, X04, X05, R15 and R16 were added
for the review comments on v1 to v3:
https://gitlab.com/loberman/tapetest (developed with AI assistance)

Changes since v3:
- Patch 1: restore after MTLOAD and MTRETEN only when the drive is
  ready (Sashiko).
- Patch 2: reset the state of all partitions after the load, as a new
  session does; a stale ST_WRITING state made st_flush() write a
  filemark at BOT of partition 0 (Sashiko).
- Patches 3 and 4: unchanged.

Changes since v2:
- Patch 2: after a successful load, set the partition to 0 for all
  partitions, not only when the current partition is 0 (Kai Mäkisara).
- New patch 3: restore the drive buffering mode after reset (Kai
  Mäkisara).
- New patch 4: relock the door after reset (Kai Mäkisara).
- Patch 1: unchanged.

Changes since v1:
- Patch 2: also reset the EOF state (and at_sm, last_block_valid) after
  the load, as MTREW does (found by Sashiko).

v3: https://marc.info/?l=linux-scsi&m=179070241545955&w=2
v2: https://marc.info/?l=linux-scsi&m=179060186958028&w=2
v1: https://marc.info/?l=linux-scsi&m=179051462299046&w=2


Laurence Oberman (4):
  scsi: st: Restore changed drive settings after reset also for MTLOAD
    and MTRETEN
  scsi: st: Record the tape position after a successful MTLOAD
  scsi: st: Restore the drive buffering mode after reset
  scsi: st: Relock the door after a reset

 drivers/scsi/st.c | 97 +++++++++++++++++++++++++++++++++++++++++++++--
 drivers/scsi/st.h |  2 +
 2 files changed, 96 insertions(+), 3 deletions(-)

-- 
2.55.0


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

* [PATCH v4 1/4] scsi: st: Restore changed drive settings after reset also for MTLOAD and MTRETEN
  2026-09-29 19:28 [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD Laurence Oberman
@ 2026-09-29 19:28 ` Laurence Oberman
  2026-09-29 19:28 ` [PATCH v4 2/4] scsi: st: Record the tape position after a successful MTLOAD Laurence Oberman
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Laurence Oberman @ 2026-09-29 19:28 UTC (permalink / raw)
  To: linux-scsi
  Cc: Martin K . Petersen, James E . J . Bottomley, Kai Makisara,
	John Meneghini, emilne, bgurney

A device reset returns the drive's density and block size to their
defaults.  Commit 7081dc75df79 ("scsi: st: Restore some drive settings
after reset") re-applies values changed by the user when the position is
recovered with MTREW, MTSEEK or MTEOM.  MTLOAD and MTRETEN are also
allowed to clear the reset condition and also leave the same medium at
BOT, but they restore nothing.

Because check_tape() reads the drive's block size with MODE SENSE on
every open, the driver silently switches to the drive default after the
reset.  An application that set fixed-block mode with MTSETBLK and
recovers with MTLOAD or MTRETEN keeps writing, but variable-length
blocks, without any error.

Restore the changed density and block size for MTLOAD and MTRETEN as
well.  Both operations may make the drive report a new medium, and the
new session started by check_tape() clears the "changed" flags and
applies the mode defaults.  So save the values before the operation, let
check_tape() run first (do_load_unload() already calls it for MTLOAD;
call it after MTRETEN), and then re-apply them.  Retry the restore once
in case a unit attention is still pending.  Only restore when the drive is
ready after the operation: with an immediate-mode load and O_NONBLOCK,
check_tape() does not wait and the drive may still be loading.
In immediate mode (MT_ST_NOWAIT) MTRETEN may return before the
retension has finished; do not wait for it there.

MTOFFL is not changed: the medium is unloaded and a different one may be
loaded next, for which the mode defaults apply.

Reproduced with scsi_debug (which reports a new medium after MTRETEN and
MTLOAD) and with IBM LTO drives on FC (which do not).

Fixes: 7081dc75df79 ("scsi: st: Restore some drive settings after reset")
Assisted-by: Claude sashiko
Signed-off-by: Laurence Oberman <loberman@redhat.com>
---
v4: restore after MTLOAD and MTRETEN only when the drive is ready
    (Sashiko).
v2, v3: no changes.

 drivers/scsi/st.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index f1c3c49..6e5e6f6 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3586,6 +3586,23 @@ out:
 	return retval;
 }
 
+/*
+ * Re-apply a density and block size that were changed by the user before a
+ * device reset (a negative value means "not changed").  A unit attention
+ * still pending after the operation (e.g. new medium after a load) fails the
+ * first MODE SELECT, so retry each once.  As in the other post-reset restore
+ * path, errors are ignored and one setting failing does not prevent
+ * restoring the other.
+ */
+static void st_restore_changed_settings(struct scsi_tape *STp, int density,
+					int blksize)
+{
+	if (density >= 0 && st_int_ioctl(STp, MTSETDENSITY, density))
+		st_int_ioctl(STp, MTSETDENSITY, density);
+	if (blksize >= 0 && st_int_ioctl(STp, MTSETBLK, blksize))
+		st_int_ioctl(STp, MTSETBLK, blksize);
+}
+
 /* The ioctl command */
 static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 {
@@ -3594,6 +3611,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 	int retval = 0;
 	unsigned int blk;
 	bool cmd_mtiocget;
+	int restore_density = -1, restore_blksize = -1;
 	struct scsi_tape *STp = file->private_data;
 	struct st_modedef *STm;
 	struct st_partstat *STps;
@@ -3740,6 +3758,17 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 					st_int_ioctl(STp, MTSETDENSITY, STp->changed_density);
 				if (STp->blksize_changed)
 					st_int_ioctl(STp, MTSETBLK, STp->changed_blksize);
+			} else if (mtc.mt_op == MTLOAD || mtc.mt_op == MTRETEN) {
+				/*
+				 * The same medium ends up at BOT, so the settings
+				 * apply as with MTREW.  The operation may start a
+				 * new session, which clears the "changed" flags:
+				 * save the values and restore them afterwards.
+				 */
+				if (STp->density_changed)
+					restore_density = STp->changed_density;
+				if (STp->blksize_changed)
+					restore_blksize = STp->changed_blksize;
 			}
 		}
 
@@ -3819,6 +3848,14 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 
 		if (mtc.mt_op == MTLOAD) {
 			retval = do_load_unload(STp, file, max(1, mtc.mt_count));
+			/*
+			 * Restore only if the drive is ready: after an
+			 * immediate-mode load with O_NONBLOCK, check_tape()
+			 * does not wait and the drive may still be loading.
+			 */
+			if (!retval && STp->ready == ST_READY)
+				st_restore_changed_settings(STp, restore_density,
+							    restore_blksize);
 			goto out;
 		}
 
@@ -3837,6 +3874,20 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 			retval = st_compression(STp, (mtc.mt_count & 1));
 		else
 			retval = st_int_ioctl(STp, mtc.mt_op, mtc.mt_count);
+		if (!retval && mtc.mt_op == MTRETEN && !STp->immediate &&
+		    (restore_density >= 0 || restore_blksize >= 0)) {
+			/*
+			 * Retension reloads the medium and the drive may
+			 * report a new medium.  Let check_tape() start the new
+			 * session (applying the mode defaults) now, as for
+			 * MTLOAD; otherwise it happens at the next open and
+			 * overrides the restored settings.
+			 */
+			if (check_tape(STp, file) >= 0 &&
+			    STp->ready == ST_READY)
+				st_restore_changed_settings(STp, restore_density,
+							    restore_blksize);
+		}
 		goto out;
 	}
 	if (!STm->defined) {
-- 
2.43.0


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

* [PATCH v4 2/4] scsi: st: Record the tape position after a successful MTLOAD
  2026-09-29 19:28 [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD Laurence Oberman
  2026-09-29 19:28 ` [PATCH v4 1/4] scsi: st: Restore changed drive settings after reset also for MTLOAD and MTRETEN Laurence Oberman
@ 2026-09-29 19:28 ` Laurence Oberman
  2026-09-29 19:28 ` [PATCH v4 3/4] scsi: st: Restore the drive buffering mode after reset Laurence Oberman
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Laurence Oberman @ 2026-09-29 19:28 UTC (permalink / raw)
  To: linux-scsi
  Cc: Martin K . Petersen, James E . J . Bottomley, Kai Makisara,
	John Meneghini, emilne, bgurney

Commit 0b120edb37dc ("scsi: st: Add MTIOCGET and MTLOAD to ioctls allowed
after device reset") allows MTLOAD to clear the reset condition because
the tape location is known after MTLOAD.  But the driver does not record
it: reset_state() sets the file and block numbers to -1, and
do_load_unload() leaves them there.  check_tape() sets them to 0 only for
a new session, which requires a new-medium unit attention.  Drives that
do not report one when the medium was already loaded (seen with IBM LTO
drives) keep reporting file/block -1 in MTIOCGET and no BOT, although the
tape is at the beginning.

After a successful load, reset the partition and the state of all
partitions, as the new-session path in check_tape() does: partition 0,
position at BOT, EOF state cleared and no pending write.  Otherwise the
driver may still record the previous partition, so that a later MTSETPART
to that partition is not performed; a read after loading at EOD fails
with EIO; and a partition left in the ST_WRITING state by a partition
switch in read() or write() makes st_flush() write a filemark at the
beginning of partition 0 when the device is closed.

Fixes: 0b120edb37dc ("scsi: st: Add MTIOCGET and MTLOAD to ioctls allowed after device reset")
Suggested-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
Assisted-by: Claude sashiko
Signed-off-by: Laurence Oberman <loberman@redhat.com>
---
v4: reset the state of all partitions after the load, as a new session
    does; a stale ST_WRITING state made st_flush() write a filemark at
    BOT of partition 0 (Sashiko).  Reproduced on an IBM LTO-5: write in
    partition 0, MTSETPART 1, read(), MTLOAD, close.
v3: set the partition to 0 for all partitions, not only when the current
    partition is 0 (Kai Mäkisara).
v2: also reset the EOF state after the load, as MTREW does (Sashiko).

 drivers/scsi/st.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 6e5e6f6..aa4d2ce 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -2686,6 +2686,30 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
 		else {
 			STp->rew_at_close = STp->autorew_dev;
 			retval = check_tape(STp, filp);
+			/*
+			 * LOAD leaves the medium at the beginning of partition
+			 * 0.  check_tape() records that only for a new session;
+			 * without a new-medium unit attention (the medium was
+			 * already loaded) the partition and the partition state
+			 * would be left as before the load.  Reset them as a
+			 * new session does, for all partitions: a stale
+			 * ST_WRITING state would make st_flush() write a
+			 * filemark at the beginning of partition 0.
+			 */
+			if (retval == CHKRES_READY) {
+				int i;
+
+				STp->partition = STp->new_partition = 0;
+				for (i = 0; i < ST_NBR_PARTITIONS; i++) {
+					STps = &(STp->ps[i]);
+					STps->rw = ST_IDLE;
+					STps->eof = ST_NOEOF;
+					STps->at_sm = 0;
+					STps->last_block_valid = 0;
+					STps->drv_block = 0;
+					STps->drv_file = 0;
+				}
+			}
 			if (retval > 0)
 				retval = 0;
 		}
-- 
2.43.0


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

* [PATCH v4 3/4] scsi: st: Restore the drive buffering mode after reset
  2026-09-29 19:28 [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD Laurence Oberman
  2026-09-29 19:28 ` [PATCH v4 1/4] scsi: st: Restore changed drive settings after reset also for MTLOAD and MTRETEN Laurence Oberman
  2026-09-29 19:28 ` [PATCH v4 2/4] scsi: st: Record the tape position after a successful MTLOAD Laurence Oberman
@ 2026-09-29 19:28 ` Laurence Oberman
  2026-09-29 19:28 ` [PATCH v4 4/4] scsi: st: Relock the door after a reset Laurence Oberman
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Laurence Oberman @ 2026-09-29 19:28 UTC (permalink / raw)
  To: linux-scsi
  Cc: Martin K . Petersen, James E . J . Bottomley, Kai Makisara,
	John Meneghini, emilne, bgurney

A device reset also returns the drive's buffered mode to its default.
check_tape() reads the buffered mode with MODE SENSE on every open, so
st follows the drive and a mode set by the user with MTSETDRVBUFFER is
lost without any indication.  The value is also written back by every
later MODE SELECT, including the one that restores a changed block size.

Unlike density and block size, the buffered mode has no "changed" state
that could be used to restore it.  Record the value set with
MTSETDRVBUFFER and restore it after a reset together with density and
block size: when MTREW, MTSEEK or MTEOM clear the reset condition, and
after MTLOAD and MTRETEN.  It is restored first, so that the MODE SELECTs
for density and block size carry the right value.

The buffered mode is a drive setting, not a property of the medium, so
it is not cleared when a new session starts.

Suggested-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
Assisted-by: Claude sashiko
Signed-off-by: Laurence Oberman <loberman@redhat.com>
---
v4: no changes.
v3: new patch (Kai Mäkisara).

 drivers/scsi/st.c | 43 ++++++++++++++++++++++++++++---------------
 drivers/scsi/st.h |  2 ++
 2 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index aa4d2ce..f548197 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -2963,9 +2963,11 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
 		direction = DMA_TO_DEVICE;
 
 		memset((STp->buffer)->b_data, 0, 12);
-		if (cmd_in == MTSETDRVBUFFER)
+		if (cmd_in == MTSETDRVBUFFER) {
 			(STp->buffer)->b_data[2] = (arg & 7) << 4;
-		else
+			STp->drv_buffer_changed = 1;	/* At least we tried ;-) */
+			STp->changed_drv_buffer = arg & 7;
+		} else
 			(STp->buffer)->b_data[2] =
 			    STp->drv_buffer << 4;
 		(STp->buffer)->b_data[3] = 8;	/* block descriptor length */
@@ -3611,16 +3613,19 @@ out:
 }
 
 /*
- * Re-apply a density and block size that were changed by the user before a
- * device reset (a negative value means "not changed").  A unit attention
- * still pending after the operation (e.g. new medium after a load) fails the
- * first MODE SELECT, so retry each once.  As in the other post-reset restore
- * path, errors are ignored and one setting failing does not prevent
- * restoring the other.
+ * Re-apply a drive buffering mode, density and block size that were changed
+ * by the user before a device reset (a negative value means "not changed").
+ * The buffering mode goes first: the other MODE SELECTs send the current
+ * STp->drv_buffer.  A unit attention still pending after the operation
+ * (e.g. new medium after a load) fails the first MODE SELECT, so retry each
+ * once.  As in the other post-reset restore path, errors are ignored and one
+ * setting failing does not prevent restoring the others.
  */
-static void st_restore_changed_settings(struct scsi_tape *STp, int density,
-					int blksize)
+static void st_restore_changed_settings(struct scsi_tape *STp, int drv_buffer,
+					int density, int blksize)
 {
+	if (drv_buffer >= 0 && st_int_ioctl(STp, MTSETDRVBUFFER, drv_buffer))
+		st_int_ioctl(STp, MTSETDRVBUFFER, drv_buffer);
 	if (density >= 0 && st_int_ioctl(STp, MTSETDENSITY, density))
 		st_int_ioctl(STp, MTSETDENSITY, density);
 	if (blksize >= 0 && st_int_ioctl(STp, MTSETBLK, blksize))
@@ -3635,7 +3640,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 	int retval = 0;
 	unsigned int blk;
 	bool cmd_mtiocget;
-	int restore_density = -1, restore_blksize = -1;
+	int restore_drv_buffer = -1, restore_density = -1, restore_blksize = -1;
 	struct scsi_tape *STp = file->private_data;
 	struct st_modedef *STm;
 	struct st_partstat *STps;
@@ -3778,6 +3783,9 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 					STp->partition = 0;
 					switch_partition(STp);
 				}
+				if (STp->drv_buffer_changed)
+					st_int_ioctl(STp, MTSETDRVBUFFER,
+						     STp->changed_drv_buffer);
 				if (STp->density_changed)
 					st_int_ioctl(STp, MTSETDENSITY, STp->changed_density);
 				if (STp->blksize_changed)
@@ -3789,6 +3797,8 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 				 * new session, which clears the "changed" flags:
 				 * save the values and restore them afterwards.
 				 */
+				if (STp->drv_buffer_changed)
+					restore_drv_buffer = STp->changed_drv_buffer;
 				if (STp->density_changed)
 					restore_density = STp->changed_density;
 				if (STp->blksize_changed)
@@ -3878,7 +3888,8 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 			 * does not wait and the drive may still be loading.
 			 */
 			if (!retval && STp->ready == ST_READY)
-				st_restore_changed_settings(STp, restore_density,
+				st_restore_changed_settings(STp, restore_drv_buffer,
+							    restore_density,
 							    restore_blksize);
 			goto out;
 		}
@@ -3899,7 +3910,8 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 		else
 			retval = st_int_ioctl(STp, mtc.mt_op, mtc.mt_count);
 		if (!retval && mtc.mt_op == MTRETEN && !STp->immediate &&
-		    (restore_density >= 0 || restore_blksize >= 0)) {
+		    (restore_drv_buffer >= 0 || restore_density >= 0 ||
+		     restore_blksize >= 0)) {
 			/*
 			 * Retension reloads the medium and the drive may
 			 * report a new medium.  Let check_tape() start the new
@@ -3909,7 +3921,8 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 			 */
 			if (check_tape(STp, file) >= 0 &&
 			    STp->ready == ST_READY)
-				st_restore_changed_settings(STp, restore_density,
+				st_restore_changed_settings(STp, restore_drv_buffer,
+							    restore_density,
 							    restore_blksize);
 		}
 		goto out;
@@ -4517,7 +4530,7 @@ static int st_probe(struct scsi_device *SDp)
 	tpnt->modes[0].defined = 1;
 
 	tpnt->density_changed = tpnt->compression_changed =
-	    tpnt->blksize_changed = 0;
+	    tpnt->blksize_changed = tpnt->drv_buffer_changed = 0;
 	mutex_init(&tpnt->lock);
 
 	idr_preload(GFP_KERNEL);
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 0d7c4b8..c580024 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -162,10 +162,12 @@ struct scsi_tape {
 	unsigned char in_use;
 	unsigned char blksize_changed;
 	unsigned char density_changed;
+	unsigned char drv_buffer_changed;
 	unsigned char compression_changed;
 	unsigned char drv_buffer;
 	unsigned char density;
 	unsigned char changed_density;
+	unsigned char changed_drv_buffer;
 	unsigned char door_locked;
 	unsigned char autorew_dev;   /* auto-rewind device */
 	unsigned char rew_at_close;  /* rewind necessary at close */
-- 
2.43.0


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

* [PATCH v4 4/4] scsi: st: Relock the door after a reset
  2026-09-29 19:28 [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD Laurence Oberman
                   ` (2 preceding siblings ...)
  2026-09-29 19:28 ` [PATCH v4 3/4] scsi: st: Restore the drive buffering mode after reset Laurence Oberman
@ 2026-09-29 19:28 ` Laurence Oberman
  2026-09-30 15:58 ` [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD "Kai Mäkisara (Kolumbus)"
  2026-10-03 14:36 ` Martin K. Petersen (Oracle)
  5 siblings, 0 replies; 7+ messages in thread
From: Laurence Oberman @ 2026-09-29 19:28 UTC (permalink / raw)
  To: linux-scsi
  Cc: Martin K . Petersen, James E . J . Bottomley, Kai Makisara,
	John Meneghini, emilne, bgurney

With auto-lock enabled, st locks the door at the first read or write and
records ST_LOCKED_AUTO.  A device reset clears the drive's medium removal
prevention, but st keeps its state, so it never locks the door again and
the medium can be removed from the drive while it is in use.

Set the lock state to ST_UNLOCKED when a reset is recognized.  The door
is then locked again at the next read or write.

Suggested-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
Assisted-by: Claude sashiko
Signed-off-by: Laurence Oberman <loberman@redhat.com>
---
v4: no changes.
v3: new patch (Kai Mäkisara).

 drivers/scsi/st.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index f548197..e089d3a 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -368,6 +368,8 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
 	if (ctr != STp->por_ctr) {
 		STp->por_ctr = ctr;
 		STp->pos_unknown = 1; /* ASC => power on / reset */
+		/* The reset allowed medium removal; relock at next access */
+		STp->door_locked = ST_UNLOCKED;
 		st_printk(KERN_WARNING, STp, "Power on/reset recognized.");
 	}
 
@@ -426,6 +428,7 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
 	if (cmdstatp->have_sense && scode == UNIT_ATTENTION &&
 		cmdstatp->sense_hdr.asc == 0x29 && !STp->pos_unknown) {
 		STp->pos_unknown = 1; /* ASC => power on / reset */
+		STp->door_locked = ST_UNLOCKED;
 		st_printk(KERN_WARNING, STp, "Power on/reset recognized.");
 	}
 
-- 
2.43.0


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

* Re: [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD
  2026-09-29 19:28 [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD Laurence Oberman
                   ` (3 preceding siblings ...)
  2026-09-29 19:28 ` [PATCH v4 4/4] scsi: st: Relock the door after a reset Laurence Oberman
@ 2026-09-30 15:58 ` "Kai Mäkisara (Kolumbus)"
  2026-10-03 14:36 ` Martin K. Petersen (Oracle)
  5 siblings, 0 replies; 7+ messages in thread
From: "Kai Mäkisara (Kolumbus)" @ 2026-09-30 15:58 UTC (permalink / raw)
  To: Laurence Oberman
  Cc: linux-scsi, Martin K . Petersen, James E . J . Bottomley,
	John Meneghini, emilne, bgurney



> On 29. Sep 2026, at 22.28, Laurence Oberman <loberman@redhat.com> wrote:
> 
> After a device reset st blocks tape access until one of MTREW, MTOFFL,
> MTLOAD, MTRETEN, MTERASE, MTSEEK or MTEOM clears the reset condition.
> Testing the reset handling on scsi_debug and on IBM LTO drives found that
> several settings and parts of the driver state do not survive the reset
> or an MTLOAD.
...

Looks good. For the whole series:

Reviewed-by: Kai Mäkisara <kai.makisara@kolumbus.fi <mailto:kai.makisara@kolumbus.fi>>

Thanks,
Kai


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

* Re: [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD
  2026-09-29 19:28 [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD Laurence Oberman
                   ` (4 preceding siblings ...)
  2026-09-30 15:58 ` [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD "Kai Mäkisara (Kolumbus)"
@ 2026-10-03 14:36 ` Martin K. Petersen (Oracle)
  5 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen (Oracle) @ 2026-10-03 14:36 UTC (permalink / raw)
  To: Laurence Oberman
  Cc: linux-scsi, Martin K . Petersen, James E . J . Bottomley,
	Kai Makisara, John Meneghini, emilne, bgurney


Laurence,

> After a device reset st blocks tape access until one of MTREW, MTOFFL,
> MTLOAD, MTRETEN, MTERASE, MTSEEK or MTEOM clears the reset condition.
> Testing the reset handling on scsi_debug and on IBM LTO drives found that
> several settings and parts of the driver state do not survive the reset
> or an MTLOAD.

Applied to 7.4/scsi-staging, thanks!

-- 
Martin K. Petersen

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

end of thread, other threads:[~2026-10-03 14:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-29 19:28 [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD Laurence Oberman
2026-09-29 19:28 ` [PATCH v4 1/4] scsi: st: Restore changed drive settings after reset also for MTLOAD and MTRETEN Laurence Oberman
2026-09-29 19:28 ` [PATCH v4 2/4] scsi: st: Record the tape position after a successful MTLOAD Laurence Oberman
2026-09-29 19:28 ` [PATCH v4 3/4] scsi: st: Restore the drive buffering mode after reset Laurence Oberman
2026-09-29 19:28 ` [PATCH v4 4/4] scsi: st: Relock the door after a reset Laurence Oberman
2026-09-30 15:58 ` [PATCH v4 0/4] scsi: st: Restore drive settings and state after reset and MTLOAD "Kai Mäkisara (Kolumbus)"
2026-10-03 14:36 ` Martin K. Petersen (Oracle)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox