Skip to content

mmc: block: Fix pending_writes underflow on non-CQE hosts#7508

Open
mairacanal wants to merge 1 commit into
raspberrypi:rpi-6.18.yfrom
mairacanal:mmc/fix-underflow
Open

mmc: block: Fix pending_writes underflow on non-CQE hosts#7508
mairacanal wants to merge 1 commit into
raspberrypi:rpi-6.18.yfrom
mairacanal:mmc/fix-underflow

Conversation

@mairacanal

Copy link
Copy Markdown
Contributor

The posted-write accounting mirrors in_flight[], but on the plain blk-mq completion path (hosts with neither CQE nor HSQ) pending_writes is decremented twice per write: once in mmc_blk_mq_complete_rq() and again in mmc_blk_mq_dec_in_flight(). Both run for a single request, since mmc_blk_mq_post_req() first triggers the .complete callback via blk_mq_complete_request() and then calls mmc_blk_mq_dec_in_flight(). As in_flight[] is only decremented in the latter, pending_writes drifts one below in_flight[] for every completed write and underflows.

This stayed hidden on the CQE/HSQ hosts the feature targets, where completion goes solely through mmc_blk_cqe_complete_rq() and decrements once. It surfaces on plain-mq hosts such as the bcm2835-sdhost, tripping the WARN_ON_ONCE() on the first write once the rootfs is remounted read-write:

  ------------[ cut here ]------------
  WARNING: CPU: 0 PID: 84 at drivers/mmc/core/queue.c:350 mmc_mq_queue_rq+0x2a0/0x2f8
  Modules linked in: sch_fq_codel uinput i2c_dev zram lz4_compress fuse drm drm_panel_orientation_quirks backlight nfnetlink ipv6 libsha1
  CPU: 0 UID: 0 PID: 84 Comm: kworker/0:1H Not tainted 6.18.38-v8-tile-alloc-256-32+ #15 PREEMPT
  Hardware name: Raspberry Pi 3 Model B Plus Rev 1.3 (DT)
  Workqueue: kblockd blk_mq_requeue_work
  pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
  pc : mmc_mq_queue_rq+0x2a0/0x2f8
  lr : mmc_mq_queue_rq+0x284/0x2f8
  Call trace:
   mmc_mq_queue_rq+0x2a0/0x2f8 (P)
   blk_mq_dispatch_rq_list+0x2c8/0x718
   __blk_mq_sched_dispatch_requests+0xec/0x570
   blk_mq_sched_dispatch_requests+0x3c/0x88
   blk_mq_run_hw_queue+0xf4/0x128
   blk_mq_run_hw_queues+0xc4/0x140
   blk_mq_requeue_work+0x188/0x1c0
   process_scheduled_works+0x180/0x3d0
   worker_thread+0x268/0x3e8
   kthread+0x140/0x250
   ret_from_fork+0x10/0x20
  ---[ end trace 0000000000000000 ]---

Decrement pending_writes only where in_flight[] is decremented, dropping the redundant decrement in mmc_blk_mq_complete_rq() so the counter tracks in_flight[] exactly. The CQE path is unaffected.


I found this warning while booting my Raspberry Pi 3B+ from a SD card. The warning appears during the system boot and bring up and it appears to be harmless, that is: I was able to boot normally even with the warning. However, while investigating the origins of the warning, I found this refcount issue. After this patch, the warning no longer appears.

Let me know your thoughts.

The posted-write accounting mirrors in_flight[], but on the plain blk-mq
completion path (hosts with neither CQE nor HSQ) pending_writes is
decremented twice per write: once in mmc_blk_mq_complete_rq() and again
in mmc_blk_mq_dec_in_flight(). Both run for a single request, since
mmc_blk_mq_post_req() first triggers the .complete callback via
blk_mq_complete_request() and then calls mmc_blk_mq_dec_in_flight().
As in_flight[] is only decremented in the latter, pending_writes drifts
one below in_flight[] for every completed write and underflows.

This stayed hidden on the CQE/HSQ hosts the feature targets, where
completion goes solely through mmc_blk_cqe_complete_rq() and decrements
once. It surfaces on plain-mq hosts such as the bcm2835-sdhost, tripping
the WARN_ON_ONCE() on the first write once the rootfs is remounted
read-write:

  ------------[ cut here ]------------
  WARNING: CPU: 0 PID: 84 at drivers/mmc/core/queue.c:350 mmc_mq_queue_rq+0x2a0/0x2f8
  Modules linked in: sch_fq_codel uinput i2c_dev zram lz4_compress fuse drm drm_panel_orientation_quirks backlight nfnetlink ipv6 libsha1
  CPU: 0 UID: 0 PID: 84 Comm: kworker/0:1H Not tainted 6.18.38-v8-tile-alloc-256-32+ raspberrypi#15 PREEMPT
  Hardware name: Raspberry Pi 3 Model B Plus Rev 1.3 (DT)
  Workqueue: kblockd blk_mq_requeue_work
  pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
  pc : mmc_mq_queue_rq+0x2a0/0x2f8
  lr : mmc_mq_queue_rq+0x284/0x2f8
  Call trace:
   mmc_mq_queue_rq+0x2a0/0x2f8 (P)
   blk_mq_dispatch_rq_list+0x2c8/0x718
   __blk_mq_sched_dispatch_requests+0xec/0x570
   blk_mq_sched_dispatch_requests+0x3c/0x88
   blk_mq_run_hw_queue+0xf4/0x128
   blk_mq_run_hw_queues+0xc4/0x140
   blk_mq_requeue_work+0x188/0x1c0
   process_scheduled_works+0x180/0x3d0
   worker_thread+0x268/0x3e8
   kthread+0x140/0x250
   ret_from_fork+0x10/0x20
  ---[ end trace 0000000000000000 ]---

Decrement pending_writes only where in_flight[] is decremented, dropping
the redundant decrement in mmc_blk_mq_complete_rq() so the counter tracks
in_flight[] exactly. The CQE path is unaffected.

Fixes: e6c1e86 ("mmc: restrict posted write counts for SD cards in CQ mode")
Signed-off-by: Maíra Canal <mcanal@igalia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant