kernel - Fix duplicate da0 or da* and locked up boot
authorMatthew Dillon <dillon@apollo.backplane.com>
Sat, 21 Apr 2018 01:18:52 +0000 (18:18 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sat, 21 Apr 2018 01:18:52 +0000 (18:18 -0700)
* Fix duplicate da* reporting at boot which usually results in
  the boot locking up.

* The diskinfo was being installed while before CAM's softc->state
  normalized, potentially allowing I/O to occur during the probe
  sequence and causing the probe state to be repeated.

  Delay calling disk_setdiskinfo() until after softc->state is
  normalized.

sys/bus/cam/scsi/scsi_cd.c
sys/bus/cam/scsi/scsi_da.c

index cfb146c..636c1f7 100644 (file)
@@ -1670,6 +1670,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
                struct  disk_info info;
                char    announce_buf[120];
                struct  cd_params *cdp;
+               int doinfo = 0;
 
                cdp = &softc->params;
                bzero(&info, sizeof(info));
@@ -1689,7 +1690,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
                                  cdp->disksize, (u_long)cdp->blksize);
                        info.d_media_blksize = cdp->blksize;
                        info.d_media_blocks = cdp->disksize;
-                       disk_setdiskinfo(&softc->disk, &info);
+                       doinfo = 1;
                } else {
                        int     error;
 
@@ -1763,7 +1764,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
                                                sense_key_desc,
                                                asc_desc);
                                        info.d_media_blksize = 2048;
-                                       disk_setdiskinfo(&softc->disk, &info);
+                                       doinfo = 1;
                                } else if (SID_TYPE(&cgd.inq_data) == T_CDROM) {
                                        /*
                                         * We only print out an error for
@@ -1831,6 +1832,9 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
                 */
                xpt_release_ccb(done_ccb);
                cam_periph_unhold(periph, 0);
+               if (doinfo) {
+                       disk_setdiskinfo(&softc->disk, &info);
+               }
                return;
        }
        case CD_CCB_WAITING:
index 9607f43..c5b6e64 100644 (file)
@@ -1741,6 +1741,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
                struct     scsi_read_capacity_data *rdcap;
                struct     scsi_read_capacity_data_16 *rcaplong;
                char       announce_buf[80];
+               int        doinfo = 0;
 
                rdcap = NULL;
                rcaplong = NULL;
@@ -1792,7 +1793,6 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
                                dp->secsize, dp->heads, dp->secs_per_track,
                                dp->cylinders);
                        
-                       CAM_SIM_UNLOCK(periph->sim);
                        info.d_media_blksize = softc->params.secsize;
                        info.d_media_blocks = softc->params.sectors;
                        info.d_media_size = 0;
@@ -1802,8 +1802,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
                        info.d_secpercyl = softc->params.heads *
                                                softc->params.secs_per_track;
                        info.d_serialno = xpt_path_serialno(periph->path);
-                       disk_setdiskinfo(&softc->disk, &info);
-                       CAM_SIM_LOCK(periph->sim);
+                       doinfo = 1;
                } else {
                        int     error;
 
@@ -1880,7 +1879,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
                                                sense_key_desc,
                                                asc_desc);
                                        info.d_media_blksize = 512;
-                                       disk_setdiskinfo(&softc->disk, &info);
+                                       doinfo = 1;
                                } else {
                                        if (have_sense)
                                                scsi_sense_print(
@@ -1929,6 +1928,11 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
                 */
                xpt_release_ccb(done_ccb);
                cam_periph_unhold(periph, 0);
+               if (doinfo) {
+                       CAM_SIM_UNLOCK(periph->sim);
+                       disk_setdiskinfo(&softc->disk, &info);
+                       CAM_SIM_LOCK(periph->sim);
+               }
                return;
        }
        case DA_CCB_WAITING: