Skip to content

Commit 0264762

Browse files
Merge patch series "scsi: st: scsi_error: More reset patches"
Kai Mäkisara <Kai.Makisara@kolumbus.fi> says: The first patch re-applies after device reset some settings changed by the user (partition, density, block size). The second and third patch address the case where more than one ULD access the same device. The Unit Attention (UA) sense data is sent only to one ULD and the others miss it. The st driver needs to find out if device reset or media change has happened. The second patch adds counters for New Media and Power On/Reset (POR) Unit Attentions to the scsi_device struct. The third one changes st so that these are used: if the value in the scsi_device struct does not match the one stored locally, the corresponding UA has happened. Use of the was_reset flag has been removed. The fourth patch adds a file to sysfs to tell the user if reads/writes to a tape are blocked following a device reset. Link: https://lore.kernel.org/r/20250120194925.44432-1-Kai.Makisara@kolumbus.fi Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2 parents 14807b4 + 2c445d5 commit 0264762

File tree

5 files changed

+97
-8
lines changed

5 files changed

+97
-8
lines changed

Documentation/scsi/st.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ enabled driver and mode options. The value in the file is a bit mask where the
157157
bit definitions are the same as those used with MTSETDRVBUFFER in setting the
158158
options.
159159

160+
Each directory contains the entry 'position_lost_in_reset'. If this value is
161+
one, reading and writing to the device is blocked after device reset. Most
162+
devices rewind the tape after reset and the writes/read don't access the
163+
tape position the user expects.
164+
160165
A link named 'tape' is made from the SCSI device directory to the class
161166
directory corresponding to the mode 0 auto-rewind device (e.g., st0).
162167

drivers/scsi/scsi_error.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,18 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
547547

548548
scsi_report_sense(sdev, &sshdr);
549549

550+
if (sshdr.sense_key == UNIT_ATTENTION) {
551+
/*
552+
* Increment the counters for Power on/Reset or New Media so
553+
* that all ULDs interested in these can see that those have
554+
* happened, even if someone else gets the sense data.
555+
*/
556+
if (sshdr.asc == 0x28)
557+
scmd->device->ua_new_media_ctr++;
558+
else if (sshdr.asc == 0x29)
559+
scmd->device->ua_por_ctr++;
560+
}
561+
550562
if (scsi_sense_is_deferred(&sshdr))
551563
return NEEDS_RETRY;
552564

drivers/scsi/st.c

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,11 @@ static const char *st_formats[] = {
163163

164164
static int debugging = DEBUG;
165165

166+
/* Setting these non-zero may risk recognizing resets */
166167
#define MAX_RETRIES 0
167168
#define MAX_WRITE_RETRIES 0
168169
#define MAX_READY_RETRIES 0
170+
169171
#define NO_TAPE NOT_READY
170172

171173
#define ST_TIMEOUT (900 * HZ)
@@ -357,10 +359,18 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
357359
{
358360
int result = SRpnt->result;
359361
u8 scode;
362+
unsigned int ctr;
360363
DEB(const char *stp;)
361364
char *name = STp->name;
362365
struct st_cmdstatus *cmdstatp;
363366

367+
ctr = scsi_get_ua_por_ctr(STp->device);
368+
if (ctr != STp->por_ctr) {
369+
STp->por_ctr = ctr;
370+
STp->pos_unknown = 1; /* ASC => power on / reset */
371+
st_printk(KERN_WARNING, STp, "Power on/reset recognized.");
372+
}
373+
364374
if (!result)
365375
return 0;
366376

@@ -413,10 +423,11 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
413423
if (cmdstatp->have_sense &&
414424
cmdstatp->sense_hdr.asc == 0 && cmdstatp->sense_hdr.ascq == 0x17)
415425
STp->cleaning_req = 1; /* ASC and ASCQ => cleaning requested */
416-
if (cmdstatp->have_sense && scode == UNIT_ATTENTION && cmdstatp->sense_hdr.asc == 0x29)
426+
if (cmdstatp->have_sense && scode == UNIT_ATTENTION &&
427+
cmdstatp->sense_hdr.asc == 0x29 && !STp->pos_unknown) {
417428
STp->pos_unknown = 1; /* ASC => power on / reset */
418-
419-
STp->pos_unknown |= STp->device->was_reset;
429+
st_printk(KERN_WARNING, STp, "Power on/reset recognized.");
430+
}
420431

421432
if (cmdstatp->have_sense &&
422433
scode == RECOVERED_ERROR
@@ -952,7 +963,6 @@ static void reset_state(struct scsi_tape *STp)
952963
STp->partition = find_partition(STp);
953964
if (STp->partition < 0)
954965
STp->partition = 0;
955-
STp->new_partition = STp->partition;
956966
}
957967
}
958968

@@ -969,6 +979,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
969979
{
970980
int attentions, waits, max_wait, scode;
971981
int retval = CHKRES_READY, new_session = 0;
982+
unsigned int ctr;
972983
unsigned char cmd[MAX_COMMAND_SIZE];
973984
struct st_request *SRpnt = NULL;
974985
struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
@@ -1025,6 +1036,13 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
10251036
}
10261037
}
10271038

1039+
ctr = scsi_get_ua_new_media_ctr(STp->device);
1040+
if (ctr != STp->new_media_ctr) {
1041+
STp->new_media_ctr = ctr;
1042+
new_session = 1;
1043+
DEBC_printk(STp, "New tape session.");
1044+
}
1045+
10281046
retval = (STp->buffer)->syscall_result;
10291047
if (!retval)
10301048
retval = new_session ? CHKRES_NEW_SESSION : CHKRES_READY;
@@ -2930,14 +2948,17 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
29302948
if (cmd_in == MTSETDENSITY) {
29312949
(STp->buffer)->b_data[4] = arg;
29322950
STp->density_changed = 1; /* At least we tried ;-) */
2951+
STp->changed_density = arg;
29332952
} else if (cmd_in == SET_DENS_AND_BLK)
29342953
(STp->buffer)->b_data[4] = arg >> 24;
29352954
else
29362955
(STp->buffer)->b_data[4] = STp->density;
29372956
if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
29382957
ltmp = arg & MT_ST_BLKSIZE_MASK;
2939-
if (cmd_in == MTSETBLK)
2958+
if (cmd_in == MTSETBLK) {
29402959
STp->blksize_changed = 1; /* At least we tried ;-) */
2960+
STp->changed_blksize = arg;
2961+
}
29412962
} else
29422963
ltmp = STp->block_size;
29432964
(STp->buffer)->b_data[9] = (ltmp >> 16);
@@ -3636,9 +3657,23 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
36363657
retval = (-EIO);
36373658
goto out;
36383659
}
3639-
reset_state(STp);
3640-
/* remove this when the midlevel properly clears was_reset */
3641-
STp->device->was_reset = 0;
3660+
reset_state(STp); /* Clears pos_unknown */
3661+
3662+
/* Fix the device settings after reset, ignore errors */
3663+
if (mtc.mt_op == MTREW || mtc.mt_op == MTSEEK ||
3664+
mtc.mt_op == MTEOM) {
3665+
if (STp->can_partitions) {
3666+
/* STp->new_partition contains the
3667+
* latest partition set
3668+
*/
3669+
STp->partition = 0;
3670+
switch_partition(STp);
3671+
}
3672+
if (STp->density_changed)
3673+
st_int_ioctl(STp, MTSETDENSITY, STp->changed_density);
3674+
if (STp->blksize_changed)
3675+
st_int_ioctl(STp, MTSETBLK, STp->changed_blksize);
3676+
}
36423677
}
36433678

36443679
if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
@@ -4384,6 +4419,9 @@ static int st_probe(struct device *dev)
43844419
goto out_idr_remove;
43854420
}
43864421

4422+
tpnt->new_media_ctr = scsi_get_ua_new_media_ctr(SDp);
4423+
tpnt->por_ctr = scsi_get_ua_por_ctr(SDp);
4424+
43874425
dev_set_drvdata(dev, tpnt);
43884426

43894427

@@ -4665,6 +4703,24 @@ options_show(struct device *dev, struct device_attribute *attr, char *buf)
46654703
}
46664704
static DEVICE_ATTR_RO(options);
46674705

4706+
/**
4707+
* position_lost_in_reset_show - Value 1 indicates that reads, writes, etc.
4708+
* are blocked because a device reset has occurred and no operation positioning
4709+
* the tape has been issued.
4710+
* @dev: struct device
4711+
* @attr: attribute structure
4712+
* @buf: buffer to return formatted data in
4713+
*/
4714+
static ssize_t position_lost_in_reset_show(struct device *dev,
4715+
struct device_attribute *attr, char *buf)
4716+
{
4717+
struct st_modedef *STm = dev_get_drvdata(dev);
4718+
struct scsi_tape *STp = STm->tape;
4719+
4720+
return sprintf(buf, "%d", STp->pos_unknown);
4721+
}
4722+
static DEVICE_ATTR_RO(position_lost_in_reset);
4723+
46684724
/* Support for tape stats */
46694725

46704726
/**
@@ -4849,6 +4905,7 @@ static struct attribute *st_dev_attrs[] = {
48494905
&dev_attr_default_density.attr,
48504906
&dev_attr_default_compression.attr,
48514907
&dev_attr_options.attr,
4908+
&dev_attr_position_lost_in_reset.attr,
48524909
NULL,
48534910
};
48544911

drivers/scsi/st.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,18 +165,24 @@ struct scsi_tape {
165165
unsigned char compression_changed;
166166
unsigned char drv_buffer;
167167
unsigned char density;
168+
unsigned char changed_density;
168169
unsigned char door_locked;
169170
unsigned char autorew_dev; /* auto-rewind device */
170171
unsigned char rew_at_close; /* rewind necessary at close */
171172
unsigned char inited;
172173
unsigned char cleaning_req; /* cleaning requested? */
173174
unsigned char first_tur; /* first TEST UNIT READY */
174175
int block_size;
176+
int changed_blksize;
175177
int min_block;
176178
int max_block;
177179
int recover_count; /* From tape opening */
178180
int recover_reg; /* From last status call */
179181

182+
/* The saved values of midlevel counters */
183+
unsigned int new_media_ctr;
184+
unsigned int por_ctr;
185+
180186
#if DEBUG
181187
unsigned char write_pending;
182188
int nbr_finished;

include/scsi/scsi_device.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ struct scsi_device {
247247
unsigned int queue_stopped; /* request queue is quiesced */
248248
bool offline_already; /* Device offline message logged */
249249

250+
unsigned int ua_new_media_ctr; /* Counter for New Media UNIT ATTENTIONs */
251+
unsigned int ua_por_ctr; /* Counter for Power On / Reset UAs */
252+
250253
atomic_t disk_events_disable_depth; /* disable depth for disk events */
251254

252255
DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
@@ -684,6 +687,12 @@ static inline int scsi_device_busy(struct scsi_device *sdev)
684687
return sbitmap_weight(&sdev->budget_map);
685688
}
686689

690+
/* Macros to access the UNIT ATTENTION counters */
691+
#define scsi_get_ua_new_media_ctr(sdev) \
692+
((const unsigned int)(sdev->ua_new_media_ctr))
693+
#define scsi_get_ua_por_ctr(sdev) \
694+
((const unsigned int)(sdev->ua_por_ctr))
695+
687696
#define MODULE_ALIAS_SCSI_DEVICE(type) \
688697
MODULE_ALIAS("scsi:t-" __stringify(type) "*")
689698
#define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x"

0 commit comments

Comments
 (0)