History

mtd: mtdoops: synchronize kmsg_dumper

The kmsg_dumper can be called from any context and CPU, possibly from multiple CPUs simultaneously. Since the writing of the buffer can occur from a later scheduled work queue, the oops buffer must be protected against simultaneous dumping. Use an atomic bit to mark when the buffer is protected. Release the protection in between setting the buffer and the actual writing in order for a possible panic (immediate write) to be written during the scheduling of a previous oops (delayed write). An atomic bit (rather than a spinlock) was chosen so that no scheduling or preemption side-effects would be introduced. The MTD kmsg_dumper may dump directly or it may be delayed (via scheduled work). Depending on the context, different MTD callbacks are used. For example, mtd_write() expects to be called in a non-atomic context and may take a mutex.

John Ogness committed 5 years ago

Commit 40ddbba1 parent fdd2c1f1 file · +11 −1Browse files

Unified · Split

drivers/mtd/mtdoops.c+11−1
@@ -52,6 +52,7 @@ static struct mtdoops_context { · 51 unmodified lines
5252 int nextcount;
5353 unsigned long *oops_page_used;
5454
55+ unsigned long oops_buf_busy;
5556 void *oops_buf;
5657 } oops_cxt;
5758
@@ -180,6 +181,9 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic) · 122 unmodified lines
180181 u32 *hdr;
181182 int ret;
182183
184+ if (test_and_set_bit(0, &cxt->oops_buf_busy))
185+ return;
186+
183187 /* Add mtdoops header to the buffer */
184188 hdr = cxt->oops_buf;
185189 hdr[0] = cxt->nextcount;
@@ -190,7 +194,7 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic) · 4 unmodified lines
190194 record_size, &retlen, cxt->oops_buf);
191195 if (ret == -EOPNOTSUPP) {
192196 printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
193− return;
197+ goto out;
194198 }
195199 } else
196200 ret = mtd_write(mtd, cxt->nextpage * record_size,
@@ -203,6 +207,8 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic) · 6 unmodified lines
203207 memset(cxt->oops_buf, 0xff, record_size);
204208
205209 mtdoops_inc_counter(cxt);
210+out:
211+ clear_bit(0, &cxt->oops_buf_busy);
206212 }
207213
208214 static void mtdoops_workfunc_write(struct work_struct *work)
@@ -276,8 +282,11 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper, · 67 unmodified lines
276282 if (reason == KMSG_DUMP_OOPS && !dump_oops)
277283 return;
278284
285+ if (test_and_set_bit(0, &cxt->oops_buf_busy))
286+ return;
279287 kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,
280288 record_size - MTDOOPS_HEADER_SIZE, NULL);
289+ clear_bit(0, &cxt->oops_buf_busy);
281290
282291 if (reason != KMSG_DUMP_OOPS) {
283292 /* Panics must be written immediately */
@@ -394,6 +403,7 @@ static int __init mtdoops_init(void) · 110 unmodified lines
394403 return -ENOMEM;
395404 }
396405 memset(cxt->oops_buf, 0xff, record_size);
406+ cxt->oops_buf_busy = 0;
397407
398408 INIT_WORK(&cxt->work_erase, mtdoops_workfunc_erase);
399409 INIT_WORK(&cxt->work_write, mtdoops_workfunc_write);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t