@@ -3134,6 +3134,99 @@ static inline void printk_kthreads_check_locked(void) { }
31343134
31353135#endif /* CONFIG_PRINTK */
31363136
3137+
3138+ /*
3139+ * Print out one record for each console.
3140+ *
3141+ * @do_cond_resched is set by the caller. It can be true only in schedulable
3142+ * context.
3143+ *
3144+ * @next_seq is set to the sequence number after the last available record.
3145+ * The value is valid only when there is at least one usable console and all
3146+ * usable consoles were flushed.
3147+ *
3148+ * @handover will be set to true if a printk waiter has taken over the
3149+ * console_lock, in which case the caller is no longer holding the
3150+ * console_lock. Otherwise it is set to false.
3151+ *
3152+ * @any_usable will be set to true if there are any usable consoles.
3153+ *
3154+ * Returns true when there was at least one usable console and a record was
3155+ * flushed. A returned false indicates there were no records to flush for any
3156+ * of the consoles. It may also indicate that there were no usable consoles,
3157+ * the context has been lost or there is a panic suitation. Regardless the
3158+ * reason, the caller should assume it is not useful to immediately try again.
3159+ *
3160+ * Requires the console_lock.
3161+ */
3162+ static bool console_flush_one_record (bool do_cond_resched , u64 * next_seq , bool * handover ,
3163+ bool * any_usable )
3164+ {
3165+ struct console_flush_type ft ;
3166+ bool any_progress = false;
3167+ struct console * con ;
3168+ int cookie ;
3169+
3170+ printk_get_console_flush_type (& ft );
3171+
3172+ cookie = console_srcu_read_lock ();
3173+ for_each_console_srcu (con ) {
3174+ short flags = console_srcu_read_flags (con );
3175+ u64 printk_seq ;
3176+ bool progress ;
3177+
3178+ /*
3179+ * console_flush_one_record() is only responsible for
3180+ * nbcon consoles when the nbcon consoles cannot print via
3181+ * their atomic or threaded flushing.
3182+ */
3183+ if ((flags & CON_NBCON ) && (ft .nbcon_atomic || ft .nbcon_offload ))
3184+ continue ;
3185+
3186+ if (!console_is_usable (con , flags , !do_cond_resched ))
3187+ continue ;
3188+ * any_usable = true;
3189+
3190+ if (flags & CON_NBCON ) {
3191+ progress = nbcon_legacy_emit_next_record (con , handover , cookie ,
3192+ !do_cond_resched );
3193+ printk_seq = nbcon_seq_read (con );
3194+ } else {
3195+ progress = console_emit_next_record (con , handover , cookie );
3196+ printk_seq = con -> seq ;
3197+ }
3198+
3199+ /*
3200+ * If a handover has occurred, the SRCU read lock
3201+ * is already released.
3202+ */
3203+ if (* handover )
3204+ return false;
3205+
3206+ /* Track the next of the highest seq flushed. */
3207+ if (printk_seq > * next_seq )
3208+ * next_seq = printk_seq ;
3209+
3210+ if (!progress )
3211+ continue ;
3212+ any_progress = true;
3213+
3214+ /* Allow panic_cpu to take over the consoles safely. */
3215+ if (panic_on_other_cpu ())
3216+ goto abandon ;
3217+
3218+ if (do_cond_resched )
3219+ cond_resched ();
3220+ }
3221+ console_srcu_read_unlock (cookie );
3222+
3223+ return any_progress ;
3224+
3225+ abandon :
3226+ console_srcu_read_unlock (cookie );
3227+ return false;
3228+ }
3229+
31373230/*
31383231 * Print out all remaining records to all consoles.
31393232 *
@@ -3159,77 +3252,24 @@ static inline void printk_kthreads_check_locked(void) { }
31593252 */
31603253static bool console_flush_all (bool do_cond_resched , u64 * next_seq , bool * handover )
31613254{
3162- struct console_flush_type ft ;
31633255 bool any_usable = false;
3164- struct console * con ;
31653256 bool any_progress ;
3166- int cookie ;
31673257
31683258 * next_seq = 0 ;
31693259 * handover = false;
31703260
31713261 do {
3172- any_progress = false;
3262+ any_progress = console_flush_one_record (do_cond_resched , next_seq , handover ,
3263+ & any_usable );
31733264
3174- printk_get_console_flush_type (& ft );
3175-
3176- cookie = console_srcu_read_lock ();
3177- for_each_console_srcu (con ) {
3178- short flags = console_srcu_read_flags (con );
3179- u64 printk_seq ;
3180- bool progress ;
3265+ if (* handover )
3266+ return false;
31813267
3182- /*
3183- * console_flush_all() is only responsible for nbcon
3184- * consoles when the nbcon consoles cannot print via
3185- * their atomic or threaded flushing.
3186- */
3187- if ((flags & CON_NBCON ) && (ft .nbcon_atomic || ft .nbcon_offload ))
3188- continue ;
3189-
3190- if (!console_is_usable (con , flags , !do_cond_resched ))
3191- continue ;
3192- any_usable = true;
3193-
3194- if (flags & CON_NBCON ) {
3195- progress = nbcon_legacy_emit_next_record (con , handover , cookie ,
3196- !do_cond_resched );
3197- printk_seq = nbcon_seq_read (con );
3198- } else {
3199- progress = console_emit_next_record (con , handover , cookie );
3200- printk_seq = con -> seq ;
3201- }
3202-
3203- /*
3204- * If a handover has occurred, the SRCU read lock
3205- * is already released.
3206- */
3207- if (* handover )
3208- return false;
3209-
3210- /* Track the next of the highest seq flushed. */
3211- if (printk_seq > * next_seq )
3212- * next_seq = printk_seq ;
3213-
3214- if (!progress )
3215- continue ;
3216- any_progress = true;
3217-
3218- /* Allow panic_cpu to take over the consoles safely. */
3219- if (panic_on_other_cpu ())
3220- goto abandon ;
3221-
3222- if (do_cond_resched )
3223- cond_resched ();
3224- }
3225- console_srcu_read_unlock (cookie );
3268+ if (panic_on_other_cpu ())
3269+ return false;
32263270 } while (any_progress );
32273271
32283272 return any_usable ;
3229-
3230- abandon :
3231- console_srcu_read_unlock (cookie );
3232- return false;
32333273}
32343274
32353275static void __console_flush_and_unlock (void )
0 commit comments