Page MenuHomeFreeBSD

XPT_TIMEOUT for CAM framework for scheduling CCB completion entirely in XPT layer
Needs ReviewPublic

Authored by kibab on Jul 17 2017, 10:01 AM.



As part of getting rid of ugly sleeps in the MMCCAM code I propose to create a new function code called XPT_TIMEOUT to allow scheduling completion of CCBs. Having it in the CAM framework makes it possible to just create a CCB with func_code set to XPT_TIMEOUT and specify a timeout and a completion callback, and then the framework will take care of marking CCB as completed and calling a specified callback.

One issue with the attached patch is that it seems that the callback is called by callout framework directly, not cam_doneq thread. I need help to understand how to do this properly and if such functionality is required at all.

Test Plan

After properly implementing this function code, the following sequence of commands should complete without panic when running FreeBSD 12 in bhyve:

  1. kldload mmcnull
  2. camcontrol rescan 0:0:0

Right now the following happens at the end:

(mmcprobe0:mmcnull0:0:0:0): xpt_signal_timeout_passed: time is up
(mmcprobe0:mmcnull0:0:0:0): xpt_done: func= 0x940 XPT_TIMEOUT status 0x1
(mmcprobe0:mmcnull0:0:0:0): mmcprobe_done
Transition POWER_OFF -> POWER_UP after timeout
(mmcprobe0:mmcnull0:0:0:0): Probe PROBE_RESET to PROBE_IDENTIFY_POWER_UP
(mmcprobe0:mmcnull0:0:0:0): xpt_schedule
(mmcprobe0:mmcnull0:0:0:0): xpt_setup_ccb
(mmcprobe0:mmcnull0:0:0:0): mmcprobe_start
(mmcprobe0:mmcnull0:0:0:0): xpt_action: func 0x15 XPT_GET_TRAN_SETTINGS
(mmcprobe0:mmcnull0:0:0:0): mmc_action! func_code=15, action XPT_GET_TRAN_SETTINGS
(mmcprobe0:mmcnull0:0:0:0): xpt_action_default: func 0x15 XPT_GET_TRAN_SETTINGS
(mmcprobe0:mmcnull0:0:0:0): Calling sim->sim_action(): func=0x15
mmcnull0: action: func_code 15
(mmcprobe0:mmcnull0:0:0:0): xpt_done: func= 0x15 XPT_GET_TRAN_SETTINGS status 0x1
(mmcprobe0:mmcnull0:0:0:0): sim->sim_action returned: status=0x1
(mmcprobe0:mmcnull0:0:0:0): xpt_action_default: func= 0x15 XPT_GET_TRAN_SETTINGS status 0x1
(mmcprobe0:mmcnull0:0:0:0): xpt_action: func 0x16 XPT_SET_TRAN_SETTINGS
(mmcprobe0:mmcnull0:0:0:0): mmc_action! func_code=16, action XPT_SET_TRAN_SETTINGS
(mmcprobe0:mmcnull0:0:0:0): xpt_action_default: func 0x16 XPT_SET_TRAN_SETTINGS
(mmcprobe0:mmcnull0:0:0:0): Calling sim->sim_action(): func=0x16
mmcnull0: action: func_code 16
mmcnull0: Got XPT_SET_TRAN_SETTINGS, should update IOS...
(mmcprobe0:mmcnull0:0:0:0): xpt_done: func= 0x16 XPT_SET_TRAN_SETTINGS status 0x1
(mmcprobe0:mmcnull0:0:0:0): sim->sim_action returned: status=0x1
(mmcprobe0:mmcnull0:0:0:0): xpt_action_default: func= 0x16 XPT_SET_TRAN_SETTINGS status 0x1
panic: sleepq_add: td 0xfffff8000260f000 to sleep on wchan 0xfffff80002555c00 with sleeping prohibited
cpuid = 0
time = 1531914219
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe002c86f620
vpanic() at vpanic+0x19c/frame 0xfffffe002c86f6a0
kassert_panic() at kassert_panic+0x126/frame 0xfffffe002c86f710
sleepq_add() at sleepq_add+0x34f/frame 0xfffffe002c86f760
_sleep() at _sleep+0x28d/frame 0xfffffe002c86f800
mmcprobe_start() at mmcprobe_start+0xa3d/frame 0xfffffe002c86f850
xpt_run_allocq() at xpt_run_allocq+0x1d9/frame 0xfffffe002c86f890
xpt_schedule() at xpt_schedule+0x1d0/frame 0xfffffe002c86f990
mmcprobe_done() at mmcprobe_done+0x18e7/frame 0xfffffe002c86f9f0
xpt_done_process() at xpt_done_process+0x2dc/frame 0xfffffe002c86fa20
xpt_done_td() at xpt_done_td+0x146/frame 0xfffffe002c86fa70
fork_exit() at fork_exit+0x84/frame 0xfffffe002c86fab0
fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe002c86fab0
--- trap 0, rip = 0, rsp = 0, rbp = 0 ---
KDB: enter: panic
[ thread pid 2 tid 100019 ]
Stopped at      kdb_enter+0x3b: movq    $0,kdb_why

Diff Detail

rS FreeBSD src repository - subversion
Lint Skipped
Unit Tests Skipped
Build Status
Buildable 10521

Event Timeline

I think this functionality may be redundant. There is already support for freeze release timeout, which allows to execute some CCBs after specified amount of time.