Commit cfe2790b authored by John Ogness's avatar John Ogness Committed by Petr Mladek

printk: move printk_info into separate array

The majority of the size of a descriptor is taken up by meta data,
which is often not of interest to the ringbuffer (for example,
when performing state checks). Since descriptors are often
temporarily stored on the stack, keeping their size minimal will
help reduce stack pressure.

Rather than embedding the printk_info into the descriptor, create
a separate printk_info array. The index of a descriptor in the
descriptor array corresponds to the printk_info with the same
index in the printk_info array. The rules for validity of a
printk_info match the existing rules for the data blocks: the
descriptor must be in a consistent state.
Signed-off-by: default avatarJohn Ogness <john.ogness@linutronix.de>
Reviewed-by: default avatarPetr Mladek <pmladek@suse.com>
Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20200918223421.21621-2-john.ogness@linutronix.de
parent f5f022e5
......@@ -959,11 +959,11 @@ void log_buf_vmcoreinfo_setup(void)
VMCOREINFO_STRUCT_SIZE(prb_desc_ring);
VMCOREINFO_OFFSET(prb_desc_ring, count_bits);
VMCOREINFO_OFFSET(prb_desc_ring, descs);
VMCOREINFO_OFFSET(prb_desc_ring, infos);
VMCOREINFO_OFFSET(prb_desc_ring, head_id);
VMCOREINFO_OFFSET(prb_desc_ring, tail_id);
VMCOREINFO_STRUCT_SIZE(prb_desc);
VMCOREINFO_OFFSET(prb_desc, info);
VMCOREINFO_OFFSET(prb_desc, state_var);
VMCOREINFO_OFFSET(prb_desc, text_blk_lpos);
VMCOREINFO_OFFSET(prb_desc, dict_blk_lpos);
......@@ -1097,11 +1097,13 @@ static char setup_dict_buf[CONSOLE_EXT_LOG_MAX] __initdata;
void __init setup_log_buf(int early)
{
struct printk_info *new_infos;
unsigned int new_descs_count;
struct prb_desc *new_descs;
struct printk_info info;
struct printk_record r;
size_t new_descs_size;
size_t new_infos_size;
unsigned long flags;
char *new_dict_buf;
char *new_log_buf;
......@@ -1142,8 +1144,7 @@ void __init setup_log_buf(int early)
if (unlikely(!new_dict_buf)) {
pr_err("log_buf_len: %lu dict bytes not available\n",
new_log_buf_len);
memblock_free(__pa(new_log_buf), new_log_buf_len);
return;
goto err_free_log_buf;
}
new_descs_size = new_descs_count * sizeof(struct prb_desc);
......@@ -1151,9 +1152,15 @@ void __init setup_log_buf(int early)
if (unlikely(!new_descs)) {
pr_err("log_buf_len: %zu desc bytes not available\n",
new_descs_size);
memblock_free(__pa(new_dict_buf), new_log_buf_len);
memblock_free(__pa(new_log_buf), new_log_buf_len);
return;
goto err_free_dict_buf;
}
new_infos_size = new_descs_count * sizeof(struct printk_info);
new_infos = memblock_alloc(new_infos_size, LOG_ALIGN);
if (unlikely(!new_infos)) {
pr_err("log_buf_len: %zu info bytes not available\n",
new_infos_size);
goto err_free_descs;
}
prb_rec_init_rd(&r, &info,
......@@ -1163,7 +1170,8 @@ void __init setup_log_buf(int early)
prb_init(&printk_rb_dynamic,
new_log_buf, ilog2(new_log_buf_len),
new_dict_buf, ilog2(new_log_buf_len),
new_descs, ilog2(new_descs_count));
new_descs, ilog2(new_descs_count),
new_infos);
logbuf_lock_irqsave(flags);
......@@ -1192,6 +1200,14 @@ void __init setup_log_buf(int early)
pr_info("log_buf_len: %u bytes\n", log_buf_len);
pr_info("early log buf free: %u(%u%%)\n",
free, (free * 100) / __LOG_BUF_LEN);
return;
err_free_descs:
memblock_free(__pa(new_descs), new_descs_size);
err_free_dict_buf:
memblock_free(__pa(new_dict_buf), new_log_buf_len);
err_free_log_buf:
memblock_free(__pa(new_log_buf), new_log_buf_len);
}
static bool __read_mostly ignore_loglevel;
......
This diff is collapsed.
......@@ -58,7 +58,6 @@ struct prb_data_blk_lpos {
* @state_var: A bitwise combination of descriptor ID and descriptor state.
*/
struct prb_desc {
struct printk_info info;
atomic_long_t state_var;
struct prb_data_blk_lpos text_blk_lpos;
struct prb_data_blk_lpos dict_blk_lpos;
......@@ -76,6 +75,7 @@ struct prb_data_ring {
struct prb_desc_ring {
unsigned int count_bits;
struct prb_desc *descs;
struct printk_info *infos;
atomic_long_t head_id;
atomic_long_t tail_id;
};
......@@ -237,30 +237,32 @@ enum desc_state {
static char _##name##_dict[1U << ((avgdictbits) + (descbits))] \
__aligned(__alignof__(unsigned long)); \
static struct prb_desc _##name##_descs[_DESCS_COUNT(descbits)] = { \
/* the initial head and tail */ \
[_DESCS_COUNT(descbits) - 1] = { \
/* reusable */ \
.state_var = ATOMIC_INIT(DESC0_SV(descbits)), \
/* no associated data block */ \
.text_blk_lpos = FAILED_BLK_LPOS, \
.dict_blk_lpos = FAILED_BLK_LPOS, \
}, \
}; \
static struct printk_info _##name##_infos[_DESCS_COUNT(descbits)] = { \
/* this will be the first record reserved by a writer */ \
[0] = { \
.info = { \
/* will be incremented to 0 on the first reservation */ \
.seq = -(u64)_DESCS_COUNT(descbits), \
}, \
}, \
/* the initial head and tail */ \
[_DESCS_COUNT(descbits) - 1] = { \
.info = { \
/* reports the first seq value during the bootstrap phase */ \
.seq = 0, \
}, \
/* reusable */ \
.state_var = ATOMIC_INIT(DESC0_SV(descbits)), \
/* no associated data block */ \
.text_blk_lpos = FAILED_BLK_LPOS, \
.dict_blk_lpos = FAILED_BLK_LPOS, \
}, \
}; \
static struct printk_ringbuffer name = { \
.desc_ring = { \
.count_bits = descbits, \
.descs = &_##name##_descs[0], \
.infos = &_##name##_infos[0], \
.head_id = ATOMIC_INIT(DESC0_ID(descbits)), \
.tail_id = ATOMIC_INIT(DESC0_ID(descbits)), \
}, \
......@@ -336,7 +338,8 @@ void prb_final_commit(struct prb_reserved_entry *e);
void prb_init(struct printk_ringbuffer *rb,
char *text_buf, unsigned int text_buf_size,
char *dict_buf, unsigned int dict_buf_size,
struct prb_desc *descs, unsigned int descs_count_bits);
struct prb_desc *descs, unsigned int descs_count_bits,
struct printk_info *infos);
unsigned int prb_record_text_space(struct prb_reserved_entry *e);
/* Reader Interface */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment