On 5/3/19 10:47 AM, Evan Green wrote: > Hey blockies, ^^^^^^^^^^^^ That's the weirdest greeting I have encountered so far on the linux-block mailing list. > I'm seeing a hung task in the kernel, and I wanted to share it in case > it's a known issue. I'm still trying to wrap my head around the stacks > myself. This is our Chrome OS 4.19 kernel, which is admittedly not > 100% vanilla mainline master, but we try to keep it pretty close. > > I can reproduce this reliably within our chrome OS installer, where > it's trying to dd from my system disk (NVMe) to a loop device backed > by a removable UFS card (4kb sectors) in a USB dongle. Although this is not the only possible cause such hangs are often caused by a block driver or SCSI LLD not completing a request. A list of pending requests can be obtained e.g. by running the attached script. Bart.
#!/bin/bash show_state() { local a dev=$1 for a in device/state queue/scheduler; do [ -e "$dev/$a" ] && grep -aH . "$dev/$a" done } if [ -e /sys/kernel/debug/block ]; then devs=($(cd /sys/kernel/debug/block && echo ./*)) else devs=($(cd /sys/class/block && echo ./*)) fi cd /sys/class/block || exit $? for dev in "${devs[@]}"; do dev="${dev#./}" echo "$dev" pending=0 if [ -e "$dev/mq" ]; then for f in "$dev"/mq/*/{pending,*/rq_list}; do [ -e "$f" ] || continue if { read -r line1 && read -r line2; } <"$f"; then echo "$f" echo "$line1 $line2" >/dev/null head -n 9 "$f" ((pending++)) fi done fi ( busy=0 cd /sys/kernel/debug/block >&/dev/null && { grep -aH . $dev/requeue_list; true; } && for d in "$dev"/mq/hctx* "$dev"/hctx*; do [ ! -d "$d" ] && continue { [ ! -e "$d/tags" ] || grep -q '^busy=0$' "$d/tags"; } && { [ ! -e "$d/sched_tags" ] || [ "$(<"$d/sched_tags")" = "" ] || grep -q '^busy=0$' "$d/sched_tags"; } && continue ((busy++)) for f in "$d"/{active,busy,dispatch,flags,requeue_list,sched_tags,state,tags*,cpu*/rq_list,sched/*rqs}; do [ -e "$f" ] && grep -aH . "$f" done done exit $busy ) pending=$((pending+$?)) if [ "$pending" -gt 0 ]; then ( cd /sys/kernel/debug/block >&/dev/null && if [ -e "$dev/mq/state" ]; then grep -aH . "$dev/mq/state" else grep -aH . "$dev/state" fi ) show_state "$dev" fi done