@@ -3538,6 +3538,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;
@@ -3651,6 +3652,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 &&
@@ -3764,17 +3766,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;
+ /* flush fails -> modify status accordingly */
+ if (cmd_mtiocget && STp->pos_unknown) {
+ 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)) {
@@ -3788,7 +3801,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;