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
52 int nextcount;52 int nextcount;
53 unsigned long *oops_page_used;53 unsigned long *oops_page_used;
54 54
55 unsigned long oops_buf_busy;
55 void *oops_buf;56 void *oops_buf;
56} oops_cxt;57} oops_cxt;
57 58
@@ -180,6 +181,9 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic) · 122 unmodified lines
180 u32 *hdr;181 u32 *hdr;
181 int ret;182 int ret;
182 183
184 if (test_and_set_bit(0, &cxt->oops_buf_busy))
185 return;
186
183 /* Add mtdoops header to the buffer */187 /* Add mtdoops header to the buffer */
184 hdr = cxt->oops_buf;188 hdr = cxt->oops_buf;
185 hdr[0] = cxt->nextcount;189 hdr[0] = cxt->nextcount;
@@ -190,7 +194,7 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic) · 4 unmodified lines
190 record_size, &retlen, cxt->oops_buf);194 record_size, &retlen, cxt->oops_buf);
191 if (ret == -EOPNOTSUPP) {195 if (ret == -EOPNOTSUPP) {
192 printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");196 printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
193 return;197 goto out;
194 }198 }
195 } else199 } else
196 ret = mtd_write(mtd, cxt->nextpage * record_size,200 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
203 memset(cxt->oops_buf, 0xff, record_size);207 memset(cxt->oops_buf, 0xff, record_size);
204 208
205 mtdoops_inc_counter(cxt);209 mtdoops_inc_counter(cxt);
210out:
211 clear_bit(0, &cxt->oops_buf_busy);
206}212}
207 213
208static void mtdoops_workfunc_write(struct work_struct *work)214static void mtdoops_workfunc_write(struct work_struct *work)
@@ -276,8 +282,11 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper, · 67 unmodified lines
276 if (reason == KMSG_DUMP_OOPS && !dump_oops)282 if (reason == KMSG_DUMP_OOPS && !dump_oops)
277 return;283 return;
278 284
285 if (test_and_set_bit(0, &cxt->oops_buf_busy))
286 return;
279 kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,287 kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,
280 record_size - MTDOOPS_HEADER_SIZE, NULL);288 record_size - MTDOOPS_HEADER_SIZE, NULL);
289 clear_bit(0, &cxt->oops_buf_busy);
281 290
282 if (reason != KMSG_DUMP_OOPS) {291 if (reason != KMSG_DUMP_OOPS) {
283 /* Panics must be written immediately */292 /* Panics must be written immediately */
@@ -394,6 +403,7 @@ static int __init mtdoops_init(void) · 110 unmodified lines
394 return -ENOMEM;403 return -ENOMEM;
395 }404 }
396 memset(cxt->oops_buf, 0xff, record_size);405 memset(cxt->oops_buf, 0xff, record_size);
406 cxt->oops_buf_busy = 0;
397 407
398 INIT_WORK(&cxt->work_erase, mtdoops_workfunc_erase);408 INIT_WORK(&cxt->work_erase, mtdoops_workfunc_erase);
399 INIT_WORK(&cxt->work_write, mtdoops_workfunc_write);409 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