Driver core changes for 6.8-rc1

Here are the set of driver core and kernfs changes for 6.8-rc1.  Nothing
 major in here this release cycle, just lots of small cleanups and some
 tweaks on kernfs that in the very end, got reverted and will come back
 in a safer way next release cycle.
 
 Included in here are:
   - more driver core 'const' cleanups and fixes
   - fw_devlink=rpm is now the default behavior
   - kernfs tiny changes to remove some string functions
   - cpu handling in the driver core is updated to work better on many
     systems that add topologies and cpus after booting
   - other minor changes and cleanups
 
 All of the cpu handling patches have been acked by the respective
 maintainers and are coming in here in one series.  Everything has been
 in linux-next for a while with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZaeOrg8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ymtcwCffzvKKkSY9qAp6+0v2WQNkZm1JWoAoJCPYUwF
 If6wEoPLWvRfKx4gIoq9
 =D96r
 -----END PGP SIGNATURE-----

Merge tag 'driver-core-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core updates from Greg KH:
 "Here are the set of driver core and kernfs changes for 6.8-rc1.
  Nothing major in here this release cycle, just lots of small cleanups
  and some tweaks on kernfs that in the very end, got reverted and will
  come back in a safer way next release cycle.

  Included in here are:

   - more driver core 'const' cleanups and fixes

   - fw_devlink=rpm is now the default behavior

   - kernfs tiny changes to remove some string functions

   - cpu handling in the driver core is updated to work better on many
     systems that add topologies and cpus after booting

   - other minor changes and cleanups

  All of the cpu handling patches have been acked by the respective
  maintainers and are coming in here in one series. Everything has been
  in linux-next for a while with no reported issues"

* tag 'driver-core-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (51 commits)
  Revert "kernfs: convert kernfs_idr_lock to an irq safe raw spinlock"
  kernfs: convert kernfs_idr_lock to an irq safe raw spinlock
  class: fix use-after-free in class_register()
  PM: clk: make pm_clk_add_notifier() take a const pointer
  EDAC: constantify the struct bus_type usage
  kernfs: fix reference to renamed function
  driver core: device.h: fix Excess kernel-doc description warning
  driver core: class: fix Excess kernel-doc description warning
  driver core: mark remaining local bus_type variables as const
  driver core: container: make container_subsys const
  driver core: bus: constantify subsys_register() calls
  driver core: bus: make bus_sort_breadthfirst() take a const pointer
  kernfs: d_obtain_alias(NULL) will do the right thing...
  driver core: Better advertise dev_err_probe()
  kernfs: Convert kernfs_path_from_node_locked() from strlcpy() to strscpy()
  kernfs: Convert kernfs_name_locked() from strlcpy() to strscpy()
  kernfs: Convert kernfs_walk_ns() from strlcpy() to strscpy()
  initramfs: Expose retained initrd as sysfs file
  fs/kernfs/dir: obey S_ISGID
  kernel/cgroup: use kernfs_create_dir_ns()
  ...
This commit is contained in:
Linus Torvalds 2024-01-18 09:48:40 -08:00
commit 80955ae955
51 changed files with 207 additions and 253 deletions

View File

@ -0,0 +1,8 @@
What: /sys/firmware/initrd
Date: December 2023
Contact: Alexander Graf <graf@amazon.com>
Description:
When the kernel was booted with an initrd and the
"retain_initrd" option is set on the kernel command
line, /sys/firmware/initrd contains the contents of the
initrd that the kernel was booted with.

View File

@ -2449,7 +2449,7 @@
between unregistering the boot console and initializing
the real console.
keepinitrd [HW,ARM]
keepinitrd [HW,ARM] See retain_initrd.
kernelcore= [KNL,X86,IA-64,PPC]
Format: nn[KMGTPE] | nn% | "mirror"
@ -5604,7 +5604,8 @@
Useful for devices that are detected asynchronously
(e.g. USB and MMC devices).
retain_initrd [RAM] Keep initrd memory after extraction
retain_initrd [RAM] Keep initrd memory after extraction. After boot, it will
be accessible via /sys/firmware/initrd.
retbleed= [X86] Control mitigation of RETBleed (Arbitrary
Speculative Code Execution with Return Instructions)

View File

@ -133,6 +133,7 @@ config ARM64
select GENERIC_ARCH_TOPOLOGY
select GENERIC_CLOCKEVENTS_BROADCAST
select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_DEVICES
select GENERIC_CPU_VULNERABILITIES
select GENERIC_EARLY_IOREMAP
select GENERIC_IDLE_POLL_SETUP

View File

@ -38,7 +38,6 @@ struct cpuinfo_32bit {
};
struct cpuinfo_arm64 {
struct cpu cpu;
struct kobject kobj;
u64 reg_ctr;
u64 reg_cntfrq;

View File

@ -402,20 +402,11 @@ static inline bool cpu_can_disable(unsigned int cpu)
return false;
}
static int __init topology_init(void)
bool arch_cpu_is_hotpluggable(int num)
{
int i;
for_each_possible_cpu(i) {
struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
cpu->hotpluggable = cpu_can_disable(i);
register_cpu(cpu, i);
return cpu_can_disable(num);
}
return 0;
}
subsys_initcall(topology_init);
static void dump_kernel_offset(void)
{
const unsigned long offset = kaslr_offset();

View File

@ -5,6 +5,7 @@ config LOONGARCH
select ACPI
select ACPI_GENERIC_GSI if ACPI
select ACPI_MCFG if ACPI
select ACPI_HOTPLUG_CPU if ACPI_PROCESSOR && HOTPLUG_CPU
select ACPI_PPTT if ACPI
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
select ARCH_BINFMT_ELF_STATE
@ -71,6 +72,7 @@ config LOONGARCH
select GENERIC_CLOCKEVENTS
select GENERIC_CMOS_UPDATE
select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_DEVICES
select GENERIC_ENTRY
select GENERIC_GETTIMEOFDAY
select GENERIC_IOREMAP if !ARCH_IOREMAP

View File

@ -10,47 +10,9 @@
#include <acpi/processor.h>
static DEFINE_PER_CPU(struct cpu, cpu_devices);
#ifdef CONFIG_HOTPLUG_CPU
int arch_register_cpu(int cpu)
bool arch_cpu_is_hotpluggable(int cpu)
{
int ret;
struct cpu *c = &per_cpu(cpu_devices, cpu);
c->hotpluggable = 1;
ret = register_cpu(c, cpu);
if (ret < 0)
pr_warn("register_cpu %d failed (%d)\n", cpu, ret);
return ret;
return !io_master(cpu);
}
EXPORT_SYMBOL(arch_register_cpu);
void arch_unregister_cpu(int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
c->hotpluggable = 0;
unregister_cpu(c);
}
EXPORT_SYMBOL(arch_unregister_cpu);
#endif
static int __init topology_init(void)
{
int i, ret;
for_each_present_cpu(i) {
struct cpu *c = &per_cpu(cpu_devices, i);
c->hotpluggable = !io_master(i);
ret = register_cpu(c, i);
if (ret < 0)
pr_warn("topology_init: register_cpu %d failed (%d)\n", i, ret);
}
return 0;
}
subsys_initcall(topology_init);

View File

@ -72,6 +72,7 @@ config RISCV
select GENERIC_ARCH_TOPOLOGY
select GENERIC_ATOMIC64 if !64BIT
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_CPU_DEVICES
select GENERIC_EARLY_IOREMAP
select GENERIC_ENTRY
select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO

View File

@ -50,7 +50,6 @@ atomic_t hart_lottery __section(".sdata")
#endif
;
unsigned long boot_cpu_hartid;
static DEFINE_PER_CPU(struct cpu, cpu_devices);
/*
* Place kernel memory regions on the resource tree so that
@ -298,24 +297,11 @@ void __init setup_arch(char **cmdline_p)
riscv_user_isa_enable();
}
static int __init topology_init(void)
bool arch_cpu_is_hotpluggable(int cpu)
{
int i, ret;
for_each_possible_cpu(i) {
struct cpu *cpu = &per_cpu(cpu_devices, i);
cpu->hotpluggable = cpu_has_hotplug(i);
ret = register_cpu(cpu, i);
if (unlikely(ret))
pr_warn("Warning: %s: register_cpu %d failed (%d)\n",
__func__, i, ret);
return cpu_has_hotplug(cpu);
}
return 0;
}
subsys_initcall(topology_init);
void free_initmem(void)
{
if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) {

View File

@ -59,6 +59,7 @@ config X86
#
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
select ACPI_HOTPLUG_CPU if ACPI_PROCESSOR && HOTPLUG_CPU
select ARCH_32BIT_OFF_T if X86_32
select ARCH_CLOCKSOURCE_INIT
select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
@ -148,6 +149,7 @@ config X86
select GENERIC_CLOCKEVENTS_MIN_ADJUST
select GENERIC_CMOS_UPDATE
select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_DEVICES
select GENERIC_CPU_VULNERABILITIES
select GENERIC_EARLY_IOREMAP
select GENERIC_ENTRY

View File

@ -23,10 +23,6 @@ static inline void prefill_possible_map(void) {}
#endif /* CONFIG_SMP */
struct x86_cpu {
struct cpu cpu;
};
#ifdef CONFIG_HOTPLUG_CPU
extern void soft_restart_cpu(void);
#endif

View File

@ -35,38 +35,9 @@
#include <asm/io_apic.h>
#include <asm/cpu.h>
static DEFINE_PER_CPU(struct x86_cpu, cpu_devices);
#ifdef CONFIG_HOTPLUG_CPU
int arch_register_cpu(int cpu)
bool arch_cpu_is_hotpluggable(int cpu)
{
struct x86_cpu *xc = per_cpu_ptr(&cpu_devices, cpu);
xc->cpu.hotpluggable = cpu > 0;
return register_cpu(&xc->cpu, cpu);
}
EXPORT_SYMBOL(arch_register_cpu);
void arch_unregister_cpu(int num)
{
unregister_cpu(&per_cpu(cpu_devices, num).cpu);
}
EXPORT_SYMBOL(arch_unregister_cpu);
#else /* CONFIG_HOTPLUG_CPU */
int __init arch_register_cpu(int num)
{
return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
return cpu > 0;
}
#endif /* CONFIG_HOTPLUG_CPU */
static int __init topology_init(void)
{
int i;
for_each_present_cpu(i)
arch_register_cpu(i);
return 0;
}
subsys_initcall(topology_init);

View File

@ -314,7 +314,6 @@ config ACPI_HOTPLUG_CPU
bool
depends on ACPI_PROCESSOR && HOTPLUG_CPU
select ACPI_CONTAINER
default y
config ACPI_PROCESSOR_AGGREGATOR
tristate "Processor Aggregator"

View File

@ -184,24 +184,6 @@ static void __init acpi_pcc_cpufreq_init(void) {}
/* Initialization */
#ifdef CONFIG_ACPI_HOTPLUG_CPU
int __weak acpi_map_cpu(acpi_handle handle,
phys_cpuid_t physid, u32 acpi_id, int *pcpu)
{
return -ENODEV;
}
int __weak acpi_unmap_cpu(int cpu)
{
return -ENODEV;
}
int __weak arch_register_cpu(int cpu)
{
return -ENODEV;
}
void __weak arch_unregister_cpu(int cpu) {}
static int acpi_processor_hotadd_init(struct acpi_processor *pr)
{
unsigned long long sta;

View File

@ -881,6 +881,7 @@ static struct fwnode_handle *acpi_parse_string_ref(const struct fwnode_handle *f
* @index: Index of the reference to return
* @num_args: Maximum number of arguments after each reference
* @args: Location to store the returned reference with optional arguments
* (may be NULL)
*
* Find property with @name, verifify that it is a package containing at least
* one object reference and if so, store the ACPI device object pointer to the
@ -938,6 +939,9 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
if (!device)
return -EINVAL;
if (!args)
return 0;
args->fwnode = acpi_fwnode_handle(device);
args->nargs = 0;

View File

@ -219,20 +219,34 @@ static DECLARE_WORK(update_topology_flags_work, update_topology_flags_workfn);
static DEVICE_ATTR_RO(cpu_capacity);
static int cpu_capacity_sysctl_add(unsigned int cpu)
{
struct device *cpu_dev = get_cpu_device(cpu);
if (!cpu_dev)
return -ENOENT;
device_create_file(cpu_dev, &dev_attr_cpu_capacity);
return 0;
}
static int cpu_capacity_sysctl_remove(unsigned int cpu)
{
struct device *cpu_dev = get_cpu_device(cpu);
if (!cpu_dev)
return -ENOENT;
device_remove_file(cpu_dev, &dev_attr_cpu_capacity);
return 0;
}
static int register_cpu_capacity_sysctl(void)
{
int i;
struct device *cpu;
for_each_possible_cpu(i) {
cpu = get_cpu_device(i);
if (!cpu) {
pr_err("%s: too early to get CPU%d device!\n",
__func__, i);
continue;
}
device_create_file(cpu, &dev_attr_cpu_capacity);
}
cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "topology/cpu-capacity",
cpu_capacity_sysctl_add, cpu_capacity_sysctl_remove);
return 0;
}

View File

@ -244,7 +244,7 @@ static void auxiliary_bus_shutdown(struct device *dev)
auxdrv->shutdown(auxdev);
}
static struct bus_type auxiliary_bus_type = {
static const struct bus_type auxiliary_bus_type = {
.name = "auxiliary",
.probe = auxiliary_bus_probe,
.remove = auxiliary_bus_remove,

View File

@ -1030,7 +1030,7 @@ static void device_insertion_sort_klist(struct device *a, struct list_head *list
list_move_tail(&a->p->knode_bus.n_node, list);
}
void bus_sort_breadthfirst(struct bus_type *bus,
void bus_sort_breadthfirst(const struct bus_type *bus,
int (*compare)(const struct device *a,
const struct device *b))
{
@ -1194,7 +1194,7 @@ static void system_root_device_release(struct device *dev)
kfree(dev);
}
static int subsys_register(struct bus_type *subsys,
static int subsys_register(const struct bus_type *subsys,
const struct attribute_group **groups,
struct kobject *parent_of_root)
{
@ -1264,7 +1264,7 @@ err_sp:
* directory itself and not some create fake root-device placed in
* /sys/devices/system/<name>.
*/
int subsys_system_register(struct bus_type *subsys,
int subsys_system_register(const struct bus_type *subsys,
const struct attribute_group **groups)
{
return subsys_register(subsys, groups, &system_kset->kobj);
@ -1282,7 +1282,7 @@ EXPORT_SYMBOL_GPL(subsys_system_register);
* There's no restriction on device naming. This is for kernel software
* constructs which need sysfs interface.
*/
int subsys_virtual_register(struct bus_type *subsys,
int subsys_virtual_register(const struct bus_type *subsys,
const struct attribute_group **groups)
{
struct kobject *virtual_dir;

View File

@ -213,6 +213,7 @@ int class_register(const struct class *cls)
return 0;
err_out:
lockdep_unregister_key(key);
kfree(cp);
return error;
}

View File

@ -24,7 +24,7 @@ static int container_offline(struct device *dev)
return cdev->offline ? cdev->offline(cdev) : 0;
}
struct bus_type container_subsys = {
const struct bus_type container_subsys = {
.name = CONTAINER_BUS_NAME,
.dev_name = CONTAINER_BUS_NAME,
.online = trivial_online,

View File

@ -298,7 +298,7 @@ static inline bool device_link_flag_is_sync_state_only(u32 flags)
* Check if @target depends on @dev or any device dependent on it (its child or
* its consumer etc). Return 1 if that is the case or 0 otherwise.
*/
int device_is_dependent(struct device *dev, void *target)
static int device_is_dependent(struct device *dev, void *target)
{
struct device_link *link;
int ret;
@ -1641,7 +1641,7 @@ static void device_links_purge(struct device *dev)
#define FW_DEVLINK_FLAGS_RPM (FW_DEVLINK_FLAGS_ON | \
DL_FLAG_PM_RUNTIME)
static u32 fw_devlink_flags = FW_DEVLINK_FLAGS_ON;
static u32 fw_devlink_flags = FW_DEVLINK_FLAGS_RPM;
static int __init fw_devlink_setup(char *arg)
{
if (!arg)
@ -4944,13 +4944,14 @@ define_dev_printk_level(_dev_info, KERN_INFO);
*
* return dev_err_probe(dev, err, ...);
*
* Note that it is deemed acceptable to use this function for error
* prints during probe even if the @err is known to never be -EPROBE_DEFER.
* Using this helper in your probe function is totally fine even if @err is
* known to never be -EPROBE_DEFER.
* The benefit compared to a normal dev_err() is the standardized format
* of the error code and the fact that the error code is returned.
* of the error code, it being emitted symbolically (i.e. you get "EAGAIN"
* instead of "-35") and the fact that the error code is returned which allows
* more compact error paths.
*
* Returns @err.
*
*/
int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
{

View File

@ -525,19 +525,42 @@ bool cpu_is_hotpluggable(unsigned int cpu)
EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
#ifdef CONFIG_GENERIC_CPU_DEVICES
static DEFINE_PER_CPU(struct cpu, cpu_devices);
#endif
DEFINE_PER_CPU(struct cpu, cpu_devices);
bool __weak arch_cpu_is_hotpluggable(int cpu)
{
return false;
}
int __weak arch_register_cpu(int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
c->hotpluggable = arch_cpu_is_hotpluggable(cpu);
return register_cpu(c, cpu);
}
#ifdef CONFIG_HOTPLUG_CPU
void __weak arch_unregister_cpu(int num)
{
unregister_cpu(&per_cpu(cpu_devices, num));
}
#endif /* CONFIG_HOTPLUG_CPU */
#endif /* CONFIG_GENERIC_CPU_DEVICES */
static void __init cpu_dev_register_generic(void)
{
#ifdef CONFIG_GENERIC_CPU_DEVICES
int i;
int i, ret;
for_each_possible_cpu(i) {
if (register_cpu(&per_cpu(cpu_devices, i), i))
panic("Failed to register CPU device");
if (!IS_ENABLED(CONFIG_GENERIC_CPU_DEVICES))
return;
for_each_present_cpu(i) {
ret = arch_register_cpu(i);
if (ret)
pr_warn("register_cpu %d failed (%d)\n", i, ret);
}
#endif
}
#ifdef CONFIG_GENERIC_CPU_VULNERABILITIES

View File

@ -313,7 +313,7 @@ static void deferred_probe_timeout_work_func(struct work_struct *work)
mutex_lock(&deferred_probe_mutex);
list_for_each_entry(p, &deferred_probe_pending_list, deferred_probe)
dev_info(p->device, "deferred probe pending\n");
dev_info(p->device, "deferred probe pending: %s", p->deferred_probe_reason ?: "(reason unknown)\n");
mutex_unlock(&deferred_probe_mutex);
fw_devlink_probing_done();

View File

@ -35,8 +35,8 @@ void __init driver_init(void)
of_core_init();
platform_bus_init();
auxiliary_bus_init();
cpu_dev_init();
memory_dev_init();
node_dev_init();
cpu_dev_init();
container_dev_init();
}

View File

@ -82,7 +82,7 @@ static int isa_bus_resume(struct device *dev)
return 0;
}
static struct bus_type isa_bus_type = {
static const struct bus_type isa_bus_type = {
.name = "isa",
.match = isa_bus_match,
.probe = isa_bus_probe,

View File

@ -68,7 +68,7 @@ static inline unsigned long phys_to_block_id(unsigned long phys)
static int memory_subsys_online(struct device *dev);
static int memory_subsys_offline(struct device *dev);
static struct bus_type memory_subsys = {
static const struct bus_type memory_subsys = {
.name = MEMORY_CLASS_NAME,
.dev_name = MEMORY_CLASS_NAME,
.online = memory_subsys_online,

View File

@ -21,7 +21,7 @@
#include <linux/swap.h>
#include <linux/slab.h>
static struct bus_type node_subsys = {
static const struct bus_type node_subsys = {
.name = "node",
.dev_name = "node",
};
@ -868,11 +868,15 @@ int __register_one_node(int nid)
{
int error;
int cpu;
struct node *node;
node_devices[nid] = kzalloc(sizeof(struct node), GFP_KERNEL);
if (!node_devices[nid])
node = kzalloc(sizeof(struct node), GFP_KERNEL);
if (!node)
return -ENOMEM;
INIT_LIST_HEAD(&node->access_list);
node_devices[nid] = node;
error = register_node(node_devices[nid], nid);
/* link cpu under this node */
@ -881,7 +885,6 @@ int __register_one_node(int nid)
register_cpu_under_node(cpu, nid);
}
INIT_LIST_HEAD(&node_devices[nid]->access_list);
node_init_caches(nid);
return error;

View File

@ -793,7 +793,7 @@ static int pm_clk_notify(struct notifier_block *nb,
* the remaining members of @clknb should be populated prior to calling this
* routine.
*/
void pm_clk_add_notifier(struct bus_type *bus,
void pm_clk_add_notifier(const struct bus_type *bus,
struct pm_clk_notifier_block *clknb)
{
if (!bus || !clknb)

View File

@ -543,6 +543,7 @@ EXPORT_SYMBOL_GPL(fwnode_property_match_property_string);
* @nargs: Number of arguments. Ignored if @nargs_prop is non-NULL.
* @index: Index of the reference, from zero onwards.
* @args: Result structure with reference and integer arguments.
* May be NULL.
*
* Obtain a reference based on a named property in an fwnode, with
* integer arguments.

View File

@ -28,7 +28,7 @@ struct soc_device {
int soc_dev_num;
};
static struct bus_type soc_bus_type = {
static const struct bus_type soc_bus_type = {
.name = "soc",
};
static bool soc_bus_registered;
@ -106,7 +106,7 @@ static void soc_release(struct device *dev)
{
struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
ida_free(&soc_ida, soc_dev->soc_dev_num);
kfree(soc_dev->dev.groups);
kfree(soc_dev);
}
@ -155,7 +155,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
soc_attr_groups[1] = soc_dev_attr->custom_attr_group;
/* Fetch a unique (reclaimable) SOC ID. */
ret = ida_simple_get(&soc_ida, 0, 0, GFP_KERNEL);
ret = ida_alloc(&soc_ida, GFP_KERNEL);
if (ret < 0)
goto out3;
soc_dev->soc_dev_num = ret;

View File

@ -541,6 +541,9 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
if (nargs > NR_FWNODE_REFERENCE_ARGS)
return -EINVAL;
if (!args)
return 0;
args->fwnode = software_node_get(refnode);
args->nargs = nargs;
@ -747,10 +750,10 @@ static void software_node_release(struct kobject *kobj)
struct swnode *swnode = kobj_to_swnode(kobj);
if (swnode->parent) {
ida_simple_remove(&swnode->parent->child_ids, swnode->id);
ida_free(&swnode->parent->child_ids, swnode->id);
list_del(&swnode->entry);
} else {
ida_simple_remove(&swnode_root_ids, swnode->id);
ida_free(&swnode_root_ids, swnode->id);
}
if (swnode->allocated)
@ -776,8 +779,8 @@ swnode_register(const struct software_node *node, struct swnode *parent,
if (!swnode)
return ERR_PTR(-ENOMEM);
ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids,
0, 0, GFP_KERNEL);
ret = ida_alloc(parent ? &parent->child_ids : &swnode_root_ids,
GFP_KERNEL);
if (ret < 0) {
kfree(swnode);
return ERR_PTR(ret);

View File

@ -176,7 +176,7 @@ struct edac_device_ctl_info {
struct edac_dev_sysfs_attribute *sysfs_attributes;
/* pointer to main 'edac' subsys in sysfs */
struct bus_type *edac_subsys;
const struct bus_type *edac_subsys;
/* the internal state of this controller instance */
int op_state;

View File

@ -229,7 +229,7 @@ static struct kobj_type ktype_device_ctrl = {
int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
{
struct device *dev_root;
struct bus_type *edac_subsys;
const struct bus_type *edac_subsys;
int err = -ENODEV;
edac_dbg(1, "\n");

View File

@ -67,7 +67,7 @@ char *edac_op_state_to_string(int opstate)
* sysfs object: /sys/devices/system/edac
* need to export to other files
*/
static struct bus_type edac_subsys = {
static const struct bus_type edac_subsys = {
.name = "edac",
.dev_name = "edac",
};
@ -90,7 +90,7 @@ static void edac_subsys_exit(void)
}
/* return pointer to the 'edac' node in sysfs */
struct bus_type *edac_get_sysfs_subsys(void)
const struct bus_type *edac_get_sysfs_subsys(void)
{
return &edac_subsys;
}

View File

@ -338,7 +338,7 @@ static struct kobj_type ktype_edac_pci_main_kobj = {
static int edac_pci_main_kobj_setup(void)
{
int err = -ENODEV;
struct bus_type *edac_subsys;
const struct bus_type *edac_subsys;
struct device *dev_root;
edac_dbg(0, "\n");

View File

@ -2668,7 +2668,7 @@ static void genpd_release_dev(struct device *dev)
kfree(dev);
}
static struct bus_type genpd_bus_type = {
static const struct bus_type genpd_bus_type = {
.name = "genpd",
};

View File

@ -54,9 +54,9 @@ static bool kernfs_lockdep(struct kernfs_node *kn)
static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen)
{
if (!kn)
return strlcpy(buf, "(null)", buflen);
return strscpy(buf, "(null)", buflen);
return strlcpy(buf, kn->parent ? kn->name : "/", buflen);
return strscpy(buf, kn->parent ? kn->name : "/", buflen);
}
/* kernfs_node_depth - compute depth from @from to @to */
@ -127,7 +127,7 @@ static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a,
*
* [3] when @kn_to is %NULL result will be "(null)"
*
* Return: the length of the full path. If the full length is equal to or
* Return: the length of the constructed path. If the path would have been
* greater than @buflen, @buf contains the truncated path with the trailing
* '\0'. On error, -errno is returned.
*/
@ -138,16 +138,17 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
struct kernfs_node *kn, *common;
const char parent_str[] = "/..";
size_t depth_from, depth_to, len = 0;
ssize_t copied;
int i, j;
if (!kn_to)
return strlcpy(buf, "(null)", buflen);
return strscpy(buf, "(null)", buflen);
if (!kn_from)
kn_from = kernfs_root(kn_to)->kn;
if (kn_from == kn_to)
return strlcpy(buf, "/", buflen);
return strscpy(buf, "/", buflen);
common = kernfs_common_ancestor(kn_from, kn_to);
if (WARN_ON(!common))
@ -158,18 +159,19 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
buf[0] = '\0';
for (i = 0; i < depth_from; i++)
len += strlcpy(buf + len, parent_str,
len < buflen ? buflen - len : 0);
for (i = 0; i < depth_from; i++) {
copied = strscpy(buf + len, parent_str, buflen - len);
if (copied < 0)
return copied;
len += copied;
}
/* Calculate how many bytes we need for the rest */
for (i = depth_to - 1; i >= 0; i--) {
for (kn = kn_to, j = 0; j < i; j++)
kn = kn->parent;
len += strlcpy(buf + len, "/",
len < buflen ? buflen - len : 0);
len += strlcpy(buf + len, kn->name,
len < buflen ? buflen - len : 0);
len += scnprintf(buf + len, buflen - len, "/%s", kn->name);
}
return len;
@ -182,12 +184,12 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
* @buflen: size of @buf
*
* Copies the name of @kn into @buf of @buflen bytes. The behavior is
* similar to strlcpy().
* similar to strscpy().
*
* Fills buffer with "(null)" if @kn is %NULL.
*
* Return: the length of @kn's name and if @buf isn't long enough,
* it's filled up to @buflen-1 and nul terminated.
* Return: the resulting length of @buf. If @buf isn't long enough,
* it's filled up to @buflen-1 and nul terminated, and returns -E2BIG.
*
* This function can be called from any context.
*/
@ -214,7 +216,7 @@ int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
* path (which includes '..'s) as needed to reach from @from to @to is
* returned.
*
* Return: the length of the full path. If the full length is equal to or
* Return: the length of the constructed path. If the path would have been
* greater than @buflen, @buf contains the truncated path with the trailing
* '\0'. On error, -errno is returned.
*/
@ -265,12 +267,10 @@ void pr_cont_kernfs_path(struct kernfs_node *kn)
sz = kernfs_path_from_node(kn, NULL, kernfs_pr_cont_buf,
sizeof(kernfs_pr_cont_buf));
if (sz < 0) {
pr_cont("(error)");
goto out;
}
if (sz >= sizeof(kernfs_pr_cont_buf)) {
if (sz == -E2BIG)
pr_cont("(name too long)");
else
pr_cont("(error)");
goto out;
}
@ -676,6 +676,18 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
{
struct kernfs_node *kn;
if (parent->mode & S_ISGID) {
/* this code block imitates inode_init_owner() for
* kernfs
*/
if (parent->iattr)
gid = parent->iattr->ia_gid;
if (flags & KERNFS_DIR)
mode |= S_ISGID;
}
kn = __kernfs_new_node(kernfs_root(parent), parent,
name, mode, uid, gid, flags);
if (kn) {
@ -850,16 +862,16 @@ static struct kernfs_node *kernfs_walk_ns(struct kernfs_node *parent,
const unsigned char *path,
const void *ns)
{
size_t len;
ssize_t len;
char *p, *name;
lockdep_assert_held_read(&kernfs_root(parent)->kernfs_rwsem);
spin_lock_irq(&kernfs_pr_cont_lock);
len = strlcpy(kernfs_pr_cont_buf, path, sizeof(kernfs_pr_cont_buf));
len = strscpy(kernfs_pr_cont_buf, path, sizeof(kernfs_pr_cont_buf));
if (len >= sizeof(kernfs_pr_cont_buf)) {
if (len < 0) {
spin_unlock_irq(&kernfs_pr_cont_lock);
return NULL;
}

View File

@ -447,7 +447,7 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma)
* warnings and we don't want to add spurious locking dependency
* between the two. Check whether mmap is actually implemented
* without grabbing @of->mutex by testing HAS_MMAP flag. See the
* comment in kernfs_file_open() for more details.
* comment in kernfs_fop_open() for more details.
*/
if (!(of->kn->flags & KERNFS_HAS_MMAP))
return -ENODEV;

View File

@ -125,9 +125,6 @@ static struct dentry *__kernfs_fh_to_dentry(struct super_block *sb,
inode = kernfs_get_inode(sb, kn);
kernfs_put(kn);
if (!inode)
return ERR_PTR(-ESTALE);
return d_obtain_alias(inode);
}

View File

@ -81,7 +81,7 @@ void sysfs_remove_dir(struct kobject *kobj)
struct kernfs_node *kn = kobj->sd;
/*
* In general, kboject owner is responsible for ensuring removal
* In general, kobject owner is responsible for ensuring removal
* doesn't race with other operations and sysfs doesn't provide any
* protection; however, when @kobj is used as a symlink target, the
* symlinking entity usually doesn't own @kobj and thus has no

View File

@ -12,7 +12,7 @@
#include <linux/device.h>
/* drivers/base/power/container.c */
extern struct bus_type container_subsys;
extern const struct bus_type container_subsys;
struct container_dev {
struct device dev;

View File

@ -80,6 +80,7 @@ extern __printf(4, 5)
struct device *cpu_device_create(struct device *parent, void *drvdata,
const struct attribute_group **groups,
const char *fmt, ...);
extern bool arch_cpu_is_hotpluggable(int cpu);
extern int arch_register_cpu(int cpu);
extern void arch_unregister_cpu(int cpu);
#ifdef CONFIG_HOTPLUG_CPU
@ -88,6 +89,10 @@ extern ssize_t arch_cpu_probe(const char *, size_t);
extern ssize_t arch_cpu_release(const char *, size_t);
#endif
#ifdef CONFIG_GENERIC_CPU_DEVICES
DECLARE_PER_CPU(struct cpu, cpu_devices);
#endif
/*
* These states are not related to the core CPU hotplug mechanism. They are
* used by various (sub)architectures to track internal state

View File

@ -63,7 +63,7 @@ struct msi_device_data;
*/
struct subsys_interface {
const char *name;
struct bus_type *subsys;
const struct bus_type *subsys;
struct list_head node;
int (*add_dev)(struct device *dev, struct subsys_interface *sif);
void (*remove_dev)(struct device *dev, struct subsys_interface *sif);
@ -72,9 +72,9 @@ struct subsys_interface {
int subsys_interface_register(struct subsys_interface *sif);
void subsys_interface_unregister(struct subsys_interface *sif);
int subsys_system_register(struct bus_type *subsys,
int subsys_system_register(const struct bus_type *subsys,
const struct attribute_group **groups);
int subsys_virtual_register(struct bus_type *subsys,
int subsys_virtual_register(const struct bus_type *subsys,
const struct attribute_group **groups);
/*
@ -662,7 +662,6 @@ struct device_physical_location {
* @id: device instance
* @devres_lock: Spinlock to protect the resource of the device.
* @devres_head: The resources list of the device.
* @knode_class: The node used to add the device to the class list.
* @class: The class of the device.
* @groups: Optional attribute groups.
* @release: Callback to free the device after all references have
@ -1073,7 +1072,6 @@ int device_rename(struct device *dev, const char *new_name);
int device_move(struct device *dev, struct device *new_parent,
enum dpm_order dpm_order);
int device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid);
int device_is_dependent(struct device *dev, void *target);
static inline bool device_supports_offline(struct device *dev)
{

View File

@ -232,7 +232,7 @@ bus_find_device_by_acpi_dev(const struct bus_type *bus, const void *adev)
int bus_for_each_drv(const struct bus_type *bus, struct device_driver *start,
void *data, int (*fn)(struct device_driver *, void *));
void bus_sort_breadthfirst(struct bus_type *bus,
void bus_sort_breadthfirst(const struct bus_type *bus,
int (*compare)(const struct device *a,
const struct device *b));
/*

View File

@ -40,8 +40,6 @@ struct fwnode_handle;
* for the devices belonging to the class. Usually tied to
* device's namespace.
* @pm: The default device power management operations of this class.
* @p: The private data of the driver core, no one other than the
* driver core can touch this.
*
* A class is a higher-level view of a device that abstracts out low-level
* implementation details. Drivers may see a SCSI disk or an ATA disk, but,

View File

@ -30,7 +30,7 @@ struct device;
extern int edac_op_state;
struct bus_type *edac_get_sysfs_subsys(void);
const struct bus_type *edac_get_sysfs_subsys(void);
static inline void opstate_init(void)
{
@ -495,7 +495,7 @@ struct edac_raw_error_desc {
*/
struct mem_ctl_info {
struct device dev;
struct bus_type *bus;
const struct bus_type *bus;
struct list_head link; /* for global list of mem_ctl_info structs */

View File

@ -91,10 +91,10 @@ static inline int devm_pm_clk_create(struct device *dev)
#endif
#ifdef CONFIG_HAVE_CLK
extern void pm_clk_add_notifier(struct bus_type *bus,
extern void pm_clk_add_notifier(const struct bus_type *bus,
struct pm_clk_notifier_block *clknb);
#else
static inline void pm_clk_add_notifier(struct bus_type *bus,
static inline void pm_clk_add_notifier(const struct bus_type *bus,
struct pm_clk_notifier_block *clknb)
{
}

View File

@ -574,6 +574,16 @@ extern unsigned long __initramfs_size;
#include <linux/initrd.h>
#include <linux/kexec.h>
static ssize_t raw_read(struct file *file, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t pos, size_t count)
{
memcpy(buf, attr->private + pos, count);
return count;
}
static BIN_ATTR(initrd, 0440, raw_read, NULL, 0);
void __init reserve_initrd_mem(void)
{
phys_addr_t start;
@ -715,8 +725,14 @@ done:
* If the initrd region is overlapped with crashkernel reserved region,
* free only memory that is not part of crashkernel region.
*/
if (!do_retain_initrd && initrd_start && !kexec_free_initrd())
if (!do_retain_initrd && initrd_start && !kexec_free_initrd()) {
free_initrd_mem(initrd_start, initrd_end);
} else if (do_retain_initrd && initrd_start) {
bin_attr_initrd.size = initrd_end - initrd_start;
bin_attr_initrd.private = (void *)initrd_start;
if (sysfs_create_bin_file(firmware_kobj, &bin_attr_initrd))
pr_err("Failed to create initrd sysfs file");
}
initrd_start = 0;
initrd_end = 0;

View File

@ -802,7 +802,7 @@ void cgroup1_release_agent(struct work_struct *work)
goto out_free;
ret = cgroup_path_ns(cgrp, pathbuf, PATH_MAX, &init_cgroup_ns);
if (ret < 0 || ret >= PATH_MAX)
if (ret < 0)
goto out_free;
argv[0] = agentbuf;

View File

@ -1906,7 +1906,7 @@ int cgroup_show_path(struct seq_file *sf, struct kernfs_node *kf_node,
len = kernfs_path_from_node(kf_node, ns_cgroup->kn, buf, PATH_MAX);
spin_unlock_irq(&css_set_lock);
if (len >= PATH_MAX)
if (len == -E2BIG)
len = -ERANGE;
else if (len > 0) {
seq_escape(sf, buf, " \t\n\\");
@ -4182,20 +4182,6 @@ static struct kernfs_ops cgroup_kf_ops = {
.seq_show = cgroup_seqfile_show,
};
/* set uid and gid of cgroup dirs and files to that of the creator */
static int cgroup_kn_set_ugid(struct kernfs_node *kn)
{
struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID,
.ia_uid = current_fsuid(),
.ia_gid = current_fsgid(), };
if (uid_eq(iattr.ia_uid, GLOBAL_ROOT_UID) &&
gid_eq(iattr.ia_gid, GLOBAL_ROOT_GID))
return 0;
return kernfs_setattr(kn, &iattr);
}
static void cgroup_file_notify_timer(struct timer_list *timer)
{
cgroup_file_notify(container_of(timer, struct cgroup_file,
@ -4208,25 +4194,18 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp,
char name[CGROUP_FILE_NAME_MAX];
struct kernfs_node *kn;
struct lock_class_key *key = NULL;
int ret;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
key = &cft->lockdep_key;
#endif
kn = __kernfs_create_file(cgrp->kn, cgroup_file_name(cgrp, cft, name),
cgroup_file_mode(cft),
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
current_fsuid(), current_fsgid(),
0, cft->kf_ops, cft,
NULL, key);
if (IS_ERR(kn))
return PTR_ERR(kn);
ret = cgroup_kn_set_ugid(kn);
if (ret) {
kernfs_remove(kn);
return ret;
}
if (cft->file_offset) {
struct cgroup_file *cfile = (void *)css + cft->file_offset;
@ -5629,7 +5608,9 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name,
goto out_cancel_ref;
/* create the directory */
kn = kernfs_create_dir(parent->kn, name, mode, cgrp);
kn = kernfs_create_dir_ns(parent->kn, name, mode,
current_fsuid(), current_fsgid(),
cgrp, NULL);
if (IS_ERR(kn)) {
ret = PTR_ERR(kn);
goto out_stat_exit;
@ -5774,10 +5755,6 @@ int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, umode_t mode)
*/
kernfs_get(cgrp->kn);
ret = cgroup_kn_set_ugid(cgrp->kn);
if (ret)
goto out_destroy;
ret = css_populate_dir(&cgrp->self);
if (ret)
goto out_destroy;
@ -6316,7 +6293,7 @@ int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns,
if (cgroup_on_dfl(cgrp) || !(tsk->flags & PF_EXITING)) {
retval = cgroup_path_ns_locked(cgrp, buf, PATH_MAX,
current->nsproxy->cgroup_ns);
if (retval >= PATH_MAX)
if (retval == -E2BIG)
retval = -ENAMETOOLONG;
if (retval < 0)
goto out_unlock;

View File

@ -5092,7 +5092,7 @@ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns,
retval = cgroup_path_ns(css->cgroup, buf, PATH_MAX,
current->nsproxy->cgroup_ns);
css_put(css);
if (retval >= PATH_MAX)
if (retval == -E2BIG)
retval = -ENAMETOOLONG;
if (retval < 0)
goto out_free;