There is a block of code in brelse() that for some write errors will clear the error and call bdirty() as a way to retry failed writes. This code was introduced 20 years ago:
r43043 | dg | 1999-01-22 00:59:05 -0800 (Fri, 22 Jan 1999) | 7 lines
Don't throw away the buffer contents on a fatal write error; just mark
the buffer as still being dirty. This isn't a perfect solution, but
throwing away the buffer contents will often result in filesystem
corruption and this solution will at least correctly deal with transient
errors.
Submitted by: Kirk McKusick <mckusick@mckusick.com>
At the time, this was a convenient way to handle transient failures when the underlying disk drivers were not very good about retrying operations. Since then, the CAM layer was written, and it has much better retry logic, so this code in brelse() is no longer needed for its original purpose. Further, this redirtying in brelse() does not currently handle B_PAGING buffers correctly and results in panics like this:
panic: cannot reassign paging buffer
cpuid = 22
time = 1521247837
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe257f51e160
vpanic() at vpanic+0x19c/frame 0xfffffe257f51e1e0
panic() at panic+0x43/frame 0xfffffe257f51e240
reassignbuf() at reassignbuf+0x273/frame 0xfffffe257f51e280
bdirty() at bdirty+0x2e/frame 0xfffffe257f51e2a0
brelse() at brelse+0x110/frame 0xfffffe257f51e300
bufdone() at bufdone+0x87/frame 0xfffffe257f51e320
g_io_deliver() at g_io_deliver+0x202/frame 0xfffffe257f51e380
g_io_deliver() at g_io_deliver+0x202/frame 0xfffffe257f51e3e0
g_disk_done() at g_disk_done+0x122/frame 0xfffffe257f51e430
bioq_flush() at bioq_flush+0x87/frame 0xfffffe257f51e460
cam_iosched_fini() at cam_iosched_fini+0x4b/frame 0xfffffe257f51e480
adacleanup() at adacleanup+0x56/frame 0xfffffe257f51e4b0
cam_periph_release_locked_buses() at cam_periph_release_locked_buses+0xa7/frame 0xfffffe257f51e9c0
cam_periph_release_locked() at cam_periph_release_locked+0x1b/frame 0xfffffe257f51e9e0
xpt_done_process() at xpt_done_process+0x68d/frame 0xfffffe257f51ea20
xpt_done_td() at xpt_done_td+0x186/frame 0xfffffe257f51ea70
fork_exit() at fork_exit+0x82/frame 0xfffffe257f51eab0
fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe257f51eab0
So the best way to fix the B_PAGING problem with this code is to simply remove it. This patch does exactly that.