aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk/printk.c
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.cz>2014-06-04 19:11:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-04 19:54:16 -0400
commit0a581694ab7a5bc083d710df8a552a6a055b005f (patch)
treee0d7f4644f3c4cd2c0b69cafaeac2aa39c15c053 /kernel/printk/printk.c
parentb300a4ea665f7fa44f015616ac1874deca891c5e (diff)
printk: split code for making free space in the log buffer
The check for free space in the log buffer always passes when "first_seq" and "next_seq" are equal. In theory, it might cause writing outside of the log buffer. Fortunately, the current usage looks safe because the used "text" and "dict" buffers are quite limited. See the second patch for more details. Anyway, it is better to be on the safe side and add a check. An easy solution is done in the 2nd patch and it is improved in the 4th patch. 5th patch fixes the computation of the printed message length. 1st and 3rd patches just do some code refactoring to make the other patches easier. This patch (of 5): There will be needed some fixes in the check for free space. They will be easier if the code is moved outside of the quite long log_store() function. This patch does not change the existing behavior. Signed-off-by: Petr Mladek <pmladek@suse.cz> Cc: Jan Kara <jack@suse.cz> Cc: Jiri Kosina <jkosina@suse.cz> Cc: Kay Sievers <kay@vrfy.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/printk/printk.c')
-rw-r--r--kernel/printk/printk.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 221229cf0190..99b7a2d87b6a 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -297,6 +297,34 @@ static u32 log_next(u32 idx)
297 return idx + msg->len; 297 return idx + msg->len;
298} 298}
299 299
300/* check whether there is enough free space for the given message */
301static int logbuf_has_space(u32 msg_size)
302{
303 u32 free;
304
305 if (log_next_idx > log_first_idx)
306 free = max(log_buf_len - log_next_idx, log_first_idx);
307 else
308 free = log_first_idx - log_next_idx;
309
310 /*
311 * We need space also for an empty header that signalizes wrapping
312 * of the buffer.
313 */
314 return free >= msg_size + sizeof(struct printk_log);
315}
316
317static void log_make_free_space(u32 msg_size)
318{
319 while (log_first_seq < log_next_seq) {
320 if (logbuf_has_space(msg_size))
321 return;
322 /* drop old messages until we have enough continuous space */
323 log_first_idx = log_next(log_first_idx);
324 log_first_seq++;
325 }
326}
327
300/* insert record into the buffer, discard old ones, update heads */ 328/* insert record into the buffer, discard old ones, update heads */
301static void log_store(int facility, int level, 329static void log_store(int facility, int level,
302 enum log_flags flags, u64 ts_nsec, 330 enum log_flags flags, u64 ts_nsec,
@@ -311,21 +339,7 @@ static void log_store(int facility, int level,
311 pad_len = (-size) & (LOG_ALIGN - 1); 339 pad_len = (-size) & (LOG_ALIGN - 1);
312 size += pad_len; 340 size += pad_len;
313 341
314 while (log_first_seq < log_next_seq) { 342 log_make_free_space(size);
315 u32 free;
316
317 if (log_next_idx > log_first_idx)
318 free = max(log_buf_len - log_next_idx, log_first_idx);
319 else
320 free = log_first_idx - log_next_idx;
321
322 if (free >= size + sizeof(struct printk_log))
323 break;
324
325 /* drop old messages until we have enough contiuous space */
326 log_first_idx = log_next(log_first_idx);
327 log_first_seq++;
328 }
329 343
330 if (log_next_idx + size + sizeof(struct printk_log) > log_buf_len) { 344 if (log_next_idx + size + sizeof(struct printk_log) > log_buf_len) {
331 /* 345 /*