Messages in this thread | | | Subject | Re: [PATCH v3] printk: Have printk() never buffer its data | From | Joe Perches <> | Date | Wed, 27 Jun 2012 22:00:14 -0700 |
| |
On Thu, 2012-06-28 at 09:38 +0200, Kay Sievers wrote: > Here we share the continuation buffer with the console copy logic, > and partial lines are always immediately flushed to the available > consoles. They are still buffered internally to improve the > readability and integrity of the messages and minimize the amount > of needed record headers to store.
trivia:
> diff --git a/kernel/printk.c b/kernel/printk.c
> @@ -329,8 +337,13 @@ static void log_store(int facility, int level, > msg->text_len = text_len; > memcpy(log_dict(msg), dict, dict_len); > msg->dict_len = dict_len; > - msg->level = (facility << 3) | (level & 7); > - msg->ts_nsec = local_clock(); > + msg->facility = facility; > + msg->level = level & 7;
Doesn't need & 7
> + msg->flags = flags & 0x1f; > + if (ts_nsec > 0) > + msg->ts_nsec = ts_nsec; > + else > + msg->ts_nsec = local_clock();
Why local_clock? ts_nsec really can be 0. []
> @@ -1294,15 +1311,92 @@ static inline void printk_delay(void) > } > } > > +/* > + * Continuation lines are buffered, and not committed to the record buffer > + * until the line is complete, or a race forces it. The line fragments > + * though, are printed immediately to the consoles to ensure everything has > + * reached the console in case of a kernel crash. > + */ > +static struct cont { > + char buf[LOG_LINE_MAX]; > + size_t len; /* length == 0 means unused buffer */ > + size_t cons; /* bytes written to console */ > + struct task_struct *owner; /* task of first print*/ > + u64 ts_nsec; /* time of first print */ > + u8 level; /* log level of first message */ > + u8 facility; /* log level of first message */ > + bool flushed:1; /* buffer sealed and committed */
bool flushed:1 seems unnecessary. bool flushed seems more appropriate.
> +} cont; > + > +static void cont_flush(void) > +{ > + if (cont.flushed) > + return; > + if (cont.len == 0) > + return; > + > + log_store(cont.facility, cont.level, LOG_NOCONS, cont.ts_nsec, > + NULL, 0, cont.buf, cont.len); > + > + cont.flushed = true; > +} > + > +static bool cont_add(int facility, int level, const char *text, size_t len) > +{ > + if (cont.len && cont.flushed) > + return false; > + > + if (cont.len + len > sizeof(cont.buf)) { > + cont_flush(); > + return false; > + } > + > + if (!cont.len) { > + cont.facility = facility; > + cont.level = level; > + cont.owner = current; > + cont.ts_nsec = local_clock(); > + cont.cons = 0; > + cont.flushed = false; > + } > + > + memcpy(cont.buf + cont.len, text, len);
Looks like you can still overrun cont.buf.
| |