Linux SCSI subsystem development
 help / color / mirror / Atom feed
From: Laurence Oberman <loberman@redhat.com>
To: linux-scsi@vger.kernel.org
Cc: "Martin K . Petersen" <mkp@kernel.org>,
	"James E . J . Bottomley" <James.Bottomley@HansenPartnership.com>,
	Kai Makisara <Kai.Makisara@kolumbus.fi>,
	John Meneghini <jmeneghi@redhat.com>,
	emilne@redhat.com, bgurney@redhat.com
Subject: [PATCH v2 1/2] scsi: st: Restore changed drive settings after reset also for MTLOAD and MTRETEN
Date: Mon, 28 Sep 2026 09:25:38 -0400	[thread overview]
Message-ID: <20260928132539.56876-2-loberman@redhat.com> (raw)
In-Reply-To: <20260928132539.56876-1-loberman@redhat.com>

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.
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>
---
 drivers/scsi/st.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index f1c3c4946637..0a4263bef9cb 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3586,6 +3586,23 @@ static long st_common_ioctl(struct scsi_tape *STp, struct st_modedef *STm,
 	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,9 @@ 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));
+			if (!retval)
+				st_restore_changed_settings(STp, restore_density,
+							    restore_blksize);
 			goto out;
 		}
 
@@ -3837,6 +3869,19 @@ 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)
+				st_restore_changed_settings(STp, restore_density,
+							    restore_blksize);
+		}
 		goto out;
 	}
 	if (!STm->defined) {
-- 
2.55.0


  reply	other threads:[~2026-09-28 13:25 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-28 13:25 [PATCH v2 0/2] scsi: st: Fix drive settings and position after reset recovery with MTLOAD/MTRETEN Laurence Oberman
2026-09-28 13:25 ` Laurence Oberman [this message]
2026-09-29 14:15   ` [PATCH v2 1/2] scsi: st: Restore changed drive settings after reset also for MTLOAD and MTRETEN "Kai Mäkisara (Kolumbus)"
2026-09-29 17:17     ` Laurence Oberman
2026-09-28 13:25 ` [PATCH v2 2/2] scsi: st: Record the tape position after a successful MTLOAD Laurence Oberman
2026-09-29 12:39   ` "Kai Mäkisara (Kolumbus)"
2026-09-29 13:30     ` Laurence Oberman
2026-09-29 17:18     ` Laurence Oberman

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=20260928132539.56876-2-loberman@redhat.com \
    --to=loberman@redhat.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=Kai.Makisara@kolumbus.fi \
    --cc=bgurney@redhat.com \
    --cc=emilne@redhat.com \
    --cc=jmeneghi@redhat.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=mkp@kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox