Commit 279afdfe78a020b4b1a68bffd0009b961b12982e

Authored by Ewan D. Milne
Committed by James Bottomley
1 parent f8813d260e

[SCSI] Generate uevents on certain unit attention codes

Generate a uevent when the following Unit Attention ASC/ASCQ
codes are received:

    2A/01  MODE PARAMETERS CHANGED
    2A/09  CAPACITY DATA HAS CHANGED
    38/07  THIN PROVISIONING SOFT THRESHOLD REACHED
    3F/03  INQUIRY DATA HAS CHANGED
    3F/0E  REPORTED LUNS DATA HAS CHANGED

Log kernel messages when the following Unit Attention ASC/ASCQ
codes are received that are not as specific as those above:

    2A/xx  PARAMETERS CHANGED
    3F/xx  TARGET OPERATING CONDITIONS HAVE CHANGED

Added logic to set expecting_lun_change for other LUNs on the target
after REPORTED LUNS DATA HAS CHANGED is received, so that duplicate
uevents are not generated, and clear expecting_lun_change when a
REPORT LUNS command completes, in accordance with the SPC-3
specification regarding reporting of the 3F 0E ASC/ASCQ UA.

[jejb: remove SPC3 test in scsi_report_lun_change and some docbook fixes and
       unused variable fix, both reported by Fengguang Wu]
Signed-off-by: Ewan D. Milne <emilne@redhat.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

Showing 4 changed files with 127 additions and 22 deletions Side-by-side Diff

drivers/scsi/scsi_error.c
... ... @@ -223,7 +223,75 @@
223 223 }
224 224 #endif
225 225  
  226 + /**
  227 + * scsi_report_lun_change - Set flag on all *other* devices on the same target
  228 + * to indicate that a UNIT ATTENTION is expected.
  229 + * @sdev: Device reporting the UNIT ATTENTION
  230 + */
  231 +static void scsi_report_lun_change(struct scsi_device *sdev)
  232 +{
  233 + sdev->sdev_target->expecting_lun_change = 1;
  234 +}
  235 +
226 236 /**
  237 + * scsi_report_sense - Examine scsi sense information and log messages for
  238 + * certain conditions, also issue uevents for some of them.
  239 + * @sdev: Device reporting the sense code
  240 + * @sshdr: sshdr to be examined
  241 + */
  242 +static void scsi_report_sense(struct scsi_device *sdev,
  243 + struct scsi_sense_hdr *sshdr)
  244 +{
  245 + enum scsi_device_event evt_type = SDEV_EVT_MAXBITS; /* i.e. none */
  246 +
  247 + if (sshdr->sense_key == UNIT_ATTENTION) {
  248 + if (sshdr->asc == 0x3f && sshdr->ascq == 0x03) {
  249 + evt_type = SDEV_EVT_INQUIRY_CHANGE_REPORTED;
  250 + sdev_printk(KERN_WARNING, sdev,
  251 + "Inquiry data has changed");
  252 + } else if (sshdr->asc == 0x3f && sshdr->ascq == 0x0e) {
  253 + evt_type = SDEV_EVT_LUN_CHANGE_REPORTED;
  254 + scsi_report_lun_change(sdev);
  255 + sdev_printk(KERN_WARNING, sdev,
  256 + "Warning! Received an indication that the "
  257 + "LUN assignments on this target have "
  258 + "changed. The Linux SCSI layer does not "
  259 + "automatically remap LUN assignments.\n");
  260 + } else if (sshdr->asc == 0x3f)
  261 + sdev_printk(KERN_WARNING, sdev,
  262 + "Warning! Received an indication that the "
  263 + "operating parameters on this target have "
  264 + "changed. The Linux SCSI layer does not "
  265 + "automatically adjust these parameters.\n");
  266 +
  267 + if (sshdr->asc == 0x38 && sshdr->ascq == 0x07) {
  268 + evt_type = SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED;
  269 + sdev_printk(KERN_WARNING, sdev,
  270 + "Warning! Received an indication that the "
  271 + "LUN reached a thin provisioning soft "
  272 + "threshold.\n");
  273 + }
  274 +
  275 + if (sshdr->asc == 0x2a && sshdr->ascq == 0x01) {
  276 + evt_type = SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED;
  277 + sdev_printk(KERN_WARNING, sdev,
  278 + "Mode parameters changed");
  279 + } else if (sshdr->asc == 0x2a && sshdr->ascq == 0x09) {
  280 + evt_type = SDEV_EVT_CAPACITY_CHANGE_REPORTED;
  281 + sdev_printk(KERN_WARNING, sdev,
  282 + "Capacity data has changed");
  283 + } else if (sshdr->asc == 0x2a)
  284 + sdev_printk(KERN_WARNING, sdev,
  285 + "Parameters changed");
  286 + }
  287 +
  288 + if (evt_type != SDEV_EVT_MAXBITS) {
  289 + set_bit(evt_type, sdev->pending_events);
  290 + schedule_work(&sdev->event_work);
  291 + }
  292 +}
  293 +
  294 +/**
227 295 * scsi_check_sense - Examine scsi cmd sense
228 296 * @scmd: Cmd to have sense checked.
229 297 *
... ... @@ -250,6 +318,8 @@
250 318 */
251 319 return SUCCESS;
252 320  
  321 + scsi_report_sense(sdev, &sshdr);
  322 +
253 323 if (scsi_sense_is_deferred(&sshdr))
254 324 return NEEDS_RETRY;
255 325  
... ... @@ -315,6 +385,14 @@
315 385 }
316 386 }
317 387 /*
  388 + * we might also expect a cc/ua if another LUN on the target
  389 + * reported a UA with an ASC/ASCQ of 3F 0E -
  390 + * REPORTED LUNS DATA HAS CHANGED.
  391 + */
  392 + if (scmd->device->sdev_target->expecting_lun_change &&
  393 + sshdr.asc == 0x3f && sshdr.ascq == 0x0e)
  394 + return NEEDS_RETRY;
  395 + /*
318 396 * if the device is in the process of becoming ready, we
319 397 * should retry.
320 398 */
... ... @@ -327,26 +405,6 @@
327 405 if (scmd->device->allow_restart &&
328 406 (sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
329 407 return FAILED;
330   -
331   - if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e)
332   - scmd_printk(KERN_WARNING, scmd,
333   - "Warning! Received an indication that the "
334   - "LUN assignments on this target have "
335   - "changed. The Linux SCSI layer does not "
336   - "automatically remap LUN assignments.\n");
337   - else if (sshdr.asc == 0x3f)
338   - scmd_printk(KERN_WARNING, scmd,
339   - "Warning! Received an indication that the "
340   - "operating parameters on this target have "
341   - "changed. The Linux SCSI layer does not "
342   - "automatically adjust these parameters.\n");
343   -
344   - if (sshdr.asc == 0x38 && sshdr.ascq == 0x07)
345   - scmd_printk(KERN_WARNING, scmd,
346   - "Warning! Received an indication that the "
347   - "LUN reached a thin provisioning soft "
348   - "threshold.\n");
349   -
350 408 /*
351 409 * Pass the UA upwards for a determination in the completion
352 410 * functions.
... ... @@ -1574,6 +1632,8 @@
1574 1632 */
1575 1633 return ADD_TO_MLQUEUE;
1576 1634 case GOOD:
  1635 + if (scmd->cmnd[0] == REPORT_LUNS)
  1636 + scmd->device->sdev_target->expecting_lun_change = 0;
1577 1637 scsi_handle_queue_ramp_up(scmd->device);
1578 1638 case COMMAND_TERMINATED:
1579 1639 return SUCCESS;
drivers/scsi/scsi_lib.c
... ... @@ -2253,7 +2253,21 @@
2253 2253 case SDEV_EVT_MEDIA_CHANGE:
2254 2254 envp[idx++] = "SDEV_MEDIA_CHANGE=1";
2255 2255 break;
2256   -
  2256 + case SDEV_EVT_INQUIRY_CHANGE_REPORTED:
  2257 + envp[idx++] = "SDEV_UA=INQUIRY_DATA_HAS_CHANGED";
  2258 + break;
  2259 + case SDEV_EVT_CAPACITY_CHANGE_REPORTED:
  2260 + envp[idx++] = "SDEV_UA=CAPACITY_DATA_HAS_CHANGED";
  2261 + break;
  2262 + case SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED:
  2263 + envp[idx++] = "SDEV_UA=THIN_PROVISIONING_SOFT_THRESHOLD_REACHED";
  2264 + break;
  2265 + case SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED:
  2266 + envp[idx++] = "SDEV_UA=MODE_PARAMETERS_CHANGED";
  2267 + break;
  2268 + case SDEV_EVT_LUN_CHANGE_REPORTED:
  2269 + envp[idx++] = "SDEV_UA=REPORTED_LUNS_DATA_HAS_CHANGED";
  2270 + break;
2257 2271 default:
2258 2272 /* do nothing */
2259 2273 break;
2260 2274  
... ... @@ -2274,10 +2288,15 @@
2274 2288 void scsi_evt_thread(struct work_struct *work)
2275 2289 {
2276 2290 struct scsi_device *sdev;
  2291 + enum scsi_device_event evt_type;
2277 2292 LIST_HEAD(event_list);
2278 2293  
2279 2294 sdev = container_of(work, struct scsi_device, event_work);
2280 2295  
  2296 + for (evt_type = SDEV_EVT_FIRST; evt_type <= SDEV_EVT_LAST; evt_type++)
  2297 + if (test_and_clear_bit(evt_type, sdev->pending_events))
  2298 + sdev_evt_send_simple(sdev, evt_type, GFP_KERNEL);
  2299 +
2281 2300 while (1) {
2282 2301 struct scsi_event *evt;
2283 2302 struct list_head *this, *tmp;
... ... @@ -2347,6 +2366,11 @@
2347 2366 /* evt_type-specific initialization, if any */
2348 2367 switch (evt_type) {
2349 2368 case SDEV_EVT_MEDIA_CHANGE:
  2369 + case SDEV_EVT_INQUIRY_CHANGE_REPORTED:
  2370 + case SDEV_EVT_CAPACITY_CHANGE_REPORTED:
  2371 + case SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED:
  2372 + case SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED:
  2373 + case SDEV_EVT_LUN_CHANGE_REPORTED:
2350 2374 default:
2351 2375 /* do nothing */
2352 2376 break;
drivers/scsi/scsi_sysfs.c
... ... @@ -739,6 +739,11 @@
739 739 #define REF_EVT(name) &dev_attr_evt_##name.attr
740 740  
741 741 DECLARE_EVT(media_change, MEDIA_CHANGE)
  742 +DECLARE_EVT(inquiry_change_reported, INQUIRY_CHANGE_REPORTED)
  743 +DECLARE_EVT(capacity_change_reported, CAPACITY_CHANGE_REPORTED)
  744 +DECLARE_EVT(soft_threshold_reached, SOFT_THRESHOLD_REACHED_REPORTED)
  745 +DECLARE_EVT(mode_parameter_change_reported, MODE_PARAMETER_CHANGE_REPORTED)
  746 +DECLARE_EVT(lun_change_reported, LUN_CHANGE_REPORTED)
742 747  
743 748 /* Default template for device attributes. May NOT be modified */
744 749 static struct attribute *scsi_sdev_attrs[] = {
... ... @@ -759,6 +764,11 @@
759 764 &dev_attr_ioerr_cnt.attr,
760 765 &dev_attr_modalias.attr,
761 766 REF_EVT(media_change),
  767 + REF_EVT(inquiry_change_reported),
  768 + REF_EVT(capacity_change_reported),
  769 + REF_EVT(soft_threshold_reached),
  770 + REF_EVT(mode_parameter_change_reported),
  771 + REF_EVT(lun_change_reported),
762 772 NULL
763 773 };
764 774  
include/scsi/scsi_device.h
... ... @@ -52,8 +52,15 @@
52 52  
53 53 enum scsi_device_event {
54 54 SDEV_EVT_MEDIA_CHANGE = 1, /* media has changed */
  55 + SDEV_EVT_INQUIRY_CHANGE_REPORTED, /* 3F 03 UA reported */
  56 + SDEV_EVT_CAPACITY_CHANGE_REPORTED, /* 2A 09 UA reported */
  57 + SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED, /* 38 07 UA reported */
  58 + SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED, /* 2A 01 UA reported */
  59 + SDEV_EVT_LUN_CHANGE_REPORTED, /* 3F 0E UA reported */
55 60  
56   - SDEV_EVT_LAST = SDEV_EVT_MEDIA_CHANGE,
  61 + SDEV_EVT_FIRST = SDEV_EVT_MEDIA_CHANGE,
  62 + SDEV_EVT_LAST = SDEV_EVT_LUN_CHANGE_REPORTED,
  63 +
57 64 SDEV_EVT_MAXBITS = SDEV_EVT_LAST + 1
58 65 };
59 66  
... ... @@ -164,6 +171,7 @@
164 171 atomic_t disk_events_disable_depth; /* disable depth for disk events */
165 172  
166 173 DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
  174 + DECLARE_BITMAP(pending_events, SDEV_EVT_MAXBITS); /* pending events */
167 175 struct list_head event_list; /* asserted events */
168 176 struct work_struct event_work;
169 177  
... ... @@ -261,6 +269,9 @@
261 269 * means no lun present. */
262 270 unsigned int no_report_luns:1; /* Don't use
263 271 * REPORT LUNS for scanning. */
  272 + unsigned int expecting_lun_change:1; /* A device has reported
  273 + * a 3F/0E UA, other devices on
  274 + * the same target will also. */
264 275 /* commands actually active on LLD. protected by host lock. */
265 276 unsigned int target_busy;
266 277 /*