2023-10-09 16:58:13

by Max Kellermann

[permalink] [raw]
Subject: [PATCH 1/7] drivers/rtc/sysfs: move code to count_attribute_groups()

This avoids overloading the "groups" variable for three different
purposes

Signed-off-by: Max Kellermann <[email protected]>
---
drivers/rtc/sysfs.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/rtc/sysfs.c b/drivers/rtc/sysfs.c
index e3062c4d3f2c..617933d52324 100644
--- a/drivers/rtc/sysfs.c
+++ b/drivers/rtc/sysfs.c
@@ -313,21 +313,25 @@ const struct attribute_group **rtc_get_dev_attribute_groups(void)
return rtc_attr_groups;
}

+static size_t count_attribute_groups(const struct attribute_group *const*groups)
+{
+ size_t count = 0;
+
+ for (; *groups; ++groups)
+ ++count;
+ return count;
+}
+
int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
{
- size_t old_cnt = 0, add_cnt = 0, new_cnt;
+ size_t old_cnt, add_cnt, new_cnt;
const struct attribute_group **groups, **old;

if (!grps)
return -EINVAL;

- groups = rtc->dev.groups;
- if (groups)
- for (; *groups; groups++)
- old_cnt++;
-
- for (groups = grps; *groups; groups++)
- add_cnt++;
+ old_cnt = rtc->dev.groups ? count_attribute_groups(rtc->dev.groups) : 0;
+ add_cnt = count_attribute_groups(grps);

new_cnt = old_cnt + add_cnt + 1;
groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL);
--
2.39.2


2023-10-09 16:58:13

by Max Kellermann

[permalink] [raw]
Subject: [PATCH 2/7] drivers/hwmon: add local variable for newly allocated attribute_group**

This allows the compiler to keep the pointer in a register and
prepares for making the struct field "const".

Signed-off-by: Max Kellermann <[email protected]>
---
drivers/hwmon/hwmon.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index c7dd3f5b2bd5..e50ab229b27d 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -783,6 +783,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
hdev = &hwdev->dev;

if (chip) {
+ const struct attribute_group **new_groups;
struct attribute **attrs;
int ngroups = 2; /* terminating NULL plus &hwdev->groups */

@@ -790,8 +791,8 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
for (i = 0; groups[i]; i++)
ngroups++;

- hwdev->groups = kcalloc(ngroups, sizeof(*groups), GFP_KERNEL);
- if (!hwdev->groups) {
+ hwdev->groups = new_groups = kcalloc(ngroups, sizeof(*new_groups), GFP_KERNEL);
+ if (!new_groups) {
err = -ENOMEM;
goto free_hwmon;
}
@@ -804,14 +805,14 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,

hwdev->group.attrs = attrs;
ngroups = 0;
- hwdev->groups[ngroups++] = &hwdev->group;
+ new_groups[ngroups++] = &hwdev->group;

if (groups) {
for (i = 0; groups[i]; i++)
- hwdev->groups[ngroups++] = groups[i];
+ new_groups[ngroups++] = groups[i];
}

- hdev->groups = hwdev->groups;
+ hdev->groups = new_groups;
} else {
hdev->groups = groups;
}
--
2.39.2

2023-10-09 16:58:15

by Max Kellermann

[permalink] [raw]
Subject: [PATCH 5/7] drivers/tty/serial_core: add local variable for newly allocated attribute_group**

This allows the compiler to keep the pointer in a register and
prepares for making the struct field "const".

Signed-off-by: Max Kellermann <[email protected]>
---
drivers/tty/serial/serial_core.c | 11 ++++++-----
include/linux/serial_core.h | 4 ++--
2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 7bdc21d5e13b..e253ef474fb4 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -3082,6 +3082,7 @@ static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *u
struct uart_state *state;
struct tty_port *port;
int ret = 0;
+ const struct attribute_group **tty_groups;
struct device *tty_dev;
int num_groups;

@@ -3132,22 +3133,22 @@ static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *u
if (uport->attr_group)
num_groups++;

- uport->tty_groups = kcalloc(num_groups, sizeof(*uport->tty_groups),
+ uport->tty_groups = tty_groups = kcalloc(num_groups, sizeof(*tty_groups),
GFP_KERNEL);
- if (!uport->tty_groups) {
+ if (!tty_groups) {
ret = -ENOMEM;
goto out;
}
- uport->tty_groups[0] = &tty_dev_attr_group;
+ tty_groups[0] = &tty_dev_attr_group;
if (uport->attr_group)
- uport->tty_groups[1] = uport->attr_group;
+ tty_groups[1] = uport->attr_group;

/*
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this port's parameters.
*/
tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver,
- uport->line, uport->dev, port, uport->tty_groups);
+ uport->line, uport->dev, port, tty_groups);
if (!IS_ERR(tty_dev)) {
device_set_wakeup_capable(tty_dev, 1);
} else {
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index bb6f073bc159..597de109dbf5 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -578,8 +578,8 @@ struct uart_port {
unsigned char suspended;
unsigned char console_reinit;
const char *name; /* port name */
- struct attribute_group *attr_group; /* port specific attributes */
- const struct attribute_group **tty_groups; /* all attributes (serial core use only) */
+ const struct attribute_group *attr_group; /* port specific attributes */
+ const struct attribute_group *const*tty_groups; /* all attributes (serial core use only) */
struct serial_rs485 rs485;
struct serial_rs485 rs485_supported; /* Supported mask for serial_rs485 */
struct gpio_desc *rs485_term_gpio; /* enable RS485 bus termination */
--
2.39.2

2023-10-09 16:58:47

by Max Kellermann

[permalink] [raw]
Subject: [PATCH 4/7] drivers/counter: add local variable for newly allocated attribute_group**

This allows the compiler to keep the pointer in a register and
prepares for making the struct field "const".

Signed-off-by: Max Kellermann <[email protected]>
---
drivers/counter/counter-sysfs.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/counter/counter-sysfs.c b/drivers/counter/counter-sysfs.c
index 42c523343d32..47e1e2c61cf0 100644
--- a/drivers/counter/counter-sysfs.c
+++ b/drivers/counter/counter-sysfs.c
@@ -1122,6 +1122,7 @@ int counter_sysfs_add(struct counter_device *const counter)
struct counter_attribute_group *cattr_groups;
size_t i, j;
int err;
+ const struct attribute_group **dev_groups;
struct attribute_group *groups;
struct counter_attribute *p;

@@ -1141,9 +1142,9 @@ int counter_sysfs_add(struct counter_device *const counter)
return err;

/* Allocate attribute group pointers for association with device */
- dev->groups = devm_kcalloc(dev, num_groups + 1, sizeof(*dev->groups),
+ dev->groups = dev_groups = devm_kcalloc(dev, num_groups + 1, sizeof(*dev_groups),
GFP_KERNEL);
- if (!dev->groups)
+ if (!dev_groups)
return -ENOMEM;

/* Allocate space for attribute groups */
@@ -1169,7 +1170,7 @@ int counter_sysfs_add(struct counter_device *const counter)
groups[i].attrs[j++] = &p->dev_attr.attr;

/* Associate attribute group */
- dev->groups[i] = &groups[i];
+ dev_groups[i] = &groups[i];
}

return 0;
--
2.39.2

2023-10-09 16:58:57

by Max Kellermann

[permalink] [raw]
Subject: [PATCH 7/7] block, drivers: make lots of attribute_group globals const

This moves those variables to the ".rodata" section which reduces the
kernel size a bit and protects the variables by putting them on
read-only pages at runtime.

Signed-off-by: Max Kellermann <[email protected]>
---
block/blk-sysfs.c | 6 +++---
block/genhd.c | 4 ++--
block/partitions/core.c | 2 +-
drivers/base/cacheinfo.c | 2 +-
drivers/block/loop.c | 2 +-
drivers/block/rbd.c | 4 ++--
drivers/input/input.c | 2 +-
drivers/input/serio/serio.c | 2 +-
drivers/pci/pci-sysfs.c | 8 ++++----
drivers/pci/pci.h | 6 +++---
drivers/pps/sysfs.c | 2 +-
drivers/rtc/sysfs.c | 2 +-
drivers/tty/serial/8250/8250_port.c | 2 +-
fs/ocfs2/cluster/sys.c | 2 +-
include/linux/khugepaged.h | 2 +-
include/linux/pps_kernel.h | 2 +-
mm/khugepaged.c | 2 +-
17 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 63e481262336..feea5d68b5a1 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -699,12 +699,12 @@ static umode_t blk_mq_queue_attr_visible(struct kobject *kobj,
return attr->mode;
}

-static struct attribute_group queue_attr_group = {
+static const struct attribute_group queue_attr_group = {
.attrs = queue_attrs,
.is_visible = queue_attr_visible,
};

-static struct attribute_group blk_mq_queue_attr_group = {
+static const struct attribute_group blk_mq_queue_attr_group = {
.attrs = blk_mq_queue_attrs,
.is_visible = blk_mq_queue_attr_visible,
};
@@ -750,7 +750,7 @@ static const struct sysfs_ops queue_sysfs_ops = {
.store = queue_attr_store,
};

-static const struct attribute_group *blk_queue_attr_groups[] = {
+static const struct attribute_group *const blk_queue_attr_groups[] = {
&queue_attr_group,
&blk_mq_queue_attr_group,
NULL
diff --git a/block/genhd.c b/block/genhd.c
index d82560a79b04..9fa16e5de6d2 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1115,12 +1115,12 @@ static umode_t disk_visible(struct kobject *kobj, struct attribute *a, int n)
return a->mode;
}

-static struct attribute_group disk_attr_group = {
+static const struct attribute_group disk_attr_group = {
.attrs = disk_attrs,
.is_visible = disk_visible,
};

-static const struct attribute_group *disk_attr_groups[] = {
+static const struct attribute_group *const disk_attr_groups[] = {
&disk_attr_group,
#ifdef CONFIG_BLK_DEV_IO_TRACE
&blk_trace_attr_group,
diff --git a/block/partitions/core.c b/block/partitions/core.c
index e137a87f4db0..463298e26757 100644
--- a/block/partitions/core.c
+++ b/block/partitions/core.c
@@ -232,7 +232,7 @@ static const struct attribute_group part_attr_group = {
.attrs = part_attrs,
};

-static const struct attribute_group *part_attr_groups[] = {
+static const struct attribute_group *const part_attr_groups[] = {
&part_attr_group,
#ifdef CONFIG_BLK_DEV_IO_TRACE
&blk_trace_attr_group,
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index b91c31c2a393..3642eed8ef74 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -786,7 +786,7 @@ static const struct attribute_group cache_default_group = {
.is_visible = cache_default_attrs_is_visible,
};

-static const struct attribute_group *cache_default_groups[] = {
+static const struct attribute_group *const cache_default_groups[] = {
&cache_default_group,
NULL,
};
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 9f2d412fc560..c1718b17b5ef 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -736,7 +736,7 @@ static struct attribute *loop_attrs[] = {
NULL,
};

-static struct attribute_group loop_attribute_group = {
+static const struct attribute_group loop_attribute_group = {
.name = "loop",
.attrs= loop_attrs,
};
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index a999b698b131..73e616453c34 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -5246,11 +5246,11 @@ static struct attribute *rbd_attrs[] = {
NULL
};

-static struct attribute_group rbd_attr_group = {
+static const struct attribute_group rbd_attr_group = {
.attrs = rbd_attrs,
};

-static const struct attribute_group *rbd_attr_groups[] = {
+static const struct attribute_group *const rbd_attr_groups[] = {
&rbd_attr_group,
NULL
};
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 8c5fdb0f858a..d97126d54947 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1597,7 +1597,7 @@ static const struct attribute_group input_dev_caps_attr_group = {
.attrs = input_dev_caps_attrs,
};

-static const struct attribute_group *input_dev_attr_groups[] = {
+static const struct attribute_group *const input_dev_attr_groups[] = {
&input_dev_attr_group,
&input_dev_id_attr_group,
&input_dev_caps_attr_group,
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 767fc9efb4a8..ef82d20572b0 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -474,7 +474,7 @@ static const struct attribute_group serio_device_attr_group = {
.attrs = serio_device_attrs,
};

-static const struct attribute_group *serio_device_attr_groups[] = {
+static const struct attribute_group *const serio_device_attr_groups[] = {
&serio_id_attr_group,
&serio_device_attr_group,
NULL
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index d9eede2dbc0e..f2147da6e4a5 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -455,7 +455,7 @@ static const struct attribute_group pci_bus_group = {
.attrs = pci_bus_attrs,
};

-const struct attribute_group *pci_bus_groups[] = {
+const struct attribute_group *const pci_bus_groups[] = {
&pci_bus_group,
NULL,
};
@@ -647,7 +647,7 @@ static const struct attribute_group pcibus_group = {
.attrs = pcibus_attrs,
};

-const struct attribute_group *pcibus_groups[] = {
+const struct attribute_group *const pcibus_groups[] = {
&pcibus_group,
NULL,
};
@@ -1604,7 +1604,7 @@ static const struct attribute_group pci_dev_group = {
.attrs = pci_dev_attrs,
};

-const struct attribute_group *pci_dev_groups[] = {
+const struct attribute_group *const pci_dev_groups[] = {
&pci_dev_group,
&pci_dev_config_attr_group,
&pci_dev_rom_attr_group,
@@ -1641,7 +1641,7 @@ static const struct attribute_group pcie_dev_attr_group = {
.is_visible = pcie_dev_attrs_are_visible,
};

-static const struct attribute_group *pci_dev_attr_groups[] = {
+static const struct attribute_group *const pci_dev_attr_groups[] = {
&pci_dev_attr_group,
&pci_dev_hp_attr_group,
#ifdef CONFIG_PCI_IOV
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 39a8932dc340..046d6c9944cd 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -182,10 +182,10 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
return (dev->no_d1d2 || parent_dstates);

}
-extern const struct attribute_group *pci_dev_groups[];
-extern const struct attribute_group *pcibus_groups[];
+extern const struct attribute_group *const pci_dev_groups[];
+extern const struct attribute_group *const pcibus_groups[];
extern const struct device_type pci_dev_type;
-extern const struct attribute_group *pci_bus_groups[];
+extern const struct attribute_group *const pci_bus_groups[];

extern unsigned long pci_hotplug_io_size;
extern unsigned long pci_hotplug_mmio_size;
diff --git a/drivers/pps/sysfs.c b/drivers/pps/sysfs.c
index 134bc33f6ad0..355ce20b6e53 100644
--- a/drivers/pps/sysfs.c
+++ b/drivers/pps/sysfs.c
@@ -93,7 +93,7 @@ static const struct attribute_group pps_group = {
.attrs = pps_attrs,
};

-const struct attribute_group *pps_groups[] = {
+const struct attribute_group *const pps_groups[] = {
&pps_group,
NULL,
};
diff --git a/drivers/rtc/sysfs.c b/drivers/rtc/sysfs.c
index 9c45c2557e28..c126cb706b27 100644
--- a/drivers/rtc/sysfs.c
+++ b/drivers/rtc/sysfs.c
@@ -303,7 +303,7 @@ static struct attribute_group rtc_attr_group = {
.attrs = rtc_attrs,
};

-static const struct attribute_group *rtc_attr_groups[] = {
+static const struct attribute_group *const rtc_attr_groups[] = {
&rtc_attr_group,
NULL
};
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 141627370aab..7af8f196e00f 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -3187,7 +3187,7 @@ static struct attribute *serial8250_dev_attrs[] = {
NULL
};

-static struct attribute_group serial8250_dev_attr_group = {
+static const struct attribute_group serial8250_dev_attr_group = {
.attrs = serial8250_dev_attrs,
};

diff --git a/fs/ocfs2/cluster/sys.c b/fs/ocfs2/cluster/sys.c
index 022f716c74ff..63e14ef53610 100644
--- a/fs/ocfs2/cluster/sys.c
+++ b/fs/ocfs2/cluster/sys.c
@@ -31,7 +31,7 @@ static struct attribute *o2cb_attrs[] = {
NULL,
};

-static struct attribute_group o2cb_attr_group = {
+static const struct attribute_group o2cb_attr_group = {
.attrs = o2cb_attrs,
};

diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h
index f68865e19b0b..85b442e9e638 100644
--- a/include/linux/khugepaged.h
+++ b/include/linux/khugepaged.h
@@ -5,7 +5,7 @@
#include <linux/sched/coredump.h> /* MMF_VM_HUGEPAGE */

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-extern struct attribute_group khugepaged_attr_group;
+extern const struct attribute_group khugepaged_attr_group;

extern int khugepaged_init(void);
extern void khugepaged_destroy(void);
diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h
index 78c8ac4951b5..996db99f983f 100644
--- a/include/linux/pps_kernel.h
+++ b/include/linux/pps_kernel.h
@@ -66,7 +66,7 @@ struct pps_device {
* Global variables
*/

-extern const struct attribute_group *pps_groups[];
+extern const struct attribute_group *const pps_groups[];

/*
* Internal functions.
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 88433cc25d8a..cd1b26075d1b 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -339,7 +339,7 @@ static struct attribute *khugepaged_attr[] = {
NULL,
};

-struct attribute_group khugepaged_attr_group = {
+const struct attribute_group khugepaged_attr_group = {
.attrs = khugepaged_attr,
.name = "khugepaged",
};
--
2.39.2

2023-10-09 16:59:08

by Max Kellermann

[permalink] [raw]
Subject: [PATCH 3/7] drivers/extcon: add local variable for newly allocated attribute_group**

This allows the compiler to keep the pointer in a register and
prepares for making the struct field "const".

Signed-off-by: Max Kellermann <[email protected]>
---
drivers/extcon/extcon.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index 6f7a60d2ed91..e879690d4fef 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -1202,6 +1202,7 @@ static int extcon_alloc_muex(struct extcon_dev *edev)
*/
static int extcon_alloc_groups(struct extcon_dev *edev)
{
+ const struct attribute_group **groups;
int index;

if (!edev)
@@ -1210,20 +1211,20 @@ static int extcon_alloc_groups(struct extcon_dev *edev)
if (!edev->max_supported)
return 0;

- edev->extcon_dev_type.groups = kcalloc(edev->max_supported + 2,
- sizeof(*edev->extcon_dev_type.groups),
+ edev->extcon_dev_type.groups = groups = kcalloc(edev->max_supported + 2,
+ sizeof(*groups),
GFP_KERNEL);
- if (!edev->extcon_dev_type.groups)
+ if (!groups)
return -ENOMEM;

edev->extcon_dev_type.name = dev_name(&edev->dev);
edev->extcon_dev_type.release = dummy_sysfs_dev_release;

for (index = 0; index < edev->max_supported; index++)
- edev->extcon_dev_type.groups[index] = &edev->cables[index].attr_g;
+ groups[index] = &edev->cables[index].attr_g;

if (edev->mutually_exclusive)
- edev->extcon_dev_type.groups[index] = &edev->attr_g_muex;
+ groups[index] = &edev->attr_g_muex;

edev->dev.type = &edev->extcon_dev_type;

--
2.39.2

2023-10-09 16:59:36

by Max Kellermann

[permalink] [raw]
Subject: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

This allows passing arrays of const pointers. The goal is to make
lots of global variables "const" to allow them to live in the
".rodata" section.

Signed-off-by: Max Kellermann <[email protected]>
---
block/genhd.c | 2 +-
drivers/base/base.h | 4 ++--
drivers/base/bus.c | 6 +++---
drivers/base/cacheinfo.c | 4 ++--
drivers/base/core.c | 14 +++++++-------
drivers/base/cpu.c | 4 ++--
drivers/base/driver.c | 4 ++--
drivers/edac/edac_mc.c | 2 +-
drivers/edac/edac_mc.h | 2 +-
drivers/edac/edac_mc_sysfs.c | 2 +-
drivers/edac/edac_module.h | 2 +-
drivers/hwmon/hwmon.c | 12 ++++++------
drivers/hwmon/pmbus/pmbus.h | 2 +-
drivers/infiniband/core/core_priv.h | 4 ++--
drivers/infiniband/core/sysfs.c | 4 ++--
drivers/infiniband/ulp/srp/ib_srp.c | 2 +-
drivers/iommu/iommu-sysfs.c | 2 +-
drivers/nvdimm/dimm_devs.c | 2 +-
drivers/nvme/host/nvme.h | 2 +-
drivers/rtc/rtc-core.h | 4 ++--
drivers/rtc/sysfs.c | 6 +++---
drivers/tty/tty_io.c | 2 +-
drivers/tty/tty_port.c | 4 ++--
fs/sysfs/group.c | 10 +++++-----
include/linux/blkdev.h | 2 +-
include/linux/coresight.h | 2 +-
include/linux/cpu.h | 2 +-
include/linux/device.h | 16 ++++++++--------
include/linux/device/bus.h | 6 +++---
include/linux/device/class.h | 4 ++--
include/linux/device/driver.h | 4 ++--
include/linux/hwmon.h | 8 ++++----
include/linux/iommu.h | 4 ++--
include/linux/kobject.h | 2 +-
include/linux/leds.h | 4 ++--
include/linux/libnvdimm.h | 8 ++++----
include/linux/miscdevice.h | 2 +-
include/linux/pci.h | 4 ++--
include/linux/perf_event.h | 2 +-
include/linux/power_supply.h | 2 +-
include/linux/rtc.h | 4 ++--
include/linux/sysfs.h | 16 ++++++++--------
include/linux/tty_driver.h | 2 +-
include/linux/tty_port.h | 4 ++--
include/linux/usb.h | 4 ++--
include/linux/w1.h | 2 +-
include/linux/watchdog.h | 2 +-
include/rdma/ib_verbs.h | 2 +-
include/scsi/scsi_host.h | 4 ++--
49 files changed, 107 insertions(+), 107 deletions(-)

diff --git a/block/genhd.c b/block/genhd.c
index cc32a0c704eb..d82560a79b04 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -394,7 +394,7 @@ int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode)
* with the kernel.
*/
int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)

{
struct device *ddev = disk_to_dev(disk);
diff --git a/drivers/base/base.h b/drivers/base/base.h
index eb4c0ace9242..a2c011d9a5ca 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -175,8 +175,8 @@ static inline void dev_sync_state(struct device *dev)
dev->driver->sync_state(dev);
}

-int driver_add_groups(struct device_driver *drv, const struct attribute_group **groups);
-void driver_remove_groups(struct device_driver *drv, const struct attribute_group **groups);
+int driver_add_groups(struct device_driver *drv, const struct attribute_group *const*groups);
+void driver_remove_groups(struct device_driver *drv, const struct attribute_group *const*groups);
void device_driver_detach(struct device *dev);

int devres_release_all(struct device *dev);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 84a21084d67d..d0331d07fffe 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -1195,7 +1195,7 @@ static void system_root_device_release(struct device *dev)
}

static int subsys_register(struct bus_type *subsys,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
struct kobject *parent_of_root)
{
struct subsys_private *sp;
@@ -1265,7 +1265,7 @@ static int subsys_register(struct bus_type *subsys,
* /sys/devices/system/<name>.
*/
int subsys_system_register(struct bus_type *subsys,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
return subsys_register(subsys, groups, &system_kset->kobj);
}
@@ -1283,7 +1283,7 @@ EXPORT_SYMBOL_GPL(subsys_system_register);
* constructs which need sysfs interface.
*/
int subsys_virtual_register(struct bus_type *subsys,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
struct kobject *virtual_dir;

diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index cbae8be1fe52..b91c31c2a393 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -803,7 +803,7 @@ __weak cache_get_priv_group(struct cacheinfo *this_leaf)
return NULL;
}

-static const struct attribute_group **
+static const struct attribute_group *const*
cache_get_attribute_groups(struct cacheinfo *this_leaf)
{
const struct attribute_group *priv_group =
@@ -868,7 +868,7 @@ static int cache_add_dev(unsigned int cpu)
int rc;
struct device *ci_dev, *parent;
struct cacheinfo *this_leaf;
- const struct attribute_group **cache_groups;
+ const struct attribute_group *const*cache_groups;

rc = cpu_cache_sysfs_init(cpu);
if (unlikely(rc < 0))
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 4d8b315c48a1..b0debc3b751d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2721,14 +2721,14 @@ static ssize_t removable_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(removable);

-int device_add_groups(struct device *dev, const struct attribute_group **groups)
+int device_add_groups(struct device *dev, const struct attribute_group *const*groups)
{
return sysfs_create_groups(&dev->kobj, groups);
}
EXPORT_SYMBOL_GPL(device_add_groups);

void device_remove_groups(struct device *dev,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
sysfs_remove_groups(&dev->kobj, groups);
}
@@ -2736,7 +2736,7 @@ EXPORT_SYMBOL_GPL(device_remove_groups);

union device_attr_group_devres {
const struct attribute_group *group;
- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;
};

static void devm_attr_group_remove(struct device *dev, void *res)
@@ -2751,7 +2751,7 @@ static void devm_attr_group_remove(struct device *dev, void *res)
static void devm_attr_groups_remove(struct device *dev, void *res)
{
union device_attr_group_devres *devres = res;
- const struct attribute_group **groups = devres->groups;
+ const struct attribute_group *const*groups = devres->groups;

dev_dbg(dev, "%s: removing groups %p\n", __func__, groups);
sysfs_remove_groups(&dev->kobj, groups);
@@ -2803,7 +2803,7 @@ EXPORT_SYMBOL_GPL(devm_device_add_group);
* Returns 0 on success or error code from sysfs_create_group on failure.
*/
int devm_device_add_groups(struct device *dev,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
union device_attr_group_devres *devres;
int error;
@@ -4281,7 +4281,7 @@ static void device_create_release(struct device *dev)
static __printf(6, 0) struct device *
device_create_groups_vargs(const struct class *class, struct device *parent,
dev_t devt, void *drvdata,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
const char *fmt, va_list args)
{
struct device *dev = NULL;
@@ -4381,7 +4381,7 @@ EXPORT_SYMBOL_GPL(device_create);
struct device *device_create_with_groups(const struct class *class,
struct device *parent, dev_t devt,
void *drvdata,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
const char *fmt, ...)
{
va_list vargs;
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 9ea22e165acd..bd51cb4e6e8c 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -434,7 +434,7 @@ static void device_create_release(struct device *dev)
__printf(4, 0)
static struct device *
__cpu_device_create(struct device *parent, void *drvdata,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
const char *fmt, va_list args)
{
struct device *dev = NULL;
@@ -467,7 +467,7 @@ __cpu_device_create(struct device *parent, void *drvdata,
}

struct device *cpu_device_create(struct device *parent, void *drvdata,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
const char *fmt, ...)
{
va_list vargs;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index c8436c26ed6a..770bc8543f46 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -200,13 +200,13 @@ void driver_remove_file(struct device_driver *drv,
EXPORT_SYMBOL_GPL(driver_remove_file);

int driver_add_groups(struct device_driver *drv,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
return sysfs_create_groups(&drv->p->kobj, groups);
}

void driver_remove_groups(struct device_driver *drv,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
sysfs_remove_groups(&drv->p->kobj, groups);
}
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 6faeb2ab3960..766ba8ac4f47 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -598,7 +598,7 @@ EXPORT_SYMBOL_GPL(edac_get_owner);

/* FIXME - should a warning be printed if no error detection? correction? */
int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
int ret = -EINVAL;
edac_dbg(0, "\n");
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index 881b00eadf7a..0ded68555d1c 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -146,7 +146,7 @@ extern const char *edac_get_owner(void);
* 0 on Success, or an error code on failure
*/
extern int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
#define edac_mc_add_mc(mci) edac_mc_add_mc_with_groups(mci, NULL)

/**
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 15f63452a9be..9ef2b139d8ae 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -931,7 +931,7 @@ static const struct device_type mci_attr_type = {
* !0 Failure
*/
int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
struct dimm_info *dimm;
int err;
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
index 47593afdc234..734673339be5 100644
--- a/drivers/edac/edac_module.h
+++ b/drivers/edac/edac_module.h
@@ -27,7 +27,7 @@
int edac_mc_sysfs_init(void);
void edac_mc_sysfs_exit(void);
extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci);
extern int edac_mc_get_log_ue(void);
extern int edac_mc_get_log_ce(void);
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index e50ab229b27d..d0305eaefa8b 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -37,7 +37,7 @@ struct hwmon_device {
const struct hwmon_chip_info *chip;
struct list_head tzdata;
struct attribute_group group;
- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;
};

#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
@@ -756,7 +756,7 @@ __hwmon_create_attrs(const void *drvdata, const struct hwmon_chip_info *chip)
static struct device *
__hwmon_device_register(struct device *dev, const char *name, void *drvdata,
const struct hwmon_chip_info *chip,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
struct hwmon_device *hwdev;
const char *label;
@@ -884,7 +884,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
struct device *
hwmon_device_register_with_groups(struct device *dev, const char *name,
void *drvdata,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
if (!name)
return ERR_PTR(-EINVAL);
@@ -911,7 +911,7 @@ struct device *
hwmon_device_register_with_info(struct device *dev, const char *name,
void *drvdata,
const struct hwmon_chip_info *chip,
- const struct attribute_group **extra_groups)
+ const struct attribute_group *const*extra_groups)
{
if (!dev || !name || !chip)
return ERR_PTR(-EINVAL);
@@ -1004,7 +1004,7 @@ static void devm_hwmon_release(struct device *dev, void *res)
struct device *
devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
void *drvdata,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
struct device **ptr, *hwdev;

@@ -1044,7 +1044,7 @@ struct device *
devm_hwmon_device_register_with_info(struct device *dev, const char *name,
void *drvdata,
const struct hwmon_chip_info *chip,
- const struct attribute_group **extra_groups)
+ const struct attribute_group *const*extra_groups)
{
struct device **ptr, *hwdev;

diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index b0832a4c690d..bf039994b84f 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -456,7 +456,7 @@ struct pmbus_driver_info {
const struct regulator_desc *reg_desc;

/* custom attributes */
- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;
};

/* Regulator ops */
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index f66f48d860ec..d4a444e52743 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -351,9 +351,9 @@ int ib_setup_device_attrs(struct ib_device *ibdev);
int rdma_compatdev_set(u8 enable);

int ib_port_register_client_groups(struct ib_device *ibdev, u32 port_num,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);

int ib_device_set_netns_put(struct sk_buff *skb,
struct ib_device *dev, u32 ns_fd);
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index ee59d7391568..fdd15d6a9c2f 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -1464,7 +1464,7 @@ int ib_setup_port_attrs(struct ib_core_device *coredev)
* Do not use. Only for legacy sysfs compatibility.
*/
int ib_port_register_client_groups(struct ib_device *ibdev, u32 port_num,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
return sysfs_create_groups(&ibdev->port_data[port_num].sysfs->kobj,
groups);
@@ -1472,7 +1472,7 @@ int ib_port_register_client_groups(struct ib_device *ibdev, u32 port_num,
EXPORT_SYMBOL(ib_port_register_client_groups);

void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
return sysfs_remove_groups(&ibdev->port_data[port_num].sysfs->kobj,
groups);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 2916e77f589b..0633b17fc082 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1021,7 +1021,7 @@ static int srp_init_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
*/
static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
{
- const struct attribute_group **g;
+ const struct attribute_group *const*g;
struct attribute **attr;

for (g = shost->hostt->shost_groups; *g; ++g) {
diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c
index cbe378c34ba3..ef92144b679f 100644
--- a/drivers/iommu/iommu-sysfs.c
+++ b/drivers/iommu/iommu-sysfs.c
@@ -53,7 +53,7 @@ postcore_initcall(iommu_dev_init);
*/
int iommu_device_sysfs_add(struct iommu_device *iommu,
struct device *parent,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
const char *fmt, ...)
{
va_list vargs;
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 1273873582be..924dfc43f94c 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -580,7 +580,7 @@ bool is_nvdimm(const struct device *dev)
static struct lock_class_key nvdimm_key;

struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
- void *provider_data, const struct attribute_group **groups,
+ void *provider_data, const struct attribute_group *const*groups,
unsigned long flags, unsigned long cmd_mask, int num_flush,
struct resource *flush_wpq, const char *dimm_id,
const struct nvdimm_security_ops *sec_ops,
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index f35647c470af..90d0a1892b23 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -524,7 +524,7 @@ struct nvme_ctrl_ops {
#define NVME_F_METADATA_SUPPORTED (1 << 1)
#define NVME_F_BLOCKING (1 << 2)

- const struct attribute_group **dev_attr_groups;
+ const struct attribute_group *const*dev_attr_groups;
int (*reg_read32)(struct nvme_ctrl *ctrl, u32 off, u32 *val);
int (*reg_write32)(struct nvme_ctrl *ctrl, u32 off, u32 val);
int (*reg_read64)(struct nvme_ctrl *ctrl, u32 off, u64 *val);
diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h
index 4b10a1b8f370..d21a967914dc 100644
--- a/drivers/rtc/rtc-core.h
+++ b/drivers/rtc/rtc-core.h
@@ -34,9 +34,9 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc)
#endif

#ifdef CONFIG_RTC_INTF_SYSFS
-const struct attribute_group **rtc_get_dev_attribute_groups(void);
+const struct attribute_group *const*rtc_get_dev_attribute_groups(void);
#else
-static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
+static inline const struct attribute_group *const*rtc_get_dev_attribute_groups(void)
{
return NULL;
}
diff --git a/drivers/rtc/sysfs.c b/drivers/rtc/sysfs.c
index 617933d52324..9c45c2557e28 100644
--- a/drivers/rtc/sysfs.c
+++ b/drivers/rtc/sysfs.c
@@ -308,7 +308,7 @@ static const struct attribute_group *rtc_attr_groups[] = {
NULL
};

-const struct attribute_group **rtc_get_dev_attribute_groups(void)
+const struct attribute_group *const*rtc_get_dev_attribute_groups(void)
{
return rtc_attr_groups;
}
@@ -322,10 +322,10 @@ static size_t count_attribute_groups(const struct attribute_group *const*groups)
return count;
}

-int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group *const*grps)
{
size_t old_cnt, add_cnt, new_cnt;
- const struct attribute_group **groups, **old;
+ const struct attribute_group **groups, *const *old;

if (!grps)
return -EINVAL;
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 8a94e5a43c6d..2bbc193a6f47 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3212,7 +3212,7 @@ static void tty_device_create_release(struct device *dev)
struct device *tty_register_device_attr(struct tty_driver *driver,
unsigned index, struct device *device,
void *drvdata,
- const struct attribute_group **attr_grp)
+ const struct attribute_group *const*attr_grp)
{
char name[64];
dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 624d104bd145..f0f95e64ca64 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -158,7 +158,7 @@ EXPORT_SYMBOL_GPL(tty_port_register_device);
struct device *tty_port_register_device_attr(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
- const struct attribute_group **attr_grp)
+ const struct attribute_group *const*attr_grp)
{
tty_port_link_device(port, driver, index);
return tty_register_device_attr(driver, index, device, drvdata,
@@ -181,7 +181,7 @@ EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
- const struct attribute_group **attr_grp)
+ const struct attribute_group *const*attr_grp)
{
struct device *dev;

diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 138676463336..4e14df4da39d 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -180,7 +180,7 @@ int sysfs_create_group(struct kobject *kobj,
EXPORT_SYMBOL_GPL(sysfs_create_group);

static int internal_create_groups(struct kobject *kobj, int update,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
int error = 0;
int i;
@@ -213,7 +213,7 @@ static int internal_create_groups(struct kobject *kobj, int update,
* Returns 0 on success or error code from sysfs_create_group on failure.
*/
int sysfs_create_groups(struct kobject *kobj,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
return internal_create_groups(kobj, 0, groups);
}
@@ -231,7 +231,7 @@ EXPORT_SYMBOL_GPL(sysfs_create_groups);
* Returns 0 on success or error code from sysfs_update_group on failure.
*/
int sysfs_update_groups(struct kobject *kobj,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
return internal_create_groups(kobj, 1, groups);
}
@@ -306,7 +306,7 @@ EXPORT_SYMBOL_GPL(sysfs_remove_group);
* If groups is not NULL, remove the specified groups from the kobject.
*/
void sysfs_remove_groups(struct kobject *kobj,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
int i;

@@ -561,7 +561,7 @@ EXPORT_SYMBOL_GPL(sysfs_group_change_owner);
* Returns 0 on success or error code on failure.
*/
int sysfs_groups_change_owner(struct kobject *kobj,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
kuid_t kuid, kgid_t kgid)
{
int error = 0, i;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index eef450f25982..7917b072775e 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -729,7 +729,7 @@ static inline unsigned int blk_queue_depth(struct request_queue *q)
for (; _bio; _bio = _bio->bi_next)

int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
static inline int __must_check add_disk(struct gendisk *disk)
{
return device_add_disk(NULL, disk, NULL);
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index a269fffaf991..5dbe3883c02f 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -157,7 +157,7 @@ struct coresight_desc {
const struct coresight_ops *ops;
struct coresight_platform_data *pdata;
struct device *dev;
- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;
const char *name;
struct csdev_access access;
};
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 0abd60a7987b..612955f50ed7 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -78,7 +78,7 @@ extern ssize_t cpu_show_gds(struct device *dev,

extern __printf(4, 5)
struct device *cpu_device_create(struct device *parent, void *drvdata,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
const char *fmt, ...);
#ifdef CONFIG_HOTPLUG_CPU
extern void unregister_cpu(struct cpu *cpu);
diff --git a/include/linux/device.h b/include/linux/device.h
index 56d93a1ffb7b..cf6ee60ecdb4 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -73,9 +73,9 @@ int subsys_interface_register(struct subsys_interface *sif);
void subsys_interface_unregister(struct subsys_interface *sif);

int subsys_system_register(struct bus_type *subsys,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
int subsys_virtual_register(struct bus_type *subsys,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);

/*
* The type of device, "struct device" is embedded in. A class
@@ -88,7 +88,7 @@ int subsys_virtual_register(struct bus_type *subsys,
*/
struct device_type {
const char *name;
- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;
int (*uevent)(const struct device *dev, struct kobj_uevent_env *env);
char *(*devnode)(const struct device *dev, umode_t *mode,
kuid_t *uid, kgid_t *gid);
@@ -782,7 +782,7 @@ struct device {
struct list_head devres_head;

const struct class *class;
- const struct attribute_group **groups; /* optional groups */
+ const struct attribute_group *const*groups; /* optional groups */

void (*release)(struct device *dev);
struct iommu_group *iommu_group;
@@ -1177,14 +1177,14 @@ device_create(const struct class *cls, struct device *parent, dev_t devt,
void *drvdata, const char *fmt, ...);
__printf(6, 7) struct device *
device_create_with_groups(const struct class *cls, struct device *parent, dev_t devt,
- void *drvdata, const struct attribute_group **groups,
+ void *drvdata, const struct attribute_group *const*groups,
const char *fmt, ...);
void device_destroy(const struct class *cls, dev_t devt);

int __must_check device_add_groups(struct device *dev,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
void device_remove_groups(struct device *dev,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);

static inline int __must_check device_add_group(struct device *dev,
const struct attribute_group *grp)
@@ -1203,7 +1203,7 @@ static inline void device_remove_group(struct device *dev,
}

int __must_check devm_device_add_groups(struct device *dev,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
int __must_check devm_device_add_group(struct device *dev,
const struct attribute_group *grp);

diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h
index ae10c4322754..5867948b64ca 100644
--- a/include/linux/device/bus.h
+++ b/include/linux/device/bus.h
@@ -80,9 +80,9 @@ struct fwnode_handle;
struct bus_type {
const char *name;
const char *dev_name;
- const struct attribute_group **bus_groups;
- const struct attribute_group **dev_groups;
- const struct attribute_group **drv_groups;
+ const struct attribute_group *const*bus_groups;
+ const struct attribute_group *const*dev_groups;
+ const struct attribute_group *const*drv_groups;

int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(const struct device *dev, struct kobj_uevent_env *env);
diff --git a/include/linux/device/class.h b/include/linux/device/class.h
index abf3d3bfb6fe..649020a67b87 100644
--- a/include/linux/device/class.h
+++ b/include/linux/device/class.h
@@ -52,8 +52,8 @@ struct fwnode_handle;
struct class {
const char *name;

- const struct attribute_group **class_groups;
- const struct attribute_group **dev_groups;
+ const struct attribute_group *const*class_groups;
+ const struct attribute_group *const*dev_groups;

int (*dev_uevent)(const struct device *dev, struct kobj_uevent_env *env);
char *(*devnode)(const struct device *dev, umode_t *mode);
diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h
index 7738f458995f..cb8171124bbf 100644
--- a/include/linux/device/driver.h
+++ b/include/linux/device/driver.h
@@ -112,8 +112,8 @@ struct device_driver {
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
- const struct attribute_group **groups;
- const struct attribute_group **dev_groups;
+ const struct attribute_group *const*groups;
+ const struct attribute_group *const*dev_groups;

const struct dev_pm_ops *pm;
void (*coredump) (struct device *dev);
diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
index 8cd6a6b33593..fa3f3a6be5b5 100644
--- a/include/linux/hwmon.h
+++ b/include/linux/hwmon.h
@@ -453,16 +453,16 @@ struct device *hwmon_device_register(struct device *dev);
struct device *
hwmon_device_register_with_groups(struct device *dev, const char *name,
void *drvdata,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
struct device *
devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
void *drvdata,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
struct device *
hwmon_device_register_with_info(struct device *dev,
const char *name, void *drvdata,
const struct hwmon_chip_info *info,
- const struct attribute_group **extra_groups);
+ const struct attribute_group *const*extra_groups);
struct device *
hwmon_device_register_for_thermal(struct device *dev, const char *name,
void *drvdata);
@@ -470,7 +470,7 @@ struct device *
devm_hwmon_device_register_with_info(struct device *dev,
const char *name, void *drvdata,
const struct hwmon_chip_info *info,
- const struct attribute_group **extra_groups);
+ const struct attribute_group *const*extra_groups);

void hwmon_device_unregister(struct device *dev);
void devm_hwmon_device_unregister(struct device *dev);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index c50a769d569a..4169cfca3098 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -441,7 +441,7 @@ int iommu_device_register(struct iommu_device *iommu,
void iommu_device_unregister(struct iommu_device *iommu);
int iommu_device_sysfs_add(struct iommu_device *iommu,
struct device *parent,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
const char *fmt, ...) __printf(4, 5);
void iommu_device_sysfs_remove(struct iommu_device *iommu);
int iommu_device_link(struct iommu_device *iommu, struct device *link);
@@ -975,7 +975,7 @@ static inline void iommu_device_unregister(struct iommu_device *iommu)

static inline int iommu_device_sysfs_add(struct iommu_device *iommu,
struct device *parent,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
const char *fmt, ...)
{
return -ENODEV;
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index c30affcc43b4..989afe775880 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -116,7 +116,7 @@ char *kobject_get_path(const struct kobject *kobj, gfp_t flag);
struct kobj_type {
void (*release)(struct kobject *kobj);
const struct sysfs_ops *sysfs_ops;
- const struct attribute_group **default_groups;
+ const struct attribute_group *const*default_groups;
const struct kobj_ns_type_operations *(*child_ns_type)(const struct kobject *kobj);
const void *(*namespace)(const struct kobject *kobj);
void (*get_ownership)(const struct kobject *kobj, kuid_t *uid, kgid_t *gid);
diff --git a/include/linux/leds.h b/include/linux/leds.h
index aa16dc2a8230..6d84f5eb0883 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -166,7 +166,7 @@ struct led_classdev {
int (*pattern_clear)(struct led_classdev *led_cdev);

struct device *dev;
- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;

struct list_head node; /* LED Device list */
const char *default_trigger; /* Trigger to use */
@@ -484,7 +484,7 @@ struct led_trigger {
/* Link to next registered trigger */
struct list_head next_trig;

- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;
};

/*
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index e772aae71843..7c629ee16215 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -82,7 +82,7 @@ typedef int (*ndctl_fn)(struct nvdimm_bus_descriptor *nd_desc,

struct device_node;
struct nvdimm_bus_descriptor {
- const struct attribute_group **attr_groups;
+ const struct attribute_group *const*attr_groups;
unsigned long cmd_mask;
unsigned long dimm_family_mask;
unsigned long bus_family_mask;
@@ -126,7 +126,7 @@ struct nd_region_desc {
struct resource *res;
struct nd_mapping_desc *mapping;
u16 num_mappings;
- const struct attribute_group **attr_groups;
+ const struct attribute_group *const*attr_groups;
struct nd_interleave_set *nd_set;
void *provider_data;
int num_lanes;
@@ -259,13 +259,13 @@ struct kobject *nvdimm_kobj(struct nvdimm *nvdimm);
unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm);
void *nvdimm_provider_data(struct nvdimm *nvdimm);
struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
- void *provider_data, const struct attribute_group **groups,
+ void *provider_data, const struct attribute_group *const*groups,
unsigned long flags, unsigned long cmd_mask, int num_flush,
struct resource *flush_wpq, const char *dimm_id,
const struct nvdimm_security_ops *sec_ops,
const struct nvdimm_fw_ops *fw_ops);
static inline struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus,
- void *provider_data, const struct attribute_group **groups,
+ void *provider_data, const struct attribute_group *const*groups,
unsigned long flags, unsigned long cmd_mask, int num_flush,
struct resource *flush_wpq)
{
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index c0fea6ca5076..32b0caf86cd1 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -83,7 +83,7 @@ struct miscdevice {
struct list_head list;
struct device *parent;
struct device *this_device;
- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;
const char *nodename;
umode_t mode;
};
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8c7c2c3c6c65..57dbfd890ae7 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -928,8 +928,8 @@ struct pci_driver {
int (*sriov_set_msix_vec_count)(struct pci_dev *vf, int msix_vec_count); /* On PF */
u32 (*sriov_get_vf_total_msix)(struct pci_dev *pf);
const struct pci_error_handlers *err_handler;
- const struct attribute_group **groups;
- const struct attribute_group **dev_groups;
+ const struct attribute_group *const*groups;
+ const struct attribute_group *const*dev_groups;
struct device_driver driver;
struct pci_dynids dynids;
bool driver_managed_dma;
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index e85cd1c0eaf3..e9d68c611974 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -306,7 +306,7 @@ struct pmu {
struct device *dev;
struct device *parent;
const struct attribute_group **attr_groups;
- const struct attribute_group **attr_update;
+ const struct attribute_group *const*attr_update;
const char *name;
int type;

diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index a427f13c757f..b7f592a20729 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -232,7 +232,7 @@ struct power_supply_config {
void *drv_data;

/* Device specific sysfs attributes */
- const struct attribute_group **attr_grp;
+ const struct attribute_group *const*attr_grp;

char **supplied_to;
size_t num_supplicants;
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 4c0bcbeb1f00..f72e70186b2f 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -247,7 +247,7 @@ static inline int devm_rtc_nvmem_register(struct rtc_device *rtc,

#ifdef CONFIG_RTC_INTF_SYSFS
int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp);
-int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps);
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group *const*grps);
#else
static inline
int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
@@ -256,7 +256,7 @@ int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
}

static inline
-int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group *const*grps)
{
return 0;
}
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index fd3fe5c8c17f..2b97fb34204b 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -307,15 +307,15 @@ void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
int __must_check sysfs_create_group(struct kobject *kobj,
const struct attribute_group *grp);
int __must_check sysfs_create_groups(struct kobject *kobj,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
int __must_check sysfs_update_groups(struct kobject *kobj,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
int sysfs_update_group(struct kobject *kobj,
const struct attribute_group *grp);
void sysfs_remove_group(struct kobject *kobj,
const struct attribute_group *grp);
void sysfs_remove_groups(struct kobject *kobj,
- const struct attribute_group **groups);
+ const struct attribute_group *const*groups);
int sysfs_add_file_to_group(struct kobject *kobj,
const struct attribute *attr, const char *group);
void sysfs_remove_file_from_group(struct kobject *kobj,
@@ -348,7 +348,7 @@ int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid);
int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ,
const char *name, kuid_t kuid, kgid_t kgid);
int sysfs_groups_change_owner(struct kobject *kobj,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
kuid_t kuid, kgid_t kgid);
int sysfs_group_change_owner(struct kobject *kobj,
const struct attribute_group *groups, kuid_t kuid,
@@ -487,13 +487,13 @@ static inline int sysfs_create_group(struct kobject *kobj,
}

static inline int sysfs_create_groups(struct kobject *kobj,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
return 0;
}

static inline int sysfs_update_groups(struct kobject *kobj,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
return 0;
}
@@ -510,7 +510,7 @@ static inline void sysfs_remove_group(struct kobject *kobj,
}

static inline void sysfs_remove_groups(struct kobject *kobj,
- const struct attribute_group **groups)
+ const struct attribute_group *const*groups)
{
}

@@ -591,7 +591,7 @@ static inline int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t k
}

static inline int sysfs_groups_change_owner(struct kobject *kobj,
- const struct attribute_group **groups,
+ const struct attribute_group *const*groups,
kuid_t kuid, kgid_t kgid)
{
return 0;
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 18beff0cec1a..3041bebb1051 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -571,7 +571,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
struct device *dev);
struct device *tty_register_device_attr(struct tty_driver *driver,
unsigned index, struct device *device, void *drvdata,
- const struct attribute_group **attr_grp);
+ const struct attribute_group *const*attr_grp);
void tty_unregister_device(struct tty_driver *driver, unsigned index);

#ifdef CONFIG_PROC_FS
diff --git a/include/linux/tty_port.h b/include/linux/tty_port.h
index 6b367eb17979..811aa134150c 100644
--- a/include/linux/tty_port.h
+++ b/include/linux/tty_port.h
@@ -146,14 +146,14 @@ struct device *tty_port_register_device(struct tty_port *port,
struct device *tty_port_register_device_attr(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
- const struct attribute_group **attr_grp);
+ const struct attribute_group *const*attr_grp);
struct device *tty_port_register_device_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device);
struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
- const struct attribute_group **attr_grp);
+ const struct attribute_group *const*attr_grp);
void tty_port_unregister_device(struct tty_port *port,
struct tty_driver *driver, unsigned index);
int tty_port_alloc_xmit_buf(struct tty_port *port);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index a21074861f91..321ded34928f 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1239,7 +1239,7 @@ struct usb_driver {
int (*post_reset)(struct usb_interface *intf);

const struct usb_device_id *id_table;
- const struct attribute_group **dev_groups;
+ const struct attribute_group *const*dev_groups;

struct usb_dynids dynids;
struct usbdrv_wrap drvwrap;
@@ -1287,7 +1287,7 @@ struct usb_device_driver {

int (*suspend) (struct usb_device *udev, pm_message_t message);
int (*resume) (struct usb_device *udev, pm_message_t message);
- const struct attribute_group **dev_groups;
+ const struct attribute_group *const*dev_groups;
struct usbdrv_wrap drvwrap;
const struct usb_device_id *id_table;
unsigned int supports_autosuspend:1;
diff --git a/include/linux/w1.h b/include/linux/w1.h
index 9a2a0ef39018..0c86a9ed7013 100644
--- a/include/linux/w1.h
+++ b/include/linux/w1.h
@@ -253,7 +253,7 @@ void w1_remove_master_device(struct w1_bus_master *master);
struct w1_family_ops {
int (*add_slave)(struct w1_slave *sl);
void (*remove_slave)(struct w1_slave *sl);
- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;
const struct hwmon_chip_info *chip_info;
};

diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index 99660197a36c..1f4a0fae13ab 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -94,7 +94,7 @@ struct watchdog_ops {
struct watchdog_device {
int id;
struct device *parent;
- const struct attribute_group **groups;
+ const struct attribute_group *const*groups;
const struct watchdog_info *info;
const struct watchdog_ops *ops;
const struct watchdog_governor *gov;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 533ab92684d8..1a9511b99506 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2343,7 +2343,7 @@ struct ib_device_ops {
* mechanism exists only for existing drivers.
*/
const struct attribute_group *device_group;
- const struct attribute_group **port_groups;
+ const struct attribute_group *const*port_groups;

int (*post_send)(struct ib_qp *qp, const struct ib_send_wr *send_wr,
const struct ib_send_wr **bad_send_wr);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 4c2dc8150c6d..c9da91e96232 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -478,13 +478,13 @@ struct scsi_host_template {
/*
* Pointer to the SCSI host sysfs attribute groups, NULL terminated.
*/
- const struct attribute_group **shost_groups;
+ const struct attribute_group *const*shost_groups;

/*
* Pointer to the SCSI device attribute groups for this host,
* NULL terminated.
*/
- const struct attribute_group **sdev_groups;
+ const struct attribute_group *const*sdev_groups;

/*
* Vendor Identifier associated with the host
--
2.39.2

2023-10-09 17:19:14

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH 2/7] drivers/hwmon: add local variable for newly allocated attribute_group**

On Mon, Oct 09, 2023 at 06:57:35PM +0200, Max Kellermann wrote:
> This allows the compiler to keep the pointer in a register and
> prepares for making the struct field "const".
>
> Signed-off-by: Max Kellermann <[email protected]>

I have no idea what this is about, and I don't see how that would
improve anything, but ...

> ---
> drivers/hwmon/hwmon.c | 11 ++++++-----
> 1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
> index c7dd3f5b2bd5..e50ab229b27d 100644
> --- a/drivers/hwmon/hwmon.c
> +++ b/drivers/hwmon/hwmon.c
> @@ -783,6 +783,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
> hdev = &hwdev->dev;
>
> if (chip) {
> + const struct attribute_group **new_groups;
> struct attribute **attrs;
> int ngroups = 2; /* terminating NULL plus &hwdev->groups */
>
> @@ -790,8 +791,8 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
> for (i = 0; groups[i]; i++)
> ngroups++;
>
> - hwdev->groups = kcalloc(ngroups, sizeof(*groups), GFP_KERNEL);
> - if (!hwdev->groups) {
> + hwdev->groups = new_groups = kcalloc(ngroups, sizeof(*new_groups), GFP_KERNEL);

CHECK: multiple assignments should be avoided
#101: FILE: drivers/hwmon/hwmon.c:794:
+ hwdev->groups = new_groups = kcalloc(ngroups, sizeof(*new_groups), GFP_KERNEL);

either case, this change is not acceptable.

Guenter

2023-10-09 17:24:10

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 1/7] drivers/rtc/sysfs: move code to count_attribute_groups()

On Mon, Oct 09, 2023 at 06:57:34PM +0200, Max Kellermann wrote:
> This avoids overloading the "groups" variable for three different
> purposes

What 3 different purposes?

And you sent a patch series that hit a lot of different subsystems and
maintainers all at once, but you didn't cc: all of us. Who is supposed
to take these?

But step back, _WHY_ are all of these changes needed? I don't see a
cover letter explaining the rational, and on their own, they really
don't do anything, so it's really confusing as to what is going on here.

thanks,

greg k-h

2023-10-09 17:24:58

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Mon, Oct 09, 2023 at 06:57:39PM +0200, Max Kellermann wrote:
> This allows passing arrays of const pointers. The goal is to make
> lots of global variables "const" to allow them to live in the
> ".rodata" section.
>
> Signed-off-by: Max Kellermann <[email protected]>

In my opinion this touches way too many subsystems in a single patch.
If someting is wrong with just one of the changes, it will be all but
impossible to revert the whole thing.

Also, I don't know why checkpatch is happy with all the

const struct attribute_group *const*groups;

instead of

const struct attribute_group *const *groups;

but I still don't like it.

Guenter

2023-10-09 17:26:24

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Mon, Oct 09, 2023 at 06:57:39PM +0200, Max Kellermann wrote:
> This allows passing arrays of const pointers. The goal is to make
> lots of global variables "const" to allow them to live in the
> ".rodata" section.

I'm all for doing this type of work, but this is going to be rough. You
sent patch 6/7 that hit almost all subsystems at once :(

Also, the code:

> -int driver_add_groups(struct device_driver *drv, const struct attribute_group **groups);
> -void driver_remove_groups(struct device_driver *drv, const struct attribute_group **groups);
> +int driver_add_groups(struct device_driver *drv, const struct attribute_group *const*groups);
> +void driver_remove_groups(struct device_driver *drv, const struct attribute_group *const*groups);
> void device_driver_detach(struct device *dev);

"*const*groups"? That's a parsing nightmare, really hard for humans to
read and understand. Doesn't checkpatch complain about this?

thanks,

greg k-h

2023-10-09 17:28:11

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 2/7] drivers/hwmon: add local variable for newly allocated attribute_group**

On Mon, Oct 09, 2023 at 06:57:35PM +0200, Max Kellermann wrote:
> This allows the compiler to keep the pointer in a register and

Maybe, maybe not, there's no guarantee for register usage.

And it doesn't matter, this is a very slow path, no registers are
required :)

> prepares for making the struct field "const".

What struct field?


>
> Signed-off-by: Max Kellermann <[email protected]>
> ---
> drivers/hwmon/hwmon.c | 11 ++++++-----
> 1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
> index c7dd3f5b2bd5..e50ab229b27d 100644
> --- a/drivers/hwmon/hwmon.c
> +++ b/drivers/hwmon/hwmon.c
> @@ -783,6 +783,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
> hdev = &hwdev->dev;
>
> if (chip) {
> + const struct attribute_group **new_groups;
> struct attribute **attrs;
> int ngroups = 2; /* terminating NULL plus &hwdev->groups */
>
> @@ -790,8 +791,8 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
> for (i = 0; groups[i]; i++)
> ngroups++;
>
> - hwdev->groups = kcalloc(ngroups, sizeof(*groups), GFP_KERNEL);
> - if (!hwdev->groups) {
> + hwdev->groups = new_groups = kcalloc(ngroups, sizeof(*new_groups), GFP_KERNEL);

So you have a const pointer AND a non-const pointer pointing to the same
thing?


> + if (!new_groups) {
> err = -ENOMEM;
> goto free_hwmon;
> }
> @@ -804,14 +805,14 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
>
> hwdev->group.attrs = attrs;
> ngroups = 0;
> - hwdev->groups[ngroups++] = &hwdev->group;
> + new_groups[ngroups++] = &hwdev->group;

This shoul be identical, you assign both above the same way, so why
change this?

>
> if (groups) {
> for (i = 0; groups[i]; i++)
> - hwdev->groups[ngroups++] = groups[i];
> + new_groups[ngroups++] = groups[i];

Same here.

thanks,

greg k-h

2023-10-09 17:28:23

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 3/7] drivers/extcon: add local variable for newly allocated attribute_group**

On Mon, Oct 09, 2023 at 06:57:36PM +0200, Max Kellermann wrote:
> This allows the compiler to keep the pointer in a register and
> prepares for making the struct field "const".

Again, registers have nothing to do with this.

thanks,

greg k-h

2023-10-09 17:28:38

by Max Kellermann

[permalink] [raw]
Subject: Re: [PATCH 2/7] drivers/hwmon: add local variable for newly allocated attribute_group**

On Mon, Oct 9, 2023 at 7:19 PM Guenter Roeck <[email protected]> wrote:
> I have no idea what this is about, and I don't see how that would
> improve anything, but ...

Later, we can make lots of global variables "const", which puts them
in ".rodata" (write-protected at runtime). This is some
micro-hardening.

> CHECK: multiple assignments should be avoided
> #101: FILE: drivers/hwmon/hwmon.c:794:
> + hwdev->groups = new_groups = kcalloc(ngroups, sizeof(*new_groups), GFP_KERNEL);

What program emitted this warning? checkpatch.pl had no error. I'll
change it in all patches.

> either case, this change is not acceptable.

Because of the multi-assignment, or is there something else?

2023-10-09 17:28:49

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 4/7] drivers/counter: add local variable for newly allocated attribute_group**

On Mon, Oct 09, 2023 at 06:57:37PM +0200, Max Kellermann wrote:
> This allows the compiler to keep the pointer in a register and
> prepares for making the struct field "const".

Again, nothing about registers makes sense here.

thanks,

greg k-h

2023-10-09 17:29:10

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 5/7] drivers/tty/serial_core: add local variable for newly allocated attribute_group**

On Mon, Oct 09, 2023 at 06:57:38PM +0200, Max Kellermann wrote:
> This allows the compiler to keep the pointer in a register and
> prepares for making the struct field "const".

You know what I'm going to say...

2023-10-09 17:31:01

by Max Kellermann

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Mon, Oct 9, 2023 at 7:26 PM Greg Kroah-Hartman
<[email protected]> wrote:
> I'm all for doing this type of work, but this is going to be rough. You
> sent patch 6/7 that hit almost all subsystems at once :(

I wasn't sure whether splitting patches was desired. In the past, I
was often asked to fold multiple patches into one. There are so many
opinions :-) but I'll gladly change to whatever is asked.

> "*const*groups"? That's a parsing nightmare, really hard for humans to
> read and understand. Doesn't checkpatch complain about this?

No. I'll change the coding style (and maybe take some time to fix checkpatch?)

2023-10-09 17:31:32

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 7/7] block, drivers: make lots of attribute_group globals const

On Mon, Oct 09, 2023 at 06:57:40PM +0200, Max Kellermann wrote:
> This moves those variables to the ".rodata" section which reduces the
> kernel size a bit and protects the variables by putting them on
> read-only pages at runtime.

The kernel size should still be the same overall, you are just moving
pointers from one section to another, right?

If not, what are the numbers, show them please.

But step back, are you SURE you can make these attribute group pointers
const? They are modified by some subsystems by adding or removing items
from the lists, so why does the core need to change for that?

thanks,

greg k-h

2023-10-09 17:32:17

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Mon, Oct 09, 2023 at 07:25:57PM +0200, Greg Kroah-Hartman wrote:
> On Mon, Oct 09, 2023 at 06:57:39PM +0200, Max Kellermann wrote:
> > This allows passing arrays of const pointers. The goal is to make
> > lots of global variables "const" to allow them to live in the
> > ".rodata" section.
>
> I'm all for doing this type of work, but this is going to be rough. You
> sent patch 6/7 that hit almost all subsystems at once :(

The way to do this right is one-subsystem-at-a-time, right? Why not
start there, doing it cleanly, and then at the end, change the driver
core and then just the subsystem pointers? That should be much simpler,
easier to review and verify, and many more changes (and probably take a
kernel release or two to get through.)

thanks,

greg k-h

2023-10-09 17:34:47

by Max Kellermann

[permalink] [raw]
Subject: Re: [PATCH 2/7] drivers/hwmon: add local variable for newly allocated attribute_group**

On Mon, Oct 9, 2023 at 7:27 PM Greg KH <[email protected]> wrote:
>
> On Mon, Oct 09, 2023 at 06:57:35PM +0200, Max Kellermann wrote:
> > This allows the compiler to keep the pointer in a register and
>
> Maybe, maybe not, there's no guarantee for register usage.

Agree. But without this change, register usage is effectively
prevented (much of the time). With this change, there is a chance for
better code. Yeah, it's not a critical code path, and it's only a tiny
tiny optimization - but the real reason for this patch is ....

> > - hwdev->groups = kcalloc(ngroups, sizeof(*groups), GFP_KERNEL);
> > - if (!hwdev->groups) {
> > + hwdev->groups = new_groups = kcalloc(ngroups, sizeof(*new_groups), GFP_KERNEL);
>
> So you have a const pointer AND a non-const pointer pointing to the same
> thing?

.... so I can make "hwdev->groups" const, which wouldn't allow
modifying it. (This isn't obvious in this one patch, but a later patch
in the series does this.)

There are only few functions which allocate a new pointer-array
dynamically; all others are global variables which currently cannot be
"const". This patch set does some lifting to allow adding "const".

2023-10-09 17:40:32

by Max Kellermann

[permalink] [raw]
Subject: Re: [PATCH 7/7] block, drivers: make lots of attribute_group globals const

On Mon, Oct 9, 2023 at 7:30 PM Greg Kroah-Hartman
<[email protected]> wrote:
>
> On Mon, Oct 09, 2023 at 06:57:40PM +0200, Max Kellermann wrote:
> > This moves those variables to the ".rodata" section which reduces the
> > kernel size a bit and protects the variables by putting them on
> > read-only pages at runtime.
>
> The kernel size should still be the same overall, you are just moving
> pointers from one section to another, right?
>
> If not, what are the numbers, show them please.

Before this patch series:

text data bss dec hex filename
10645342 6836166 12476420 29957928 1c91f28 vmlinux

After:

text data bss dec hex filename
10645342 6835398 12476420 29957160 1c91c28 vmlinux

(Config attached if you wish to reproduce. I'm using stock GCC from
Debian Bookworm.)

It's only a few hundred bytes, and I havn't really dug deep enough to
explain to you why this is - my goal was (semantic) const-correctness
and .rodata protection, but those numbers are a side effect that
exists.


> But step back, are you SURE you can make these attribute group pointers
> const? They are modified by some subsystems by adding or removing items
> from the lists, so why does the core need to change for that?

Some few do modify them, but they do not modify those pointers; they
allocate a new one (the 3 I sbumitted a patch for) or they modify
global variables (arch/pmu) which I'm not going to make "const". But
most globals can indeed be made "const".


Attachments:
.config (79.26 kB)

2023-10-09 18:02:14

by Max Kellermann

[permalink] [raw]
Subject: Re: [PATCH 1/7] drivers/rtc/sysfs: move code to count_attribute_groups()

On Mon, Oct 9, 2023 at 7:24 PM Greg KH <[email protected]> wrote:
> What 3 different purposes?

The variable gets initialized 3 times with different (unrelated) values:

1. count old rtc->dev.groups
2. count grps
3. allocate new rtc->dev.groups

This coding style is confusing and error prone. The code gets simpler
with this patch, because the cognitive load of understanding a
"count_attribute_groups()" call is lower than reading the "while" loop
and figuring out why it's there.

But I really wrote this patch because after making "rtc->dev.groups"
const, I cannot any longer assign it to "groups", because that
variable must remain non-const.

2023-10-09 19:37:06

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH 2/7] drivers/hwmon: add local variable for newly allocated attribute_group**

On Mon, Oct 09, 2023 at 07:28:03PM +0200, Max Kellermann wrote:
> On Mon, Oct 9, 2023 at 7:19 PM Guenter Roeck <[email protected]> wrote:
> > I have no idea what this is about, and I don't see how that would
> > improve anything, but ...
>
> Later, we can make lots of global variables "const", which puts them
> in ".rodata" (write-protected at runtime). This is some
> micro-hardening.
>
> > CHECK: multiple assignments should be avoided
> > #101: FILE: drivers/hwmon/hwmon.c:794:
> > + hwdev->groups = new_groups = kcalloc(ngroups, sizeof(*new_groups), GFP_KERNEL);
>
> What program emitted this warning? checkpatch.pl had no error. I'll
> change it in all patches.

I doubt that you ran checkpatch --strict. That check has existed in checkpatch
at least since 2007.

Also, process/coding-style.rst says:

Don't put multiple assignments on a single line either. Kernel coding style
is super simple. Avoid tricky expressions.

As far as I know that guildeline has not changed.

Now, you might argue something like "who cares about checkpatch --strict",
but in Documentation/hwmon/submitting-patches.rst we specifically say

* Please run your patch through 'checkpatch --strict'. There should be no
errors, no warnings, and few if any check messages. If there are any
messages, please be prepared to explain.

So, please explain why this message and with it the coding style violation
should be ignored.

>
> > either case, this change is not acceptable.
>
> Because of the multi-assignment, or is there something else?

I don't really see the benefit of this code, and I am not sure if the
explanation about compiler optimization is really valid. It makes me
want to run some test compliations to see if the claim is really true,
and I really don't have time for that.

Also, as Greg points out, this is not in a hot code path but executed
exactly once for each hwmon device, so making such a change with a reason
like that just invites lots of follow-up patches with similar reasons,
and then the submitters of those can point to this patch and argue
"but you accepted that one". You say "micro-hardening" above, but for
me it is time consuming micro-optimization.

Guenter

2023-10-09 20:06:28

by Max Kellermann

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Mon, Oct 9, 2023 at 7:24 PM Guenter Roeck <[email protected]> wrote:
> Also, I don't know why checkpatch is happy with all the
>
> const struct attribute_group *const*groups;
>
> instead of
>
> const struct attribute_group *const *groups;

I found out that checkpatch has no check for this at all; it does
complain about such lines, but only for local variables. But that
warning is actually a bug, because this is a check for unary
operators: it thinks the asterisk is a dereference operator, not a
pointer declaration, and complains that the unary operator must be
preceded by a space. Thus warnings on local variable are only correct
by coincidence, not by design.

Inside structs or parameters (where my coding style violations can be
found), it's a different context and thus checkpatch doesn't apply the
rules for unary operators.

2023-10-09 20:21:01

by Max Kellermann

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Mon, Oct 9, 2023 at 7:26 PM Greg Kroah-Hartman
<[email protected]> wrote:
> "*const*groups"? That's a parsing nightmare, really hard for humans to
> read and understand. Doesn't checkpatch complain about this?

No, checkpatch does not implement a check/warning for this style (see
my other email). There's no rule for this in coding-style.rst. Should
there be one?

2023-10-10 05:59:34

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Mon, Oct 09, 2023 at 10:05:55PM +0200, Max Kellermann wrote:
> On Mon, Oct 9, 2023 at 7:24 PM Guenter Roeck <[email protected]> wrote:
> > Also, I don't know why checkpatch is happy with all the
> >
> > const struct attribute_group *const*groups;
> >
> > instead of
> >
> > const struct attribute_group *const *groups;
>
> I found out that checkpatch has no check for this at all; it does
> complain about such lines, but only for local variables. But that
> warning is actually a bug, because this is a check for unary
> operators: it thinks the asterisk is a dereference operator, not a
> pointer declaration, and complains that the unary operator must be
> preceded by a space. Thus warnings on local variable are only correct
> by coincidence, not by design.
>
> Inside structs or parameters (where my coding style violations can be
> found), it's a different context and thus checkpatch doesn't apply the
> rules for unary operators.

Ok, checkpatch support isn't always required, we can notice that changes
like this obviously are not sane and shouldn't be allowed just by
reading them :)

thanks,

greg k-h

2023-10-10 06:49:10

by Joe Perches

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Mon, 2023-10-09 at 22:05 +0200, Max Kellermann wrote:
> On Mon, Oct 9, 2023 at 7:24 PM Guenter Roeck <[email protected]> wrote:
> > Also, I don't know why checkpatch is happy with all the
> >
> > const struct attribute_group *const*groups;
> >
> > instead of
> >
> > const struct attribute_group *const *groups;
>
> I found out that checkpatch has no check for this at all; it does
> complain about such lines, but only for local variables. But that
> warning is actually a bug, because this is a check for unary
> operators: it thinks the asterisk is a dereference operator, not a
> pointer declaration, and complains that the unary operator must be
> preceded by a space. Thus warnings on local variable are only correct
> by coincidence, not by design.
>
> Inside structs or parameters (where my coding style violations can be
> found), it's a different context and thus checkpatch doesn't apply the
> rules for unary operators.

My opinion is that const use in the kernel should almost
always have whitespace before and after it except when
preceded by a open parenthesis or a newline.

$ git grep -wh const -- '*.[ch]' | \
grep -oP "[ \*\(]?const[ \*]?" | \
sort | uniq -c | sort -rn
222438 const
83386 const
51667 (const
2766 *const
834 const
442 const
343 const*
88 *const
37 (const
4 *const*

2023-10-10 06:58:26

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Mon, Oct 09, 2023 at 11:48:10PM -0700, Joe Perches wrote:
> On Mon, 2023-10-09 at 22:05 +0200, Max Kellermann wrote:
> > On Mon, Oct 9, 2023 at 7:24 PM Guenter Roeck <[email protected]> wrote:
> > > Also, I don't know why checkpatch is happy with all the
> > >
> > > const struct attribute_group *const*groups;
> > >
> > > instead of
> > >
> > > const struct attribute_group *const *groups;
> >
> > I found out that checkpatch has no check for this at all; it does
> > complain about such lines, but only for local variables. But that
> > warning is actually a bug, because this is a check for unary
> > operators: it thinks the asterisk is a dereference operator, not a
> > pointer declaration, and complains that the unary operator must be
> > preceded by a space. Thus warnings on local variable are only correct
> > by coincidence, not by design.
> >
> > Inside structs or parameters (where my coding style violations can be
> > found), it's a different context and thus checkpatch doesn't apply the
> > rules for unary operators.
>
> My opinion is that const use in the kernel should almost
> always have whitespace before and after it except when
> preceded by a open parenthesis or a newline.

I totally agree.

2023-10-10 07:39:31

by Max Kellermann

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Tue, Oct 10, 2023 at 8:48 AM Joe Perches <[email protected]> wrote:
> My opinion is that const use in the kernel should almost
> always have whitespace before and after it except when
> preceded by a open parenthesis or a newline.

So it shall be "void * const foo" (16k occurrences in the kernel)
instead of "void *const foo" (3k occurrences)?

2023-10-10 08:02:30

by Joe Perches

[permalink] [raw]
Subject: Re: [PATCH 6/7] fs/sysfs/group: make attribute_group pointers const

On Tue, 2023-10-10 at 09:38 +0200, Max Kellermann wrote:
> On Tue, Oct 10, 2023 at 8:48 AM Joe Perches <[email protected]> wrote:
> > My opinion is that const use in the kernel should almost
> > always have whitespace before and after it except when
> > preceded by a open parenthesis or a newline.
>
> So it shall be "void * const foo" (16k occurrences in the kernel)
> instead of "void *const foo" (3k occurrences)?

I think so.

$ git grep -P -oh "\bconst\s*\*" | sort | uniq -c | sort -rn | head -3
2538 const *
349 const*
20 const *
$ git grep -P -oh "\*\s*const\b" | sort | uniq -c | sort -rn | head -3
16677 * const
2912 *const
8 * const

Documentation/process/coding-style.rst doesn't mention const.
Maybe it should.

2023-10-10 08:15:42

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH 1/7] drivers/rtc/sysfs: move code to count_attribute_groups()

On 09/10/2023 18:57:34+0200, Max Kellermann wrote:
> This avoids overloading the "groups" variable for three different
> purposes
>
> Signed-off-by: Max Kellermann <[email protected]>
> ---
> drivers/rtc/sysfs.c | 20 ++++++++++++--------
> 1 file changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/rtc/sysfs.c b/drivers/rtc/sysfs.c
> index e3062c4d3f2c..617933d52324 100644
> --- a/drivers/rtc/sysfs.c
> +++ b/drivers/rtc/sysfs.c
> @@ -313,21 +313,25 @@ const struct attribute_group **rtc_get_dev_attribute_groups(void)
> return rtc_attr_groups;
> }
>
> +static size_t count_attribute_groups(const struct attribute_group *const*groups)

Shouldn't that live out of the rtc subsystem?

> +{
> + size_t count = 0;
> +
> + for (; *groups; ++groups)
> + ++count;
> + return count;
> +}
> +
> int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
> {
> - size_t old_cnt = 0, add_cnt = 0, new_cnt;
> + size_t old_cnt, add_cnt, new_cnt;
> const struct attribute_group **groups, **old;
>
> if (!grps)
> return -EINVAL;
>
> - groups = rtc->dev.groups;
> - if (groups)
> - for (; *groups; groups++)
> - old_cnt++;
> -
> - for (groups = grps; *groups; groups++)
> - add_cnt++;
> + old_cnt = rtc->dev.groups ? count_attribute_groups(rtc->dev.groups) : 0;
> + add_cnt = count_attribute_groups(grps);
>
> new_cnt = old_cnt + add_cnt + 1;
> groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL);
> --
> 2.39.2
>

--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

2023-10-10 08:25:02

by Max Kellermann

[permalink] [raw]
Subject: Re: [PATCH 1/7] drivers/rtc/sysfs: move code to count_attribute_groups()

On Tue, Oct 10, 2023 at 10:15 AM Alexandre Belloni
<[email protected]> wrote:
> Shouldn't that live out of the rtc subsystem?

You suggest making this a global function? Sure, if that's preferred,
I'll change it. Whose decision is this?