mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Petr Mladek <pmladek@suse.com>
To: Matteo Croce <mcroce@linux.microsoft.com>
Cc: linux-kernel@vger.kernel.org, Mike Rapoport <rppt@kernel.org>,
	Guenter Roeck <linux@roeck-us.net>, Arnd Bergmann <arnd@arndb.de>,
	Pavel Tatashin <pasha.tatashin@soleen.com>,
	Kees Cook <keescook@chromium.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Tyler Hicks <tyhicks@linux.microsoft.com>
Subject: Re: [PATCH v2] reboot: allow to specify reboot mode via sysfs
Date: Mon, 9 Nov 2020 15:16:28 +0100	[thread overview]
Message-ID: <20201109141628.GL1602@alley> (raw)
In-Reply-To: <20201106200704.192894-1-mcroce@linux.microsoft.com>

On Fri 2020-11-06 21:07:04, Matteo Croce wrote:
> From: Matteo Croce <mcroce@microsoft.com>
> 
> The kernel cmdline reboot= option offers some sort of control
> on how the reboot is issued.
> Add handles in sysfs to allow setting these reboot options, so they
> can be changed when the system is booted, other than at boot time.
> 
> The handlers are under <sysfs>/kernel/reboot, can be read to
> get the current configuration and written to alter it.
> 
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-kernel-reboot
> @@ -0,0 +1,26 @@
> +What:		/sys/kernel/reboot
> +Date:		October 2020
> +KernelVersion:	5.11
> +Contact:	Matteo Croce <mcroce@microsoft.com>
> +Description:	Interface to set the kernel reboot mode, similarly to
> +		what can be done via the reboot= cmdline option.
> +		(see Documentation/admin-guide/kernel-parameters.txt)
> +
> +What:		/sys/kernel/reboot/mode
> +What:		/sys/kernel/reboot/type
> +What:		/sys/kernel/reboot/cpu
> +What:		/sys/kernel/reboot/force

I do not see any file where it is accumulated this way.
It seems that each path is always described separately.

I am not sure if it is really needed. But it might be needed
when processing the API documentation.

Please, split it.


> +
> +Date:		October 2020
> +Contact:	Matteo Croce <mcroce@microsoft.com>
> +Description:	Tune reboot parameters.
> +
> +		mode: Reboot mode. Valid values are:
> +		cold warm hard soft gpio
> +
> +		type: Reboot type. Valid values are:
> +		bios acpi kbd triple efi pci
> +
> +		cpu: CPU number to use to reboot.
> +
> +		force: Force an immediate reboot.
> diff --git a/kernel/reboot.c b/kernel/reboot.c
> index e7b78d5ae1ab..b9e607517ae3 100644
> --- a/kernel/reboot.c
> +++ b/kernel/reboot.c
> @@ -594,3 +594,196 @@ static int __init reboot_setup(char *str)
>  	return 1;
>  }
>  __setup("reboot=", reboot_setup);
> +
> +#ifdef CONFIG_SYSFS
> +
> +#define STARTS_WITH(s, sc) (!strncmp(s, sc, sizeof(sc)-1))
> +
> +static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> +{
> +	const char *val;
> +
> +	switch (reboot_mode) {
> +	case REBOOT_COLD:
> +		val = "cold\n";

Using "\n" everywhere is weird. Also the same strings are
repeated in the next functions.

I suggest to define them only once, e.g.

#define REBOOT_COLD_STR "cold"
#define REBOOT_WARM_STR "warm"

and use here:

	case REBOOT_COLD:
		val = REBOOT_COLD_STR;

and then at the end

	return sprintf(buf, "%s\n", val);


> +		break;
> +	case REBOOT_WARM:
> +		val = "warm\n";
> +		break;
> +	case REBOOT_HARD:
> +		val = "hard\n";
> +		break;
> +	case REBOOT_SOFT:
> +		val = "soft\n";
> +		break;
> +	case REBOOT_GPIO:
> +		val = "gpio\n";
> +		break;
> +	default:
> +		val = "undefined\n";
> +	}
> +
> +	return strscpy(buf, val, 10);

"undefined\n" needs 11 bytes to store also the trailing '\0'.
Anyway, the buffer should be big enough for all variants.


> +}
> +static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr,
> +			  const char *buf, size_t count)
> +{
> +	if (!capable(CAP_SYS_BOOT))
> +		return -EPERM;
> +
> +	if (STARTS_WITH(buf, "cold"))
> +		reboot_mode = REBOOT_COLD;

I would prefer to open code this and use strlen(). It will be obvious
what the code does immediately. And I am sure that compilators
will optimize out the strlen().


	if (strncmp(buf, REBOOT_COLD_STR, strlen(REBOOT_COLD_STR)) == 0)
		reboot_mode = REBOOT_COLD;
	else if (strncmp(buf, REBOOT_WARM_STR, strlen(REBOOT_WARM_STR) == 0)
		reboot_mode = REBOOT_WARM;
	...



> +	else if (STARTS_WITH(buf, "warm"))
> +		reboot_mode = REBOOT_WARM;
> +	else if (STARTS_WITH(buf, "hard"))
> +		reboot_mode = REBOOT_HARD;
> +	else if (STARTS_WITH(buf, "soft"))
> +		reboot_mode = REBOOT_SOFT;
> +	else if (STARTS_WITH(buf, "gpio"))
> +		reboot_mode = REBOOT_GPIO;
> +	else
> +		return -EINVAL;
> +
> +	return count;
> +}
> +static struct kobj_attribute reboot_mode_attr = __ATTR_RW(mode);
> +
> +static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> +{
> +	const char *val;
> +
> +	switch (reboot_type) {
> +	case BOOT_TRIPLE:
> +		val = "triple\n";

Same here

		var = BOOT_TRIPLE_STR;

> +		break;
> +	case BOOT_KBD:
> +		val = "kbd\n";
> +		break;
> +	case BOOT_BIOS:
> +		val = "bios\n";
> +		break;
> +	case BOOT_ACPI:
> +		val = "acpi\n";
> +		break;
> +	case BOOT_EFI:
> +		val = "efi\n";
> +		break;
> +	case BOOT_CF9_FORCE:
> +		val = "cf9_force\n";
> +		break;
> +	case BOOT_CF9_SAFE:
> +		val = "cf9_safe\n";
> +		break;
> +	default:
> +		val = "undefined\n";
> +	}
> +
> +	return strscpy(buf, val, 10);
> +}
> +static ssize_t type_store(struct kobject *kobj, struct kobj_attribute *attr,
> +			  const char *buf, size_t count)
> +{
> +	if (!capable(CAP_SYS_BOOT))
> +		return -EPERM;
> +
> +	if (STARTS_WITH(buf, "triple"))
> +		reboot_type = BOOT_TRIPLE;

and here:

	if (strncmp(buf, REBOOT_TRIPLE_STR, strlen(REBOOT_TRIPLE_STR)) == 0)
		reboot_type = REBOOT_TRIPLE;


> +	else if (STARTS_WITH(buf, "kbd"))
> +		reboot_type = BOOT_KBD;
> +	else if (STARTS_WITH(buf, "bios"))
> +		reboot_type = BOOT_BIOS;
> +	else if (STARTS_WITH(buf, "acpi"))
> +		reboot_type = BOOT_ACPI;
> +	else if (STARTS_WITH(buf, "efi"))
> +		reboot_type = BOOT_EFI;
> +	else if (STARTS_WITH(buf, "cf9_force"))
> +		reboot_type = BOOT_CF9_FORCE;
> +	else if (STARTS_WITH(buf, "cf9_safe"))
> +		reboot_type = BOOT_CF9_SAFE;
> +	else
> +		return -EINVAL;
> +
> +	return count;
> +}
> +static struct kobj_attribute reboot_type_attr = __ATTR_RW(type);
> +
> +static ssize_t force_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> +{
> +	return sprintf(buf, "%d\n", reboot_force);
> +}
> +static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
> +			  const char *buf, size_t count)
> +{
> +	if (!capable(CAP_SYS_BOOT))
> +		return -EPERM;
> +
> +	if (buf[0] != '0' && buf[0] != '1')
> +		return -EINVAL;

Please use kstrtobool() that supports also other boolean values,
for example, 'Y', 'n'.

> +	rc = kstrtouint(buf, 0, &cpunum);
> +
> +	reboot_force = buf[0] - '0';
> +
> +	return count;
> +}

> +static int __init reboot_ksysfs_init(void)
> +{
> +	struct kobject *reboot_kobj;
> +	int ret;
> +
> +	reboot_kobj = kobject_create_and_add("reboot", kernel_kobj);
> +	if (!reboot_kobj)
> +		return -ENOMEM;
> +
> +	ret = sysfs_create_group(reboot_kobj, &reboot_attr_group);
> +	if (ret) {
> +		kobject_put(reboot_kobj);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +core_initcall(reboot_ksysfs_init);

There is no need to create the sysfs interface this early. In fact, it
might even break because the parent "kernel" node is defined
as core_initcall() as well. The order is not defined in this case.

I would do it as sybsys_initcall() like or even late_initcall().

Best Regards,
Petr

  parent reply	other threads:[~2020-11-09 14:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-06 20:07 Matteo Croce
2020-11-06 22:33 ` Andrew Morton
2020-11-06 23:19   ` Matteo Croce
2020-11-09 14:16 ` Petr Mladek [this message]
2020-11-09 15:03   ` Matteo Croce

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=20201109141628.GL1602@alley \
    --to=pmladek@suse.com \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=mcroce@linux.microsoft.com \
    --cc=pasha.tatashin@soleen.com \
    --cc=rppt@kernel.org \
    --cc=tyhicks@linux.microsoft.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®