From cfc94cdf8e0f14e692a5a40ef3cc10f464b2511b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 9 May 2007 13:19:52 +0200 Subject: debugfs: add rename for debugfs files Implement debugfs_rename() to allow renaming files/directories in debugfs. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- include/linux/debugfs.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include/linux') diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 5a9c49534d08..104e51e20e14 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -38,6 +38,9 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, void debugfs_remove(struct dentry *dentry); +struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, + struct dentry *new_dir, const char *new_name); + struct dentry *debugfs_create_u8(const char *name, mode_t mode, struct dentry *parent, u8 *value); struct dentry *debugfs_create_u16(const char *name, mode_t mode, @@ -85,6 +88,12 @@ static inline struct dentry *debugfs_create_symlink(const char *name, static inline void debugfs_remove(struct dentry *dentry) { } +static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, + struct dentry *new_dir, char *new_name) +{ + return ERR_PTR(-ENODEV); +} + static inline struct dentry *debugfs_create_u8(const char *name, mode_t mode, struct dentry *parent, u8 *value) -- cgit v1.2.3-71-gd317 From 4f5c791a850e5305a5b1b48d0e4b4de248dc96f9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 8 May 2007 22:07:02 +0200 Subject: DMI-based module autoloading The patch below adds DMI/SMBIOS based module autoloading to the Linux kernel. The idea is to load laptop drivers automatically (and other drivers which cannot be autoloaded otherwise), based on the DMI system identification information of the BIOS. Right now most distros manually try to load all available laptop drivers on bootup in the hope that at least one of them loads successfully. This patch does away with all that, and uses udev to automatically load matching drivers on the right machines. Basically the patch just exports the DMI information that has been parsed by the kernel anyway to userspace via a sysfs device /sys/class/dmi/id and makes sure that proper modalias attributes are available. Besides adding the "modalias" attribute it also adds attributes for a few other DMI fields which might be useful for writing udev rules. This patch is not an attempt to export the entire DMI/SMBIOS data to userspace. We already have "dmidecode" which parses the complete DMI info from userspace. The purpose of this patch is machine model identification and good udev integration. To take advantage of DMI based module autoloading, a driver should export one or more MODULE_ALIAS fields similar to these: MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*"); MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); These lines are specific to my msi-laptop.c driver. They are basically just a concatenation of a few carefully selected DMI fields with all potentially bad characters stripped. Besides laptop drivers, modules like "hdaps", the i2c modules and the hwmon modules are good candidates for "dmi:" MODULE_ALIAS lines. Besides merely exporting the DMI data via sysfs the patch adds support for a few more DMI fields. Especially the CHASSIS fields are very useful to identify different laptop modules. The patch also adds working MODULE_ALIAS lines to my msi-laptop.c driver. I'd like to thank Kay Sievers for helping me to clean up this patch for posting it on lkml. Patch is against Linus' current GIT HEAD. Should probably apply to older kernels as well without modification. Signed-off-by: Lennart Poettering Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/Kconfig | 9 ++ drivers/firmware/Makefile | 1 + drivers/firmware/dmi-id.c | 222 ++++++++++++++++++++++++++++++++++++++++++++ drivers/firmware/dmi_scan.c | 73 +++++++++++++-- drivers/misc/msi-laptop.c | 44 ++++++++- include/linux/dmi.h | 8 ++ 6 files changed, 348 insertions(+), 9 deletions(-) create mode 100644 drivers/firmware/dmi-id.c (limited to 'include/linux') diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 88f462122a30..05f02a326f1c 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -84,4 +84,13 @@ config DCDBAS Say Y or M here to enable the driver for use by Dell systems management software such as Dell OpenManage. +config DMIID + bool "Export DMI identification via sysfs to userspace" + depends on DMI + default y + help + Say Y here if you want to query SMBIOS/DMI system identification + information from userspace through /sys/class/dmi/id/ or if you want + DMI-based module auto-loading. + endmenu diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 98e395f4bb29..8d4ebc805a50 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_PCDP) += pcdp.o obj-$(CONFIG_DELL_RBU) += dell_rbu.o obj-$(CONFIG_DCDBAS) += dcdbas.o +obj-$(CONFIG_DMIID) += dmi-id.o diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c new file mode 100644 index 000000000000..59c3b5aa89f4 --- /dev/null +++ b/drivers/firmware/dmi-id.c @@ -0,0 +1,222 @@ +/* + * Export SMBIOS/DMI info via sysfs to userspace + * + * Copyright 2007, Lennart Poettering + * + * Licensed under GPLv2 + */ + +#include +#include +#include +#include +#include +#include + +#define DEFINE_DMI_ATTR(_name, _mode, _show) \ +static struct device_attribute sys_dmi_##_name##_attr = \ + __ATTR(_name, _mode, _show, NULL); + +#define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \ +static ssize_t sys_dmi_##_name##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *page) \ +{ \ + ssize_t len; \ + len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(_field)); \ + page[len-1] = '\n'; \ + return len; \ +} \ +DEFINE_DMI_ATTR(_name, _mode, sys_dmi_##_name##_show); + +DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor, 0444, DMI_BIOS_VENDOR); +DEFINE_DMI_ATTR_WITH_SHOW(bios_version, 0444, DMI_BIOS_VERSION); +DEFINE_DMI_ATTR_WITH_SHOW(bios_date, 0444, DMI_BIOS_DATE); +DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor, 0444, DMI_SYS_VENDOR); +DEFINE_DMI_ATTR_WITH_SHOW(product_name, 0444, DMI_PRODUCT_NAME); +DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION); +DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL); +DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID); +DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR); +DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME); +DEFINE_DMI_ATTR_WITH_SHOW(board_version, 0444, DMI_BOARD_VERSION); +DEFINE_DMI_ATTR_WITH_SHOW(board_serial, 0400, DMI_BOARD_SERIAL); +DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag, 0444, DMI_BOARD_ASSET_TAG); +DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor, 0444, DMI_CHASSIS_VENDOR); +DEFINE_DMI_ATTR_WITH_SHOW(chassis_type, 0444, DMI_CHASSIS_TYPE); +DEFINE_DMI_ATTR_WITH_SHOW(chassis_version, 0444, DMI_CHASSIS_VERSION); +DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial, 0400, DMI_CHASSIS_SERIAL); +DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag, 0444, DMI_CHASSIS_ASSET_TAG); + +static void ascii_filter(char *d, const char *s) +{ + /* Filter out characters we don't want to see in the modalias string */ + for (; *s; s++) + if (*s > ' ' && *s < 127 && *s != ':') + *(d++) = *s; + + *d = 0; +} + +static ssize_t get_modalias(char *buffer, size_t buffer_size) +{ + static const struct mafield { + const char *prefix; + int field; + } fields[] = { + { "bvn", DMI_BIOS_VENDOR }, + { "bvr", DMI_BIOS_VERSION }, + { "bd", DMI_BIOS_DATE }, + { "svn", DMI_SYS_VENDOR }, + { "pn", DMI_PRODUCT_NAME }, + { "pvr", DMI_PRODUCT_VERSION }, + { "rvn", DMI_BOARD_VENDOR }, + { "rn", DMI_BOARD_NAME }, + { "rvr", DMI_BOARD_VERSION }, + { "cvn", DMI_CHASSIS_VENDOR }, + { "ct", DMI_CHASSIS_TYPE }, + { "cvr", DMI_CHASSIS_VERSION }, + { NULL, DMI_NONE } + }; + + ssize_t l, left; + char *p; + const struct mafield *f; + + strcpy(buffer, "dmi"); + p = buffer + 3; left = buffer_size - 4; + + for (f = fields; f->prefix && left > 0; f++) { + const char *c; + char *t; + + c = dmi_get_system_info(f->field); + if (!c) + continue; + + t = kmalloc(strlen(c) + 1, GFP_KERNEL); + if (!t) + break; + ascii_filter(t, c); + l = scnprintf(p, left, ":%s%s", f->prefix, t); + kfree(t); + + p += l; + left -= l; + } + + p[0] = ':'; + p[1] = 0; + + return p - buffer + 1; +} + +static ssize_t sys_dmi_modalias_show(struct device *dev, + struct device_attribute *attr, char *page) +{ + ssize_t r; + r = get_modalias(page, PAGE_SIZE-1); + page[r] = '\n'; + page[r+1] = 0; + return r+1; +} + +DEFINE_DMI_ATTR(modalias, 0444, sys_dmi_modalias_show); + +static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2]; + +static struct attribute_group sys_dmi_attribute_group = { + .attrs = sys_dmi_attributes, +}; + +static struct attribute_group* sys_dmi_attribute_groups[] = { + &sys_dmi_attribute_group, + NULL +}; + +static int dmi_dev_uevent(struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size) +{ + strcpy(buffer, "MODALIAS="); + get_modalias(buffer+9, buffer_size-9); + envp[0] = buffer; + envp[1] = NULL; + + return 0; +} + +static struct class dmi_class = { + .name = "dmi", + .dev_release = (void(*)(struct device *)) kfree, + .dev_uevent = dmi_dev_uevent, +}; + +static struct device *dmi_dev; + +/* Initialization */ + +#define ADD_DMI_ATTR(_name, _field) \ + if (dmi_get_system_info(_field)) \ + sys_dmi_attributes[i++] = & sys_dmi_##_name##_attr.attr; + +extern int dmi_available; + +static int __init dmi_id_init(void) +{ + int ret, i; + + if (!dmi_available) + return -ENODEV; + + /* Not necessarily all DMI fields are available on all + * systems, hence let's built an attribute table of just + * what's available */ + i = 0; + ADD_DMI_ATTR(bios_vendor, DMI_BIOS_VENDOR); + ADD_DMI_ATTR(bios_version, DMI_BIOS_VERSION); + ADD_DMI_ATTR(bios_date, DMI_BIOS_DATE); + ADD_DMI_ATTR(sys_vendor, DMI_SYS_VENDOR); + ADD_DMI_ATTR(product_name, DMI_PRODUCT_NAME); + ADD_DMI_ATTR(product_version, DMI_PRODUCT_VERSION); + ADD_DMI_ATTR(product_serial, DMI_PRODUCT_SERIAL); + ADD_DMI_ATTR(product_uuid, DMI_PRODUCT_UUID); + ADD_DMI_ATTR(board_vendor, DMI_BOARD_VENDOR); + ADD_DMI_ATTR(board_name, DMI_BOARD_NAME); + ADD_DMI_ATTR(board_version, DMI_BOARD_VERSION); + ADD_DMI_ATTR(board_serial, DMI_BOARD_SERIAL); + ADD_DMI_ATTR(board_asset_tag, DMI_BOARD_ASSET_TAG); + ADD_DMI_ATTR(chassis_vendor, DMI_CHASSIS_VENDOR); + ADD_DMI_ATTR(chassis_type, DMI_CHASSIS_TYPE); + ADD_DMI_ATTR(chassis_version, DMI_CHASSIS_VERSION); + ADD_DMI_ATTR(chassis_serial, DMI_CHASSIS_SERIAL); + ADD_DMI_ATTR(chassis_asset_tag, DMI_CHASSIS_ASSET_TAG); + sys_dmi_attributes[i++] = &sys_dmi_modalias_attr.attr; + + ret = class_register(&dmi_class); + if (ret) + return ret; + + dmi_dev = kzalloc(sizeof(*dmi_dev), GFP_KERNEL); + if (!dmi_dev) { + ret = -ENOMEM; + goto fail_class_unregister; + } + + dmi_dev->class = &dmi_class; + strcpy(dmi_dev->bus_id, "id"); + dmi_dev->groups = sys_dmi_attribute_groups; + + ret = device_register(dmi_dev); + if (ret) + goto fail_class_unregister; + + return 0; + +fail_class_unregister: + + class_unregister(&dmi_class); + + return ret; +} + +arch_initcall(dmi_id_init); diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 37deee6c0c1c..f7318b3b51f2 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -84,6 +84,7 @@ static int __init dmi_checksum(u8 *buf) static char *dmi_ident[DMI_STRING_MAX]; static LIST_HEAD(dmi_devices); +int dmi_available; /* * Save a DMI string @@ -102,6 +103,51 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) dmi_ident[slot] = p; } +static void __init dmi_save_uuid(struct dmi_header *dm, int slot, int index) +{ + u8 *d = (u8*) dm + index; + char *s; + int is_ff = 1, is_00 = 1, i; + + if (dmi_ident[slot]) + return; + + for (i = 0; i < 16 && (is_ff || is_00); i++) { + if(d[i] != 0x00) is_ff = 0; + if(d[i] != 0xFF) is_00 = 0; + } + + if (is_ff || is_00) + return; + + s = dmi_alloc(16*2+4+1); + if (!s) + return; + + sprintf(s, + "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], + d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + + dmi_ident[slot] = s; +} + +static void __init dmi_save_type(struct dmi_header *dm, int slot, int index) +{ + u8 *d = (u8*) dm + index; + char *s; + + if (dmi_ident[slot]) + return; + + s = dmi_alloc(4); + if (!s) + return; + + sprintf(s, "%u", *d & 0x7F); + dmi_ident[slot] = s; +} + static void __init dmi_save_devices(struct dmi_header *dm) { int i, count = (dm->length - sizeof(struct dmi_header)) / 2; @@ -192,11 +238,21 @@ static void __init dmi_decode(struct dmi_header *dm) dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); + dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8); break; case 2: /* Base Board Information */ dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); dmi_save_ident(dm, DMI_BOARD_NAME, 5); dmi_save_ident(dm, DMI_BOARD_VERSION, 6); + dmi_save_ident(dm, DMI_BOARD_SERIAL, 7); + dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8); + break; + case 3: /* Chassis Information */ + dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4); + dmi_save_type(dm, DMI_CHASSIS_TYPE, 5); + dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6); + dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7); + dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8); break; case 10: /* Onboard Devices Information */ dmi_save_devices(dm); @@ -243,18 +299,20 @@ void __init dmi_scan_machine(void) if (efi.smbios == EFI_INVALID_TABLE_ADDR) goto out; - /* This is called as a core_initcall() because it isn't - * needed during early boot. This also means we can - * iounmap the space when we're done with it. - */ + /* This is called as a core_initcall() because it isn't + * needed during early boot. This also means we can + * iounmap the space when we're done with it. + */ p = dmi_ioremap(efi.smbios, 32); if (p == NULL) goto out; rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ dmi_iounmap(p, 32); - if (!rc) + if (!rc) { + dmi_available = 1; return; + } } else { /* @@ -268,8 +326,10 @@ void __init dmi_scan_machine(void) for (q = p; q < p + 0x10000; q += 16) { rc = dmi_present(q); - if (!rc) + if (!rc) { + dmi_available = 1; return; + } } } out: printk(KERN_INFO "DMI not present or invalid.\n"); @@ -404,3 +464,4 @@ int dmi_get_year(int field) return year; } + diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c index 41e901f53e7c..932a415197b3 100644 --- a/drivers/misc/msi-laptop.c +++ b/drivers/misc/msi-laptop.c @@ -23,6 +23,8 @@ * msi-laptop.c - MSI S270 laptop support. This laptop is sold under * various brands, including "Cytron/TCM/Medion/Tchibo MD96100". * + * Driver also supports S271, S420 models. + * * This driver exports a few files in /sys/devices/platform/msi-laptop-pf/: * * lcd_level - Screen brightness: contains a single integer in the @@ -281,25 +283,56 @@ static struct platform_device *msipf_device; /* Initialization */ +static int dmi_check_cb(struct dmi_system_id *id) +{ + printk("msi-laptop: Identified laptop model '%s'.\n", id->ident); + return 0; +} + static struct dmi_system_id __initdata msi_dmi_table[] = { { .ident = "MSI S270", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"), DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"), - } + DMI_MATCH(DMI_PRODUCT_VERSION, "0131"), + DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD") + }, + .callback = dmi_check_cb + }, + { + .ident = "MSI S271", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-1058"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0581"), + DMI_MATCH(DMI_BOARD_NAME, "MS-1058") + }, + .callback = dmi_check_cb + }, + { + .ident = "MSI S420", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-1412"), + DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), + DMI_MATCH(DMI_BOARD_NAME, "MS-1412") + }, + .callback = dmi_check_cb }, { .ident = "Medion MD96100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"), DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"), - } + DMI_MATCH(DMI_PRODUCT_VERSION, "0131"), + DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD") + }, + .callback = dmi_check_cb }, { } }; - static int __init msi_init(void) { int ret; @@ -394,3 +427,8 @@ MODULE_AUTHOR("Lennart Poettering"); MODULE_DESCRIPTION("MSI Laptop Support"); MODULE_VERSION(MSI_DRIVER_VERSION); MODULE_LICENSE("GPL"); + +MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); +MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*"); +MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); +MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 904bf3d2d90b..b8ac7b01c45e 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -12,9 +12,17 @@ enum dmi_field { DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_PRODUCT_SERIAL, + DMI_PRODUCT_UUID, DMI_BOARD_VENDOR, DMI_BOARD_NAME, DMI_BOARD_VERSION, + DMI_BOARD_SERIAL, + DMI_BOARD_ASSET_TAG, + DMI_CHASSIS_VENDOR, + DMI_CHASSIS_TYPE, + DMI_CHASSIS_VERSION, + DMI_CHASSIS_SERIAL, + DMI_CHASSIS_ASSET_TAG, DMI_STRING_MAX, }; -- cgit v1.2.3-71-gd317 From 9cddad77574313fcee36c5e60122718daa7c0361 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 13 Jun 2007 15:53:34 +0200 Subject: PM: Remove pm_parent from struct dev_pm_info The pm_parent member of struct dev_pm_info (defined in include/linux/pm.h) is only used to check if the device's parent is in the right state while the device is being suspended or resumed. However, this can be done just as well with the help of the parent pointer in struct device, so pm_parent can be removed along with some code that handles it. Signed-off-by: Rafael J. Wysocki Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 30 ++++-------------------------- drivers/base/power/resume.c | 7 +++---- drivers/base/power/suspend.c | 7 +++---- include/linux/pm.h | 3 --- 4 files changed, 10 insertions(+), 37 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 7b3cc3c15b9d..eb9f38d0aa58 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -33,28 +33,7 @@ DEFINE_MUTEX(dpm_list_mtx); int (*platform_enable_wakeup)(struct device *dev, int is_on); - -/** - * device_pm_set_parent - Specify power dependency. - * @dev: Device who needs power. - * @parent: Device that supplies power. - * - * This function is used to manually describe a power-dependency - * relationship. It may be used to specify a transversal relationship - * (where the power supplier is not the physical (or electrical) - * ancestor of a specific device. - * The effect of this is that the supplier will not be powered down - * before the power dependent. - */ - -void device_pm_set_parent(struct device * dev, struct device * parent) -{ - put_device(dev->power.pm_parent); - dev->power.pm_parent = get_device(parent); -} -EXPORT_SYMBOL_GPL(device_pm_set_parent); - -int device_pm_add(struct device * dev) +int device_pm_add(struct device *dev) { int error; @@ -63,21 +42,20 @@ int device_pm_add(struct device * dev) kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); list_add_tail(&dev->power.entry, &dpm_active); - device_pm_set_parent(dev, dev->parent); - if ((error = dpm_sysfs_add(dev))) + error = dpm_sysfs_add(dev); + if (error) list_del(&dev->power.entry); mutex_unlock(&dpm_list_mtx); return error; } -void device_pm_remove(struct device * dev) +void device_pm_remove(struct device *dev) { pr_debug("PM: Removing info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); dpm_sysfs_remove(dev); - put_device(dev->power.pm_parent); list_del_init(&dev->power.entry); mutex_unlock(&dpm_list_mtx); } diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index f6cfea496ea0..99679e7a6cc6 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c @@ -29,12 +29,11 @@ int resume_device(struct device * dev) down(&dev->sem); - if (dev->power.pm_parent - && dev->power.pm_parent->power.power_state.event) { + if (dev->parent && dev->parent->power.power_state.event) { dev_err(dev, "PM: resume from %d, parent %s still %d\n", dev->power.power_state.event, - dev->power.pm_parent->bus_id, - dev->power.pm_parent->power.power_state.event); + dev->parent->bus_id, + dev->parent->power.power_state.event); } if (dev->bus && dev->bus->resume) { diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 9d6701cd7f10..19fae88de7b3 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -55,13 +55,12 @@ int suspend_device(struct device * dev, pm_message_t state) dev_dbg(dev, "PM: suspend %d-->%d\n", dev->power.power_state.event, state.event); } - if (dev->power.pm_parent - && dev->power.pm_parent->power.power_state.event) { + if (dev->parent && dev->parent->power.power_state.event) { dev_err(dev, "PM: suspend %d->%d, parent %s already %d\n", dev->power.power_state.event, state.event, - dev->power.pm_parent->bus_id, - dev->power.pm_parent->power.power_state.event); + dev->parent->bus_id, + dev->parent->power.power_state.event); } dev->power.prev_state = dev->power.power_state; diff --git a/include/linux/pm.h b/include/linux/pm.h index b2c4fde4e994..3fd65ad4b097 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -269,13 +269,10 @@ struct dev_pm_info { unsigned should_wakeup:1; pm_message_t prev_state; void * saved_state; - struct device * pm_parent; struct list_head entry; #endif }; -extern void device_pm_set_parent(struct device * dev, struct device * parent); - extern int device_power_down(pm_message_t state); extern void device_power_up(void); extern void device_resume(void); -- cgit v1.2.3-71-gd317 From cc4900690bf77257996e90f0059eb074b8db52e6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 13 Jun 2007 15:55:34 +0200 Subject: PM: Remove saved_state from struct dev_pm_info The saved_state member of struct dev_pm_info, defined in include/linux/pm.h, is not used anywhere, so it can be removed. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- include/linux/pm.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/pm.h b/include/linux/pm.h index 3fd65ad4b097..6e7f06671683 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -268,7 +268,6 @@ struct dev_pm_info { #ifdef CONFIG_PM unsigned should_wakeup:1; pm_message_t prev_state; - void * saved_state; struct list_head entry; #endif }; -- cgit v1.2.3-71-gd317 From 515c53576299e32d6bdb6295cfa2fe1307516eb4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 17 Jun 2007 19:48:06 +0200 Subject: PM: Remove prev_state from struct dev_pm_info The prev_state member of struct dev_pm_info (defined in include/linux/pm.h) is only used during a resume to check if the device's state before the suspend was 'off', in which case the device is not resumed. However, in such cases the decision whether or not to resume the device should be made on the driver level and the resume callbacks from the device's bus and class should be executed anyway (the may be needed for some things other than just powering on the device). Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/resume.c | 3 +-- drivers/base/power/suspend.c | 2 -- drivers/usb/core/hub.c | 5 ----- include/linux/pm.h | 1 - 4 files changed, 1 insertion(+), 10 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index 99679e7a6cc6..0c9610688542 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c @@ -88,8 +88,7 @@ void dpm_resume(void) list_move_tail(entry, &dpm_active); mutex_unlock(&dpm_list_mtx); - if (!dev->power.prev_state.event) - resume_device(dev); + resume_device(dev); mutex_lock(&dpm_list_mtx); put_device(dev); } diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index af2cedfbc1b4..5178b0fbd82e 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -71,8 +71,6 @@ int suspend_device(struct device * dev, pm_message_t state) dev->parent->power.power_state.event); } - dev->power.prev_state = dev->power.power_state; - if (dev->class && dev->class->suspend && !dev->power.power_state.event) { suspend_device_dbg(dev, state, "class "); error = dev->class->suspend(dev, state); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 24f10a19dbdb..a9cf8b30bccc 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1109,11 +1109,6 @@ void usb_root_hub_lost_power(struct usb_device *rhdev) dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); - /* Make sure no potential wakeup events get lost, - * by forcing the root hub to be resumed. - */ - rhdev->dev.power.prev_state.event = PM_EVENT_ON; - spin_lock_irqsave(&device_state_lock, flags); hub = hdev_to_hub(rhdev); for (port1 = 1; port1 <= rhdev->maxchild; ++port1) { diff --git a/include/linux/pm.h b/include/linux/pm.h index 6e7f06671683..273781c82e4d 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -267,7 +267,6 @@ struct dev_pm_info { unsigned can_wakeup:1; #ifdef CONFIG_PM unsigned should_wakeup:1; - pm_message_t prev_state; struct list_head entry; #endif }; -- cgit v1.2.3-71-gd317 From 72dba584b695d8bc8c1a50ed54ad4cba7c62314d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jun 2007 03:45:13 +0900 Subject: ida: implement idr based id allocator Implement idr based id allocator. ida is used the same way idr is used but lacks id -> ptr translation and thus consumes much less memory. struct ida_bitmap is attached as leaf nodes to idr tree which is managed by the idr code. Each ida_bitmap is 128bytes long and contains slightly less than a thousand slots. ida is more aggressive with releasing extra resources acquired using ida_pre_get(). After every successful id allocation, ida frees one reserved idr_layer if possible. Reserved ida_bitmap is not freed automatically but only one ida_bitmap is reserved and it's almost always used right away. Under most circumstances, ida won't hold on to memory for too long which isn't actively used. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- include/linux/idr.h | 29 +++++++ lib/idr.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 274 insertions(+) (limited to 'include/linux') diff --git a/include/linux/idr.h b/include/linux/idr.h index 826803449db7..915572fa030b 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -83,4 +83,33 @@ void idr_remove(struct idr *idp, int id); void idr_destroy(struct idr *idp); void idr_init(struct idr *idp); + +/* + * IDA - IDR based id allocator, use when translation from id to + * pointer isn't necessary. + */ +#define IDA_CHUNK_SIZE 128 /* 128 bytes per chunk */ +#define IDA_BITMAP_LONGS (128 / sizeof(long) - 1) +#define IDA_BITMAP_BITS (IDA_BITMAP_LONGS * sizeof(long) * 8) + +struct ida_bitmap { + long nr_busy; + unsigned long bitmap[IDA_BITMAP_LONGS]; +}; + +struct ida { + struct idr idr; + struct ida_bitmap *free_bitmap; +}; + +#define IDA_INIT(name) { .idr = IDR_INIT(name), .free_bitmap = NULL, } +#define DEFINE_IDA(name) struct ida name = IDA_INIT(name) + +int ida_pre_get(struct ida *ida, gfp_t gfp_mask); +int ida_get_new_above(struct ida *ida, int starting_id, int *p_id); +int ida_get_new(struct ida *ida, int *p_id); +void ida_remove(struct ida *ida, int id); +void ida_destroy(struct ida *ida); +void ida_init(struct ida *ida); + #endif /* __IDR_H__ */ diff --git a/lib/idr.c b/lib/idr.c index 30b33e2e7a50..b98f01a2eb94 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -506,3 +506,248 @@ void idr_init(struct idr *idp) spin_lock_init(&idp->lock); } EXPORT_SYMBOL(idr_init); + + +/* + * IDA - IDR based ID allocator + * + * this is id allocator without id -> pointer translation. Memory + * usage is much lower than full blown idr because each id only + * occupies a bit. ida uses a custom leaf node which contains + * IDA_BITMAP_BITS slots. + * + * 2007-04-25 written by Tejun Heo + */ + +static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap) +{ + unsigned long flags; + + if (!ida->free_bitmap) { + spin_lock_irqsave(&ida->idr.lock, flags); + if (!ida->free_bitmap) { + ida->free_bitmap = bitmap; + bitmap = NULL; + } + spin_unlock_irqrestore(&ida->idr.lock, flags); + } + + kfree(bitmap); +} + +/** + * ida_pre_get - reserve resources for ida allocation + * @ida: ida handle + * @gfp_mask: memory allocation flag + * + * This function should be called prior to locking and calling the + * following function. It preallocates enough memory to satisfy the + * worst possible allocation. + * + * If the system is REALLY out of memory this function returns 0, + * otherwise 1. + */ +int ida_pre_get(struct ida *ida, gfp_t gfp_mask) +{ + /* allocate idr_layers */ + if (!idr_pre_get(&ida->idr, gfp_mask)) + return 0; + + /* allocate free_bitmap */ + if (!ida->free_bitmap) { + struct ida_bitmap *bitmap; + + bitmap = kmalloc(sizeof(struct ida_bitmap), gfp_mask); + if (!bitmap) + return 0; + + free_bitmap(ida, bitmap); + } + + return 1; +} +EXPORT_SYMBOL(ida_pre_get); + +/** + * ida_get_new_above - allocate new ID above or equal to a start id + * @ida: ida handle + * @staring_id: id to start search at + * @p_id: pointer to the allocated handle + * + * Allocate new ID above or equal to @ida. It should be called with + * any required locks. + * + * If memory is required, it will return -EAGAIN, you should unlock + * and go back to the ida_pre_get() call. If the ida is full, it will + * return -ENOSPC. + * + * @p_id returns a value in the range 0 ... 0x7fffffff. + */ +int ida_get_new_above(struct ida *ida, int starting_id, int *p_id) +{ + struct idr_layer *pa[MAX_LEVEL]; + struct ida_bitmap *bitmap; + unsigned long flags; + int idr_id = starting_id / IDA_BITMAP_BITS; + int offset = starting_id % IDA_BITMAP_BITS; + int t, id; + + restart: + /* get vacant slot */ + t = idr_get_empty_slot(&ida->idr, idr_id, pa); + if (t < 0) { + if (t == -1) + return -EAGAIN; + else /* will be -3 */ + return -ENOSPC; + } + + if (t * IDA_BITMAP_BITS >= MAX_ID_BIT) + return -ENOSPC; + + if (t != idr_id) + offset = 0; + idr_id = t; + + /* if bitmap isn't there, create a new one */ + bitmap = (void *)pa[0]->ary[idr_id & IDR_MASK]; + if (!bitmap) { + spin_lock_irqsave(&ida->idr.lock, flags); + bitmap = ida->free_bitmap; + ida->free_bitmap = NULL; + spin_unlock_irqrestore(&ida->idr.lock, flags); + + if (!bitmap) + return -EAGAIN; + + memset(bitmap, 0, sizeof(struct ida_bitmap)); + pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap; + pa[0]->count++; + } + + /* lookup for empty slot */ + t = find_next_zero_bit(bitmap->bitmap, IDA_BITMAP_BITS, offset); + if (t == IDA_BITMAP_BITS) { + /* no empty slot after offset, continue to the next chunk */ + idr_id++; + offset = 0; + goto restart; + } + + id = idr_id * IDA_BITMAP_BITS + t; + if (id >= MAX_ID_BIT) + return -ENOSPC; + + __set_bit(t, bitmap->bitmap); + if (++bitmap->nr_busy == IDA_BITMAP_BITS) + idr_mark_full(pa, idr_id); + + *p_id = id; + + /* Each leaf node can handle nearly a thousand slots and the + * whole idea of ida is to have small memory foot print. + * Throw away extra resources one by one after each successful + * allocation. + */ + if (ida->idr.id_free_cnt || ida->free_bitmap) { + struct idr_layer *p = alloc_layer(&ida->idr); + if (p) + kmem_cache_free(idr_layer_cache, p); + } + + return 0; +} +EXPORT_SYMBOL(ida_get_new_above); + +/** + * ida_get_new - allocate new ID + * @ida: idr handle + * @p_id: pointer to the allocated handle + * + * Allocate new ID. It should be called with any required locks. + * + * If memory is required, it will return -EAGAIN, you should unlock + * and go back to the idr_pre_get() call. If the idr is full, it will + * return -ENOSPC. + * + * @id returns a value in the range 0 ... 0x7fffffff. + */ +int ida_get_new(struct ida *ida, int *p_id) +{ + return ida_get_new_above(ida, 0, p_id); +} +EXPORT_SYMBOL(ida_get_new); + +/** + * ida_remove - remove the given ID + * @ida: ida handle + * @id: ID to free + */ +void ida_remove(struct ida *ida, int id) +{ + struct idr_layer *p = ida->idr.top; + int shift = (ida->idr.layers - 1) * IDR_BITS; + int idr_id = id / IDA_BITMAP_BITS; + int offset = id % IDA_BITMAP_BITS; + int n; + struct ida_bitmap *bitmap; + + /* clear full bits while looking up the leaf idr_layer */ + while ((shift > 0) && p) { + n = (idr_id >> shift) & IDR_MASK; + __clear_bit(n, &p->bitmap); + p = p->ary[n]; + shift -= IDR_BITS; + } + + if (p == NULL) + goto err; + + n = idr_id & IDR_MASK; + __clear_bit(n, &p->bitmap); + + bitmap = (void *)p->ary[n]; + if (!test_bit(offset, bitmap->bitmap)) + goto err; + + /* update bitmap and remove it if empty */ + __clear_bit(offset, bitmap->bitmap); + if (--bitmap->nr_busy == 0) { + __set_bit(n, &p->bitmap); /* to please idr_remove() */ + idr_remove(&ida->idr, idr_id); + free_bitmap(ida, bitmap); + } + + return; + + err: + printk(KERN_WARNING + "ida_remove called for id=%d which is not allocated.\n", id); +} +EXPORT_SYMBOL(ida_remove); + +/** + * ida_destroy - release all cached layers within an ida tree + * ida: ida handle + */ +void ida_destroy(struct ida *ida) +{ + idr_destroy(&ida->idr); + kfree(ida->free_bitmap); +} +EXPORT_SYMBOL(ida_destroy); + +/** + * ida_init - initialize ida handle + * @ida: ida handle + * + * This function is use to set up the handle (@ida) that you will pass + * to the rest of the functions. + */ +void ida_init(struct ida *ida) +{ + memset(ida, 0, sizeof(struct ida)); + idr_init(&ida->idr); + +} +EXPORT_SYMBOL(ida_init); -- cgit v1.2.3-71-gd317 From 0c096b507f15397da890051ee73de4266d3941fb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jun 2007 03:45:15 +0900 Subject: sysfs: add sysfs_dirent->s_name Add s_name to sysfs_dirent. This is to further reduce dependency to the associated dentry. Name is copied for directories and symlinks but not for attributes. Where possible, name dereferences are converted to use sd->s_name. sysfs_symlink->link_name and sysfs_get_name() are unused now and removed. This change allows symlink to be implemented using sysfs_dirent tree proper, which is the last remaining dentry-dependent sysfs walk. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 67 +++++++++++++++++++++++++++++++++------------------ fs/sysfs/file.c | 2 +- fs/sysfs/inode.c | 33 +------------------------ fs/sysfs/symlink.c | 8 +----- fs/sysfs/sysfs.h | 7 +++--- include/linux/sysfs.h | 1 + 6 files changed, 51 insertions(+), 67 deletions(-) (limited to 'include/linux') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 5d50e1ddfbd1..6e8d6f54f082 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -54,10 +54,11 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) if (sd->s_type & SYSFS_KOBJ_LINK) { struct sysfs_symlink * sl = sd->s_element; - kfree(sl->link_name); kobject_put(sl->target_kobj); kfree(sl); } + if (sd->s_type & SYSFS_COPY_NAME) + kfree(sd->s_name); kfree(sd->s_iattr); sysfs_free_ino(sd->s_ino); kmem_cache_free(sysfs_dir_cachep, sd); @@ -94,29 +95,41 @@ static struct dentry_operations sysfs_dentry_ops = { .d_iput = sysfs_d_iput, }; -struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, int type) +struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element, + umode_t mode, int type) { - struct sysfs_dirent * sd; + char *dup_name = NULL; + struct sysfs_dirent *sd = NULL; + + if (type & SYSFS_COPY_NAME) { + name = dup_name = kstrdup(name, GFP_KERNEL); + if (!name) + goto err_out; + } sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); if (!sd) - return NULL; + goto err_out; - if (sysfs_alloc_ino(&sd->s_ino)) { - kmem_cache_free(sysfs_dir_cachep, sd); - return NULL; - } + if (sysfs_alloc_ino(&sd->s_ino)) + goto err_out; atomic_set(&sd->s_count, 1); atomic_set(&sd->s_event, 1); INIT_LIST_HEAD(&sd->s_children); INIT_LIST_HEAD(&sd->s_sibling); + sd->s_name = name; sd->s_element = element; sd->s_mode = mode; sd->s_type = type; return sd; + + err_out: + kfree(dup_name); + kmem_cache_free(sysfs_dir_cachep, sd); + return NULL; } void sysfs_attach_dirent(struct sysfs_dirent *sd, @@ -148,8 +161,7 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { if (sd->s_element) { - const unsigned char *existing = sysfs_get_name(sd); - if (strcmp(existing, new)) + if (strcmp(sd->s_name, new)) continue; else return -EEXIST; @@ -203,7 +215,7 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, goto out_dput; error = -ENOMEM; - sd = sysfs_new_dirent(kobj, mode, SYSFS_DIR); + sd = sysfs_new_dirent(name, kobj, mode, SYSFS_DIR); if (!sd) goto out_drop; sysfs_attach_dirent(sd, parent->d_fsdata, dentry); @@ -334,9 +346,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { if (sd->s_type & SYSFS_NOT_PINNED) { - const unsigned char * name = sysfs_get_name(sd); - - if (strcmp(name, dentry->d_name.name)) + if (strcmp(sd->s_name, dentry->d_name.name)) continue; if (sd->s_type & SYSFS_KOBJ_LINK) @@ -427,9 +437,11 @@ void sysfs_remove_dir(struct kobject * kobj) int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, const char *new_name) { + struct sysfs_dirent *sd = kobj->dentry->d_fsdata; + struct sysfs_dirent *parent_sd = new_parent->d_fsdata; + struct dentry *new_dentry; + char *dup_name; int error; - struct dentry * new_dentry; - struct sysfs_dirent *sd, *parent_sd; if (!new_parent) return -EFAULT; @@ -457,22 +469,31 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, if (new_dentry->d_inode) goto out_dput; + /* rename kobject and sysfs_dirent */ + error = -ENOMEM; + new_name = dup_name = kstrdup(new_name, GFP_KERNEL); + if (!new_name) + goto out_drop; + error = kobject_set_name(kobj, "%s", new_name); if (error) - goto out_drop; + goto out_free; + kfree(sd->s_name); + sd->s_name = new_name; + + /* move under the new parent */ d_add(new_dentry, NULL); d_move(kobj->dentry, new_dentry); - sd = kobj->dentry->d_fsdata; - parent_sd = new_parent->d_fsdata; - list_del_init(&sd->s_sibling); list_add(&sd->s_sibling, &parent_sd->s_children); error = 0; goto out_unlock; + out_free: + kfree(dup_name); out_drop: d_drop(new_dentry); out_dput: @@ -535,7 +556,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file) struct sysfs_dirent * sd; mutex_lock(&dentry->d_inode->i_mutex); - sd = sysfs_new_dirent(NULL, 0, 0); + sd = sysfs_new_dirent("_DIR_", NULL, 0, 0); if (sd) sysfs_attach_dirent(sd, parent_sd, NULL); mutex_unlock(&dentry->d_inode->i_mutex); @@ -605,7 +626,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) if (!next->s_element) continue; - name = sysfs_get_name(next); + name = next->s_name; len = strlen(name); ino = next->s_ino; @@ -717,7 +738,7 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) if (!shadow) goto nomem; - sd = sysfs_new_dirent(kobj, inode->i_mode, SYSFS_DIR); + sd = sysfs_new_dirent("_SHADOW_", kobj, inode->i_mode, SYSFS_DIR); if (!sd) goto nomem; /* point to parent_sd but don't attach to it */ diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index fd4b6dc03d2d..8240b1687dd0 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -454,7 +454,7 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) goto out_unlock; } - sd = sysfs_new_dirent((void *)attr, mode, type); + sd = sysfs_new_dirent(attr->name, (void *)attr, mode, type); if (!sd) { error = -ENOMEM; goto out_unlock; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 5266eec15f6e..5c605b0003a8 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -191,37 +191,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) return error; } -/* - * Get the name for corresponding element represented by the given sysfs_dirent - */ -const unsigned char * sysfs_get_name(struct sysfs_dirent *sd) -{ - struct attribute * attr; - struct bin_attribute * bin_attr; - struct sysfs_symlink * sl; - - BUG_ON(!sd || !sd->s_element); - - switch (sd->s_type) { - case SYSFS_DIR: - /* Always have a dentry so use that */ - return sd->s_dentry->d_name.name; - - case SYSFS_KOBJ_ATTR: - attr = sd->s_element; - return attr->name; - - case SYSFS_KOBJ_BIN_ATTR: - bin_attr = sd->s_element; - return bin_attr->attr.name; - - case SYSFS_KOBJ_LINK: - sl = sd->s_element; - return sl->link_name; - } - return NULL; -} - static inline void orphan_all_buffers(struct inode *node) { struct sysfs_buffer_collection *set; @@ -305,7 +274,7 @@ int sysfs_hash_and_remove(struct dentry * dir, const char * name) list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { if (!sd->s_element) continue; - if (!strcmp(sysfs_get_name(sd), name)) { + if (!strcmp(sd->s_name, name)) { list_del_init(&sd->s_sibling); sysfs_drop_dentry(sd, dir); sysfs_put(sd); diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index d96bb9cbc9d4..c72820450e7c 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -57,14 +57,9 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj if (!sl) goto err_out; - sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL); - if (!sl->link_name) - goto err_out; - - strcpy(sl->link_name, name); sl->target_kobj = kobject_get(target); - sd = sysfs_new_dirent(sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); + sd = sysfs_new_dirent(name, sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); if (!sd) goto err_out; sysfs_attach_dirent(sd, parent_sd, NULL); @@ -74,7 +69,6 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj err_out: if (sl) { kobject_put(sl->target_kobj); - kfree(sl->link_name); kfree(sl); } return error; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index ce05d6fd7522..d34b008537d5 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -3,6 +3,7 @@ struct sysfs_dirent { struct sysfs_dirent * s_parent; struct list_head s_sibling; struct list_head s_children; + const char * s_name; void * s_element; int s_type; umode_t s_mode; @@ -21,8 +22,8 @@ extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); extern void release_sysfs_dirent(struct sysfs_dirent * sd); extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); -extern struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, - int type); +extern struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element, + umode_t mode, int type); extern void sysfs_attach_dirent(struct sysfs_dirent *sd, struct sysfs_dirent *parent_sd, struct dentry *dentry); @@ -34,7 +35,6 @@ extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * na extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); extern void sysfs_remove_subdir(struct dentry *); -extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); @@ -48,7 +48,6 @@ extern const struct inode_operations sysfs_dir_inode_operations; extern const struct inode_operations sysfs_symlink_inode_operations; struct sysfs_symlink { - char * link_name; struct kobject * target_kobj; }; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 7d5d1ec95c2e..2f86b080b39d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -76,6 +76,7 @@ struct sysfs_ops { #define SYSFS_KOBJ_BIN_ATTR 0x0008 #define SYSFS_KOBJ_LINK 0x0020 #define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK) +#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) #ifdef CONFIG_SYSFS -- cgit v1.2.3-71-gd317 From 7b595756ec1f49e0049a9e01a1298d53a7faaa15 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jun 2007 03:45:17 +0900 Subject: sysfs: kill unnecessary attribute->owner sysfs is now completely out of driver/module lifetime game. After deletion, a sysfs node doesn't access anything outside sysfs proper, so there's no reason to hold onto the attribute owners. Note that often the wrong modules were accounted for as owners leading to accessing removed modules. This patch kills now unnecessary attribute->owner. Note that with this change, userland holding a sysfs node does not prevent the backing module from being unloaded. For more info regarding lifetime rule cleanup, please read the following message. http://article.gmane.org/gmane.linux.kernel/510293 (tweaked by Greg to not delete the field just yet, to make it easier to merge things properly.) Signed-off-by: Tejun Heo Cc: Cornelia Huck Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- arch/ppc/syslib/mv64x60.c | 1 - arch/s390/kernel/ipl.c | 2 -- drivers/base/bus.c | 2 -- drivers/base/class.c | 2 -- drivers/base/core.c | 4 ---- drivers/base/firmware_class.c | 2 +- drivers/block/pktcdvd.c | 3 +-- drivers/char/ipmi/ipmi_msghandler.c | 10 ---------- drivers/cpufreq/cpufreq_stats.c | 3 +-- drivers/cpufreq/cpufreq_userspace.c | 2 +- drivers/cpufreq/freq_table.c | 1 - drivers/firmware/dcdbas.h | 3 +-- drivers/firmware/dell_rbu.c | 6 +++--- drivers/firmware/edd.c | 2 +- drivers/firmware/efivars.c | 6 +++--- drivers/i2c/chips/eeprom.c | 1 - drivers/i2c/chips/max6875.c | 1 - drivers/infiniband/core/sysfs.c | 1 - drivers/input/mouse/psmouse.h | 1 - drivers/macintosh/windfarm_core.c | 2 -- drivers/misc/asus-laptop.c | 3 +-- drivers/net/ibmveth.c | 2 +- drivers/parisc/pdc_stable.c | 4 ++-- drivers/pci/hotplug/acpiphp_ibm.c | 1 - drivers/pci/pci-sysfs.c | 4 ---- drivers/pci/probe.c | 2 -- drivers/pcmcia/socket_sysfs.c | 2 +- drivers/rapidio/rio-sysfs.c | 1 - drivers/rtc/rtc-ds1553.c | 1 - drivers/rtc/rtc-ds1742.c | 1 - drivers/s390/cio/chp.c | 2 -- drivers/s390/net/qeth_sys.c | 2 +- drivers/scsi/arcmsr/arcmsr_attr.c | 3 --- drivers/scsi/libsas/sas_expander.c | 1 - drivers/scsi/lpfc/lpfc_attr.c | 2 -- drivers/scsi/qla2xxx/qla_attr.c | 6 ------ drivers/spi/at25.c | 1 - drivers/video/aty/radeon_base.c | 2 -- drivers/video/backlight/backlight.c | 2 +- drivers/video/backlight/lcd.c | 2 +- drivers/w1/slaves/w1_ds2433.c | 1 - drivers/w1/slaves/w1_therm.c | 1 - drivers/w1/w1.c | 2 -- drivers/zorro/zorro-sysfs.c | 1 - fs/ecryptfs/main.c | 2 -- fs/ocfs2/cluster/masklog.c | 1 - fs/partitions/check.c | 1 - fs/sysfs/bin.c | 19 +++++-------------- fs/sysfs/file.c | 21 +++++---------------- include/linux/sysdev.h | 3 +-- include/linux/sysfs.h | 12 ++++++++---- kernel/module.c | 9 +++------ kernel/params.c | 1 - net/bridge/br_sysfs_br.c | 3 +-- net/bridge/br_sysfs_if.c | 3 +-- 55 files changed, 44 insertions(+), 135 deletions(-) (limited to 'include/linux') diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 8485a68cd475..032f4b7f4225 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -2415,7 +2415,6 @@ static struct bin_attribute mv64xxx_hs_reg_attr = { /* Hotswap register */ .attr = { .name = "hs_reg", .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, }, .size = VAL_LEN_MAX, .read = mv64xxx_hs_reg_read, diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 82b131ddd7ff..9a13b24ee1ab 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -312,7 +312,6 @@ static struct bin_attribute ipl_parameter_attr = { .attr = { .name = "binary_parameter", .mode = S_IRUGO, - .owner = THIS_MODULE, }, .size = PAGE_SIZE, .read = &ipl_parameter_read, @@ -336,7 +335,6 @@ static struct bin_attribute ipl_scp_data_attr = { .attr = { .name = "scp_data", .mode = S_IRUGO, - .owner = THIS_MODULE, }, .size = PAGE_SIZE, .read = &ipl_scp_data_read, diff --git a/drivers/base/bus.c b/drivers/base/bus.c index f299e0d6abc4..61c67526a656 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -574,7 +574,6 @@ static int add_probe_files(struct bus_type *bus) bus->drivers_probe_attr.attr.name = "drivers_probe"; bus->drivers_probe_attr.attr.mode = S_IWUSR; - bus->drivers_probe_attr.attr.owner = bus->owner; bus->drivers_probe_attr.store = store_drivers_probe; retval = bus_create_file(bus, &bus->drivers_probe_attr); if (retval) @@ -582,7 +581,6 @@ static int add_probe_files(struct bus_type *bus) bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe"; bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO; - bus->drivers_autoprobe_attr.attr.owner = bus->owner; bus->drivers_autoprobe_attr.show = show_drivers_autoprobe; bus->drivers_autoprobe_attr.store = store_drivers_autoprobe; retval = bus_create_file(bus, &bus->drivers_autoprobe_attr); diff --git a/drivers/base/class.c b/drivers/base/class.c index 8c506dbe3913..9cbfde23b9e3 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -605,7 +605,6 @@ int class_device_add(struct class_device *class_dev) goto out3; class_dev->uevent_attr.attr.name = "uevent"; class_dev->uevent_attr.attr.mode = S_IWUSR; - class_dev->uevent_attr.attr.owner = parent_class->owner; class_dev->uevent_attr.store = store_uevent; error = class_device_create_file(class_dev, &class_dev->uevent_attr); if (error) @@ -620,7 +619,6 @@ int class_device_add(struct class_device *class_dev) } attr->attr.name = "dev"; attr->attr.mode = S_IRUGO; - attr->attr.owner = parent_class->owner; attr->show = show_dev; error = class_device_create_file(class_dev, attr); if (error) { diff --git a/drivers/base/core.c b/drivers/base/core.c index cff4fbfbb055..e3fb87bfc6e1 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -683,8 +683,6 @@ int device_add(struct device *dev) dev->uevent_attr.attr.name = "uevent"; dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR; - if (dev->driver) - dev->uevent_attr.attr.owner = dev->driver->owner; dev->uevent_attr.store = store_uevent; dev->uevent_attr.show = show_uevent; error = device_create_file(dev, &dev->uevent_attr); @@ -700,8 +698,6 @@ int device_add(struct device *dev) } attr->attr.name = "dev"; attr->attr.mode = S_IRUGO; - if (dev->driver) - attr->attr.owner = dev->driver->owner; attr->show = show_dev; error = device_create_file(dev, attr); if (error) { diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 89a5f4a54913..0e511485d2e6 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -271,7 +271,7 @@ out: } static struct bin_attribute firmware_attr_data_tmpl = { - .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE}, + .attr = {.name = "data", .mode = 0644}, .size = 0, .read = firmware_data_read, .write = firmware_data_write, diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index f1b9dd7d47d6..ce64e86d6ffb 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -146,8 +146,7 @@ static void pkt_kobj_release(struct kobject *kobj) **********************************************************/ #define DEF_ATTR(_obj,_name,_mode) \ - static struct attribute _obj = { \ - .name = _name, .owner = THIS_MODULE, .mode = _mode } + static struct attribute _obj = { .name = _name, .mode = _mode } /********************************************************** /sys/class/pktcdvd/pktcdvd[0-7]/ diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 8e222f2b80cc..b5df7e61aeb2 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2171,52 +2171,42 @@ static int create_files(struct bmc_device *bmc) int err; bmc->device_id_attr.attr.name = "device_id"; - bmc->device_id_attr.attr.owner = THIS_MODULE; bmc->device_id_attr.attr.mode = S_IRUGO; bmc->device_id_attr.show = device_id_show; bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; - bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; bmc->revision_attr.attr.name = "revision"; - bmc->revision_attr.attr.owner = THIS_MODULE; bmc->revision_attr.attr.mode = S_IRUGO; bmc->revision_attr.show = revision_show; bmc->firmware_rev_attr.attr.name = "firmware_revision"; - bmc->firmware_rev_attr.attr.owner = THIS_MODULE; bmc->firmware_rev_attr.attr.mode = S_IRUGO; bmc->firmware_rev_attr.show = firmware_rev_show; bmc->version_attr.attr.name = "ipmi_version"; - bmc->version_attr.attr.owner = THIS_MODULE; bmc->version_attr.attr.mode = S_IRUGO; bmc->version_attr.show = ipmi_version_show; bmc->add_dev_support_attr.attr.name = "additional_device_support"; - bmc->add_dev_support_attr.attr.owner = THIS_MODULE; bmc->add_dev_support_attr.attr.mode = S_IRUGO; bmc->add_dev_support_attr.show = add_dev_support_show; bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; - bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; bmc->manufacturer_id_attr.attr.mode = S_IRUGO; bmc->manufacturer_id_attr.show = manufacturer_id_show; bmc->product_id_attr.attr.name = "product_id"; - bmc->product_id_attr.attr.owner = THIS_MODULE; bmc->product_id_attr.attr.mode = S_IRUGO; bmc->product_id_attr.show = product_id_show; bmc->guid_attr.attr.name = "guid"; - bmc->guid_attr.attr.owner = THIS_MODULE; bmc->guid_attr.attr.mode = S_IRUGO; bmc->guid_attr.show = guid_show; bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; - bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index d2f0cbd8b8f3..917b9bab9ccb 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -25,8 +25,7 @@ static spinlock_t cpufreq_stats_lock; #define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \ static struct freq_attr _attr_##_name = {\ - .attr = {.name = __stringify(_name), .owner = THIS_MODULE, \ - .mode = _mode, }, \ + .attr = {.name = __stringify(_name), .mode = _mode, }, \ .show = _show,\ }; diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 860345c7799a..a648970338b0 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -120,7 +120,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) static struct freq_attr freq_attr_scaling_setspeed = { - .attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE }, + .attr = { .name = "scaling_setspeed", .mode = 0644 }, .show = show_speed, .store = store_speed, }; diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index e7490925fdcf..5409f3afb3f8 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -199,7 +199,6 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) struct freq_attr cpufreq_freq_attr_scaling_available_freqs = { .attr = { .name = "scaling_available_frequencies", .mode = 0444, - .owner=THIS_MODULE }, .show = show_available_freqs, }; diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h index 58a85182b3e8..dcdba0f1b32c 100644 --- a/drivers/firmware/dcdbas.h +++ b/drivers/firmware/dcdbas.h @@ -67,8 +67,7 @@ #define DCDBAS_BIN_ATTR_RW(_name) \ struct bin_attribute bin_attr_##_name = { \ .attr = { .name = __stringify(_name), \ - .mode = 0600, \ - .owner = THIS_MODULE }, \ + .mode = 0600 }, \ .read = _name##_read, \ .write = _name##_write, \ } diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index fc702e40bd43..f8afecb7d0cf 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -687,18 +687,18 @@ static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer, } static struct bin_attribute rbu_data_attr = { - .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, + .attr = {.name = "data", .mode = 0444}, .read = read_rbu_data, }; static struct bin_attribute rbu_image_type_attr = { - .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, + .attr = {.name = "image_type", .mode = 0644}, .read = read_rbu_image_type, .write = write_rbu_image_type, }; static struct bin_attribute rbu_packet_size_attr = { - .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644}, + .attr = {.name = "packet_size", .mode = 0644}, .read = read_rbu_packet_size, .write = write_rbu_packet_size, }; diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index d8806e4f1829..15232271d848 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -74,7 +74,7 @@ static struct edd_device *edd_devices[EDD_MBR_SIG_MAX]; #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \ struct edd_attribute edd_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .test = _test, \ }; diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 1324984a4c35..bfd2d67df689 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -131,21 +131,21 @@ struct efivar_attribute { #define EFI_ATTR(_name, _mode, _show, _store) \ struct subsys_attribute efi_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ + .attr = {.name = __stringify(_name), .mode = _mode}, \ .show = _show, \ .store = _store, \ }; #define EFIVAR_ATTR(_name, _mode, _show, _store) \ struct efivar_attribute efivar_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ + .attr = {.name = __stringify(_name), .mode = _mode}, \ .show = _show, \ .store = _store, \ }; #define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \ struct subsys_attribute var_subsys_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ + .attr = {.name = __stringify(_name), .mode = _mode}, \ .show = _show, \ .store = _store, \ }; diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index bfce13c8f1ff..5990dd5fc773 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -143,7 +143,6 @@ static struct bin_attribute eeprom_attr = { .attr = { .name = "eeprom", .mode = S_IRUGO, - .owner = THIS_MODULE, }, .size = EEPROM_SIZE, .read = eeprom_read, diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index 76645c142977..1405ce5b236c 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c @@ -152,7 +152,6 @@ static struct bin_attribute user_eeprom_attr = { .attr = { .name = "eeprom", .mode = S_IRUGO, - .owner = THIS_MODULE, }, .size = USER_EEPROM_SIZE, .read = max6875_read, diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 08c299ebf4a8..bf9b99292048 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -479,7 +479,6 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *, element->attr.attr.name = element->name; element->attr.attr.mode = S_IRUGO; - element->attr.attr.owner = THIS_MODULE; element->attr.show = show; element->index = i; diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 27a68835b5ba..1317bdd8cc7c 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -119,7 +119,6 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ .attr = { \ .name = __stringify(_name), \ .mode = _mode, \ - .owner = THIS_MODULE, \ }, \ .show = psmouse_attr_show_helper, \ .store = psmouse_attr_set_helper, \ diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 11ced17f438a..4fcb245ba184 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c @@ -212,7 +212,6 @@ int wf_register_control(struct wf_control *new_ct) list_add(&new_ct->link, &wf_controls); new_ct->attr.attr.name = new_ct->name; - new_ct->attr.attr.owner = THIS_MODULE; new_ct->attr.attr.mode = 0644; new_ct->attr.show = wf_show_control; new_ct->attr.store = wf_store_control; @@ -325,7 +324,6 @@ int wf_register_sensor(struct wf_sensor *new_sr) list_add(&new_sr->link, &wf_sensors); new_sr->attr.attr.name = new_sr->name; - new_sr->attr.attr.owner = THIS_MODULE; new_sr->attr.attr.mode = 0444; new_sr->attr.show = wf_show_sensor; new_sr->attr.store = NULL; diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 4f9060a2a2f2..7798f590e5aa 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c @@ -737,8 +737,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) struct device_attribute dev_attr_##_name = { \ .attr = { \ .name = __stringify(_name), \ - .mode = 0, \ - .owner = THIS_MODULE }, \ + .mode = 0 }, \ .show = NULL, \ .store = NULL, \ } diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 6ec3d500f334..d96eb7229548 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1337,7 +1337,7 @@ const char * buf, size_t count) #define ATTR(_name, _mode) \ struct attribute veth_##_name##_attr = { \ - .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \ + .name = __stringify(_name), .mode = _mode, \ }; static ATTR(active, 0644); diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 924ef0609460..fc4bde259dc7 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -121,14 +121,14 @@ struct pdcspath_entry pdcspath_entry_##_name = { \ #define PDCS_ATTR(_name, _mode, _show, _store) \ struct subsys_attribute pdcs_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ + .attr = {.name = __stringify(_name), .mode = _mode}, \ .show = _show, \ .store = _store, \ }; #define PATHS_ATTR(_name, _mode, _show, _store) \ struct pdcspath_attribute paths_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ + .attr = {.name = __stringify(_name), .mode = _mode}, \ .show = _show, \ .store = _store, \ }; diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index e7322c25d377..74556ec31a5b 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -117,7 +117,6 @@ static struct notification ibm_note; static struct bin_attribute ibm_apci_table_attr = { .attr = { .name = "apci_table", - .owner = THIS_MODULE, .mode = S_IRUGO, }, .read = ibm_read_apci_table, diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 284e83a527f9..d448f8df8613 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -499,7 +499,6 @@ static int pci_create_resource_files(struct pci_dev *pdev) sprintf(res_attr_name, "resource%d", i); res_attr->attr.name = res_attr_name; res_attr->attr.mode = S_IRUSR | S_IWUSR; - res_attr->attr.owner = THIS_MODULE; res_attr->size = pci_resource_len(pdev, i); res_attr->mmap = pci_mmap_resource; res_attr->private = &pdev->resource[i]; @@ -582,7 +581,6 @@ static struct bin_attribute pci_config_attr = { .attr = { .name = "config", .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, }, .size = 256, .read = pci_read_config, @@ -593,7 +591,6 @@ static struct bin_attribute pcie_config_attr = { .attr = { .name = "config", .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, }, .size = 4096, .read = pci_read_config, @@ -628,7 +625,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); rom_attr->attr.name = "rom"; rom_attr->attr.mode = S_IRUSR; - rom_attr->attr.owner = THIS_MODULE; rom_attr->read = pci_read_rom; rom_attr->write = pci_write_rom; retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e48fcf089621..08783bd381f5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -39,7 +39,6 @@ static void pci_create_legacy_files(struct pci_bus *b) b->legacy_io->attr.name = "legacy_io"; b->legacy_io->size = 0xffff; b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; - b->legacy_io->attr.owner = THIS_MODULE; b->legacy_io->read = pci_read_legacy_io; b->legacy_io->write = pci_write_legacy_io; class_device_create_bin_file(&b->class_dev, b->legacy_io); @@ -49,7 +48,6 @@ static void pci_create_legacy_files(struct pci_bus *b) b->legacy_mem->attr.name = "legacy_mem"; b->legacy_mem->size = 1024*1024; b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR; - b->legacy_mem->attr.owner = THIS_MODULE; b->legacy_mem->mmap = pci_mmap_legacy_mem; class_device_create_bin_file(&b->class_dev, b->legacy_mem); } diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index a2bb46526b56..dbfbe65779e5 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -366,7 +366,7 @@ static struct device_attribute *pccard_socket_attributes[] = { }; static struct bin_attribute pccard_cis_attr = { - .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE}, + .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR }, .size = 0x200, .read = pccard_show_cis, .write = pccard_store_cis, diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index eed91434417d..a3972b9f96e6 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -197,7 +197,6 @@ static struct bin_attribute rio_config_attr = { .attr = { .name = "config", .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, }, .size = 0x200000, .read = rio_read_config, diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index afa64c7fa2e2..b024cfb558f4 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -290,7 +290,6 @@ static struct bin_attribute ds1553_nvram_attr = { .attr = { .name = "nvram", .mode = S_IRUGO | S_IWUGO, - .owner = THIS_MODULE, }, .size = RTC_OFFSET, .read = ds1553_nvram_read, diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index d68288b389dc..1638acdbc913 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -159,7 +159,6 @@ static struct bin_attribute ds1742_nvram_attr = { .attr = { .name = "nvram", .mode = S_IRUGO | S_IWUGO, - .owner = THIS_MODULE, }, .read = ds1742_nvram_read, .write = ds1742_nvram_write, diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index ac289e6eadfe..96a8a72a6083 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -165,7 +165,6 @@ static struct bin_attribute chp_measurement_chars_attr = { .attr = { .name = "measurement_chars", .mode = S_IRUSR, - .owner = THIS_MODULE, }, .size = sizeof(struct cmg_chars), .read = chp_measurement_chars_read, @@ -217,7 +216,6 @@ static struct bin_attribute chp_measurement_attr = { .attr = { .name = "measurement", .mode = S_IRUSR, - .owner = THIS_MODULE, }, .size = sizeof(struct cmg_entry), .read = chp_measurement_read, diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 65ffc21afc37..bb0287ad1aac 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -991,7 +991,7 @@ static struct attribute_group qeth_osn_device_attr_group = { #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \ struct device_attribute dev_attr_##_id = { \ - .attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\ + .attr = {.name=__stringify(_name), .mode=_mode, },\ .show = _show, \ .store = _store, \ }; diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 03bfed61bffc..8908228bc134 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -188,7 +188,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { .attr = { .name = "mu_read", .mode = S_IRUSR , - .owner = THIS_MODULE, }, .size = 1032, .read = arcmsr_sysfs_iop_message_read, @@ -198,7 +197,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { .attr = { .name = "mu_write", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 1032, .write = arcmsr_sysfs_iop_message_write, @@ -208,7 +206,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { .attr = { .name = "mu_clear", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 1, .write = arcmsr_sysfs_iop_message_clear, diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index e34442e405e8..578ed79f4148 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -1368,7 +1368,6 @@ static void sas_ex_smp_hook(struct domain_device *dev) memset(bin_attr, 0, sizeof(*bin_attr)); bin_attr->attr.name = SMP_BIN_ATTR_NAME; - bin_attr->attr.owner = THIS_MODULE; bin_attr->attr.mode = 0600; bin_attr->size = 0; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 95fe77e816f8..f81fe501a4a1 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1200,7 +1200,6 @@ static struct bin_attribute sysfs_ctlreg_attr = { .attr = { .name = "ctlreg", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = 256, .read = sysfs_ctlreg_read, @@ -1422,7 +1421,6 @@ static struct bin_attribute sysfs_mbox_attr = { .attr = { .name = "mbox", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = MAILBOX_CMD_SIZE, .read = sysfs_mbox_read, diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 8081b637d97e..96587253bfa9 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -73,7 +73,6 @@ static struct bin_attribute sysfs_fw_dump_attr = { .attr = { .name = "fw_dump", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = 0, .read = qla2x00_sysfs_read_fw_dump, @@ -149,7 +148,6 @@ static struct bin_attribute sysfs_nvram_attr = { .attr = { .name = "nvram", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = 512, .read = qla2x00_sysfs_read_nvram, @@ -198,7 +196,6 @@ static struct bin_attribute sysfs_optrom_attr = { .attr = { .name = "optrom", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = OPTROM_SIZE_24XX, .read = qla2x00_sysfs_read_optrom, @@ -279,7 +276,6 @@ static struct bin_attribute sysfs_optrom_ctl_attr = { .attr = { .name = "optrom_ctl", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 0, .write = qla2x00_sysfs_write_optrom_ctl, @@ -327,7 +323,6 @@ static struct bin_attribute sysfs_vpd_attr = { .attr = { .name = "vpd", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = 0, .read = qla2x00_sysfs_read_vpd, @@ -375,7 +370,6 @@ static struct bin_attribute sysfs_sfp_attr = { .attr = { .name = "sfp", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = SFP_DEV_SIZE * 2, .read = qla2x00_sysfs_read_sfp, diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c index 8efa07e8b8c2..fde1dededba3 100644 --- a/drivers/spi/at25.c +++ b/drivers/spi/at25.c @@ -314,7 +314,6 @@ static int at25_probe(struct spi_device *spi) */ at25->bin.attr.name = "eeprom"; at25->bin.attr.mode = S_IRUSR; - at25->bin.attr.owner = THIS_MODULE; at25->bin.read = at25_bin_read; at25->bin.size = at25->chip.byte_len; diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 2ce050193018..3b3c6571f583 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -2126,7 +2126,6 @@ static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, si static struct bin_attribute edid1_attr = { .attr = { .name = "edid1", - .owner = THIS_MODULE, .mode = 0444, }, .size = EDID_LENGTH, @@ -2136,7 +2135,6 @@ static struct bin_attribute edid1_attr = { static struct bin_attribute edid2_attr = { .attr = { .name = "edid2", - .owner = THIS_MODULE, .mode = 0444, }, .size = EDID_LENGTH, diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index c65e81ff3578..7e06223bca94 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -172,7 +172,7 @@ static struct class backlight_class = { #define DECLARE_ATTR(_name,_mode,_show,_store) \ { \ - .attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ + .attr = { .name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .store = _store, \ } diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 6ef8f0a7a137..648b53c1fdea 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -157,7 +157,7 @@ static struct class lcd_class = { #define DECLARE_ATTR(_name,_mode,_show,_store) \ { \ - .attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ + .attr = { .name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .store = _store, \ } diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index 8ea17a53eed8..4e13aa71adea 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c @@ -252,7 +252,6 @@ static struct bin_attribute w1_f23_bin_attr = { .attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, }, .size = W1_EEPROM_SIZE, .read = w1_f23_read_bin, diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 1a6937dc190b..8ba4e572e09c 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -48,7 +48,6 @@ static struct bin_attribute w1_therm_bin_attr = { .attr = { .name = "w1_slave", .mode = S_IRUGO, - .owner = THIS_MODULE, }, .size = W1_SLAVE_DATA_SIZE, .read = w1_therm_read_bin, diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 7d6876dbcc96..1838cb29b646 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -128,7 +128,6 @@ static struct bin_attribute w1_slave_attr_bin_id = { .attr = { .name = "id", .mode = S_IRUGO, - .owner = THIS_MODULE, }, .size = 8, .read = w1_slave_read_id, @@ -167,7 +166,6 @@ static struct bin_attribute w1_default_attr = { .attr = { .name = "rw", .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, }, .size = PAGE_SIZE, .read = w1_default_read, diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index c3ba0ec334c4..7e03cc68b182 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -78,7 +78,6 @@ static struct bin_attribute zorro_config_attr = { .attr = { .name = "config", .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE }, .size = sizeof(struct ConfigDev), .read = zorro_read_config, diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 606128f5c927..02ca6f1e55d7 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -840,8 +840,6 @@ static int __init ecryptfs_init(void) goto out; } kobj_set_kset_s(&ecryptfs_subsys, fs_subsys); - sysfs_attr_version.attr.owner = THIS_MODULE; - sysfs_attr_version_str.attr.owner = THIS_MODULE; rc = do_sysfs_registration(); if (rc) { printk(KERN_ERR "sysfs registration failed\n"); diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 2b205f5d5790..e9e042b93dbf 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -74,7 +74,6 @@ struct mlog_attribute { #define define_mask(_name) { \ .attr = { \ .name = #_name, \ - .owner = THIS_MODULE, \ .mode = S_IRUGO | S_IWUSR, \ }, \ .mask = ML_##_name, \ diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 9a3a058f3553..98e0b85a9bb2 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -397,7 +397,6 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, static struct attribute addpartattr = { .name = "whole_disk", .mode = S_IRUSR | S_IRGRP | S_IROTH, - .owner = THIS_MODULE, }; sysfs_create_file(&p->kobj, &addpartattr); diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 618b8aea6a7b..3c5574a40b09 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -175,25 +175,20 @@ static int open(struct inode * inode, struct file * file) if (!sysfs_get_active(attr_sd)) return -ENODEV; - /* Grab the module reference for this attribute */ - error = -ENODEV; - if (!try_module_get(attr->attr.owner)) - goto err_sput; - error = -EACCES; if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap)) - goto err_mput; + goto err_out; if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap)) - goto err_mput; + goto err_out; error = -ENOMEM; bb = kzalloc(sizeof(*bb), GFP_KERNEL); if (!bb) - goto err_mput; + goto err_out; bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!bb->buffer) - goto err_mput; + goto err_out; mutex_init(&bb->mutex); file->private_data = bb; @@ -203,9 +198,7 @@ static int open(struct inode * inode, struct file * file) sysfs_get(attr_sd); return 0; - err_mput: - module_put(attr->attr.owner); - err_sput: + err_out: sysfs_put_active(attr_sd); kfree(bb); return error; @@ -214,13 +207,11 @@ static int open(struct inode * inode, struct file * file) static int release(struct inode * inode, struct file * file) { struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; - struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; struct bin_buffer *bb = file->private_data; if (bb->mmapped) sysfs_put_active_two(attr_sd); sysfs_put(attr_sd); - module_put(attr->attr.owner); kfree(bb->buffer); kfree(bb); return 0; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index d673d9b5d33f..a84b734f7b29 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -241,7 +241,6 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t static int sysfs_open_file(struct inode *inode, struct file *file) { struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; - struct attribute *attr = attr_sd->s_elem.attr.attr; struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; struct sysfs_buffer * buffer; struct sysfs_ops * ops = NULL; @@ -251,11 +250,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file) if (!sysfs_get_active_two(attr_sd)) return -ENODEV; - /* Grab the module reference for this attribute */ - error = -ENODEV; - if (!try_module_get(attr->owner)) - goto err_sput; - /* if the kobject has no ktype, then we assume that it is a subsystem * itself, and use ops for it. */ @@ -272,7 +266,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) * or the subsystem have no operations. */ if (!ops) - goto err_mput; + goto err_out; /* File needs write support. * The inode's perms must say it's ok, @@ -280,7 +274,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) */ if (file->f_mode & FMODE_WRITE) { if (!(inode->i_mode & S_IWUGO) || !ops->store) - goto err_mput; + goto err_out; } /* File needs read support. @@ -289,7 +283,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) */ if (file->f_mode & FMODE_READ) { if (!(inode->i_mode & S_IRUGO) || !ops->show) - goto err_mput; + goto err_out; } /* No error? Great, allocate a buffer for the file, and store it @@ -298,7 +292,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) error = -ENOMEM; buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); if (!buffer) - goto err_mput; + goto err_out; init_MUTEX(&buffer->sem); buffer->needs_read_fill = 1; @@ -310,9 +304,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) sysfs_get(attr_sd); return 0; - err_mput: - module_put(attr->owner); - err_sput: + err_out: sysfs_put_active_two(attr_sd); return error; } @@ -320,12 +312,9 @@ static int sysfs_open_file(struct inode *inode, struct file *file) static int sysfs_release(struct inode * inode, struct file * filp) { struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; - struct attribute *attr = attr_sd->s_elem.attr.attr; struct sysfs_buffer *buffer = filp->private_data; sysfs_put(attr_sd); - /* After this point, attr should not be accessed. */ - module_put(attr->owner); if (buffer) { if (buffer->page) diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index e699ab279c2c..e285746588d6 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h @@ -101,8 +101,7 @@ struct sysdev_attribute { #define _SYSDEV_ATTR(_name,_mode,_show,_store) \ { \ - .attr = { .name = __stringify(_name), .mode = _mode, \ - .owner = THIS_MODULE }, \ + .attr = { .name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .store = _store, \ } diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 2f86b080b39d..161e19aa2b4f 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -20,9 +20,13 @@ struct module; struct nameidata; struct dentry; +/* FIXME + * The *owner field is no longer used, but leave around + * until the tree gets cleaned up fully. + */ struct attribute { const char * name; - struct module * owner; + struct module * owner; mode_t mode; }; @@ -39,14 +43,14 @@ struct attribute_group { */ #define __ATTR(_name,_mode,_show,_store) { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .store = _store, \ } #define __ATTR_RO(_name) { \ - .attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \ - .show = _name##_show, \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = _name##_show, \ } #define __ATTR_NULL { .attr = { .name = NULL } } diff --git a/kernel/module.c b/kernel/module.c index 9bd93de01f4a..015d60cfd90e 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -488,8 +488,7 @@ static void free_modinfo_##field(struct module *mod) \ mod->field = NULL; \ } \ static struct module_attribute modinfo_##field = { \ - .attr = { .name = __stringify(field), .mode = 0444, \ - .owner = THIS_MODULE }, \ + .attr = { .name = __stringify(field), .mode = 0444 }, \ .show = show_modinfo_##field, \ .setup = setup_modinfo_##field, \ .test = modinfo_##field##_exists, \ @@ -793,7 +792,7 @@ static ssize_t show_refcnt(struct module_attribute *mattr, } static struct module_attribute refcnt = { - .attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE }, + .attr = { .name = "refcnt", .mode = 0444 }, .show = show_refcnt, }; @@ -851,7 +850,7 @@ static ssize_t show_initstate(struct module_attribute *mattr, } static struct module_attribute initstate = { - .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE }, + .attr = { .name = "initstate", .mode = 0444 }, .show = show_initstate, }; @@ -1032,7 +1031,6 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, sattr->mattr.show = module_sect_show; sattr->mattr.store = NULL; sattr->mattr.attr.name = sattr->name; - sattr->mattr.attr.owner = mod; sattr->mattr.attr.mode = S_IRUGO; *(gattr++) = &(sattr++)->mattr.attr; } @@ -1090,7 +1088,6 @@ int module_add_modinfo_attrs(struct module *mod) if (!attr->test || (attr->test && attr->test(mod))) { memcpy(temp_attr, attr, sizeof(*temp_attr)); - temp_attr->attr.owner = mod; error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); ++temp_attr; } diff --git a/kernel/params.c b/kernel/params.c index e61c46c97ce7..effbaaedd7f3 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -491,7 +491,6 @@ param_sysfs_setup(struct module_kobject *mk, pattr->mattr.show = param_attr_show; pattr->mattr.store = param_attr_store; pattr->mattr.attr.name = (char *)&kp->name[name_skip]; - pattr->mattr.attr.owner = mk->mod; pattr->mattr.attr.mode = kp->perm; *(gattr++) = &(pattr++)->mattr.attr; } diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 33c6c4a7c689..31ace23a0914 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -383,8 +383,7 @@ static ssize_t brforward_read(struct kobject *kobj, char *buf, static struct bin_attribute bridge_forward = { .attr = { .name = SYSFS_BRIDGE_FDB, - .mode = S_IRUGO, - .owner = THIS_MODULE, }, + .mode = S_IRUGO, }, .read = brforward_read, }; diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 2da22927d8dd..79db51fcb476 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -29,8 +29,7 @@ struct brport_attribute { #define BRPORT_ATTR(_name,_mode,_show,_store) \ struct brport_attribute brport_attr_##_name = { \ .attr = {.name = __stringify(_name), \ - .mode = _mode, \ - .owner = THIS_MODULE, }, \ + .mode = _mode }, \ .show = _show, \ .store = _store, \ }; -- cgit v1.2.3-71-gd317 From ad6a1e1c66009ba9dcd2f5c90ffa1fb4ce72fce0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jun 2007 03:45:17 +0900 Subject: driver-core: make devt_attr and uevent_attr static devt_attr and uevent_attr are either allocated dynamically with or embedded in device and class_device as they needed their owner field set to the module implementing the driver. Now that sysfs implements immediate disconnect and owner field removed from struct attribute, there is no reason to do this. Remove these attributes from [class_]device and use static attribute structures instead. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 44 ++++++++++++++++---------------------------- drivers/base/core.c | 45 +++++++++++++++------------------------------ include/linux/device.h | 5 ----- 3 files changed, 31 insertions(+), 63 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/class.c b/drivers/base/class.c index 9cbfde23b9e3..4d2222618b78 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -312,9 +312,6 @@ static void class_dev_release(struct kobject * kobj) pr_debug("device class '%s': release.\n", cd->class_id); - kfree(cd->devt_attr); - cd->devt_attr = NULL; - if (cd->release) cd->release(cd); else if (cls->release) @@ -547,6 +544,9 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf) return print_dev_t(buf, class_dev->devt); } +static struct class_device_attribute class_devt_attr = + __ATTR(dev, S_IRUGO, show_dev, NULL); + static ssize_t store_uevent(struct class_device *class_dev, const char *buf, size_t count) { @@ -554,6 +554,9 @@ static ssize_t store_uevent(struct class_device *class_dev, return count; } +static struct class_device_attribute class_uevent_attr = + __ATTR(uevent, S_IWUSR, NULL, store_uevent); + void class_device_initialize(struct class_device *class_dev) { kobj_set_kset_s(class_dev, class_obj_subsys); @@ -603,30 +606,15 @@ int class_device_add(struct class_device *class_dev) &parent_class->subsys.kobj, "subsystem"); if (error) goto out3; - class_dev->uevent_attr.attr.name = "uevent"; - class_dev->uevent_attr.attr.mode = S_IWUSR; - class_dev->uevent_attr.store = store_uevent; - error = class_device_create_file(class_dev, &class_dev->uevent_attr); + + error = class_device_create_file(class_dev, &class_uevent_attr); if (error) goto out3; if (MAJOR(class_dev->devt)) { - struct class_device_attribute *attr; - attr = kzalloc(sizeof(*attr), GFP_KERNEL); - if (!attr) { - error = -ENOMEM; - goto out4; - } - attr->attr.name = "dev"; - attr->attr.mode = S_IRUGO; - attr->show = show_dev; - error = class_device_create_file(class_dev, attr); - if (error) { - kfree(attr); + error = class_device_create_file(class_dev, &class_devt_attr); + if (error) goto out4; - } - - class_dev->devt_attr = attr; } error = class_device_add_attrs(class_dev); @@ -669,10 +657,10 @@ int class_device_add(struct class_device *class_dev) out6: class_device_remove_attrs(class_dev); out5: - if (class_dev->devt_attr) - class_device_remove_file(class_dev, class_dev->devt_attr); + if (MAJOR(class_dev->devt)) + class_device_remove_file(class_dev, &class_devt_attr); out4: - class_device_remove_file(class_dev, &class_dev->uevent_attr); + class_device_remove_file(class_dev, &class_uevent_attr); out3: kobject_del(&class_dev->kobj); out2: @@ -772,9 +760,9 @@ void class_device_del(struct class_device *class_dev) sysfs_remove_link(&class_dev->kobj, "device"); } sysfs_remove_link(&class_dev->kobj, "subsystem"); - class_device_remove_file(class_dev, &class_dev->uevent_attr); - if (class_dev->devt_attr) - class_device_remove_file(class_dev, class_dev->devt_attr); + class_device_remove_file(class_dev, &class_uevent_attr); + if (MAJOR(class_dev->devt)) + class_device_remove_file(class_dev, &class_devt_attr); class_device_remove_attrs(class_dev); class_device_remove_groups(class_dev); diff --git a/drivers/base/core.c b/drivers/base/core.c index e3fb87bfc6e1..0455aa78fa13 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -310,6 +310,9 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, return count; } +static struct device_attribute uevent_attr = + __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent); + static int device_add_attributes(struct device *dev, struct device_attribute *attrs) { @@ -423,6 +426,9 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr, return print_dev_t(buf, dev->devt); } +static struct device_attribute devt_attr = + __ATTR(dev, S_IRUGO, show_dev, NULL); + /* * devices_subsys - structure to be registered with kobject core. */ @@ -681,31 +687,14 @@ int device_add(struct device *dev) blocking_notifier_call_chain(&dev->bus->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev); - dev->uevent_attr.attr.name = "uevent"; - dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR; - dev->uevent_attr.store = store_uevent; - dev->uevent_attr.show = show_uevent; - error = device_create_file(dev, &dev->uevent_attr); + error = device_create_file(dev, &uevent_attr); if (error) goto attrError; if (MAJOR(dev->devt)) { - struct device_attribute *attr; - attr = kzalloc(sizeof(*attr), GFP_KERNEL); - if (!attr) { - error = -ENOMEM; - goto ueventattrError; - } - attr->attr.name = "dev"; - attr->attr.mode = S_IRUGO; - attr->show = show_dev; - error = device_create_file(dev, attr); - if (error) { - kfree(attr); + error = device_create_file(dev, &devt_attr); + if (error) goto ueventattrError; - } - - dev->devt_attr = attr; } if (dev->class) { @@ -766,10 +755,8 @@ int device_add(struct device *dev) BUS_NOTIFY_DEL_DEVICE, dev); device_remove_attrs(dev); AttrsError: - if (dev->devt_attr) { - device_remove_file(dev, dev->devt_attr); - kfree(dev->devt_attr); - } + if (MAJOR(dev->devt)) + device_remove_file(dev, &devt_attr); if (dev->class) { sysfs_remove_link(&dev->kobj, "subsystem"); @@ -791,7 +778,7 @@ int device_add(struct device *dev) } } ueventattrError: - device_remove_file(dev, &dev->uevent_attr); + device_remove_file(dev, &uevent_attr); attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); @@ -868,10 +855,8 @@ void device_del(struct device * dev) if (parent) klist_del(&dev->knode_parent); - if (dev->devt_attr) { - device_remove_file(dev, dev->devt_attr); - kfree(dev->devt_attr); - } + if (MAJOR(dev->devt)) + device_remove_file(dev, &devt_attr); if (dev->class) { sysfs_remove_link(&dev->kobj, "subsystem"); /* If this is not a "fake" compatible device, remove the @@ -925,7 +910,7 @@ void device_del(struct device * dev) up(&dev->class->sem); } } - device_remove_file(dev, &dev->uevent_attr); + device_remove_file(dev, &uevent_attr); device_remove_attrs(dev); bus_remove_device(dev); diff --git a/include/linux/device.h b/include/linux/device.h index 2e1a2988b7e1..be2debed70d2 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -238,7 +238,6 @@ extern int __must_check class_device_create_file(struct class_device *, * @devt: for internal use by the driver core only. * @node: for internal use by the driver core only. * @kobj: for internal use by the driver core only. - * @devt_attr: for internal use by the driver core only. * @groups: optional additional groups to be created * @dev: if set, a symlink to the struct device is created in the sysfs * directory for this struct class device. @@ -263,8 +262,6 @@ struct class_device { struct kobject kobj; struct class * class; /* required */ dev_t devt; /* dev_t, creates the sysfs "dev" */ - struct class_device_attribute *devt_attr; - struct class_device_attribute uevent_attr; struct device * dev; /* not necessary, but nice to have */ void * class_data; /* class-specific data */ struct class_device *parent; /* parent of this child device, if there is one */ @@ -419,8 +416,6 @@ struct device { struct device_type *type; unsigned is_registered:1; unsigned uevent_suppress:1; - struct device_attribute uevent_attr; - struct device_attribute *devt_attr; struct semaphore sem; /* semaphore to synchronize calls to * its driver. -- cgit v1.2.3-71-gd317 From b402d72cf7b338a074e3c12b305ec79284e18845 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jun 2007 04:27:21 +0900 Subject: sysfs: rename sysfs_dirent->s_type to s_flags and make room for flags Rename sysfs_dirent->s_type to s_flags, pack type into lower eight bits and reserve the rest for flags. sysfs_type() can used to access the type. All existing sd->s_type accesses are converted to use sysfs_type(). While at it, type test is changed to equality test instead of bit-and test where appropriate. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 33 ++++++++++++++++++++------------- fs/sysfs/inode.c | 8 ++++---- fs/sysfs/mount.c | 2 +- fs/sysfs/sysfs.h | 7 ++++++- include/linux/sysfs.h | 3 +++ 5 files changed, 34 insertions(+), 19 deletions(-) (limited to 'include/linux') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index b4074adbab01..eb9bc0a8717b 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -218,9 +218,9 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) repeat: parent_sd = sd->s_parent; - if (sd->s_type & SYSFS_KOBJ_LINK) + if (sysfs_type(sd) == SYSFS_KOBJ_LINK) sysfs_put(sd->s_elem.symlink.target_sd); - if (sd->s_type & SYSFS_COPY_NAME) + if (sysfs_type(sd) & SYSFS_COPY_NAME) kfree(sd->s_name); kfree(sd->s_iattr); sysfs_free_ino(sd->s_ino); @@ -282,7 +282,7 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) sd->s_name = name; sd->s_mode = mode; - sd->s_type = type; + sd->s_flags = type; return sd; @@ -330,7 +330,7 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, struct sysfs_dirent * sd; for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) { - if (sd->s_type) { + if (sysfs_type(sd)) { if (strcmp(sd->s_name, new)) continue; else @@ -446,11 +446,12 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, { struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata; struct sysfs_dirent * sd; + struct bin_attribute *bin_attr; struct inode *inode; int found = 0; for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) { - if ((sd->s_type & SYSFS_NOT_PINNED) && + if ((sysfs_type(sd) & SYSFS_NOT_PINNED) && !strcmp(sd->s_name, dentry->d_name.name)) { found = 1; break; @@ -468,16 +469,22 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, if (inode->i_state & I_NEW) { /* initialize inode according to type */ - if (sd->s_type & SYSFS_KOBJ_ATTR) { + switch (sysfs_type(sd)) { + case SYSFS_KOBJ_ATTR: inode->i_size = PAGE_SIZE; inode->i_fop = &sysfs_file_operations; - } else if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) { - struct bin_attribute *bin_attr = - sd->s_elem.bin_attr.bin_attr; + break; + case SYSFS_KOBJ_BIN_ATTR: + bin_attr = sd->s_elem.bin_attr.bin_attr; inode->i_size = bin_attr->size; inode->i_fop = &bin_fops; - } else if (sd->s_type & SYSFS_KOBJ_LINK) + break; + case SYSFS_KOBJ_LINK: inode->i_op = &sysfs_symlink_inode_operations; + break; + default: + BUG(); + } } sysfs_instantiate(dentry, inode); @@ -532,7 +539,7 @@ static void __sysfs_remove_dir(struct dentry *dentry) while (*pos) { struct sysfs_dirent *sd = *pos; - if (sd->s_type && (sd->s_type & SYSFS_NOT_PINNED)) { + if (sysfs_type(sd) && (sysfs_type(sd) & SYSFS_NOT_PINNED)) { *pos = sd->s_sibling; sd->s_sibling = removed; removed = sd; @@ -775,7 +782,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) const char * name; int len; - if (!next->s_type) + if (!sysfs_type(next)) continue; name = next->s_name; @@ -824,7 +831,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) pos = &sd->s_children; while (n && *pos) { struct sysfs_dirent *next = *pos; - if (next->s_type) + if (sysfs_type(next)) n--; pos = &(*pos)->s_sibling; } diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 63daa06c4194..ee3a5d957051 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -242,7 +242,7 @@ void sysfs_drop_dentry(struct sysfs_dirent *sd) dput(dentry); /* XXX: unpin if directory, this will go away soon */ - if (sd->s_type & SYSFS_DIR) + if (sysfs_type(sd) == SYSFS_DIR) dput(dentry); /* adjust nlink and update timestamp */ @@ -254,7 +254,7 @@ void sysfs_drop_dentry(struct sysfs_dirent *sd) inode->i_ctime = curtime; drop_nlink(inode); - if (sd->s_type & SYSFS_DIR) + if (sysfs_type(sd) == SYSFS_DIR) drop_nlink(inode); mutex_unlock(&inode->i_mutex); @@ -267,7 +267,7 @@ void sysfs_drop_dentry(struct sysfs_dirent *sd) mutex_lock(&inode->i_mutex); inode->i_ctime = inode->i_mtime = curtime; - if (sd->s_type & SYSFS_DIR) + if (sysfs_type(sd) == SYSFS_DIR) drop_nlink(inode); mutex_unlock(&inode->i_mutex); @@ -293,7 +293,7 @@ int sysfs_hash_and_remove(struct dentry * dir, const char * name) for (pos = &parent_sd->s_children; *pos; pos = &(*pos)->s_sibling) { sd = *pos; - if (!sd->s_type) + if (!sysfs_type(sd)) continue; if (!strcmp(sd->s_name, name)) { *pos = sd->s_sibling; diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 4be9593ea000..078537e5d696 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -26,7 +26,7 @@ static const struct super_operations sysfs_ops = { static struct sysfs_dirent sysfs_root = { .s_count = ATOMIC_INIT(1), - .s_type = SYSFS_ROOT, + .s_flags = SYSFS_ROOT, .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, .s_ino = 1, }; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6f8aaf3805d2..06b5085804a1 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -34,7 +34,7 @@ struct sysfs_dirent { struct sysfs_elem_bin_attr bin_attr; } s_elem; - int s_type; + unsigned int s_flags; umode_t s_mode; ino_t s_ino; struct dentry * s_dentry; @@ -86,6 +86,11 @@ extern const struct file_operations bin_fops; extern const struct inode_operations sysfs_dir_inode_operations; extern const struct inode_operations sysfs_symlink_inode_operations; +static inline unsigned int sysfs_type(struct sysfs_dirent *sd) +{ + return sd->s_flags & SYSFS_TYPE_MASK; +} + static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) { if (sd) { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 161e19aa2b4f..58135509023e 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -74,6 +74,7 @@ struct sysfs_ops { ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); }; +#define SYSFS_TYPE_MASK 0x00ff #define SYSFS_ROOT 0x0001 #define SYSFS_DIR 0x0002 #define SYSFS_KOBJ_ATTR 0x0004 @@ -82,6 +83,8 @@ struct sysfs_ops { #define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK) #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) +#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK + #ifdef CONFIG_SYSFS extern int sysfs_schedule_callback(struct kobject *kobj, -- cgit v1.2.3-71-gd317 From 380e6fbb729a55b73d5d8409551474884e0d93fc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jun 2007 04:27:22 +0900 Subject: sysfs: implement SYSFS_FLAG_REMOVED flag Implement SYSFS_FLAG_REMOVED flag which currently is used only to improve sanity check in sysfs_deactivate(). The flag will be used to make directory entries reclamiable. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 4 +++- fs/sysfs/inode.c | 1 + include/linux/sysfs.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index eb9bc0a8717b..f2ea00683ec9 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -171,7 +171,7 @@ void sysfs_deactivate(struct sysfs_dirent *sd) DECLARE_COMPLETION_ONSTACK(wait); int v; - BUG_ON(sd->s_sibling); + BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED)); sd->s_sibling = (void *)&wait; /* atomic_add_return() is a mb(), put_active() will always see @@ -506,6 +506,7 @@ static void remove_dir(struct dentry * d) mutex_lock(&parent->d_inode->i_mutex); sysfs_unlink_sibling(sd); + sd->s_flags |= SYSFS_FLAG_REMOVED; pr_debug(" o %s removing done (%d)\n",d->d_name.name, atomic_read(&d->d_count)); @@ -540,6 +541,7 @@ static void __sysfs_remove_dir(struct dentry *dentry) struct sysfs_dirent *sd = *pos; if (sysfs_type(sd) && (sysfs_type(sd) & SYSFS_NOT_PINNED)) { + sd->s_flags |= SYSFS_FLAG_REMOVED; *pos = sd->s_sibling; sd->s_sibling = removed; removed = sd; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index ee3a5d957051..e2f6ef138d20 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -296,6 +296,7 @@ int sysfs_hash_and_remove(struct dentry * dir, const char * name) if (!sysfs_type(sd)) continue; if (!strcmp(sd->s_name, name)) { + sd->s_flags |= SYSFS_FLAG_REMOVED; *pos = sd->s_sibling; sd->s_sibling = NULL; found = 1; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 58135509023e..2a6df6444e69 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -84,6 +84,7 @@ struct sysfs_ops { #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK +#define SYSFS_FLAG_REMOVED 0x0100 #ifdef CONFIG_SYSFS -- cgit v1.2.3-71-gd317 From 608e266a2d4e62c1b98c1c573064b6afe8c06a58 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jun 2007 04:27:22 +0900 Subject: sysfs: make kobj point to sysfs_dirent instead of dentry As kobj sysfs dentries and inodes are gonna be made reclaimable, dentry can't be used as naming token for sysfs file/directory, replace kobj->dentry with kobj->sd. The only external interface change is shadow directory handling. All other changes are contained in kobj and sysfs. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/bin.c | 6 +-- fs/sysfs/dir.c | 119 ++++++++++++++++++++++++------------------------ fs/sysfs/file.c | 47 +++++++++---------- fs/sysfs/group.c | 55 +++++++++++----------- fs/sysfs/inode.c | 11 +++-- fs/sysfs/symlink.c | 22 ++++----- fs/sysfs/sysfs.h | 10 ++-- include/linux/kobject.h | 9 ++-- include/linux/sysfs.h | 19 ++++---- lib/kobject.c | 10 ++-- 10 files changed, 156 insertions(+), 152 deletions(-) (limited to 'include/linux') diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 3c5574a40b09..55796bdacd3d 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -234,9 +234,9 @@ const struct file_operations bin_fops = { int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) { - BUG_ON(!kobj || !kobj->dentry || !attr); + BUG_ON(!kobj || !kobj->sd || !attr); - return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR); + return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR); } @@ -248,7 +248,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) { - if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) { + if (sysfs_hash_and_remove(kobj->sd, attr->attr.name) < 0) { printk(KERN_ERR "%s: " "bad dentry or inode or no such file: \"%s\"\n", __FUNCTION__, attr->attr.name); diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 4762a9aa0b27..31b6cf30636d 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -368,9 +368,10 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, return sd; } -static int create_dir(struct kobject *kobj, struct dentry *parent, - const char *name, struct dentry **p_dentry) +static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, + const char *name, struct sysfs_dirent **p_sd) { + struct dentry *parent = parent_sd->s_dentry; int error; umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; struct dentry *dentry; @@ -409,14 +410,14 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, /* link in */ error = -EEXIST; - if (sysfs_find_dirent(parent->d_fsdata, name)) + if (sysfs_find_dirent(parent_sd, name)) goto out_iput; sysfs_instantiate(dentry, inode); inc_nlink(parent->d_inode); - sysfs_attach_dirent(sd, parent->d_fsdata, dentry); + sysfs_attach_dirent(sd, parent_sd, dentry); - *p_dentry = dentry; + *p_sd = sd; error = 0; goto out_unlock; /* pin directory dentry in core */ @@ -433,38 +434,37 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, return error; } - -int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d) +int sysfs_create_subdir(struct kobject *kobj, const char *name, + struct sysfs_dirent **p_sd) { - return create_dir(k,k->dentry,n,d); + return create_dir(kobj, kobj->sd, name, p_sd); } /** * sysfs_create_dir - create a directory for an object. * @kobj: object we're creating directory for. - * @shadow_parent: parent parent object. + * @shadow_parent: parent object. */ - -int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent) +int sysfs_create_dir(struct kobject *kobj, + struct sysfs_dirent *shadow_parent_sd) { - struct dentry * dentry = NULL; - struct dentry * parent; + struct sysfs_dirent *parent_sd, *sd; int error = 0; BUG_ON(!kobj); - if (shadow_parent) - parent = shadow_parent; + if (shadow_parent_sd) + parent_sd = shadow_parent_sd; else if (kobj->parent) - parent = kobj->parent->dentry; + parent_sd = kobj->parent->sd; else if (sysfs_mount && sysfs_mount->mnt_sb) - parent = sysfs_mount->mnt_sb->s_root; + parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; else return -EFAULT; - error = create_dir(kobj,parent,kobject_name(kobj),&dentry); + error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd); if (!error) - kobj->dentry = dentry; + kobj->sd = sd; return error; } @@ -525,18 +525,16 @@ const struct inode_operations sysfs_dir_inode_operations = { .setattr = sysfs_setattr, }; -static void remove_dir(struct dentry * d) +static void remove_dir(struct sysfs_dirent *sd) { - struct dentry *parent = d->d_parent; - struct sysfs_dirent *sd = d->d_fsdata; + struct dentry *parent = sd->s_parent->s_dentry; mutex_lock(&parent->d_inode->i_mutex); sysfs_unlink_sibling(sd); sd->s_flags |= SYSFS_FLAG_REMOVED; - pr_debug(" o %s removing done (%d)\n",d->d_name.name, - atomic_read(&d->d_count)); + pr_debug(" o %s removing done\n", sd->s_name); mutex_unlock(&parent->d_inode->i_mutex); @@ -545,25 +543,26 @@ static void remove_dir(struct dentry * d) sysfs_put(sd); } -void sysfs_remove_subdir(struct dentry * d) +void sysfs_remove_subdir(struct sysfs_dirent *sd) { - remove_dir(d); + remove_dir(sd); } -static void __sysfs_remove_dir(struct dentry *dentry) +static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) { struct sysfs_dirent *removed = NULL; - struct sysfs_dirent *parent_sd; struct sysfs_dirent **pos; + struct dentry *dir; - if (!dentry) + if (!dir_sd) return; - pr_debug("sysfs %s: removing dir\n",dentry->d_name.name); - mutex_lock(&dentry->d_inode->i_mutex); - parent_sd = dentry->d_fsdata; - pos = &parent_sd->s_children; + dir = dir_sd->s_dentry; + + pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); + mutex_lock(&dir->d_inode->i_mutex); + pos = &dir_sd->s_children; while (*pos) { struct sysfs_dirent *sd = *pos; @@ -575,7 +574,7 @@ static void __sysfs_remove_dir(struct dentry *dentry) } else pos = &(*pos)->s_sibling; } - mutex_unlock(&dentry->d_inode->i_mutex); + mutex_unlock(&dir->d_inode->i_mutex); while (removed) { struct sysfs_dirent *sd = removed; @@ -588,7 +587,7 @@ static void __sysfs_remove_dir(struct dentry *dentry) sysfs_put(sd); } - remove_dir(dentry); + remove_dir(dir_sd); } /** @@ -602,25 +601,25 @@ static void __sysfs_remove_dir(struct dentry *dentry) void sysfs_remove_dir(struct kobject * kobj) { - struct dentry *d = kobj->dentry; + struct sysfs_dirent *sd = kobj->sd; spin_lock(&kobj_sysfs_assoc_lock); - kobj->dentry = NULL; + kobj->sd = NULL; spin_unlock(&kobj_sysfs_assoc_lock); - __sysfs_remove_dir(d); + __sysfs_remove_dir(sd); } -int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, +int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, const char *new_name) { - struct sysfs_dirent *sd = kobj->dentry->d_fsdata; - struct sysfs_dirent *parent_sd = new_parent->d_fsdata; + struct sysfs_dirent *sd = kobj->sd; + struct dentry *new_parent = new_parent_sd->s_dentry; struct dentry *new_dentry; char *dup_name; int error; - if (!new_parent) + if (!new_parent_sd) return -EFAULT; down_write(&sysfs_rename_sem); @@ -637,9 +636,9 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, * shadows of the same directory */ error = -EINVAL; - if (kobj->dentry->d_parent->d_inode != new_parent->d_inode || + if (sd->s_parent->s_dentry->d_inode != new_parent->d_inode || new_dentry->d_parent->d_inode != new_parent->d_inode || - new_dentry == kobj->dentry) + new_dentry == sd->s_dentry) goto out_dput; error = -EEXIST; @@ -661,12 +660,12 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, /* move under the new parent */ d_add(new_dentry, NULL); - d_move(kobj->dentry, new_dentry); + d_move(sd->s_dentry, new_dentry); sysfs_unlink_sibling(sd); - sysfs_get(parent_sd); + sysfs_get(new_parent_sd); sysfs_put(sd->s_parent); - sd->s_parent = parent_sd; + sd->s_parent = new_parent_sd; sysfs_link_sibling(sd); error = 0; @@ -691,9 +690,9 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) int error; old_parent_dentry = kobj->parent ? - kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; + kobj->parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root; new_parent_dentry = new_parent ? - new_parent->dentry : sysfs_mount->mnt_sb->s_root; + new_parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root; if (old_parent_dentry->d_inode == new_parent_dentry->d_inode) return 0; /* nothing to move */ @@ -705,7 +704,7 @@ again: } new_parent_sd = new_parent_dentry->d_fsdata; - sd = kobj->dentry->d_fsdata; + sd = kobj->sd; new_dentry = lookup_one_len(kobj->name, new_parent_dentry, strlen(kobj->name)); @@ -715,7 +714,7 @@ again: } else error = 0; d_add(new_dentry, NULL); - d_move(kobj->dentry, new_dentry); + d_move(sd->s_dentry, new_dentry); dput(new_dentry); /* Remove from old parent's list and insert into new parent's list. */ @@ -885,7 +884,7 @@ int sysfs_make_shadowed_dir(struct kobject *kobj, struct inode *inode; struct inode_operations *i_op; - inode = kobj->dentry->d_inode; + inode = kobj->sd->s_dentry->d_inode; if (inode->i_op != &sysfs_dir_inode_operations) return -EINVAL; @@ -912,16 +911,16 @@ int sysfs_make_shadowed_dir(struct kobject *kobj, * directory. */ -struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) +struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) { - struct dentry *dir = kobj->dentry; + struct dentry *dir = kobj->sd->s_dentry; struct inode *inode = dir->d_inode; struct dentry *parent = dir->d_parent; struct sysfs_dirent *parent_sd = parent->d_fsdata; struct dentry *shadow; struct sysfs_dirent *sd; - shadow = ERR_PTR(-EINVAL); + sd = ERR_PTR(-EINVAL); if (!sysfs_is_shadowed_inode(inode)) goto out; @@ -944,25 +943,25 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) dget(shadow); /* Extra count - pin the dentry in core */ out: - return shadow; + return sd; nomem: dput(shadow); - shadow = ERR_PTR(-ENOMEM); + sd = ERR_PTR(-ENOMEM); goto out; } /** * sysfs_remove_shadow_dir - remove an object's directory. - * @shadow: dentry of shadow directory + * @shadow_sd: sysfs_dirent of shadow directory * * The only thing special about this is that we remove any files in * the directory before we remove the directory, and we've inlined * what used to be sysfs_rmdir() below, instead of calling separately. */ -void sysfs_remove_shadow_dir(struct dentry *shadow) +void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd) { - __sysfs_remove_dir(shadow); + __sysfs_remove_dir(shadow_sd); } const struct file_operations sysfs_dir_operations = { diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index e448b88e313e..20703b9ee064 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -385,7 +385,7 @@ static struct dentry *step_down(struct dentry *dir, const char * name) void sysfs_notify(struct kobject * k, char *dir, char *attr) { - struct dentry *de = k->dentry; + struct dentry *de = k->sd->s_dentry; if (de) dget(de); if (de && dir) @@ -412,16 +412,17 @@ const struct file_operations sysfs_file_operations = { }; -int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) +int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, + int type) { - struct sysfs_dirent * parent_sd = dir->d_fsdata; + struct dentry *dir = dir_sd->s_dentry; umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; struct sysfs_dirent *sd; int error = 0; mutex_lock(&dir->d_inode->i_mutex); - if (sysfs_find_dirent(parent_sd, attr->name)) { + if (sysfs_find_dirent(dir_sd, attr->name)) { error = -EEXIST; goto out_unlock; } @@ -432,7 +433,7 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) goto out_unlock; } sd->s_elem.attr.attr = (void *)attr; - sysfs_attach_dirent(sd, parent_sd, NULL); + sysfs_attach_dirent(sd, dir_sd, NULL); out_unlock: mutex_unlock(&dir->d_inode->i_mutex); @@ -448,9 +449,9 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) { - BUG_ON(!kobj || !kobj->dentry || !attr); + BUG_ON(!kobj || !kobj->sd || !attr); - return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR); + return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR); } @@ -464,16 +465,16 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) int sysfs_add_file_to_group(struct kobject *kobj, const struct attribute *attr, const char *group) { - struct dentry *dir; + struct sysfs_dirent *dir_sd; int error; - dir = lookup_one_len(group, kobj->dentry, strlen(group)); - if (IS_ERR(dir)) - error = PTR_ERR(dir); - else { - error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR); - dput(dir); - } + dir_sd = sysfs_get_dirent(kobj->sd, group); + if (!dir_sd) + return -ENOENT; + + error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR); + sysfs_put(dir_sd); + return error; } EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); @@ -486,7 +487,7 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); */ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) { - struct dentry * dir = kobj->dentry; + struct dentry *dir = kobj->sd->s_dentry; struct dentry * victim; int res = -ENOENT; @@ -522,7 +523,7 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) */ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { - struct dentry *dir = kobj->dentry; + struct dentry *dir = kobj->sd->s_dentry; struct dentry *victim; struct inode * inode; struct iattr newattrs; @@ -560,7 +561,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) { - sysfs_hash_and_remove(kobj->dentry, attr->name); + sysfs_hash_and_remove(kobj->sd, attr->name); } @@ -573,12 +574,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) void sysfs_remove_file_from_group(struct kobject *kobj, const struct attribute *attr, const char *group) { - struct dentry *dir; + struct sysfs_dirent *dir_sd; - dir = lookup_one_len(group, kobj->dentry, strlen(group)); - if (!IS_ERR(dir)) { - sysfs_hash_and_remove(dir, attr->name); - dput(dir); + dir_sd = sysfs_get_dirent(kobj->sd, group); + if (dir_sd) { + sysfs_hash_and_remove(dir_sd, attr->name); + sysfs_put(dir_sd); } } EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 52eed2a7a5ef..f318b73c790c 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -18,26 +18,25 @@ #include "sysfs.h" -static void remove_files(struct dentry * dir, - const struct attribute_group * grp) +static void remove_files(struct sysfs_dirent *dir_sd, + const struct attribute_group *grp) { struct attribute *const* attr; for (attr = grp->attrs; *attr; attr++) - sysfs_hash_and_remove(dir,(*attr)->name); + sysfs_hash_and_remove(dir_sd, (*attr)->name); } -static int create_files(struct dentry * dir, - const struct attribute_group * grp) +static int create_files(struct sysfs_dirent *dir_sd, + const struct attribute_group *grp) { struct attribute *const* attr; int error = 0; - for (attr = grp->attrs; *attr && !error; attr++) { - error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR); - } + for (attr = grp->attrs; *attr && !error; attr++) + error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR); if (error) - remove_files(dir,grp); + remove_files(dir_sd, grp); return error; } @@ -45,44 +44,44 @@ static int create_files(struct dentry * dir, int sysfs_create_group(struct kobject * kobj, const struct attribute_group * grp) { - struct dentry * dir; + struct sysfs_dirent *sd; int error; - BUG_ON(!kobj || !kobj->dentry); + BUG_ON(!kobj || !kobj->sd); if (grp->name) { - error = sysfs_create_subdir(kobj,grp->name,&dir); + error = sysfs_create_subdir(kobj, grp->name, &sd); if (error) return error; } else - dir = kobj->dentry; - dir = dget(dir); - if ((error = create_files(dir,grp))) { + sd = kobj->sd; + sysfs_get(sd); + error = create_files(sd, grp); + if (error) { if (grp->name) - sysfs_remove_subdir(dir); + sysfs_remove_subdir(sd); } - dput(dir); + sysfs_put(sd); return error; } void sysfs_remove_group(struct kobject * kobj, const struct attribute_group * grp) { - struct dentry * dir; + struct sysfs_dirent *dir_sd = kobj->sd; + struct sysfs_dirent *sd; if (grp->name) { - dir = lookup_one_len_kern(grp->name, kobj->dentry, - strlen(grp->name)); - BUG_ON(IS_ERR(dir)); - } - else - dir = dget(kobj->dentry); + sd = sysfs_get_dirent(dir_sd, grp->name); + BUG_ON(!sd); + } else + sd = sysfs_get(dir_sd); - remove_files(dir,grp); + remove_files(sd, grp); if (grp->name) - sysfs_remove_subdir(dir); - /* release the ref. taken in this routine */ - dput(dir); + sysfs_remove_subdir(sd); + + sysfs_put(sd); } diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index e2f6ef138d20..1be853706e99 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -275,22 +275,23 @@ void sysfs_drop_dentry(struct sysfs_dirent *sd) } } -int sysfs_hash_and_remove(struct dentry * dir, const char * name) +int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) { + struct dentry *dir; struct sysfs_dirent **pos, *sd; - struct sysfs_dirent *parent_sd; int found = 0; - if (!dir) + if (!dir_sd) return -ENOENT; + dir = dir_sd->s_dentry; + if (dir->d_inode == NULL) /* no inode means this hasn't been made visible yet */ return -ENOENT; - parent_sd = dir->d_fsdata; mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); - for (pos = &parent_sd->s_children; *pos; pos = &(*pos)->s_sibling) { + for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) { sd = *pos; if (!sysfs_type(sd)) diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 45b62e229627..43cc5222f136 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -66,7 +66,6 @@ static int sysfs_add_link(struct sysfs_dirent * parent_sd, const char * name, */ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) { - struct dentry *dentry = NULL; struct sysfs_dirent *parent_sd = NULL; struct sysfs_dirent *target_sd = NULL; int error = -EEXIST; @@ -75,29 +74,28 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char if (!kobj) { if (sysfs_mount && sysfs_mount->mnt_sb) - dentry = sysfs_mount->mnt_sb->s_root; + parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; } else - dentry = kobj->dentry; + parent_sd = kobj->sd; - if (!dentry) + if (!parent_sd) return -EFAULT; - parent_sd = dentry->d_fsdata; - /* target->dentry can go away beneath us but is protected with + /* target->sd can go away beneath us but is protected with * kobj_sysfs_assoc_lock. Fetch target_sd from it. */ spin_lock(&kobj_sysfs_assoc_lock); - if (target->dentry) - target_sd = sysfs_get(target->dentry->d_fsdata); + if (target->sd) + target_sd = sysfs_get(target->sd); spin_unlock(&kobj_sysfs_assoc_lock); if (!target_sd) return -ENOENT; - mutex_lock(&dentry->d_inode->i_mutex); - if (!sysfs_find_dirent(dentry->d_fsdata, name)) + mutex_lock(&parent_sd->s_dentry->d_inode->i_mutex); + if (!sysfs_find_dirent(parent_sd, name)) error = sysfs_add_link(parent_sd, name, target_sd); - mutex_unlock(&dentry->d_inode->i_mutex); + mutex_unlock(&parent_sd->s_dentry->d_inode->i_mutex); if (error) sysfs_put(target_sd); @@ -114,7 +112,7 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char void sysfs_remove_link(struct kobject * kobj, const char * name) { - sysfs_hash_and_remove(kobj->dentry,name); + sysfs_hash_and_remove(kobj->sd, name); } static int sysfs_get_target_path(struct sysfs_dirent * parent_sd, diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index f1629b4520aa..27a5f4b4e3b0 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -69,12 +69,14 @@ extern void sysfs_attach_dirent(struct sysfs_dirent *sd, struct sysfs_dirent *parent_sd, struct dentry *dentry); -extern int sysfs_add_file(struct dentry *, const struct attribute *, int); -extern int sysfs_hash_and_remove(struct dentry * dir, const char * name); +extern int sysfs_add_file(struct sysfs_dirent *dir_sd, + const struct attribute *attr, int type); +extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name); -extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); -extern void sysfs_remove_subdir(struct dentry *); +extern int sysfs_create_subdir(struct kobject *kobj, const char *name, + struct sysfs_dirent **p_sd); +extern void sysfs_remove_subdir(struct sysfs_dirent *sd); extern void sysfs_drop_dentry(struct sysfs_dirent *sd); extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); diff --git a/include/linux/kobject.h b/include/linux/kobject.h index c288e41ba331..06cbf41d32d2 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -55,7 +55,7 @@ struct kobject { struct kobject * parent; struct kset * kset; struct kobj_type * ktype; - struct dentry * dentry; + struct sysfs_dirent * sd; wait_queue_head_t poll; }; @@ -71,13 +71,14 @@ extern void kobject_init(struct kobject *); extern void kobject_cleanup(struct kobject *); extern int __must_check kobject_add(struct kobject *); -extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *); +extern int __must_check kobject_shadow_add(struct kobject *kobj, + struct sysfs_dirent *shadow_parent); extern void kobject_del(struct kobject *); extern int __must_check kobject_rename(struct kobject *, const char *new_name); extern int __must_check kobject_shadow_rename(struct kobject *kobj, - struct dentry *new_parent, - const char *new_name); + struct sysfs_dirent *new_parent, + const char *new_name); extern int __must_check kobject_move(struct kobject *, struct kobject *); extern int __must_check kobject_register(struct kobject *); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 2a6df6444e69..4c43030fae5d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -19,6 +19,7 @@ struct kobject; struct module; struct nameidata; struct dentry; +struct sysfs_dirent; /* FIXME * The *owner field is no longer used, but leave around @@ -92,13 +93,14 @@ extern int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), void *data, struct module *owner); extern int __must_check -sysfs_create_dir(struct kobject *, struct dentry *); +sysfs_create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent_sd); extern void sysfs_remove_dir(struct kobject *); extern int __must_check -sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name); +sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, + const char *new_name); extern int __must_check sysfs_move_dir(struct kobject *, struct kobject *); @@ -138,8 +140,8 @@ void sysfs_notify(struct kobject * k, char *dir, char *attr); extern int sysfs_make_shadowed_dir(struct kobject *kobj, void * (*follow_link)(struct dentry *, struct nameidata *)); -extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj); -extern void sysfs_remove_shadow_dir(struct dentry *dir); +extern struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj); +extern void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd); extern int __must_check sysfs_init(void); @@ -151,7 +153,8 @@ static inline int sysfs_schedule_callback(struct kobject *kobj, return -ENOSYS; } -static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow) +static inline int sysfs_create_dir(struct kobject *kobj, + struct sysfs_dirent *shadow_parent_sd) { return 0; } @@ -161,9 +164,9 @@ static inline void sysfs_remove_dir(struct kobject * k) ; } -static inline int sysfs_rename_dir(struct kobject * k, - struct dentry *new_parent, - const char *new_name) +static inline int sysfs_rename_dir(struct kobject *kobj, + struct sysfs_dirent *new_parent_sd, + const char *new_name) { return 0; } diff --git a/lib/kobject.c b/lib/kobject.c index b4ebd7631700..4b08e0ff95c8 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -44,7 +44,7 @@ static int populate_dir(struct kobject * kobj) return error; } -static int create_dir(struct kobject * kobj, struct dentry *shadow_parent) +static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent) { int error = 0; if (kobject_name(kobj)) { @@ -162,7 +162,7 @@ static void unlink(struct kobject * kobj) * @shadow_parent: sysfs directory to add to. */ -int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) +int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) { int error = 0; struct kobject * parent; @@ -338,7 +338,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name) /* Note : if we want to send the new name alone, not the full path, * we could probably use kobject_name(kobj); */ - error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name); + error = sysfs_rename_dir(kobj, kobj->parent->sd, new_name); /* This function is mostly/only used for network interface. * Some hotplug package track interfaces by their name and @@ -361,8 +361,8 @@ out: * @new_name: object's new name */ -int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent, - const char *new_name) +int kobject_shadow_rename(struct kobject *kobj, + struct sysfs_dirent *new_parent, const char *new_name) { int error = 0; -- cgit v1.2.3-71-gd317 From 51225039f3cf9d250596d1344494b293274b9169 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jun 2007 04:27:25 +0900 Subject: sysfs: make directory dentries and inodes reclaimable This patch makes dentries and inodes for sysfs directories reclaimable. * sysfs_notify() is modified to walk sysfs_dirent tree instead of dentry tree. * sysfs_update_file() and sysfs_chmod_file() use sysfs_get_dentry() to grab the victim dentry. * sysfs_rename_dir() and sysfs_move_dir() grab all dentries using sysfs_get_dentry() on startup. * Dentries for all shadowed directories are pinned in memory to serve as lookup start point. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 231 +++++++++++++++++++++++++++----------------------- fs/sysfs/file.c | 134 +++++++++++++---------------- fs/sysfs/mount.c | 2 +- fs/sysfs/sysfs.h | 1 + include/linux/sysfs.h | 1 - 5 files changed, 187 insertions(+), 182 deletions(-) (limited to 'include/linux') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 987211296106..aee966c44aac 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -568,10 +568,10 @@ static void sysfs_drop_dentry(struct sysfs_dirent *sd) spin_unlock(&dcache_lock); spin_unlock(&sysfs_assoc_lock); - dput(dentry); - /* XXX: unpin if directory, this will go away soon */ - if (sysfs_type(sd) == SYSFS_DIR) + /* dentries for shadowed inodes are pinned, unpin */ + if (dentry && sysfs_is_shadowed_inode(dentry->d_inode)) dput(dentry); + dput(dentry); /* adjust nlink and update timestamp */ inode = ilookup(sysfs_sb, sd->s_ino); @@ -686,69 +686,29 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, const char *name, struct sysfs_dirent **p_sd) { - struct dentry *parent = parent_sd->s_dentry; - struct sysfs_addrm_cxt acxt; - int error; umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; - struct dentry *dentry; - struct inode *inode; + struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; - sysfs_addrm_start(&acxt, parent_sd); - /* allocate */ - dentry = lookup_one_len(name, parent, strlen(name)); - if (IS_ERR(dentry)) { - error = PTR_ERR(dentry); - goto out_finish; - } - - error = -EEXIST; - if (dentry->d_inode) - goto out_dput; - - error = -ENOMEM; sd = sysfs_new_dirent(name, mode, SYSFS_DIR); if (!sd) - goto out_drop; + return -ENOMEM; sd->s_elem.dir.kobj = kobj; - inode = sysfs_get_inode(sd); - if (!inode) - goto out_sput; - - if (inode->i_state & I_NEW) { - inode->i_op = &sysfs_dir_inode_operations; - inode->i_fop = &sysfs_dir_operations; - /* directory inodes start off with i_nlink == 2 (for ".") */ - inc_nlink(inode); - } - /* link in */ - error = -EEXIST; - if (sysfs_find_dirent(parent_sd, name)) - goto out_iput; - - sysfs_add_one(&acxt, sd); - sysfs_link_sibling(sd); - sysfs_instantiate(dentry, inode); - sysfs_attach_dentry(sd, dentry); - - *p_sd = sd; - error = 0; - goto out_finish; /* pin directory dentry in core */ + sysfs_addrm_start(&acxt, parent_sd); + if (!sysfs_find_dirent(parent_sd, name)) { + sysfs_add_one(&acxt, sd); + sysfs_link_sibling(sd); + } + if (sysfs_addrm_finish(&acxt)) { + *p_sd = sd; + return 0; + } - out_iput: - iput(inode); - out_sput: sysfs_put(sd); - out_drop: - d_drop(dentry); - out_dput: - dput(dentry); - out_finish: - sysfs_addrm_finish(&acxt); - return error; + return -EEXIST; } int sysfs_create_subdir(struct kobject *kobj, const char *name, @@ -785,6 +745,17 @@ int sysfs_create_dir(struct kobject *kobj, return error; } +static int sysfs_count_nlink(struct sysfs_dirent *sd) +{ + struct sysfs_dirent *child; + int nr = 0; + + for (child = sd->s_children; child; child = child->s_sibling) + if (sysfs_type(child) == SYSFS_DIR) + nr++; + return nr + 2; +} + static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { @@ -795,7 +766,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, int found = 0; for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) { - if ((sysfs_type(sd) & SYSFS_NOT_PINNED) && + if (sysfs_type(sd) && !strcmp(sd->s_name, dentry->d_name.name)) { found = 1; break; @@ -816,6 +787,11 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, if (inode->i_state & I_NEW) { /* initialize inode according to type */ switch (sysfs_type(sd)) { + case SYSFS_DIR: + inode->i_op = &sysfs_dir_inode_operations; + inode->i_fop = &sysfs_dir_operations; + inode->i_nlink = sysfs_count_nlink(sd); + break; case SYSFS_KOBJ_ATTR: inode->i_size = PAGE_SIZE; inode->i_fop = &sysfs_file_operations; @@ -876,7 +852,7 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) while (*pos) { struct sysfs_dirent *sd = *pos; - if (sysfs_type(sd) && (sysfs_type(sd) & SYSFS_NOT_PINNED)) { + if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) { *pos = sd->s_sibling; sd->s_sibling = NULL; sysfs_remove_one(&acxt, sd); @@ -912,14 +888,25 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, const char *new_name) { struct sysfs_dirent *sd = kobj->sd; - struct dentry *new_parent = new_parent_sd->s_dentry; - struct dentry *new_dentry; - char *dup_name; + struct dentry *new_parent = NULL; + struct dentry *old_dentry = NULL, *new_dentry = NULL; + const char *dup_name = NULL; int error; - if (!new_parent_sd) - return -EFAULT; + /* get dentries */ + old_dentry = sysfs_get_dentry(sd); + if (IS_ERR(old_dentry)) { + error = PTR_ERR(old_dentry); + goto out_dput; + } + + new_parent = sysfs_get_dentry(new_parent_sd); + if (IS_ERR(new_parent)) { + error = PTR_ERR(new_parent); + goto out_dput; + } + /* lock new_parent and get dentry for new name */ mutex_lock(&new_parent->d_inode->i_mutex); new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); @@ -933,14 +920,14 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, * shadows of the same directory */ error = -EINVAL; - if (sd->s_parent->s_dentry->d_inode != new_parent->d_inode || + if (old_dentry->d_parent->d_inode != new_parent->d_inode || new_dentry->d_parent->d_inode != new_parent->d_inode || - new_dentry == sd->s_dentry) - goto out_dput; + old_dentry == new_dentry) + goto out_unlock; error = -EEXIST; if (new_dentry->d_inode) - goto out_dput; + goto out_unlock; /* rename kobject and sysfs_dirent */ error = -ENOMEM; @@ -950,9 +937,9 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, error = kobject_set_name(kobj, "%s", new_name); if (error) - goto out_free; + goto out_drop; - kfree(sd->s_name); + dup_name = sd->s_name; sd->s_name = new_name; /* move under the new parent */ @@ -972,45 +959,58 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, error = 0; goto out_unlock; - out_free: - kfree(dup_name); out_drop: d_drop(new_dentry); - out_dput: - dput(new_dentry); out_unlock: mutex_unlock(&new_parent->d_inode->i_mutex); + out_dput: + kfree(dup_name); + dput(new_parent); + dput(old_dentry); + dput(new_dentry); return error; } -int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) +int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) { - struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry; - struct sysfs_dirent *new_parent_sd, *sd; + struct sysfs_dirent *sd = kobj->sd; + struct sysfs_dirent *new_parent_sd; + struct dentry *old_parent, *new_parent = NULL; + struct dentry *old_dentry = NULL, *new_dentry = NULL; int error; - old_parent_dentry = kobj->parent ? - kobj->parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root; - new_parent_dentry = new_parent ? - new_parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root; + BUG_ON(!sd->s_parent); + new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; + + /* get dentries */ + old_dentry = sysfs_get_dentry(sd); + if (IS_ERR(old_dentry)) { + error = PTR_ERR(old_dentry); + goto out_dput; + } + old_parent = sd->s_parent->s_dentry; + + new_parent = sysfs_get_dentry(new_parent_sd); + if (IS_ERR(new_parent)) { + error = PTR_ERR(new_parent); + goto out_dput; + } - if (old_parent_dentry->d_inode == new_parent_dentry->d_inode) - return 0; /* nothing to move */ + if (old_parent->d_inode == new_parent->d_inode) { + error = 0; + goto out_dput; /* nothing to move */ + } again: - mutex_lock(&old_parent_dentry->d_inode->i_mutex); - if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) { - mutex_unlock(&old_parent_dentry->d_inode->i_mutex); + mutex_lock(&old_parent->d_inode->i_mutex); + if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { + mutex_unlock(&old_parent->d_inode->i_mutex); goto again; } - new_parent_sd = new_parent_dentry->d_fsdata; - sd = kobj->sd; - - new_dentry = lookup_one_len(kobj->name, new_parent_dentry, - strlen(kobj->name)); + new_dentry = lookup_one_len(kobj->name, new_parent, strlen(kobj->name)); if (IS_ERR(new_dentry)) { error = PTR_ERR(new_dentry); - goto out; + goto out_unlock; } else error = 0; d_add(new_dentry, NULL); @@ -1027,10 +1027,14 @@ again: sysfs_link_sibling(sd); mutex_unlock(&sysfs_mutex); -out: - mutex_unlock(&new_parent_dentry->d_inode->i_mutex); - mutex_unlock(&old_parent_dentry->d_inode->i_mutex); + out_unlock: + mutex_unlock(&new_parent->d_inode->i_mutex); + mutex_unlock(&old_parent->d_inode->i_mutex); + out_dput: + dput(new_parent); + dput(old_dentry); + dput(new_dentry); return error; } @@ -1191,12 +1195,20 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) int sysfs_make_shadowed_dir(struct kobject *kobj, void * (*follow_link)(struct dentry *, struct nameidata *)) { + struct dentry *dentry; struct inode *inode; struct inode_operations *i_op; - inode = kobj->sd->s_dentry->d_inode; - if (inode->i_op != &sysfs_dir_inode_operations) + /* get dentry for @kobj->sd, dentry of a shadowed dir is pinned */ + dentry = sysfs_get_dentry(kobj->sd); + if (IS_ERR(dentry)) + return PTR_ERR(dentry); + + inode = dentry->d_inode; + if (inode->i_op != &sysfs_dir_inode_operations) { + dput(dentry); return -EINVAL; + } i_op = kmalloc(sizeof(*i_op), GFP_KERNEL); if (!i_op) @@ -1223,17 +1235,23 @@ int sysfs_make_shadowed_dir(struct kobject *kobj, struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) { - struct dentry *dir = kobj->sd->s_dentry; - struct inode *inode = dir->d_inode; - struct dentry *parent = dir->d_parent; - struct sysfs_dirent *parent_sd = parent->d_fsdata; - struct dentry *shadow; + struct sysfs_dirent *parent_sd = kobj->sd->s_parent; + struct dentry *dir, *parent, *shadow; + struct inode *inode; struct sysfs_dirent *sd; struct sysfs_addrm_cxt acxt; + dir = sysfs_get_dentry(kobj->sd); + if (IS_ERR(dir)) { + sd = (void *)dir; + goto out; + } + parent = dir->d_parent; + + inode = dir->d_inode; sd = ERR_PTR(-EINVAL); if (!sysfs_is_shadowed_inode(inode)) - goto out; + goto out_dput; shadow = d_alloc(parent, &dir->d_name); if (!shadow) @@ -1258,12 +1276,15 @@ struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) dget(shadow); /* Extra count - pin the dentry in core */ -out: - return sd; -nomem: + goto out_dput; + + nomem: dput(shadow); sd = ERR_PTR(-ENOMEM); - goto out; + out_dput: + dput(dir); + out: + return sd; } /** diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 69bacf1db596..cc497994b2a8 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -362,43 +362,22 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait) return POLLERR|POLLPRI; } - -static struct dentry *step_down(struct dentry *dir, const char * name) +void sysfs_notify(struct kobject *k, char *dir, char *attr) { - struct dentry * de; - - if (dir == NULL || dir->d_inode == NULL) - return NULL; - - mutex_lock(&dir->d_inode->i_mutex); - de = lookup_one_len(name, dir, strlen(name)); - mutex_unlock(&dir->d_inode->i_mutex); - dput(dir); - if (IS_ERR(de)) - return NULL; - if (de->d_inode == NULL) { - dput(de); - return NULL; - } - return de; -} + struct sysfs_dirent *sd = k->sd; -void sysfs_notify(struct kobject * k, char *dir, char *attr) -{ - struct dentry *de = k->sd->s_dentry; - if (de) - dget(de); - if (de && dir) - de = step_down(de, dir); - if (de && attr) - de = step_down(de, attr); - if (de) { - struct sysfs_dirent * sd = de->d_fsdata; - if (sd) - atomic_inc(&sd->s_event); + mutex_lock(&sysfs_mutex); + + if (sd && dir) + sd = sysfs_find_dirent(sd, dir); + if (sd && attr) + sd = sysfs_find_dirent(sd, attr); + if (sd) { + atomic_inc(&sd->s_event); wake_up_interruptible(&k->poll); - dput(de); } + + mutex_unlock(&sysfs_mutex); } EXPORT_SYMBOL_GPL(sysfs_notify); @@ -485,30 +464,31 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); */ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) { - struct dentry *dir = kobj->sd->s_dentry; - struct dentry * victim; - int res = -ENOENT; - - mutex_lock(&dir->d_inode->i_mutex); - victim = lookup_one_len(attr->name, dir, strlen(attr->name)); - if (!IS_ERR(victim)) { - /* make sure dentry is really there */ - if (victim->d_inode && - (victim->d_parent->d_inode == dir->d_inode)) { - victim->d_inode->i_mtime = CURRENT_TIME; - fsnotify_modify(victim); - res = 0; - } else - d_drop(victim); - - /** - * Drop the reference acquired from lookup_one_len() above. - */ - dput(victim); + struct sysfs_dirent *victim_sd = NULL; + struct dentry *victim = NULL; + int rc; + + rc = -ENOENT; + victim_sd = sysfs_get_dirent(kobj->sd, attr->name); + if (!victim_sd) + goto out; + + victim = sysfs_get_dentry(victim_sd); + if (IS_ERR(victim)) { + rc = PTR_ERR(victim); + victim = NULL; + goto out; } - mutex_unlock(&dir->d_inode->i_mutex); - return res; + mutex_lock(&victim->d_inode->i_mutex); + victim->d_inode->i_mtime = CURRENT_TIME; + fsnotify_modify(victim); + mutex_unlock(&victim->d_inode->i_mutex); + rc = 0; + out: + dput(victim); + sysfs_put(victim_sd); + return rc; } @@ -521,30 +501,34 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) */ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { - struct dentry *dir = kobj->sd->s_dentry; - struct dentry *victim; + struct sysfs_dirent *victim_sd = NULL; + struct dentry *victim = NULL; struct inode * inode; struct iattr newattrs; - int res = -ENOENT; - - mutex_lock(&dir->d_inode->i_mutex); - victim = lookup_one_len(attr->name, dir, strlen(attr->name)); - if (!IS_ERR(victim)) { - if (victim->d_inode && - (victim->d_parent->d_inode == dir->d_inode)) { - inode = victim->d_inode; - mutex_lock(&inode->i_mutex); - newattrs.ia_mode = (mode & S_IALLUGO) | - (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - res = notify_change(victim, &newattrs); - mutex_unlock(&inode->i_mutex); - } - dput(victim); + int rc; + + rc = -ENOENT; + victim_sd = sysfs_get_dirent(kobj->sd, attr->name); + if (!victim_sd) + goto out; + + victim = sysfs_get_dentry(victim_sd); + if (IS_ERR(victim)) { + rc = PTR_ERR(victim); + victim = NULL; + goto out; } - mutex_unlock(&dir->d_inode->i_mutex); - return res; + inode = victim->d_inode; + mutex_lock(&inode->i_mutex); + newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); + newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; + rc = notify_change(victim, &newattrs); + mutex_unlock(&inode->i_mutex); + out: + dput(victim); + sysfs_put(victim_sd); + return rc; } EXPORT_SYMBOL_GPL(sysfs_chmod_file); diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 078537e5d696..402cc356203c 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -24,7 +24,7 @@ static const struct super_operations sysfs_ops = { .drop_inode = sysfs_delete_inode, }; -static struct sysfs_dirent sysfs_root = { +struct sysfs_dirent sysfs_root = { .s_count = ATOMIC_INIT(1), .s_flags = SYSFS_ROOT, .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 72530dc666fd..6a37f2386a8d 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -52,6 +52,7 @@ struct sysfs_addrm_cxt { }; extern struct vfsmount * sysfs_mount; +extern struct sysfs_dirent sysfs_root; extern struct kmem_cache *sysfs_dir_cachep; extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 4c43030fae5d..2f58ca1af770 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -81,7 +81,6 @@ struct sysfs_ops { #define SYSFS_KOBJ_ATTR 0x0004 #define SYSFS_KOBJ_BIN_ATTR 0x0008 #define SYSFS_KOBJ_LINK 0x0020 -#define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK) #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK -- cgit v1.2.3-71-gd317 From 91a6902958f052358899f58683d44e36228d85c2 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 9 Jun 2007 13:57:22 +0800 Subject: sysfs: add parameter "struct bin_attribute *" in .read/.write methods for sysfs binary attributes Well, first of all, I don't want to change so many files either. What I do: Adding a new parameter "struct bin_attribute *" in the .read/.write methods for the sysfs binary attributes. In fact, only the four lines change in fs/sysfs/bin.c and include/linux/sysfs.h do the real work. But I have to update all the files that use binary attributes to make them compatible with the new .read and .write methods. I'm not sure if I missed any. :( Why I do this: For a sysfs attribute, we can get a pointer pointing to the struct attribute in the .show/.store method, while we can't do this for the binary attributes. I don't know why this is different, but this does make it not so handy to use the binary attributes as the regular ones. So I think this patch is reasonable. :) Who benefits from it: The patch that exposes ACPI tables in sysfs requires such an improvement. All the table binary attributes share the same .read method. Parameter "struct bin_attribute *" is used to get the table signature and instance number which are used to distinguish different ACPI table binary attributes. Without this parameter, we need to offer different .read methods for different ACPI table binary attributes. This is impossible as there are various ACPI tables on different platforms, and we don't know what they are until they are loaded. Signed-off-by: Zhang Rui Signed-off-by: Greg Kroah-Hartman --- .../firmware_sample_firmware_class.c | 2 + drivers/base/firmware_class.c | 4 +- drivers/firmware/dcdbas.c | 10 +++-- drivers/firmware/dell_rbu.c | 25 ++++++----- drivers/i2c/chips/eeprom.c | 3 +- drivers/i2c/chips/max6875.c | 5 ++- drivers/pci/hotplug/acpiphp_ibm.c | 6 ++- drivers/pci/pci-sysfs.c | 18 +++++--- drivers/pcmcia/socket_sysfs.c | 8 +++- drivers/rapidio/rio-sysfs.c | 6 ++- drivers/rtc/rtc-ds1553.c | 10 +++-- drivers/rtc/rtc-ds1742.c | 10 +++-- drivers/s390/cio/chp.c | 10 +++-- drivers/scsi/arcmsr/arcmsr_attr.c | 15 ++++--- drivers/scsi/ipr.c | 18 +++++--- drivers/scsi/libsas/sas_expander.c | 16 ++++--- drivers/scsi/lpfc/lpfc_attr.c | 12 ++++-- drivers/scsi/qla2xxx/qla_attr.c | 50 +++++++++++++--------- drivers/spi/at25.c | 6 ++- drivers/video/aty/radeon_base.c | 8 +++- drivers/w1/slaves/w1_ds2433.c | 10 +++-- drivers/w1/slaves/w1_therm.c | 7 ++- drivers/w1/w1.c | 12 ++++-- drivers/zorro/zorro-sysfs.c | 5 ++- fs/sysfs/bin.c | 4 +- include/linux/sysfs.h | 6 ++- net/bridge/br_sysfs_br.c | 5 ++- 27 files changed, 185 insertions(+), 106 deletions(-) (limited to 'include/linux') diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c index 4994f1f28f8c..fba943aacf93 100644 --- a/Documentation/firmware_class/firmware_sample_firmware_class.c +++ b/Documentation/firmware_class/firmware_sample_firmware_class.c @@ -78,6 +78,7 @@ static CLASS_DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); static ssize_t firmware_data_read(struct kobject *kobj, + struct bin_attribute *bin_attr, char *buffer, loff_t offset, size_t count) { struct class_device *class_dev = to_class_dev(kobj); @@ -88,6 +89,7 @@ static ssize_t firmware_data_read(struct kobject *kobj, return count; } static ssize_t firmware_data_write(struct kobject *kobj, + struct bin_attribute *bin_attr, char *buffer, loff_t offset, size_t count) { struct class_device *class_dev = to_class_dev(kobj); diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 0e511485d2e6..53f0ee6f3016 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -175,7 +175,7 @@ static ssize_t firmware_loading_store(struct device *dev, static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); static ssize_t -firmware_data_read(struct kobject *kobj, +firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t offset, size_t count) { struct device *dev = to_dev(kobj); @@ -240,7 +240,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) * the driver as a firmware image. **/ static ssize_t -firmware_data_write(struct kobject *kobj, +firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t offset, size_t count) { struct device *dev = to_dev(kobj); diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 1865b56fb141..18cdcb3ae1ca 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -149,8 +149,9 @@ static ssize_t smi_data_buf_size_store(struct device *dev, return count; } -static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos, - size_t count) +static ssize_t smi_data_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count) { size_t max_read; ssize_t ret; @@ -170,8 +171,9 @@ out: return ret; } -static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos, - size_t count) +static ssize_t smi_data_write(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count) { ssize_t ret; diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index f8afecb7d0cf..477a3d0e3caf 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -543,8 +543,9 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) return ret_count; } -static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, - loff_t pos, size_t count) +static ssize_t read_rbu_data(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { ssize_t ret_count = 0; @@ -591,8 +592,9 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) spin_unlock(&rbu_data.lock); } -static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, - loff_t pos, size_t count) +static ssize_t read_rbu_image_type(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { int size = 0; if (!pos) @@ -600,8 +602,9 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, return size; } -static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, - loff_t pos, size_t count) +static ssize_t write_rbu_image_type(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { int rc = count; int req_firm_rc = 0; @@ -660,8 +663,9 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, return rc; } -static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer, - loff_t pos, size_t count) +static ssize_t read_rbu_packet_size(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { int size = 0; if (!pos) { @@ -672,8 +676,9 @@ static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer, return size; } -static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer, - loff_t pos, size_t count) +static ssize_t write_rbu_packet_size(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { unsigned long temp; spin_lock(&rbu_data.lock); diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 5990dd5fc773..332816431105 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -110,7 +110,8 @@ exit: mutex_unlock(&data->update_lock); } -static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); struct eeprom_data *data = i2c_get_clientdata(client); diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index 1405ce5b236c..4e238c0a7ca3 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c @@ -125,8 +125,9 @@ exit_up: mutex_unlock(&data->update_lock); } -static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, - size_t count) +static ssize_t max6875_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct i2c_client *client = kobj_to_i2c_client(kobj); struct max6875_data *data = i2c_get_clientdata(client); diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 74556ec31a5b..70db38c0ced9 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -106,7 +106,8 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status); static void ibm_handle_events(acpi_handle handle, u32 event, void *context); static int ibm_get_table_from_acpi(char **bufp); static ssize_t ibm_read_apci_table(struct kobject *kobj, - char *buffer, loff_t pos, size_t size); + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t size); static acpi_status __init ibm_find_acpi_device(acpi_handle handle, u32 lvl, void *context, void **rv); static int __init ibm_acpiphp_init(void); @@ -357,7 +358,8 @@ read_table_done: * our solution is to only allow reading the table in all at once **/ static ssize_t ibm_read_apci_table(struct kobject *kobj, - char *buffer, loff_t pos, size_t size) + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t size) { int bytes_read = -EINVAL; char *table = NULL; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index d448f8df8613..6543cbe83be5 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -213,7 +213,8 @@ struct device_attribute pci_dev_attrs[] = { }; static ssize_t -pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) +pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); unsigned int size = 64; @@ -285,7 +286,8 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) } static ssize_t -pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) +pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); unsigned int size = count; @@ -352,7 +354,8 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) * callback routine (pci_legacy_read). */ ssize_t -pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count) +pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct pci_bus *bus = to_pci_bus(container_of(kobj, struct class_device, @@ -376,7 +379,8 @@ pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count) * callback routine (pci_legacy_write). */ ssize_t -pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count) +pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct pci_bus *bus = to_pci_bus(container_of(kobj, struct class_device, @@ -528,7 +532,8 @@ static inline void pci_remove_resource_files(struct pci_dev *dev) { return; } * writing anything except 0 enables it */ static ssize_t -pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) +pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); @@ -551,7 +556,8 @@ pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) * device corresponding to @kobj. */ static ssize_t -pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) +pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); void __iomem *rom; diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index dbfbe65779e5..b4409002b7f8 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -283,7 +283,9 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off return (ret); } -static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) +static ssize_t pccard_show_cis(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { unsigned int size = 0x200; @@ -311,7 +313,9 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size return (count); } -static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) +static ssize_t pccard_store_cis(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); cisdump_t *cis; diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index a3972b9f96e6..659e31164cf0 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -67,7 +67,8 @@ struct device_attribute rio_dev_attrs[] = { }; static ssize_t -rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) +rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct rio_dev *dev = to_rio_dev(container_of(kobj, struct device, kobj)); @@ -137,7 +138,8 @@ rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) } static ssize_t -rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) +rio_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct rio_dev *dev = to_rio_dev(container_of(kobj, struct device, kobj)); diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index b024cfb558f4..f98a83a11aae 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -258,8 +258,9 @@ static const struct rtc_class_ops ds1553_rtc_ops = { .ioctl = ds1553_rtc_ioctl, }; -static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf, - loff_t pos, size_t size) +static ssize_t ds1553_nvram_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t size) { struct platform_device *pdev = to_platform_device(container_of(kobj, struct device, kobj)); @@ -272,8 +273,9 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf, return count; } -static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf, - loff_t pos, size_t size) +static ssize_t ds1553_nvram_write(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t size) { struct platform_device *pdev = to_platform_device(container_of(kobj, struct device, kobj)); diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 1638acdbc913..d1778ae8bca5 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -127,8 +127,9 @@ static const struct rtc_class_ops ds1742_rtc_ops = { .set_time = ds1742_rtc_set_time, }; -static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf, - loff_t pos, size_t size) +static ssize_t ds1742_nvram_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t size) { struct platform_device *pdev = to_platform_device(container_of(kobj, struct device, kobj)); @@ -141,8 +142,9 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf, return count; } -static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf, - loff_t pos, size_t size) +static ssize_t ds1742_nvram_write(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t size) { struct platform_device *pdev = to_platform_device(container_of(kobj, struct device, kobj)); diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 96a8a72a6083..b57d93d986c0 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -141,8 +141,9 @@ static int s390_vary_chpid(struct chp_id chpid, int on) /* * Channel measurement related functions */ -static ssize_t chp_measurement_chars_read(struct kobject *kobj, char *buf, - loff_t off, size_t count) +static ssize_t chp_measurement_chars_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct channel_path *chp; unsigned int size; @@ -192,8 +193,9 @@ static void chp_measurement_copy_block(struct cmg_entry *buf, } while (reference_buf.values[0] != buf->values[0]); } -static ssize_t chp_measurement_read(struct kobject *kobj, char *buf, - loff_t off, size_t count) +static ssize_t chp_measurement_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct channel_path *chp; struct channel_subsystem *css; diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 8908228bc134..06c0dce3b839 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -59,8 +59,9 @@ struct class_device_attribute *arcmsr_host_attrs[]; static ssize_t -arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off, - size_t count) +arcmsr_sysfs_iop_message_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *host = class_to_shost(cdev); @@ -105,8 +106,9 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off, } static ssize_t -arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off, - size_t count) +arcmsr_sysfs_iop_message_write(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *host = class_to_shost(cdev); @@ -152,8 +154,9 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off, } static ssize_t -arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off, - size_t count) +arcmsr_sysfs_iop_message_clear(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *host = class_to_shost(cdev); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index fa6ff295e568..4a3083ea59d5 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -2465,6 +2465,7 @@ restart: /** * ipr_read_trace - Dump the adapter trace * @kobj: kobject struct + * @bin_attr: bin_attribute struct * @buf: buffer * @off: offset * @count: buffer size @@ -2472,8 +2473,9 @@ restart: * Return value: * number of bytes printed to buffer **/ -static ssize_t ipr_read_trace(struct kobject *kobj, char *buf, - loff_t off, size_t count) +static ssize_t ipr_read_trace(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *shost = class_to_shost(cdev); @@ -3166,6 +3168,7 @@ static struct class_device_attribute *ipr_ioa_attrs[] = { /** * ipr_read_dump - Dump the adapter * @kobj: kobject struct + * @bin_attr: bin_attribute struct * @buf: buffer * @off: offset * @count: buffer size @@ -3173,8 +3176,9 @@ static struct class_device_attribute *ipr_ioa_attrs[] = { * Return value: * number of bytes printed to buffer **/ -static ssize_t ipr_read_dump(struct kobject *kobj, char *buf, - loff_t off, size_t count) +static ssize_t ipr_read_dump(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *shost = class_to_shost(cdev); @@ -3327,6 +3331,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) /** * ipr_write_dump - Setup dump state of adapter * @kobj: kobject struct + * @bin_attr: bin_attribute struct * @buf: buffer * @off: offset * @count: buffer size @@ -3334,8 +3339,9 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) * Return value: * number of bytes printed to buffer **/ -static ssize_t ipr_write_dump(struct kobject *kobj, char *buf, - loff_t off, size_t count) +static ssize_t ipr_write_dump(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *shost = class_to_shost(cdev); diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 578ed79f4148..23e90c5f8f35 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -38,8 +38,10 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); #if 0 /* FIXME: smp needs to migrate into the sas class */ -static ssize_t smp_portal_read(struct kobject *, char *, loff_t, size_t); -static ssize_t smp_portal_write(struct kobject *, char *, loff_t, size_t); +static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *, + char *, loff_t, size_t); +static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *, + char *, loff_t, size_t); #endif /* ---------- SMP task management ---------- */ @@ -1845,8 +1847,9 @@ out: #if 0 /* ---------- SMP portal ---------- */ -static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs, - size_t size) +static ssize_t smp_portal_write(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t offs, size_t size) { struct domain_device *dev = to_dom_device(kobj); struct expander_device *ex = &dev->ex_dev; @@ -1872,8 +1875,9 @@ static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs, return size; } -static ssize_t smp_portal_read(struct kobject *kobj, char *buf, loff_t offs, - size_t size) +static ssize_t smp_portal_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t offs, size_t size) { struct domain_device *dev = to_dom_device(kobj); struct expander_device *ex = &dev->ex_dev; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index f81fe501a4a1..5dfda9778c80 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1133,7 +1133,8 @@ struct class_device_attribute *lpfc_host_attrs[] = { }; static ssize_t -sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count) +sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { size_t buf_off; struct Scsi_Host *host = class_to_shost(container_of(kobj, @@ -1165,7 +1166,8 @@ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count) } static ssize_t -sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { size_t buf_off; uint32_t * tmp_ptr; @@ -1221,7 +1223,8 @@ sysfs_mbox_idle (struct lpfc_hba * phba) } static ssize_t -sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count) +sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct Scsi_Host * host = class_to_shost(container_of(kobj, struct class_device, kobj)); @@ -1273,7 +1276,8 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count) } static ssize_t -sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct Scsi_Host *host = class_to_shost(container_of(kobj, struct class_device, diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 96587253bfa9..942db9de785e 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -11,8 +11,9 @@ /* SYSFS attributes --------------------------------------------------------- */ static ssize_t -qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_fw_dump(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -31,8 +32,9 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off, } static ssize_t -qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_fw_dump(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -80,8 +82,9 @@ static struct bin_attribute sysfs_fw_dump_attr = { }; static ssize_t -qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_nvram(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -100,8 +103,9 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, } static ssize_t -qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_nvram(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -155,8 +159,9 @@ static struct bin_attribute sysfs_nvram_attr = { }; static ssize_t -qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_optrom(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -174,8 +179,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off, } static ssize_t -qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_optrom(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -203,8 +209,9 @@ static struct bin_attribute sysfs_optrom_attr = { }; static ssize_t -qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -282,8 +289,9 @@ static struct bin_attribute sysfs_optrom_ctl_attr = { }; static ssize_t -qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_vpd(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -301,8 +309,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off, } static ssize_t -qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_vpd(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -330,8 +339,9 @@ static struct bin_attribute sysfs_vpd_attr = { }; static ssize_t -qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_sfp(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c index fde1dededba3..e007833cca59 100644 --- a/drivers/spi/at25.c +++ b/drivers/spi/at25.c @@ -111,7 +111,8 @@ at25_ee_read( } static ssize_t -at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct device *dev; struct at25_data *at25; @@ -236,7 +237,8 @@ at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count) } static ssize_t -at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count) +at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct device *dev; struct at25_data *at25; diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 3b3c6571f583..2349e71b0083 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -2102,7 +2102,9 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u } -static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count) +static ssize_t radeon_show_edid1(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct device *dev = container_of(kobj, struct device, kobj); struct pci_dev *pdev = to_pci_dev(dev); @@ -2113,7 +2115,9 @@ static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, si } -static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count) +static ssize_t radeon_show_edid2(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct device *dev = container_of(kobj, struct device, kobj); struct pci_dev *pdev = to_pci_dev(dev); diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index 4e13aa71adea..cab56005dd49 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c @@ -91,8 +91,9 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data, } #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ -static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off, - size_t count) +static ssize_t w1_f23_read_bin(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); #ifdef CONFIG_W1_SLAVE_DS2433_CRC @@ -199,8 +200,9 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) return 0; } -static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off, - size_t count) +static ssize_t w1_f23_write_bin(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); int addr, len, idx; diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 8ba4e572e09c..4318935678c5 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -42,7 +42,8 @@ static u8 bad_roms[][9] = { {} }; -static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t); +static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *, + char *, loff_t, size_t); static struct bin_attribute w1_therm_bin_attr = { .attr = { @@ -158,7 +159,9 @@ static int w1_therm_check_rom(u8 rom[9]) return 0; } -static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count) +static ssize_t w1_therm_read_bin(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_master *dev = sl->master; diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 1838cb29b646..f5c5b760ed7b 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -105,7 +105,9 @@ static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *a return sprintf(buf, "%s\n", sl->name); } -static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count) +static ssize_t w1_slave_read_id(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); @@ -135,7 +137,9 @@ static struct bin_attribute w1_slave_attr_bin_id = { /* Default family */ -static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count) +static ssize_t w1_default_write(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); @@ -152,7 +156,9 @@ out_up: return count; } -static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +static ssize_t w1_default_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 7e03cc68b182..9130f1c12c26 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -49,8 +49,9 @@ static ssize_t zorro_show_resource(struct device *dev, struct device_attribute * static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL); -static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off, - size_t count) +static ssize_t zorro_read_config(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device, kobj)); diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 55796bdacd3d..135353f8a296 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -40,7 +40,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) rc = -EIO; if (attr->read) - rc = attr->read(kobj, buffer, off, count); + rc = attr->read(kobj, attr, buffer, off, count); sysfs_put_active_two(attr_sd); @@ -97,7 +97,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) rc = -EIO; if (attr->write) - rc = attr->write(kobj, buffer, offset, count); + rc = attr->write(kobj, attr, buffer, offset, count); sysfs_put_active_two(attr_sd); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 2f58ca1af770..be8228e50a27 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -64,8 +64,10 @@ struct bin_attribute { struct attribute attr; size_t size; void *private; - ssize_t (*read)(struct kobject *, char *, loff_t, size_t); - ssize_t (*write)(struct kobject *, char *, loff_t, size_t); + ssize_t (*read)(struct kobject *, struct bin_attribute *, + char *, loff_t, size_t); + ssize_t (*write)(struct kobject *, struct bin_attribute *, + char *, loff_t, size_t); int (*mmap)(struct kobject *, struct bin_attribute *attr, struct vm_area_struct *vma); }; diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 31ace23a0914..4f42263e0a8a 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -360,8 +360,9 @@ static struct attribute_group bridge_group = { * * Returns the number of bytes read. */ -static ssize_t brforward_read(struct kobject *kobj, char *buf, - loff_t off, size_t count) +static ssize_t brforward_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct device *dev = to_dev(kobj); struct net_bridge *br = to_bridge(dev); -- cgit v1.2.3-71-gd317