]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: st: Restore some drive settings after reset
authorKai Mäkisara <Kai.Makisara@kolumbus.fi>
Mon, 20 Jan 2025 19:49:22 +0000 (21:49 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Jun 2025 12:37:05 +0000 (14:37 +0200)
[ Upstream commit 7081dc75df79696d8322d01821c28e53416c932c ]

Some of the allowed operations put the tape into a known position to
continue operation assuming only the tape position has changed.  But reset
sets partition, density and block size to drive default values. These
should be restored to the values before reset.

Normally the current block size and density are stored by the drive.  If
the settings have been changed, the changed values have to be saved by the
driver across reset.

Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
Link: https://lore.kernel.org/r/20250120194925.44432-2-Kai.Makisara@kolumbus.fi
Reviewed-by: John Meneghini <jmeneghi@redhat.com>
Tested-by: John Meneghini <jmeneghi@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/st.c
drivers/scsi/st.h

index 747e69abfcfce25500fb9ff8f5a11bf63b7db447..23bbb062c2aaae92e11415ac9f5a961c7e39c7fe 100644 (file)
@@ -951,7 +951,6 @@ static void reset_state(struct scsi_tape *STp)
                STp->partition = find_partition(STp);
                if (STp->partition < 0)
                        STp->partition = 0;
-               STp->new_partition = STp->partition;
        }
 }
 \f
@@ -2921,14 +2920,17 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
                if (cmd_in == MTSETDENSITY) {
                        (STp->buffer)->b_data[4] = arg;
                        STp->density_changed = 1;       /* At least we tried ;-) */
+                       STp->changed_density = arg;
                } else if (cmd_in == SET_DENS_AND_BLK)
                        (STp->buffer)->b_data[4] = arg >> 24;
                else
                        (STp->buffer)->b_data[4] = STp->density;
                if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
                        ltmp = arg & MT_ST_BLKSIZE_MASK;
-                       if (cmd_in == MTSETBLK)
+                       if (cmd_in == MTSETBLK) {
                                STp->blksize_changed = 1; /* At least we tried ;-) */
+                               STp->changed_blksize = arg;
+                       }
                } else
                        ltmp = STp->block_size;
                (STp->buffer)->b_data[9] = (ltmp >> 16);
@@ -3628,9 +3630,25 @@ static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user
                                retval = (-EIO);
                                goto out;
                        }
-                       reset_state(STp);
+                       reset_state(STp); /* Clears pos_unknown */
                        /* remove this when the midlevel properly clears was_reset */
                        STp->device->was_reset = 0;
+
+                       /* Fix the device settings after reset, ignore errors */
+                       if (mtc.mt_op == MTREW || mtc.mt_op == MTSEEK ||
+                               mtc.mt_op == MTEOM) {
+                               if (STp->can_partitions) {
+                                       /* STp->new_partition contains the
+                                        *  latest partition set
+                                        */
+                                       STp->partition = 0;
+                                       switch_partition(STp);
+                               }
+                               if (STp->density_changed)
+                                       st_int_ioctl(STp, MTSETDENSITY, STp->changed_density);
+                               if (STp->blksize_changed)
+                                       st_int_ioctl(STp, MTSETBLK, STp->changed_blksize);
+                       }
                }
 
                if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
index 95d2e7a7988dea6101ac62d4dd312a3b97810ed7..c9947abb0a451c57fec76d53d9b69cbae8b38aff 100644 (file)
@@ -168,12 +168,14 @@ struct scsi_tape {
        unsigned char compression_changed;
        unsigned char drv_buffer;
        unsigned char density;
+       unsigned char changed_density;
        unsigned char door_locked;
        unsigned char autorew_dev;   /* auto-rewind device */
        unsigned char rew_at_close;  /* rewind necessary at close */
        unsigned char inited;
        unsigned char cleaning_req;  /* cleaning requested? */
        int block_size;
+       int changed_blksize;
        int min_block;
        int max_block;
        int recover_count;     /* From tape opening */