lkml.org 
[lkml]   [2019]   [Mar]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRe: [RFC PATCH v1 19/25] printk: introduce emergency messages
    Date
    On 2019-03-08, Petr Mladek <pmladek@suse.com> wrote:
    >>> +static bool console_can_emergency(int level)
    >>> +{
    >>> + struct console *con;
    >>> +
    >>> + for_each_console(con) {
    >>> + if (!(con->flags & CON_ENABLED))
    >>> + continue;
    >>> + if (con->write_atomic && level < emergency_console_loglevel)
    >>> + return true;
    >>> + if (con->write && (con->flags & CON_BOOT))
    >>> + return true;
    >>> + }
    >>> + return false;
    >>> +}
    >>> +
    >>> +static void call_emergency_console_drivers(int level, const char *text,
    >>> + size_t text_len)
    >>> +{
    >>> + struct console *con;
    >>> +
    >>> + for_each_console(con) {
    >>> + if (!(con->flags & CON_ENABLED))
    >>> + continue;
    >>> + if (con->write_atomic && level < emergency_console_loglevel) {
    >>> + con->write_atomic(con, text, text_len);
    >>> + continue;
    >>> + }
    >>> + if (con->write && (con->flags & CON_BOOT)) {
    >>> + con->write(con, text, text_len);
    >>> + continue;
    >>> + }
    >>> + }
    >>> +}
    >>> +
    >>> +static void printk_emergency(char *buffer, int level, u64 ts_nsec, u16 cpu,
    >>> + char *text, u16 text_len)
    >>> +{
    >>> + struct printk_log msg;
    >>> + size_t prefix_len;
    >>> +
    >>> + if (!console_can_emergency(level))
    >>> + return;
    >>> +
    >>> + msg.level = level;
    >>> + msg.ts_nsec = ts_nsec;
    >>> + msg.cpu = cpu;
    >>> + msg.facility = 0;
    >>> +
    >>> + /* "text" must have PREFIX_MAX preceding bytes available */
    >>> +
    >>> + prefix_len = print_prefix(&msg,
    >>> + console_msg_format & MSG_FORMAT_SYSLOG,
    >>> + printk_time, buffer);
    >>> + /* move the prefix forward to the beginning of the message text */
    >>> + text -= prefix_len;
    >>> + memmove(text, buffer, prefix_len);
    >>> + text_len += prefix_len;
    >>> +
    >>> + text[text_len++] = '\n';
    >>> +
    >>> + call_emergency_console_drivers(level, text, text_len);
    >>
    >> So this iterates the console list and calls consoles' callbacks, but
    >> what prevents console driver to be rmmod-ed under us?
    >>
    >> CPU0 CPU1
    >>
    >> printk_emergency() rmmod netcon
    >> call_emergency_console_drivers()
    >> con_foo->flags & CON_ENABLED == 1
    >> unregister_console(con_foo)
    >> con_foo->flags &= ~CON_ENABLED
    >> __exit // con_foo gone ?
    >> con_foo->write()
    >>
    >> We use console_lock()/console_trylock() in order to protect the list
    >> and console drivers; but this brings scheduler to the picture, with
    >> all its locks.
    >
    > Great catch!

    Yes, thanks!

    > I think that it is doable to guard the list using RCU.

    I think it would be enough to take the prb_cpulock when modifying the
    console linked list. That will keep printk_emergency() out until the
    list has been updated. (registering/unregistering consoles is not
    something that happens often.)

    John Ogness

    \
     
     \ /
      Last update: 2019-03-11 13:05    [W:7.065 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site