printk: ringbuffer: Skip non-finalized records in panic
[linux-2.6-block.git] / kernel / printk / printk_ringbuffer.c
index 24b484c221e89b43572a41c6833d962139a17695..88e8f3a61922913a280c51737184a44d005916bc 100644 (file)
@@ -2099,6 +2099,10 @@ try_again:
  *
  * On failure @seq is updated to a record that is not yet available to the
  * reader, but it will be the next record available to the reader.
+ *
+ * Note: When the current CPU is in panic, this function will skip over any
+ *       non-existent/non-finalized records in order to allow the panic CPU
+ *       to print any and all records that have been finalized.
  */
 static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
                            struct printk_record *r, unsigned int *line_count)
@@ -2121,8 +2125,28 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
                        (*seq)++;
 
                } else {
-                       /* Non-existent/non-finalized record. Must stop. */
-                       return false;
+                       /*
+                        * Non-existent/non-finalized record. Must stop.
+                        *
+                        * For panic situations it cannot be expected that
+                        * non-finalized records will become finalized. But
+                        * there may be other finalized records beyond that
+                        * need to be printed for a panic situation. If this
+                        * is the panic CPU, skip this
+                        * non-existent/non-finalized record unless it is
+                        * at or beyond the head, in which case it is not
+                        * possible to continue.
+                        *
+                        * Note that new messages printed on panic CPU are
+                        * finalized when we are here. The only exception
+                        * might be the last message without trailing newline.
+                        * But it would have the sequence number returned
+                        * by "prb_next_reserve_seq() - 1".
+                        */
+                       if (this_cpu_in_panic() && ((*seq + 1) < prb_next_reserve_seq(rb)))
+                               (*seq)++;
+                       else
+                               return false;
                }
        }