Skip to content

Commit

Permalink
Merge patch series "scsi: st: Device reset patches"
Browse files Browse the repository at this point in the history
Kai Mäkisara <Kai.Makisara@kolumbus.fi> 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/20241106095723.63254-1-Kai.Makisara@kolumbus.fi
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Martin K. Petersen committed Nov 7, 2024
2 parents 007cd6b + a4550b2 commit 128faa1
Showing 1 changed file with 26 additions and 10 deletions.
36 changes: 26 additions & 10 deletions drivers/scsi/st.c
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,10 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
scode = cmdstatp->sense_hdr.sense_key;

if (scode == UNIT_ATTENTION) { /* New media? */
new_session = 1;
if (cmdstatp->sense_hdr.asc == 0x28) { /* New media */
new_session = 1;
DEBC_printk(STp, "New tape session.");
}
if (attentions < MAX_ATTENTIONS) {
attentions++;
continue;
Expand Down Expand Up @@ -3506,6 +3509,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
int i, cmd_nr, cmd_type, bt;
int retval = 0;
unsigned int blk;
bool cmd_mtiocget;
struct scsi_tape *STp = file->private_data;
struct st_modedef *STm;
struct st_partstat *STps;
Expand Down Expand Up @@ -3619,6 +3623,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
*/
if (mtc.mt_op != MTREW &&
mtc.mt_op != MTOFFL &&
mtc.mt_op != MTLOAD &&
mtc.mt_op != MTRETEN &&
mtc.mt_op != MTERASE &&
mtc.mt_op != MTSEEK &&
Expand Down Expand Up @@ -3732,17 +3737,28 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
goto out;
}

cmd_mtiocget = cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET);

if ((i = flush_buffer(STp, 0)) < 0) {
retval = i;
goto out;
}
if (STp->can_partitions &&
(i = switch_partition(STp)) < 0) {
retval = i;
goto out;
if (cmd_mtiocget && STp->pos_unknown) {
/* flush fails -> modify status accordingly */
reset_state(STp);
STp->pos_unknown = 1;
} else { /* return error */
retval = i;
goto out;
}
} else { /* flush_buffer succeeds */
if (STp->can_partitions) {
i = switch_partition(STp);
if (i < 0) {
retval = i;
goto out;
}
}
}

if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
if (cmd_mtiocget) {
struct mtget mt_status;

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

0 comments on commit 128faa1

Please sign in to comment.