Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 631c1e6b authored by Kai Mäkisara's avatar Kai Mäkisara Committed by Greg Kroah-Hartman
Browse files

scsi: st: Add MTIOCGET and MTLOAD to ioctls allowed after device reset



[ Upstream commit 0b120edb37dc9dd8ca82893d386922eb6b16f860 ]

Most drives rewind the tape when the device is reset. Reading and writing
are not allowed until something is done to make the tape position match the
user's expectation (e.g., rewind the tape). Add MTIOCGET and MTLOAD to
operations allowed after reset. MTIOCGET is modified to not touch the tape
if pos_unknown is non-zero. The tape location is known after MTLOAD.

Signed-off-by: default avatarKai Mäkisara <Kai.Makisara@kolumbus.fi>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=219419#c14
Link: https://lore.kernel.org/r/20241106095723.63254-3-Kai.Makisara@kolumbus.fi


Reviewed-by: default avatarJohn Meneghini <jmeneghi@redhat.com>
Tested-by: default avatarJohn Meneghini <jmeneghi@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent e6e6045f
Loading
Loading
Loading
Loading
+21 −8
Original line number Diff line number Diff line
@@ -3505,6 +3505,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;
@@ -3619,6 +3620,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 &&
@@ -3732,17 +3734,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) {
		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;
		}
	if (STp->can_partitions &&
	    (i = switch_partition(STp)) < 0) {
	} 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)) {