--- a/sys/bus/cam/cam_periph.c 2026-10-21 04:28:14.594687408 +0000 +++ b/sys/bus/cam/cam_periph.c 2026-10-21 04:28:14.594687408 +0000 @@ -1,20 +1,50 @@ - while (found == 0) { - ccb->cgdl.index = 0; - ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS; - while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) { + /* + * DF-2267: the outer loop previously only exited on + * CAM_GDEVLIST_LAST_DEVICE or a pass match; ERROR or + * LIST_CHANGED from every xpt_action span it forever while + * the caller held the SIM lock. Bound the restarts and + * terminate on error. + */ + { + int df_restarts = 0; - /* we want the next device in the list */ - xpt_action(ccb); - if (strncmp(ccb->cgdl.periph_name, - "pass", 4) == 0){ - found = 1; + while (found == 0) { + if (++df_restarts > 100) { + ccb->cgdl.periph_name[0] = '\0'; + ccb->cgdl.unit_number = 0; + ccb->cgdl.status = + CAM_GDEVLIST_ERROR; + break; + } + ccb->cgdl.index = 0; + ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS; + while (ccb->cgdl.status == + CAM_GDEVLIST_MORE_DEVS) { + + /* we want the next device in the list */ + xpt_action(ccb); + if (strncmp(ccb->cgdl.periph_name, + "pass", 4) == 0){ + found = 1; + break; + } + if (ccb->cgdl.status == + CAM_GDEVLIST_ERROR) { + ccb->cgdl.periph_name[0] = '\0'; + ccb->cgdl.unit_number = 0; + found = -1; /* give up */ + break; + } + } + if (found != 0) + break; + if ((ccb->cgdl.status == + CAM_GDEVLIST_LAST_DEVICE)) { + ccb->cgdl.periph_name[0] = '\0'; + ccb->cgdl.unit_number = 0; break; } } - if ((ccb->cgdl.status == CAM_GDEVLIST_LAST_DEVICE) && - (found == 0)) { - ccb->cgdl.periph_name[0] = '\0'; - ccb->cgdl.unit_number = 0; - break; - } + if (found == -1) + found = 0; } \ No newline at end of file