Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: mtdoops: panic caused mtdoops to call mtdoops_erase function immediately

The panic function disables the local interrupts, preemption, and all
other processors. When the invoked mtdoops needs to erase a used page,
calling schedule_work() to do it will not work. Instead, just call
mtdoops_erase function immediately.

Tested:
~# echo c > /proc/sysrq-trigger
[ 171.654759] sysrq: Trigger a crash
[ 171.658325] Kernel panic - not syncing: sysrq triggered crash
......
[ 172.406423] mtdoops: not ready 34, 35 (erase immediately)
[ 172.432285] mtdoops: ready 34, 35
[ 172.435633] Rebooting in 10 seconds..

Signed-off-by: Ray Zhang <sgzhang@google.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20221010045549.2221965-4-sgzhang@google.com

authored by

Ray Zhang and committed by
Miquel Raynal
7cc84e0e 340193e0

+16 -8
+16 -8
drivers/mtd/mtdoops.c
··· 170 170 mtdoops_erase(cxt); 171 171 } 172 172 173 - static void mtdoops_inc_counter(struct mtdoops_context *cxt) 173 + static void mtdoops_inc_counter(struct mtdoops_context *cxt, int panic) 174 174 { 175 175 cxt->nextpage++; 176 176 if (cxt->nextpage >= cxt->oops_pages) ··· 180 180 cxt->nextcount = 0; 181 181 182 182 if (page_is_used(cxt, cxt->nextpage)) { 183 - schedule_work(&cxt->work_erase); 184 - return; 183 + pr_debug("not ready %d, %d (erase %s)\n", 184 + cxt->nextpage, cxt->nextcount, 185 + panic ? "immediately" : "scheduled"); 186 + if (panic) { 187 + /* In case of panic, erase immediately */ 188 + mtdoops_erase(cxt); 189 + } else { 190 + /* Otherwise, schedule work to erase it "nicely" */ 191 + schedule_work(&cxt->work_erase); 192 + } 193 + } else { 194 + pr_debug("ready %d, %d (no erase)\n", 195 + cxt->nextpage, cxt->nextcount); 185 196 } 186 - 187 - pr_debug("ready %d, %d (no erase)\n", 188 - cxt->nextpage, cxt->nextcount); 189 197 } 190 198 191 199 static void mtdoops_write(struct mtdoops_context *cxt, int panic) ··· 229 221 mark_page_used(cxt, cxt->nextpage); 230 222 memset(cxt->oops_buf, 0xff, record_size); 231 223 232 - mtdoops_inc_counter(cxt); 224 + mtdoops_inc_counter(cxt, panic); 233 225 out: 234 226 clear_bit(0, &cxt->oops_buf_busy); 235 227 } ··· 294 286 cxt->nextcount = maxcount; 295 287 } 296 288 297 - mtdoops_inc_counter(cxt); 289 + mtdoops_inc_counter(cxt, 0); 298 290 } 299 291 300 292 static void mtdoops_do_dump(struct kmsg_dumper *dumper,