Skip to content

Commit 128faa1

Browse files
Merge patch series "scsi: st: Device reset patches"
Kai Mäkisara <[email protected]> says: These three patches were developed in response to Bugzilla report https://bugzilla.kernel.org/show_bug.cgi?id=219419 After device reset, the tape driver allows only operations that don't write or read anything from tape. The reason for this is that many (most ?) drives rewind the tape after reset and the subsequent reads or writes would not be at the tape location the user expects. Reading and writing is allowed again when the user does something to position the tape (e.g., rewind). The Bugzilla report considers the case when a user, after reset, tries to read the drive status with MTIOCGET ioctl, but it fails. MTIOCGET does not return much useful data after reset, but it can be allowed. MTLOAD positions the tape and it should be allowed. The second patch adds these to the set of allowed operations after device reset. The first patch fixes a bug seen when developing the second patch. V2: The third patch is added to fix a bug that resulted in not blocking writes if reset occurs while the device file is not open. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
2 parents 007cd6b + a4550b2 commit 128faa1

File tree

1 file changed

+26
-10
lines changed

1 file changed

+26
-10
lines changed

drivers/scsi/st.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,10 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
991991
scode = cmdstatp->sense_hdr.sense_key;
992992

993993
if (scode == UNIT_ATTENTION) { /* New media? */
994-
new_session = 1;
994+
if (cmdstatp->sense_hdr.asc == 0x28) { /* New media */
995+
new_session = 1;
996+
DEBC_printk(STp, "New tape session.");
997+
}
995998
if (attentions < MAX_ATTENTIONS) {
996999
attentions++;
9971000
continue;
@@ -3506,6 +3509,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
35063509
int i, cmd_nr, cmd_type, bt;
35073510
int retval = 0;
35083511
unsigned int blk;
3512+
bool cmd_mtiocget;
35093513
struct scsi_tape *STp = file->private_data;
35103514
struct st_modedef *STm;
35113515
struct st_partstat *STps;
@@ -3619,6 +3623,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
36193623
*/
36203624
if (mtc.mt_op != MTREW &&
36213625
mtc.mt_op != MTOFFL &&
3626+
mtc.mt_op != MTLOAD &&
36223627
mtc.mt_op != MTRETEN &&
36233628
mtc.mt_op != MTERASE &&
36243629
mtc.mt_op != MTSEEK &&
@@ -3732,17 +3737,28 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
37323737
goto out;
37333738
}
37343739

3740+
cmd_mtiocget = cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET);
3741+
37353742
if ((i = flush_buffer(STp, 0)) < 0) {
3736-
retval = i;
3737-
goto out;
3738-
}
3739-
if (STp->can_partitions &&
3740-
(i = switch_partition(STp)) < 0) {
3741-
retval = i;
3742-
goto out;
3743+
if (cmd_mtiocget && STp->pos_unknown) {
3744+
/* flush fails -> modify status accordingly */
3745+
reset_state(STp);
3746+
STp->pos_unknown = 1;
3747+
} else { /* return error */
3748+
retval = i;
3749+
goto out;
3750+
}
3751+
} else { /* flush_buffer succeeds */
3752+
if (STp->can_partitions) {
3753+
i = switch_partition(STp);
3754+
if (i < 0) {
3755+
retval = i;
3756+
goto out;
3757+
}
3758+
}
37433759
}
37443760

3745-
if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
3761+
if (cmd_mtiocget) {
37463762
struct mtget mt_status;
37473763

37483764
if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
@@ -3756,7 +3772,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
37563772
((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
37573773
mt_status.mt_blkno = STps->drv_block;
37583774
mt_status.mt_fileno = STps->drv_file;
3759-
if (STp->block_size != 0) {
3775+
if (STp->block_size != 0 && mt_status.mt_blkno >= 0) {
37603776
if (STps->rw == ST_WRITING)
37613777
mt_status.mt_blkno +=
37623778
(STp->buffer)->buffer_bytes / STp->block_size;

0 commit comments

Comments
 (0)