All of lore.kernel.org
 help / color / mirror / Atom feed
From: Petr Mladek <pmladek@suse.com>
To: Calvin Owens <calvinowens@fb.com>
Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	linux-api@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, kernel-team@fb.com,
	Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: Re: [PATCH 2/3] printk: Add /sys/consoles/ interface
Date: Fri, 3 Nov 2017 15:21:14 +0100	[thread overview]
Message-ID: <20171103142114.GG31148@pathway.suse.cz> (raw)
In-Reply-To: <afd350e1157ed3f31d37597d3c2ee5d9d5cfd30d.1506644730.git.calvinowens@fb.com>

On Thu 2017-09-28 17:43:56, Calvin Owens wrote:
> This adds a new sysfs interface that contains a directory for each
> console registered on the system. Each directory contains a single
> "loglevel" file for reading and setting the per-console loglevel.
> 
> We can let kobject destruction race with console removal: if it does,
> loglevel_{show,store}() will safely fail with -ENODEV. This is a little
> weird, but avoids embedding the kobject and therefore needing to totally
> refactor the way we handle console struct lifetime.

It looks like a sane approach. It might be worth a comment in the code.


>  Documentation/ABI/testing/sysfs-consoles | 13 +++++
>  include/linux/console.h                  |  1 +
>  kernel/printk/printk.c                   | 88 ++++++++++++++++++++++++++++++++
>  3 files changed, 102 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-consoles
> 
> diff --git a/Documentation/ABI/testing/sysfs-consoles b/Documentation/ABI/testing/sysfs-consoles
> new file mode 100644
> index 0000000..6a1593e
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-consoles
> @@ -0,0 +1,13 @@
> +What:		/sys/consoles/

I rather add Greg in CC. I am not 100% sure that the top level
directory is the right thing to do.

Alternative might be to hide this under /sys/kernel/consoles/.


> +Date:		September 2017
> +KernelVersion:	4.15
> +Contact:	Calvin Owens <calvinowens@fb.com>
> +Description:	The /sys/consoles tree contains a directory for each console
> +		configured on the system. These directories contain the
> +		following attributes:
> +
> +		* "loglevel"	Set the per-console loglevel: the kernel uses
> +				max(system_loglevel, perconsole_loglevel) when
> +				deciding whether to emit a given message. The
> +				default is 0, which means max() always yields
> +				the system setting in the kernel.printk sysctl.

I would call the attribute "min_loglevel". The name "loglevel" should
be reserved for the really used loglevel that depends also on the
global loglevel value.


> diff --git a/include/linux/console.h b/include/linux/console.h
> index a5b5d79..76840be 100644
> --- a/include/linux/console.h
> +++ b/include/linux/console.h
> @@ -148,6 +148,7 @@ struct console {
>  	void	*data;
>  	struct	 console *next;
>  	int	level;
> +	struct kobject *kobj;
>  };
>  
>  /*
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index 3f1675e..488bda3 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -105,6 +105,8 @@ enum devkmsg_log_masks {
>  
>  static unsigned int __read_mostly devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT;
>  
> +static struct kobject *consoles_dir_kobj;
>
>  static int __control_devkmsg(char *str)
>  {
>  	if (!str)
> @@ -2371,6 +2373,82 @@ static int __init keep_bootcon_setup(char *str)
>  
>  early_param("keep_bootcon", keep_bootcon_setup);
>  
> +static ssize_t loglevel_show(struct kobject *kobj, struct kobj_attribute *attr,
> +			     char *buf)
> +{
> +	struct console *con;
> +	ssize_t ret = -ENODEV;
> +

This might deserve a comment. Something like:

	/*
	 * Find the related struct console a safe way. The kobject
	 * desctruction is asynchronous.
	 */
> +	console_lock();
> +	for_each_console(con) {
> +		if (con->kobj == kobj) {
> +			ret = sprintf(buf, "%d\n", con->level);
> +			break;
> +		}
> +	}
> +	console_unlock();
> +
> +	return ret;
> +}
> +
> +static ssize_t loglevel_store(struct kobject *kobj, struct kobj_attribute *attr,
> +			      const char *buf, size_t count)
> +{
> +	struct console *con;
> +	ssize_t ret;
> +	int tmp;

I would use some meaningful name, e.g. new_level ;-)

> +	ret = kstrtoint(buf, 10, &tmp);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (tmp < LOGLEVEL_EMERG)
> +		return -ERANGE;
> +
> +	/*
> +	 * Mimic the behavior of /dev/kmsg with respect to minimum_loglevel
> +	 */
> +	if (tmp < minimum_console_loglevel)
> +		tmp = minimum_console_loglevel;

Hmm, I would remove this "mimic" stuff. minimum_console_loglevel is currently
used to limit operations by the syslog system call. But root is still
able modify the minimum_console_loglevel by writing into
/proc/sys/kernel/printk.

My plan is that /sys/console interface would eventually replace the
crazy /proc/sys/kernel/printk one.

In each case, the default con->level value is zero. It would be
weird if people were not able to set this value.

> +
> +	ret = -ENODEV;

I would repeat the same comment here:

	/*
	 * Find the related struct console a safe way. The kobject
	 * desctruction is asynchronous.
	 */

> +	console_lock();
> +	for_each_console(con) {
> +		if (con->kobj == kobj) {
> +			con->level = tmp;
> +			ret = count;
> +			break;
> +		}
> +	}
> +	console_unlock();
> +
> +	return ret;
> +}
> +
> +static const struct kobj_attribute console_loglevel_attr =
> +	__ATTR(loglevel, 0644, loglevel_show, loglevel_store);
> +
> +static void console_register_sysfs(struct console *newcon)
> +{
Please, add a sanity check to make sure that this API is used the
right way.

	if (WARN_ON(newcon->kobj))
		return;

> +	/*
> +	 * We might be called very early from register_console(): in that case,
> +	 * printk_late_init() will take care of this later.
> +	 */
> +	if (!consoles_dir_kobj)
> +		return;
> +
> +	newcon->kobj = kobject_create_and_add(newcon->name, consoles_dir_kobj);
> +	if (WARN_ON(!newcon->kobj))

I would just return in case of error. The error messages from
kobject_create_and_add() should be enough and actually more useful.

> +		return;
> +
> +	WARN_ON(sysfs_create_file(newcon->kobj, &console_loglevel_attr.attr));

Similar here. Well, I would destroy the kobject if the sysfs file
cannot be created:

       if (sysfs_create_file(newcon->kobj, &console_loglevel_attr.attr))
	       console_unregister_sysfs(newcon);

> +}
> +
> +static void console_unregister_sysfs(struct console *oldcon)
> +{
> +	kobject_put(oldcon->kobj);

We need to make that the carefull access in the show()/store() methods work.

	oldcon->kobj = NULL;

> +}
> +
>  /*
>   * The console driver calls this routine during kernel initialization
>   * to register the console printing procedure with printk() and to
> @@ -2495,6 +2573,7 @@ void register_console(struct console *newcon)
>  	 * By default, the per-console minimum forces no messages through.
>  	 */
>  	newcon->level = LOGLEVEL_EMERG;
> +	newcon->kobj = NULL;

IMHO, we do not need this. The pointer should already be NULL.

>  	/*
>  	 *	Put this console in the list - keep the
> @@ -2531,6 +2610,7 @@ void register_console(struct console *newcon)
>  		 */
>  		exclusive_console = newcon;
>  	}
> +	console_register_sysfs(newcon);
>  	console_unlock();
>  	console_sysfs_notify();
>  
> @@ -2597,6 +2677,7 @@ int unregister_console(struct console *console)
>  		console_drivers->flags |= CON_CONSDEV;
>  
>  	console->flags &= ~CON_ENABLED;
> +	console_unregister_sysfs(console);
>  	console_unlock();
>  	console_sysfs_notify();
>  	return res;
> @@ -2672,6 +2753,13 @@ static int __init printk_late_init(void)
>  	ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "printk:online",
>  					console_cpu_notify, NULL);
>  	WARN_ON(ret < 0);
> +
> +	consoles_dir_kobj = kobject_create_and_add("consoles", NULL);
> +	WARN_ON(!consoles_dir_kobj);

Again, I would just return in case of error.

> +	for_each_console(con)
> +		console_register_sysfs(con);
> +
>  	return 0;

Best Regards,
Petr

  reply	other threads:[~2017-11-03 14:21 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-29  0:43 [PATCH 1/3] printk: Introduce per-console loglevel setting Calvin Owens
2017-09-29  0:43 ` Calvin Owens
     [not found] ` <08c1dc1a96afd6b6aecc5ff3c7c0e62c36670893.1506644730.git.calvinowens-b10kYP2dOMg@public.gmane.org>
2017-09-29  0:43   ` [PATCH 2/3] printk: Add /sys/consoles/ interface Calvin Owens
2017-09-29  0:43     ` Calvin Owens
2017-11-03 14:21     ` Petr Mladek [this message]
2017-11-03 14:32       ` Kroah-Hartman
2017-11-03 15:46         ` Petr Mladek
     [not found]           ` <20171103154651.GJ20040-KsEp0d+Q8qECVLCxKZUutA@public.gmane.org>
2017-11-03 15:58             ` Kroah-Hartman
2017-11-03 15:58               ` Kroah-Hartman
     [not found]         ` <20171103143234.GA7801-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2017-11-08 21:32           ` Calvin Owens
2017-11-08 21:32             ` Calvin Owens
     [not found]             ` <519f471b-47dc-3367-f702-119a9d82ba9b-b10kYP2dOMg@public.gmane.org>
2017-11-09  8:03               ` Kroah-Hartman
2017-11-09  8:03                 ` Kroah-Hartman
2017-09-29  0:43 ` [PATCH 3/3] printk: Add ability to set loglevel via "console=" cmdline Calvin Owens
2017-09-29  0:43   ` Calvin Owens
2017-11-03 15:15   ` Petr Mladek
2017-10-19 23:40 ` [PATCH 1/3] printk: Introduce per-console loglevel setting Calvin Owens
2017-10-19 23:40   ` Calvin Owens
2017-10-20  8:05   ` Petr Mladek
     [not found]     ` <20171020080501.GD29163-KsEp0d+Q8qECVLCxKZUutA@public.gmane.org>
2017-10-20 17:33       ` Calvin Owens
2017-10-20 17:33         ` Calvin Owens
2017-11-03 12:00 ` Petr Mladek
2017-11-03 13:41   ` Steven Rostedt
2018-10-19  0:04 ` Sergey Senozhatsky
2018-10-19 22:03   ` Calvin Owens
2018-10-22  2:37     ` Sergey Senozhatsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171103142114.GG31148@pathway.suse.cz \
    --to=pmladek@suse.com \
    --cc=calvinowens@fb.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=kernel-team@fb.com \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=sergey.senozhatsky@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.