Messages in this thread Patch in this message | | | From | Qiujun Huang <> | Subject | [PATCH]pstore/zone: Preallocate zone buffer for psz_kmsg_write_record | Date | Wed, 28 Dec 2022 21:04:32 +0800 |
| |
The case found when triggering a panic_on_oom, pstore fails to dump kmsg. Partly fixed by: commit 99b3b837855b ("pstore/zone: Use GFP_ATOMIC to allocate zone buffer"). After the patch, it also fails sometimes. As I use 64k as kmsg_size, it's hard to get 4-order free pages sometimes at this case. So it's better to preallocate the buffer.
Signed-off-by: Qiujun Huang <hqjagain@gmail.com> --- fs/pstore/zone.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c index 2770746bb7aa..86e47dbc9d53 100644 --- a/fs/pstore/zone.c +++ b/fs/pstore/zone.c @@ -136,6 +136,7 @@ struct psz_context { struct mutex pstore_zone_info_lock; struct pstore_zone_info *pstore_zone_info; struct pstore_info pstore; + struct psz_buffer *kmsg_buf_swap; }; static struct psz_context pstore_zone_cxt;
@@ -758,14 +759,11 @@ static inline int notrace psz_kmsg_write_record(struct psz_context *cxt, if (unlikely(!zone)) return -ENOSPC;
- /* avoid destroying old data, allocate a new one */ + /* avoid destroying old data, use the swap buffer */ len = zone->buffer_size + sizeof(*zone->buffer); zone->oldbuf = zone->buffer; - zone->buffer = kzalloc(len, GFP_ATOMIC); - if (!zone->buffer) { - zone->buffer = zone->oldbuf; - return -ENOMEM; - } + zone->buffer = cxt->kmsg_buf_swap; + memset(zone->buffer, 0, len); zone->buffer->sig = zone->oldbuf->sig;
pr_debug("write %s to zone id %d\n", zone->name, zonenum); @@ -776,15 +774,14 @@ static inline int notrace psz_kmsg_write_record(struct psz_context *cxt, if (likely(!ret || ret != -ENOMSG)) { cxt->kmsg_write_cnt = zonenum + 1; cxt->kmsg_write_cnt %= cxt->kmsg_max_cnt; - /* no need to try next zone, free last zone buffer */ - kfree(zone->oldbuf); + /* no need to try next zone, put last one to swap buffer */ + cxt->kmsg_buf_swap = zone->oldbuf; zone->oldbuf = NULL; return ret; }
pr_debug("zone %u may be broken, try next dmesg zone\n", zonenum); - kfree(zone->buffer); zone->buffer = zone->oldbuf; zone->oldbuf = NULL; } @@ -1373,6 +1370,12 @@ int register_pstore_zone(struct pstore_zone_info *info) err = -ENOMEM; goto fail_free; } + + cxt->kmsg_buf_swap = kzalloc(info->kmsg_size, GFP_KERNEL); + if (!cxt->kmsg_buf_swap) { + err = -ENOMEM; + goto fail_free; + } } cxt->pstore.data = cxt;
@@ -1411,6 +1414,8 @@ int register_pstore_zone(struct pstore_zone_info *info) return 0;
fail_free: + kfree(cxt->kmsg_buf_swap); + cxt->kmsg_buf_swap = NULL; kfree(cxt->pstore.buf); cxt->pstore.buf = NULL; cxt->pstore.bufsize = 0; @@ -1445,6 +1450,9 @@ void unregister_pstore_zone(struct pstore_zone_info *info) flush_delayed_work(&psz_cleaner);
/* Clean up allocations. */ + kfree(cxt->kmsg_buf_swap); + cxt->kmsg_buf_swap = NULL; + kfree(cxt->pstore.buf); cxt->pstore.buf = NULL; cxt->pstore.bufsize = 0; -- 2.30.2
| |