From 8380770c842faef3001e44662953d64ad9a93663 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 30 Jul 2007 02:28:56 +0200 Subject: Driver core: make sysfs uevent-attributes static Attributes do not have an owner(module) anymore, so there is no need to carry the attributes in every single bus instance. Signed-off-by: Kay Sievers Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 3a38d1f70cb..5d97ca6d865 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -64,8 +64,6 @@ struct bus_type { struct bus_attribute * bus_attrs; struct device_attribute * dev_attrs; struct driver_attribute * drv_attrs; - struct bus_attribute drivers_autoprobe_attr; - struct bus_attribute drivers_probe_attr; int (*match)(struct device * dev, struct device_driver * drv); int (*uevent)(struct device *dev, char **envp, -- cgit v1.2.3-70-g09d2 From 7eff2e7a8b65c25920207324e56611150eb1cd9a Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 14 Aug 2007 15:15:12 +0200 Subject: Driver core: change add_uevent_var to use a struct This changes the uevent buffer functions to use a struct instead of a long list of parameters. It does no longer require the caller to do the proper buffer termination and size accounting, which is currently wrong in some places. It fixes a known bug where parts of the uevent environment are overwritten because of wrong index calculations. Many thanks to Mathieu Desnoyers for finding bugs and improving the error handling. Signed-off-by: Kay Sievers Cc: Mathieu Desnoyers Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- arch/ia64/sn/kernel/tiocx.c | 3 +- arch/powerpc/kernel/of_device.c | 37 ++----- arch/powerpc/kernel/vio.c | 16 +-- arch/powerpc/platforms/ps3/system-bus.c | 9 +- block/genhd.c | 35 ++----- drivers/acpi/scan.c | 16 +-- drivers/amba/bus.c | 9 +- drivers/base/class.c | 42 ++------ drivers/base/core.c | 84 +++++----------- drivers/base/firmware_class.c | 11 +- drivers/base/memory.c | 3 +- drivers/base/platform.c | 6 +- drivers/eisa/eisa-bus.c | 9 +- drivers/firewire/fw-device.c | 11 +- drivers/firmware/dmi-id.c | 17 ++-- drivers/i2c/i2c-core.c | 8 +- drivers/ide/ide.c | 17 +--- drivers/ieee1394/nodemgr.c | 17 +--- drivers/infiniband/core/sysfs.c | 9 +- drivers/input/input.c | 62 ++++-------- drivers/input/serio/serio.c | 11 +- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 4 +- drivers/misc/tifm_core.c | 9 +- drivers/mmc/core/bus.c | 21 ++-- drivers/pci/hotplug.c | 28 ++---- drivers/pci/pci-driver.c | 3 +- drivers/pci/pci.h | 3 +- drivers/pcmcia/cs.c | 10 +- drivers/pcmcia/ds.c | 26 ++--- drivers/power/power_supply.h | 3 +- drivers/power/power_supply_sysfs.c | 17 +--- drivers/s390/cio/ccwgroup.c | 3 +- drivers/s390/cio/device.c | 25 ++--- drivers/s390/crypto/ap_bus.c | 14 +-- drivers/scsi/scsi_sysfs.c | 9 +- drivers/spi/spi.c | 7 +- drivers/usb/core/driver.c | 29 ++---- drivers/usb/core/message.c | 28 ++---- drivers/w1/w1.c | 19 ++-- include/asm-powerpc/of_device.h | 2 +- include/linux/device.h | 15 +-- include/linux/kobject.h | 23 +++-- lib/kobject_uevent.c | 149 ++++++++++++---------------- net/atm/atm_sysfs.c | 7 +- net/core/net-sysfs.c | 14 +-- net/wireless/sysfs.c | 3 +- sound/aoa/soundbus/core.c | 33 ++---- 47 files changed, 300 insertions(+), 636 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 5a289e4de83..a88eba3314d 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -66,8 +66,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv) } -static int tiocx_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 89b911e83c0..8f3db32fac8 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -57,26 +57,21 @@ ssize_t of_device_get_modalias(struct of_device *ofdev, return tsize; } -int of_device_uevent(struct device *dev, - char **envp, int num_envp, char *buffer, int buffer_size) +int of_device_uevent(struct device *dev, struct kobj_uevent_env *env) { struct of_device *ofdev; const char *compat; - int i = 0, length = 0, seen = 0, cplen, sl; + int seen = 0, cplen, sl; if (!dev) return -ENODEV; ofdev = to_of_device(dev); - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "OF_NAME=%s", ofdev->node->name)) + if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "OF_TYPE=%s", ofdev->node->type)) + if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type)) return -ENOMEM; /* Since the compatible field can contain pretty much anything @@ -85,9 +80,7 @@ int of_device_uevent(struct device *dev, compat = of_get_property(ofdev->node, "compatible", &cplen); while (compat && *compat && cplen > 0) { - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "OF_COMPATIBLE_%d=%s", seen, compat)) + if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat)) return -ENOMEM; sl = strlen (compat) + 1; @@ -96,25 +89,17 @@ int of_device_uevent(struct device *dev, seen++; } - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "OF_COMPATIBLE_N=%d", seen)) + if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen)) return -ENOMEM; /* modalias is trickier, we add it in 2 steps */ - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=")) + if (add_uevent_var(env, "MODALIAS=")) return -ENOMEM; - - sl = of_device_get_modalias(ofdev, &buffer[length-1], - buffer_size-length); - if (sl >= (buffer_size-length)) + sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1], + sizeof(env->buf) - env->buflen); + if (sl >= (sizeof(env->buf) - env->buflen)) return -ENOMEM; - - length += sl; - - envp[i] = NULL; + env->buflen += sl; return 0; } diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cb22a3557c4..19a5656001c 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -317,30 +317,20 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv) return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); } -static int vio_hotplug(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env) { const struct vio_dev *vio_dev = to_vio_dev(dev); struct device_node *dn; const char *cp; - int length; - - if (!num_envp) - return -ENOMEM; dn = dev->archdata.of_node; if (!dn) return -ENODEV; - cp = of_get_property(dn, "compatible", &length); + cp = of_get_property(dn, "compatible", NULL); if (!cp) return -ENODEV; - envp[0] = buffer; - length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s", - vio_dev->type, cp); - if ((buffer_size - length) <= 0) - return -ENOMEM; - envp[1] = NULL; + add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, cp); return 0; } diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 4bb634a17e4..ea0b2c79041 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -437,18 +437,13 @@ static void ps3_system_bus_shutdown(struct device *_dev) dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); } -static int ps3_system_bus_uevent(struct device *_dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env) { struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); int i = 0, length = 0; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "MODALIAS=ps3:%d", - dev->match_id)) + if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id)) return -ENOMEM; - - envp[i] = NULL; return 0; } diff --git a/block/genhd.c b/block/genhd.c index 3af1e7a378d..e609996f2e7 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -540,61 +540,42 @@ static int block_uevent_filter(struct kset *kset, struct kobject *kobj) return ((ktype == &ktype_block) || (ktype == &ktype_part)); } -static int block_uevent(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size) +static int block_uevent(struct kset *kset, struct kobject *kobj, + struct kobj_uevent_env *env) { struct kobj_type *ktype = get_ktype(kobj); struct device *physdev; struct gendisk *disk; struct hd_struct *part; - int length = 0; - int i = 0; if (ktype == &ktype_block) { disk = container_of(kobj, struct gendisk, kobj); - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "MINOR=%u", disk->first_minor); + add_uevent_var(env, "MINOR=%u", disk->first_minor); } else if (ktype == &ktype_part) { disk = container_of(kobj->parent, struct gendisk, kobj); part = container_of(kobj, struct hd_struct, kobj); - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "MINOR=%u", + add_uevent_var(env, "MINOR=%u", disk->first_minor + part->partno); } else return 0; - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MAJOR=%u", disk->major); + add_uevent_var(env, "MAJOR=%u", disk->major); /* add physical device, backing this device */ physdev = disk->driverfs_dev; if (physdev) { char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL); - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "PHYSDEVPATH=%s", path); + add_uevent_var(env, "PHYSDEVPATH=%s", path); kfree(path); if (physdev->bus) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", - physdev->bus->name); + add_uevent_var(env, "PHYSDEVBUS=%s", physdev->bus->name); if (physdev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", - physdev->driver->name); + add_uevent_var(env, physdev->driver->name); } - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - return 0; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 64620d66874..5b4d462117c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -319,16 +319,18 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } -static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) { struct acpi_device *acpi_dev = to_acpi_device(dev); + int len; - strcpy(buffer, "MODALIAS="); - if (create_modalias(acpi_dev, buffer + 9, buffer_size - 9) > 0) { - envp[0] = buffer; - envp[1] = NULL; - } + if (add_uevent_var(env, "MODALIAS=")) + return -ENOMEM; + len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen); + if (len >= (sizeof(env->buf) - env->buflen)) + return -ENOMEM; + env->buflen += len; return 0; } diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 268e301775f..6b94fb7be5f 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -44,15 +44,12 @@ static int amba_match(struct device *dev, struct device_driver *drv) } #ifdef CONFIG_HOTPLUG -static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz) +static int amba_uevent(struct device *dev, struct kobj_uevent_env *env) { struct amba_device *pcdev = to_amba_device(dev); - int retval = 0, i = 0, len = 0; + int retval = 0; - retval = add_uevent_var(envp, nr_env, &i, - buf, bufsz, &len, - "AMBA_ID=%08x", pcdev->periphid); - envp[i] = NULL; + retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid); return retval; } #else diff --git a/drivers/base/class.c b/drivers/base/class.c index 4d2222618b7..ecd6336bffe 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -180,8 +180,7 @@ static void class_device_create_release(struct class_device *class_dev) /* needed to allow these devices to have parent class devices */ static int class_device_create_uevent(struct class_device *class_dev, - char **envp, int num_envp, - char *buffer, int buffer_size) + struct kobj_uevent_env *env) { pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id); return 0; @@ -403,64 +402,43 @@ static void remove_deprecated_class_device_links(struct class_device *cd) { } #endif -static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size) +static int class_uevent(struct kset *kset, struct kobject *kobj, + struct kobj_uevent_env *env) { struct class_device *class_dev = to_class_dev(kobj); struct device *dev = class_dev->dev; - int i = 0; - int length = 0; int retval = 0; pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); if (MAJOR(class_dev->devt)) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MAJOR=%u", MAJOR(class_dev->devt)); + add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt)); - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MINOR=%u", MINOR(class_dev->devt)); + add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt)); } if (dev) { const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); if (path) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVPATH=%s", path); + add_uevent_var(env, "PHYSDEVPATH=%s", path); kfree(path); } if (dev->bus) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", dev->bus->name); + add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name); if (dev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", dev->driver->name); + add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name); } - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - if (class_dev->uevent) { /* have the class device specific function add its stuff */ - retval = class_dev->uevent(class_dev, envp, num_envp, - buffer, buffer_size); + retval = class_dev->uevent(class_dev, env); if (retval) pr_debug("class_dev->uevent() returned %d\n", retval); } else if (class_dev->class->uevent) { /* have the class specific function add its stuff */ - retval = class_dev->class->uevent(class_dev, envp, num_envp, - buffer, buffer_size); + retval = class_dev->class->uevent(class_dev, env); if (retval) pr_debug("class->uevent() returned %d\n", retval); } diff --git a/drivers/base/core.c b/drivers/base/core.c index ec86d6fc236..d487c032dc4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -141,33 +141,23 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) return NULL; } -static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size) +static int dev_uevent(struct kset *kset, struct kobject *kobj, + struct kobj_uevent_env *env) { struct device *dev = to_dev(kobj); - int i = 0; - int length = 0; int retval = 0; /* add the major/minor if present */ if (MAJOR(dev->devt)) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MAJOR=%u", MAJOR(dev->devt)); - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MINOR=%u", MINOR(dev->devt)); + add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); + add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); } if (dev->type && dev->type->name) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVTYPE=%s", dev->type->name); + add_uevent_var(env, "DEVTYPE=%s", dev->type->name); if (dev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DRIVER=%s", dev->driver->name); + add_uevent_var(env, "DRIVER=%s", dev->driver->name); #ifdef CONFIG_SYSFS_DEPRECATED if (dev->class) { @@ -181,59 +171,43 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, path = kobject_get_path(&parent->kobj, GFP_KERNEL); if (path) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVPATH=%s", path); + add_uevent_var(env, "PHYSDEVPATH=%s", path); kfree(path); } - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", parent->bus->name); + add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name); if (parent->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", parent->driver->name); + add_uevent_var(env, "PHYSDEVDRIVER=%s", + parent->driver->name); } } else if (dev->bus) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", dev->bus->name); + add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name); if (dev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", dev->driver->name); + add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name); } #endif - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - + /* have the bus specific function add its stuff */ if (dev->bus && dev->bus->uevent) { - /* have the bus specific function add its stuff */ - retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size); + retval = dev->bus->uevent(dev, env); if (retval) pr_debug ("%s: bus uevent() returned %d\n", __FUNCTION__, retval); } + /* have the class specific function add its stuff */ if (dev->class && dev->class->dev_uevent) { - /* have the class specific function add its stuff */ - retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size); + retval = dev->class->dev_uevent(dev, env); if (retval) pr_debug("%s: class uevent() returned %d\n", __FUNCTION__, retval); } + /* have the device type specific fuction add its stuff */ if (dev->type && dev->type->uevent) { - /* have the device type specific fuction add its stuff */ - retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size); + retval = dev->type->uevent(dev, env); if (retval) pr_debug("%s: dev_type uevent() returned %d\n", __FUNCTION__, retval); @@ -253,9 +227,7 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, { struct kobject *top_kobj; struct kset *kset; - char *envp[32]; - char *data = NULL; - char *pos; + struct kobj_uevent_env *env = NULL; int i; size_t count = 0; int retval; @@ -278,26 +250,20 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, if (!kset->uevent_ops->filter(kset, &dev->kobj)) goto out; - data = (char *)get_zeroed_page(GFP_KERNEL); - if (!data) + env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); + if (!env) return -ENOMEM; /* let the kset specific function add its keys */ - pos = data; - memset(envp, 0, sizeof(envp)); - retval = kset->uevent_ops->uevent(kset, &dev->kobj, - envp, ARRAY_SIZE(envp), - pos, PAGE_SIZE); + retval = kset->uevent_ops->uevent(kset, &dev->kobj, env); if (retval) goto out; /* copy keys to file */ - for (i = 0; envp[i]; i++) { - pos = &buf[count]; - count += sprintf(pos, "%s\n", envp[i]); - } + for (i = 0; i < env->envp_idx; i++) + count += sprintf(&buf[count], "%s\n", env->envp[i]); out: - free_page((unsigned long)data); + kfree(env); return count; } diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index b24efd4e3e3..4a1b9bfc547 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -88,19 +88,14 @@ static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); static void fw_dev_release(struct device *dev); -static int firmware_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) { struct firmware_priv *fw_priv = dev_get_drvdata(dev); - int i = 0, len = 0; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "FIRMWARE=%s", fw_priv->fw_id)) + if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "TIMEOUT=%i", loading_timeout)) + if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) return -ENOMEM; - envp[i] = NULL; return 0; } diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 74b96795d2f..cb99daeae93 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -34,8 +34,7 @@ static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj) return MEMORY_CLASS_NAME; } -static int memory_uevent(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size) +static int memory_uevent(struct kset *kset, struct kobj_uevent_env *env) { int retval = 0; diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9bfc434d132..a2e3910196e 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -529,13 +529,11 @@ static struct device_attribute platform_dev_attrs[] = { __ATTR_NULL, }; -static int platform_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) { struct platform_device *pdev = to_platform_device(dev); - envp[0] = buffer; - snprintf(buffer, buffer_size, "MODALIAS=platform:%s", pdev->name); + add_uevent_var(env, "MODALIAS=platform:%s", pdev->name); return 0; } diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index d944647c82c..4d4a4739390 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -128,16 +128,11 @@ static int eisa_bus_match (struct device *dev, struct device_driver *drv) return 0; } -static int eisa_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int eisa_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct eisa_device *edev = to_eisa_device(dev); - int i = 0; - int length = 0; - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig); - envp[i] = NULL; + add_uevent_var(env, "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig); return 0; } diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 2b658634163..56681b3b297 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -130,23 +130,16 @@ static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) } static int -fw_unit_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) { struct fw_unit *unit = fw_unit(dev); char modalias[64]; - int length = 0; - int i = 0; get_modalias(unit, modalias, sizeof(modalias)); - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=%s", modalias)) + if (add_uevent_var(env, "MODALIAS=%s", modalias)) return -ENOMEM; - envp[i] = NULL; - return 0; } diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index 59c3b5aa89f..2678098d450 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c @@ -134,14 +134,17 @@ static struct attribute_group* sys_dmi_attribute_groups[] = { NULL }; -static int dmi_dev_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int dmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) { - strcpy(buffer, "MODALIAS="); - get_modalias(buffer+9, buffer_size-9); - envp[0] = buffer; - envp[1] = NULL; - + ssize_t len; + + if (add_uevent_var(env, "MODALIAS=")) + return -ENOMEM; + len = get_modalias(&env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen); + if (len >= (sizeof(env->buf) - env->buflen)) + return -ENOMEM; + env->buflen += len; return 0; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index d663e6960d9..910a62de190 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -67,20 +67,16 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) #ifdef CONFIG_HOTPLUG /* uevent helps with hotplug: modprobe -q $(MODALIAS) */ -static int i2c_device_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) { struct i2c_client *client = to_i2c_client(dev); - int i = 0, length = 0; /* by definition, legacy drivers can't hotplug */ if (dev->driver || !client->driver_name) return 0; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MODALIAS=%s", client->driver_name)) + if (add_uevent_var(env, "MODALIAS=%s", client->driver_name)) return -ENOMEM; - envp[i] = NULL; dev_dbg(dev, "uevent\n"); return 0; } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index e96212ce572..a96a8b1b353 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1663,20 +1663,13 @@ static struct device_attribute ide_dev_attrs[] = { __ATTR_NULL }; -static int ide_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int ide_uevent(struct device *dev, struct kobj_uevent_env *env) { ide_drive_t *drive = to_ide_device(dev); - int i = 0; - int length = 0; - - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MEDIA=%s", media_string(drive)); - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "DRIVENAME=%s", drive->name); - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MODALIAS=ide:m-%s", media_string(drive)); - envp[i] = NULL; + + add_uevent_var(env, "MEDIA=%s", media_string(drive)); + add_uevent_var(env, "DRIVENAME=%s", drive->name); + add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive)); return 0; } diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 2ffd53461db..1939fee616e 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -153,8 +153,7 @@ struct host_info { }; static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); -static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); +static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env); static void nodemgr_resume_ne(struct node_entry *ne); static void nodemgr_remove_ne(struct node_entry *ne); static struct node_entry *find_entry_by_guid(u64 guid); @@ -1160,12 +1159,9 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent #ifdef CONFIG_HOTPLUG -static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) { struct unit_directory *ud; - int i = 0; - int length = 0; int retval = 0; /* ieee1394:venNmoNspNverN */ char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; @@ -1180,9 +1176,7 @@ static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, #define PUT_ENVP(fmt,val) \ do { \ - retval = add_uevent_var(envp, num_envp, &i, \ - buffer, buffer_size, &length, \ - fmt, val); \ + retval = add_uevent_var(env, fmt, val); \ if (retval) \ return retval; \ } while (0) @@ -1201,15 +1195,12 @@ do { \ #undef PUT_ENVP - envp[i] = NULL; - return 0; } #else -static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 70b77ae6742..3d405068132 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -434,21 +434,18 @@ static void ib_device_release(struct class_device *cdev) kfree(dev); } -static int ib_device_uevent(struct class_device *cdev, char **envp, - int num_envp, char *buf, int size) +static int ib_device_uevent(struct class_device *cdev, + struct kobj_uevent_env *env) { struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); - int i = 0, len = 0; - if (add_uevent_var(envp, num_envp, &i, buf, size, &len, - "NAME=%s", dev->name)) + if (add_uevent_var(env, "NAME=%s", dev->name)) return -ENOMEM; /* * It would be nice to pass the node GUID with the event... */ - envp[i] = NULL; return 0; } diff --git a/drivers/input/input.c b/drivers/input/input.c index 5fe75558662..5dc361c954e 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -859,87 +859,66 @@ static void input_dev_release(struct device *device) * Input uevent interface - loading event handlers based on * device bitfields. */ -static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, - char *buffer, int buffer_size, int *cur_len, +static int input_add_uevent_bm_var(struct kobj_uevent_env *env, const char *name, unsigned long *bitmap, int max) { - if (*cur_index >= num_envp - 1) - return -ENOMEM; - - envp[*cur_index] = buffer + *cur_len; + int len; - *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name); - if (*cur_len >= buffer_size) + if (add_uevent_var(env, "%s=", name)) return -ENOMEM; - *cur_len += input_print_bitmap(buffer + *cur_len, - max(buffer_size - *cur_len, 0), - bitmap, max, 0) + 1; - if (*cur_len > buffer_size) + len = input_print_bitmap(&env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen, + bitmap, max, 0); + if (len >= (sizeof(env->buf) - env->buflen)) return -ENOMEM; - (*cur_index)++; + env->buflen += len; return 0; } -static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index, - char *buffer, int buffer_size, int *cur_len, +static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, struct input_dev *dev) { - if (*cur_index >= num_envp - 1) - return -ENOMEM; - - envp[*cur_index] = buffer + *cur_len; + int len; - *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), - "MODALIAS="); - if (*cur_len >= buffer_size) + if (add_uevent_var(env, "MODALIAS=")) return -ENOMEM; - *cur_len += input_print_modalias(buffer + *cur_len, - max(buffer_size - *cur_len, 0), - dev, 0) + 1; - if (*cur_len > buffer_size) + len = input_print_modalias(&env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen, + dev, 0); + if (len >= (sizeof(env->buf) - env->buflen)) return -ENOMEM; - (*cur_index)++; + env->buflen += len; return 0; } #define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \ do { \ - int err = add_uevent_var(envp, num_envp, &i, \ - buffer, buffer_size, &len, \ - fmt, val); \ + int err = add_uevent_var(env, fmt, val); \ if (err) \ return err; \ } while (0) #define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \ do { \ - int err = input_add_uevent_bm_var(envp, num_envp, &i, \ - buffer, buffer_size, &len, \ - name, bm, max); \ + int err = input_add_uevent_bm_var(env, name, bm, max); \ if (err) \ return err; \ } while (0) #define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \ do { \ - int err = input_add_uevent_modalias_var(envp, \ - num_envp, &i, \ - buffer, buffer_size, &len, \ - dev); \ + int err = input_add_uevent_modalias_var(env, dev); \ if (err) \ return err; \ } while (0) -static int input_dev_uevent(struct device *device, char **envp, - int num_envp, char *buffer, int buffer_size) +static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) { struct input_dev *dev = to_input_dev(device); - int i = 0; - int len = 0; INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x", dev->id.bustype, dev->id.vendor, @@ -971,7 +950,6 @@ static int input_dev_uevent(struct device *device, char **envp, INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev); - envp[i] = NULL; return 0; } diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 372ca493119..b3bc15acd3f 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -876,18 +876,14 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv) #define SERIO_ADD_UEVENT_VAR(fmt, val...) \ do { \ - int err = add_uevent_var(envp, num_envp, &i, \ - buffer, buffer_size, &len, \ - fmt, val); \ + int err = add_uevent_var(env, fmt, val); \ if (err) \ return err; \ } while (0) -static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) +static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) { struct serio *serio; - int i = 0; - int len = 0; if (!dev) return -ENODEV; @@ -900,7 +896,6 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra); SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X", serio->id.type, serio->id.proto, serio->id.id, serio->id.extra); - envp[i] = NULL; return 0; } @@ -908,7 +903,7 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf #else -static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) +static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 7a78d6b3473..2ee3c3049e8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -905,8 +905,8 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp, } -static int pvr2_sysfs_hotplug(struct device *cd,char **envp, - int numenvp,char *buf,int size) +static int pvr2_sysfs_hotplug(struct device *d, + struct kobj_uevent_env *env) { /* Even though we don't do anything here, we still need this function because sysfs will still try to call it. */ diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index d195fb088f4..8f77949f93d 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -57,16 +57,11 @@ static int tifm_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int tifm_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env) { struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); - int i = 0; - int length = 0; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "TIFM_CARD_TYPE=%s", - tifm_media_type_name(sock->type, 1))) + if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1))) return -ENOMEM; return 0; diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 8d6f6014870..b0c22cad942 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -58,12 +58,11 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv) } static int -mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, - int buf_size) +mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct mmc_card *card = dev_to_mmc_card(dev); const char *type; - int i = 0, length = 0; + int retval = 0; switch (card->type) { case MMC_TYPE_MMC: @@ -80,20 +79,14 @@ mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, } if (type) { - if (add_uevent_var(envp, num_envp, &i, - buf, buf_size, &length, - "MMC_TYPE=%s", type)) - return -ENOMEM; + retval = add_uevent_var(env, "MMC_TYPE=%s", type); + if (retval) + return retval; } - if (add_uevent_var(envp, num_envp, &i, - buf, buf_size, &length, - "MMC_NAME=%s", mmc_card_name(card))) - return -ENOMEM; + retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); - envp[i] = NULL; - - return 0; + return retval; } static int mmc_bus_probe(struct device *dev) diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c index 1c97e7dd130..2b5352a7dff 100644 --- a/drivers/pci/hotplug.c +++ b/drivers/pci/hotplug.c @@ -3,12 +3,9 @@ #include #include "pci.h" -int pci_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +int pci_uevent(struct device *dev, struct kobj_uevent_env *env) { struct pci_dev *pdev; - int i = 0; - int length = 0; if (!dev) return -ENODEV; @@ -17,37 +14,24 @@ int pci_uevent(struct device *dev, char **envp, int num_envp, if (!pdev) return -ENODEV; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PCI_CLASS=%04X", pdev->class)) + if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PCI_ID=%04X:%04X", pdev->vendor, pdev->device)) + if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, + if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, pdev->subsystem_device)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PCI_SLOT_NAME=%s", pci_name(pdev))) + if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev))) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x", + if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device, (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), (u8)(pdev->class))) return -ENOMEM; - - envp[i] = NULL; - return 0; } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 004bc248727..f61be3abfdc 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -532,8 +532,7 @@ void pci_dev_put(struct pci_dev *dev) } #ifndef CONFIG_HOTPLUG -int pci_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +int pci_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 4c36e80f6d2..b3a7d5b0f93 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1,7 +1,6 @@ /* Functions internal to the PCI core code */ -extern int pci_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); +extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env); extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); extern void pci_cleanup_rom(struct pci_dev *dev); diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index f8b13f0270d..a0aca46ce87 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -907,18 +907,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) EXPORT_SYMBOL(pcmcia_insert_card); -static int pcmcia_socket_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int pcmcia_socket_uevent(struct device *dev, + struct kobj_uevent_env *env) { struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); - int i = 0, length = 0; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "SOCKET_NO=%u", s->sock)) + if (add_uevent_var(env, "SOCKET_NO=%u", s->sock)) return -ENOMEM; - envp[i] = NULL; - return 0; } diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a99607142fc..55baa1f0fcb 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1064,11 +1064,10 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { #ifdef CONFIG_HOTPLUG -static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct pcmcia_device *p_dev; - int i, length = 0; + int i; u32 hash[4] = { 0, 0, 0, 0}; if (!dev) @@ -1083,23 +1082,13 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); } - i = 0; - - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "SOCKET_NO=%u", - p_dev->socket->sock)) + if (add_uevent_var(env, "SOCKET_NO=%u", p_dev->socket->sock)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVICE_NO=%02X", - p_dev->device_no)) + if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" + if (add_uevent_var(env, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" "pa%08Xpb%08Xpc%08Xpd%08X", p_dev->has_manf_id ? p_dev->manf_id : 0, p_dev->has_card_id ? p_dev->card_id : 0, @@ -1112,15 +1101,12 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, hash[3])) return -ENOMEM; - envp[i] = NULL; - return 0; } #else -static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h index a9880d468ee..f38ba482be7 100644 --- a/drivers/power/power_supply.h +++ b/drivers/power/power_supply.h @@ -14,8 +14,7 @@ extern int power_supply_create_attrs(struct power_supply *psy); extern void power_supply_remove_attrs(struct power_supply *psy); -extern int power_supply_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); +extern int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env); #else diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index de3155b2128..249f61bae63 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -195,11 +195,10 @@ static char *kstruprdup(const char *str, gfp_t gfp) return ret; } -int power_supply_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) { struct power_supply *psy = dev_get_drvdata(dev); - int i = 0, length = 0, ret = 0, j; + int ret = 0, j; char *prop_buf; char *attrname; @@ -212,8 +211,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name); - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "POWER_SUPPLY_NAME=%s", psy->name); + ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name); if (ret) return ret; @@ -243,9 +241,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf); - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "POWER_SUPPLY_%s=%s", - attrname, prop_buf); + ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); kfree(attrname); if (ret) goto out; @@ -282,14 +278,11 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf); - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "POWER_SUPPLY_%s=%s", - attrname, prop_buf); + ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); kfree(attrname); if (ret) goto out; } - envp[i] = NULL; out: free_page((unsigned long)prop_buf); diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index b0a18f5176a..5d967c43982 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -44,8 +44,7 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv) return 0; } static int -ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, - int buffer_size) +ccwgroup_uevent (struct device *dev, struct kobj_uevent_env *env) { /* TODO */ return 0; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e44d92eac8e..606bb53e9fa 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -78,49 +78,38 @@ static int snprint_alias(char *buf, size_t size, /* Set up environment variables for ccw device uevent. Return 0 on success, * non-zero otherwise. */ -static int ccw_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env) { struct ccw_device *cdev = to_ccwdev(dev); struct ccw_device_id *id = &(cdev->id); - int i = 0; - int len = 0; int ret; char modalias_buf[30]; /* CU_TYPE= */ - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "CU_TYPE=%04X", id->cu_type); + ret = add_uevent_var(env, "CU_TYPE=%04X", id->cu_type); if (ret) return ret; /* CU_MODEL= */ - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "CU_MODEL=%02X", id->cu_model); + ret = add_uevent_var(env, "CU_MODEL=%02X", id->cu_model); if (ret) return ret; /* The next two can be zero, that's ok for us */ /* DEV_TYPE= */ - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "DEV_TYPE=%04X", id->dev_type); + ret = add_uevent_var(env, "DEV_TYPE=%04X", id->dev_type); if (ret) return ret; /* DEV_MODEL= */ - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "DEV_MODEL=%02X", id->dev_model); + ret = add_uevent_var(env, "DEV_MODEL=%02X", id->dev_model); if (ret) return ret; /* MODALIAS= */ snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "MODALIAS=%s", modalias_buf); - if (ret) - return ret; - envp[i] = NULL; - return 0; + ret = add_uevent_var(env, "MODALIAS=%s", modalias_buf); + return ret; } struct bus_type ccw_bus_type; diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 90bd2201451..e9971304159 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -458,28 +458,22 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv) * uevent function for AP devices. It sets up a single environment * variable DEV_TYPE which contains the hardware device type. */ -static int ap_uevent (struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int ap_uevent (struct device *dev, struct kobj_uevent_env *env) { struct ap_device *ap_dev = to_ap_dev(dev); - int retval = 0, length = 0, i = 0; + int retval = 0; if (!ap_dev) return -ENODEV; /* Set up DEV_TYPE environment variable. */ - retval = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEV_TYPE=%04X", ap_dev->device_type); + retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type); if (retval) return retval; /* Add MODALIAS= */ - retval = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=ap:t%02X", ap_dev->device_type); + retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type); - envp[i] = NULL; return retval; } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 34cdce6738a..ede9986d349 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -277,16 +277,11 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } -static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct scsi_device *sdev = to_scsi_device(dev); - int i = 0; - int length = 0; - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); - envp[i] = NULL; + add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); return 0; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index e84d2159794..bcb8dd5fb0b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -67,14 +67,11 @@ static int spi_match_device(struct device *dev, struct device_driver *drv) return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; } -static int spi_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) { const struct spi_device *spi = to_spi_device(dev); - envp[0] = buffer; - snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias); - envp[1] = NULL; + add_uevent_var(env, "MODALIAS=%s", spi->modalias); return 0; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 63b1243a913..6273a5197e6 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -576,12 +576,9 @@ static int usb_device_match(struct device *dev, struct device_driver *drv) } #ifdef CONFIG_HOTPLUG -static int usb_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) { struct usb_device *usb_dev; - int i = 0; - int length = 0; if (!dev) return -ENODEV; @@ -610,51 +607,39 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, * all the device descriptors we don't tell them about. Or * act as usermode drivers. */ - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVICE=/proc/bus/usb/%03d/%03d", + if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", usb_dev->bus->busnum, usb_dev->devnum)) return -ENOMEM; #endif /* per-device configurations are common */ - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PRODUCT=%x/%x/%x", + if (add_uevent_var(env, "PRODUCT=%x/%x/%x", le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idProduct), le16_to_cpu(usb_dev->descriptor.bcdDevice))) return -ENOMEM; /* class-based driver binding models */ - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "TYPE=%d/%d/%d", + if (add_uevent_var(env, "TYPE=%d/%d/%d", usb_dev->descriptor.bDeviceClass, usb_dev->descriptor.bDeviceSubClass, usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "BUSNUM=%03d", + if (add_uevent_var(env, "BUSNUM=%03d", usb_dev->bus->busnum)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVNUM=%03d", + if (add_uevent_var(env, "DEVNUM=%03d", usb_dev->devnum)) return -ENOMEM; - envp[i] = NULL; return 0; } #else -static int usb_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index d8f7b089a8f..95a49d8efe7 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1339,14 +1339,11 @@ void usb_release_interface(struct device *dev) } #ifdef CONFIG_HOTPLUG -static int usb_if_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) { struct usb_device *usb_dev; struct usb_interface *intf; struct usb_host_interface *alt; - int i = 0; - int length = 0; if (!dev) return -ENODEV; @@ -1359,39 +1356,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, alt = intf->cur_altsetting; #ifdef CONFIG_USB_DEVICEFS - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVICE=/proc/bus/usb/%03d/%03d", + if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", usb_dev->bus->busnum, usb_dev->devnum)) return -ENOMEM; #endif - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PRODUCT=%x/%x/%x", + if (add_uevent_var(env, "PRODUCT=%x/%x/%x", le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idProduct), le16_to_cpu(usb_dev->descriptor.bcdDevice))) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "TYPE=%d/%d/%d", + if (add_uevent_var(env, "TYPE=%d/%d/%d", usb_dev->descriptor.bDeviceClass, usb_dev->descriptor.bDeviceSubClass, usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "INTERFACE=%d/%d/%d", + if (add_uevent_var(env, "INTERFACE=%d/%d/%d", alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, alt->desc.bInterfaceProtocol)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, + if (add_uevent_var(env, "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idProduct), @@ -1404,14 +1392,12 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, alt->desc.bInterfaceProtocol)) return -ENOMEM; - envp[i] = NULL; return 0; } #else -static int usb_if_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index a593f900eff..070217322c9 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -197,7 +197,7 @@ static struct w1_family w1_default_family = { .fops = &w1_default_fops, }; -static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); +static int w1_uevent(struct device *dev, struct kobj_uevent_env *env); static struct bus_type w1_bus_type = { .name = "w1", @@ -396,13 +396,12 @@ static void w1_destroy_master_attributes(struct w1_master *master) } #ifdef CONFIG_HOTPLUG -static int w1_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) { struct w1_master *md = NULL; struct w1_slave *sl = NULL; char *event_owner, *name; - int err, cur_index=0, cur_len=0; + int err; if (dev->driver == &w1_master_driver) { md = container_of(dev, struct w1_master, dev); @@ -423,23 +422,19 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp, if (dev->driver != &w1_slave_driver || !sl) return 0; - err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, - &cur_len, "W1_FID=%02X", sl->reg_num.family); + err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family); if (err) return err; - err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, - &cur_len, "W1_SLAVE_ID=%024LX", - (unsigned long long)sl->reg_num.id); - envp[cur_index] = NULL; + err = add_uevent_var(env, "W1_SLAVE_ID=%024LX", + (unsigned long long)sl->reg_num.id); if (err) return err; return 0; }; #else -static int w1_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) { return 0; } diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index ec2a8a2c737..93262f2546a 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h @@ -20,7 +20,7 @@ struct of_device extern ssize_t of_device_get_modalias(struct of_device *ofdev, char *str, ssize_t len); extern int of_device_uevent(struct device *dev, - char **envp, int num_envp, char *buffer, int buffer_size); + struct kobj_uevent_env *env); /* This is just here during the transition */ #include diff --git a/include/linux/device.h b/include/linux/device.h index 5d97ca6d865..2e15822fe40 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -66,8 +66,7 @@ struct bus_type { struct driver_attribute * drv_attrs; int (*match)(struct device * dev, struct device_driver * drv); - int (*uevent)(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size); + int (*uevent)(struct device *dev, struct kobj_uevent_env *env); int (*probe)(struct device * dev); int (*remove)(struct device * dev); void (*shutdown)(struct device * dev); @@ -187,10 +186,8 @@ struct class { struct class_device_attribute * class_dev_attrs; struct device_attribute * dev_attrs; - int (*uevent)(struct class_device *dev, char **envp, - int num_envp, char *buffer, int buffer_size); - int (*dev_uevent)(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); + int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env); + int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); void (*release)(struct class_device *dev); void (*class_release)(struct class *class); @@ -266,8 +263,7 @@ struct class_device { struct attribute_group ** groups; /* optional groups */ void (*release)(struct class_device *dev); - int (*uevent)(struct class_device *dev, char **envp, - int num_envp, char *buffer, int buffer_size); + int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env); char class_id[BUS_ID_SIZE]; /* unique to this class */ }; @@ -335,8 +331,7 @@ extern void class_device_destroy(struct class *cls, dev_t devt); struct device_type { const char *name; struct attribute_group **groups; - int (*uevent)(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); + int (*uevent)(struct device *dev, struct kobj_uevent_env *env); void (*release)(struct device *dev); int (*suspend)(struct device * dev, pm_message_t state); int (*resume)(struct device * dev); diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 949706c3362..626bdd3c3dd 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -29,6 +29,8 @@ #define KOBJ_NAME_LEN 20 #define UEVENT_HELPER_PATH_LEN 256 +#define UEVENT_NUM_ENVP 32 /* number of env pointers */ +#define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ /* path to the userspace helper executed on an event */ extern char uevent_helper[]; @@ -111,11 +113,18 @@ struct kobj_type { struct attribute ** default_attrs; }; +struct kobj_uevent_env { + char *envp[UEVENT_NUM_ENVP]; + int envp_idx; + char buf[UEVENT_BUFFER_SIZE]; + int buflen; +}; + struct kset_uevent_ops { int (*filter)(struct kset *kset, struct kobject *kobj); const char *(*name)(struct kset *kset, struct kobject *kobj); - int (*uevent)(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size); + int (*uevent)(struct kset *kset, struct kobject *kobj, + struct kobj_uevent_env *env); }; /* @@ -275,10 +284,8 @@ int kobject_uevent(struct kobject *kobj, enum kobject_action action); int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp[]); -int add_uevent_var(char **envp, int num_envp, int *cur_index, - char *buffer, int buffer_size, int *cur_len, - const char *format, ...) - __attribute__((format (printf, 7, 8))); +int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) + __attribute__((format (printf, 2, 3))); #else static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action) { return 0; } @@ -287,9 +294,7 @@ static inline int kobject_uevent_env(struct kobject *kobj, char *envp[]) { return 0; } -static inline int add_uevent_var(char **envp, int num_envp, int *cur_index, - char *buffer, int buffer_size, int *cur_len, - const char *format, ...) +static inline int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) { return 0; } #endif diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index e06a8dcec0f..7d8aeb30163 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -22,8 +22,6 @@ #include #include -#define BUFFER_SIZE 2048 /* buffer for the variables */ -#define NUM_ENVP 32 /* number of env pointers */ /* the strings here must match the enum in include/linux/kobject.h */ const char *kobject_actions[] = { @@ -54,31 +52,21 @@ static struct sock *uevent_sock; * corresponding error when it fails. */ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, - char *envp_ext[]) + char *envp_ext[]) { - char **envp; - char *buffer; - char *scratch; - const char *action_string; + struct kobj_uevent_env *env; + const char *action_string = kobject_actions[action]; const char *devpath = NULL; const char *subsystem; struct kobject *top_kobj; struct kset *kset; struct kset_uevent_ops *uevent_ops; u64 seq; - char *seq_buff; int i = 0; int retval = 0; - int j; pr_debug("%s\n", __FUNCTION__); - action_string = kobject_actions[action]; - if (!action_string) { - pr_debug("kobject attempted to send uevent without action_string!\n"); - return -EINVAL; - } - /* search the kset we belong to */ top_kobj = kobj; while (!top_kobj->kset && top_kobj->parent) { @@ -92,7 +80,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, kset = top_kobj->kset; uevent_ops = kset->uevent_ops; - /* skip the event, if the filter returns zero. */ + /* skip the event, if the filter returns zero. */ if (uevent_ops && uevent_ops->filter) if (!uevent_ops->filter(kset, kobj)) { pr_debug("kobject filter function caused the event to drop!\n"); @@ -109,18 +97,11 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, return 0; } - /* environment index */ - envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); - if (!envp) + /* environment buffer */ + env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); + if (!env) return -ENOMEM; - /* environment values */ - buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); - if (!buffer) { - retval = -ENOMEM; - goto exit; - } - /* complete object path */ devpath = kobject_get_path(kobj, GFP_KERNEL); if (!devpath) { @@ -128,29 +109,29 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, goto exit; } - /* event environemnt for helper process only */ - envp[i++] = "HOME=/"; - envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; - /* default keys */ - scratch = buffer; - envp [i++] = scratch; - scratch += sprintf(scratch, "ACTION=%s", action_string) + 1; - envp [i++] = scratch; - scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1; - envp [i++] = scratch; - scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1; - for (j = 0; envp_ext && envp_ext[j]; j++) - envp[i++] = envp_ext[j]; - /* just reserve the space, overwrite it after kset call has returned */ - envp[i++] = seq_buff = scratch; - scratch += strlen("SEQNUM=18446744073709551616") + 1; + retval = add_uevent_var(env, "ACTION=%s", action_string); + if (retval) + goto exit; + retval = add_uevent_var(env, "DEVPATH=%s", devpath); + if (retval) + goto exit; + retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem); + if (retval) + goto exit; + + /* keys passed in from the caller */ + if (envp_ext) { + for (i = 0; envp_ext[i]; i++) { + retval = add_uevent_var(env, envp_ext[i]); + if (retval) + goto exit; + } + } /* let the kset specific function add its stuff */ if (uevent_ops && uevent_ops->uevent) { - retval = uevent_ops->uevent(kset, kobj, - &envp[i], NUM_ENVP - i, scratch, - BUFFER_SIZE - (scratch - buffer)); + retval = uevent_ops->uevent(kset, kobj, env); if (retval) { pr_debug ("%s - uevent() returned %d\n", __FUNCTION__, retval); @@ -158,11 +139,13 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, } } - /* we will send an event, request a new sequence number */ + /* we will send an event, so request a new sequence number */ spin_lock(&sequence_lock); seq = ++uevent_seqnum; spin_unlock(&sequence_lock); - sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq); + retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); + if (retval) + goto exit; #if defined(CONFIG_NET) /* send netlink message */ @@ -172,17 +155,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, /* allocate message with the maximum possible size */ len = strlen(action_string) + strlen(devpath) + 2; - skb = alloc_skb(len + BUFFER_SIZE, GFP_KERNEL); + skb = alloc_skb(len + env->buflen, GFP_KERNEL); if (skb) { + char *scratch; + /* add header */ scratch = skb_put(skb, len); sprintf(scratch, "%s@%s", action_string, devpath); /* copy keys to our continuous event payload buffer */ - for (i = 2; envp[i]; i++) { - len = strlen(envp[i]) + 1; + for (i = 0; i < env->envp_idx; i++) { + len = strlen(env->envp[i]) + 1; scratch = skb_put(skb, len); - strcpy(scratch, envp[i]); + strcpy(scratch, env->envp[i]); } NETLINK_CB(skb).dst_group = 1; @@ -198,13 +183,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, argv [0] = uevent_helper; argv [1] = (char *)subsystem; argv [2] = NULL; - call_usermodehelper (argv[0], argv, envp, UMH_WAIT_EXEC); + retval = add_uevent_var(env, "HOME=/"); + if (retval) + goto exit; + retval = add_uevent_var(env, "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); + if (retval) + goto exit; + + call_usermodehelper (argv[0], argv, env->envp, UMH_WAIT_EXEC); } exit: kfree(devpath); - kfree(buffer); - kfree(envp); + kfree(env); return retval; } @@ -227,52 +218,38 @@ int kobject_uevent(struct kobject *kobj, enum kobject_action action) EXPORT_SYMBOL_GPL(kobject_uevent); /** - * add_uevent_var - helper for creating event variables - * @envp: Pointer to table of environment variables, as passed into - * uevent() method. - * @num_envp: Number of environment variable slots available, as - * passed into uevent() method. - * @cur_index: Pointer to current index into @envp. It should be - * initialized to 0 before the first call to add_uevent_var(), - * and will be incremented on success. - * @buffer: Pointer to buffer for environment variables, as passed - * into uevent() method. - * @buffer_size: Length of @buffer, as passed into uevent() method. - * @cur_len: Pointer to current length of space used in @buffer. - * Should be initialized to 0 before the first call to - * add_uevent_var(), and will be incremented on success. - * @format: Format for creating environment variable (of the form - * "XXX=%x") for snprintf(). + * add_uevent_var - add key value string to the environment buffer + * @env: environment buffer structure + * @format: printf format for the key=value pair * * Returns 0 if environment variable was added successfully or -ENOMEM * if no space was available. */ -int add_uevent_var(char **envp, int num_envp, int *cur_index, - char *buffer, int buffer_size, int *cur_len, - const char *format, ...) +int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) { va_list args; + int len; - /* - * We check against num_envp - 1 to make sure there is at - * least one slot left after we return, since kobject_uevent() - * needs to set the last slot to NULL. - */ - if (*cur_index >= num_envp - 1) + if (env->envp_idx >= ARRAY_SIZE(env->envp)) { + printk(KERN_ERR "add_uevent_var: too many keys\n"); + WARN_ON(1); return -ENOMEM; - - envp[*cur_index] = buffer + *cur_len; + } va_start(args, format); - *cur_len += vsnprintf(envp[*cur_index], - max(buffer_size - *cur_len, 0), - format, args) + 1; + len = vsnprintf(&env->buf[env->buflen], + sizeof(env->buf) - env->buflen, + format, args); va_end(args); - if (*cur_len > buffer_size) + if (len >= (sizeof(env->buf) - env->buflen)) { + printk(KERN_ERR "add_uevent_var: buffer size too small\n"); + WARN_ON(1); return -ENOMEM; + } - (*cur_index)++; + env->envp[env->envp_idx++] = &env->buf[env->buflen]; + env->buflen += len + 1; return 0; } EXPORT_SYMBOL_GPL(add_uevent_var); diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c index f094a0879c1..9ef07eda2c4 100644 --- a/net/atm/atm_sysfs.c +++ b/net/atm/atm_sysfs.c @@ -105,10 +105,9 @@ static struct class_device_attribute *atm_attrs[] = { NULL }; -static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size) +static int atm_uevent(struct class_device *cdev, struct kobj_uevent_env *env) { struct atm_dev *adev; - int i = 0, len = 0; if (!cdev) return -ENODEV; @@ -117,11 +116,9 @@ static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char if (!adev) return -ENODEV; - if (add_uevent_var(envp, num_envp, &i, buf, size, &len, - "NAME=%s%d", adev->type, adev->number)) + if (add_uevent_var(env, "NAME=%s%d", adev->type, adev->number)) return -ENOMEM; - envp[i] = NULL; return 0; } diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 909a03d6c0e..6628e457ddc 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -396,28 +396,22 @@ static struct attribute_group wireless_group = { #endif /* CONFIG_SYSFS */ #ifdef CONFIG_HOTPLUG -static int netdev_uevent(struct device *d, char **envp, - int num_envp, char *buf, int size) +static int netdev_uevent(struct device *d, struct kobj_uevent_env *env) { struct net_device *dev = to_net_dev(d); - int retval, len = 0, i = 0; + int retval; /* pass interface to uevent. */ - retval = add_uevent_var(envp, num_envp, &i, - buf, size, &len, - "INTERFACE=%s", dev->name); + retval = add_uevent_var(env, "INTERFACE=%s", dev->name); if (retval) goto exit; /* pass ifindex to uevent. * ifindex is useful as it won't change (interface name may change) * and is what RtNetlink uses natively. */ - retval = add_uevent_var(envp, num_envp, &i, - buf, size, &len, - "IFINDEX=%d", dev->ifindex); + retval = add_uevent_var(env, "IFINDEX=%d", dev->ifindex); exit: - envp[i] = NULL; return retval; } #endif diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 2d5d2255a27..29f820e1825 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -53,8 +53,7 @@ static void wiphy_dev_release(struct device *dev) } #ifdef CONFIG_HOTPLUG -static int wiphy_uevent(struct device *dev, char **envp, - int num_envp, char *buf, int size) +static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) { /* TODO, we probably need stuff here */ return 0; diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 64d16391433..f84f3e50578 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c @@ -56,13 +56,12 @@ static int soundbus_probe(struct device *dev) } -static int soundbus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct soundbus_dev * soundbus_dev; struct of_device * of; const char *compat; - int retval = 0, i = 0, length = 0; + int retval = 0; int cplen, seen = 0; if (!dev) @@ -75,15 +74,11 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp, of = &soundbus_dev->ofdev; /* stuff we want to pass to /sbin/hotplug */ - retval = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "OF_NAME=%s", of->node->name); + retval = add_uevent_var(env, "OF_NAME=%s", of->node->name); if (retval) return retval; - retval = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "OF_TYPE=%s", of->node->type); + retval = add_uevent_var(env, "OF_TYPE=%s", of->node->type); if (retval) return retval; @@ -93,27 +88,19 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp, compat = of_get_property(of->node, "compatible", &cplen); while (compat && cplen > 0) { - int tmp = length; - retval = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "OF_COMPATIBLE_%d=%s", seen, compat); + int tmp = env->buflen; + retval = add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat); if (retval) return retval; - compat += length - tmp; - cplen -= length - tmp; + compat += env->buflen - tmp; + cplen -= env->buflen - tmp; seen += 1; } - retval = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "OF_COMPATIBLE_N=%d", seen); + retval = add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); if (retval) return retval; - retval = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=%s", soundbus_dev->modalias); - - envp[i] = NULL; + retval = add_uevent_var(env, "MODALIAS=%s", soundbus_dev->modalias); return retval; } -- cgit v1.2.3-70-g09d2 From d6b05b84edf590ff872de6310ec20d60b5b37dd2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: Driver core: remove subsys_set_kset This macro is only used by the driver core and is held over from when we had subsystems. It is not needed anymore. Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 3 ++- drivers/base/class.c | 2 +- include/linux/kobject.h | 13 ------------- 3 files changed, 3 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index ff850d1b0d9..625f7e69452 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -823,7 +823,8 @@ int bus_register(struct bus_type * bus) if (retval) goto out; - subsys_set_kset(bus, bus_subsys); + bus->subsys.kobj.kset = &bus_subsys; + retval = subsystem_register(&bus->subsys); if (retval) goto out; diff --git a/drivers/base/class.c b/drivers/base/class.c index ecd6336bffe..cf9cf666f47 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -149,7 +149,7 @@ int class_register(struct class * cls) if (error) return error; - subsys_set_kset(cls, class_subsys); + cls->subsys.kobj.kset = &class_subsys; error = subsystem_register(&cls->subsys); if (!error) { diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 626bdd3c3dd..0713799fde2 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -241,19 +241,6 @@ extern struct kset hypervisor_subsys; #define kset_set_kset_s(obj,subsys) \ (obj)->kset.kobj.kset = &(subsys) -/** - * subsys_set_kset(obj,subsys) - set kset for subsystem - * @obj: ptr to some object type. - * @_subsys: a subsystem object (not a ptr). - * - * Can be used for any object type with an embedded ->subsys. - * Sets the kset of @obj's kobject to @subsys.kset. This makes - * the object a member of that kset. - */ - -#define subsys_set_kset(obj,_subsys) \ - (obj)->subsys.kobj.kset = &(_subsys) - extern void subsystem_init(struct kset *); extern int __must_check subsystem_register(struct kset *); extern void subsystem_unregister(struct kset *); -- cgit v1.2.3-70-g09d2 From 27f20e5e4e60a7f28010eeb34399fe0cc9a1a235 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: Driver core: remove kset_set_kset_s This macro is only used by the driver core and is held over from when we had subsystems. It is not needed anymore. Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 2 +- include/linux/kobject.h | 14 -------------- 2 files changed, 1 insertion(+), 15 deletions(-) (limited to 'include') diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 18febe26caa..7ad89316782 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -139,7 +139,7 @@ int sysdev_class_register(struct sysdev_class * cls) kobject_name(&cls->kset.kobj)); INIT_LIST_HEAD(&cls->drivers); cls->kset.kobj.parent = &system_subsys.kobj; - kset_set_kset_s(cls, system_subsys); + cls->kset.kobj.kset = &system_subsys; return kset_register(&cls->kset); } diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 0713799fde2..ee61ef27e79 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -227,20 +227,6 @@ extern struct kset hypervisor_subsys; #define kobj_set_kset_s(obj,subsys) \ (obj)->kobj.kset = &(subsys) -/** - * kset_set_kset_s(obj,subsys) - set kset for embedded kset. - * @obj: ptr to some object type. - * @subsys: a subsystem object (not a ptr). - * - * Can be used for any object type with an embedded ->kset. - * Sets the kset of @obj's embedded kobject (via its embedded - * kset) to @subsys.kset. This makes @obj a member of that - * kset. - */ - -#define kset_set_kset_s(obj,subsys) \ - (obj)->kset.kobj.kset = &(subsys) - extern void subsystem_init(struct kset *); extern int __must_check subsystem_register(struct kset *); extern void subsystem_unregister(struct kset *); -- cgit v1.2.3-70-g09d2 From 6e9d930d167f8957a12a80515f3c417a98296378 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: Driver core: remove subsys_put() There are no more subsystems, it's a kset now so remove the function and the only two users, which are in the driver core. Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 +- drivers/base/class.c | 2 +- include/linux/kobject.h | 5 ----- lib/kobject.c | 2 +- 4 files changed, 3 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 625f7e69452..2f775936544 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -734,7 +734,7 @@ struct bus_type *get_bus(struct bus_type *bus) void put_bus(struct bus_type * bus) { - subsys_put(&bus->subsys); + kset_put(&bus->subsys); } diff --git a/drivers/base/class.c b/drivers/base/class.c index cf9cf666f47..50e34132576 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -100,7 +100,7 @@ static struct class *class_get(struct class *cls) static void class_put(struct class * cls) { if (cls) - subsys_put(&cls->subsys); + kset_put(&cls->subsys); } diff --git a/include/linux/kobject.h b/include/linux/kobject.h index ee61ef27e79..45effedff31 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -238,11 +238,6 @@ static inline struct kset *subsys_get(struct kset *s) return NULL; } -static inline void subsys_put(struct kset *s) -{ - kset_put(s); -} - struct subsys_attribute { struct attribute attr; ssize_t (*show)(struct kset *, char *); diff --git a/lib/kobject.c b/lib/kobject.c index 4b08e0ff95c..0aa4e906916 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -681,7 +681,7 @@ int subsys_create_file(struct kset *s, struct subsys_attribute *a) if (subsys_get(s)) { error = sysfs_create_file(&s->kobj, &a->attr); - subsys_put(s); + kset_put(s); } return error; } -- cgit v1.2.3-70-g09d2 From 1ef4cfac01fb5e98900f5bdb2a722aac1daff11b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: Driver core: remove subsys_get() There are no more subsystems, it's a kset now so remove the function and the only two users, which are in the driver core. Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 +- drivers/base/class.c | 2 +- include/linux/kobject.h | 7 ------- lib/kobject.c | 2 +- 4 files changed, 3 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 2f775936544..bc38085dbb1 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -728,7 +728,7 @@ EXPORT_SYMBOL_GPL(device_reprobe); struct bus_type *get_bus(struct bus_type *bus) { - return bus ? container_of(subsys_get(&bus->subsys), + return bus ? container_of(kset_get(&bus->subsys), struct bus_type, subsys) : NULL; } diff --git a/drivers/base/class.c b/drivers/base/class.c index 50e34132576..3e9b04c30fb 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -93,7 +93,7 @@ void class_remove_file(struct class * cls, const struct class_attribute * attr) static struct class *class_get(struct class *cls) { if (cls) - return container_of(subsys_get(&cls->subsys), struct class, subsys); + return container_of(kset_get(&cls->subsys), struct class, subsys); return NULL; } diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 45effedff31..c0fb535d7ac 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -231,13 +231,6 @@ extern void subsystem_init(struct kset *); extern int __must_check subsystem_register(struct kset *); extern void subsystem_unregister(struct kset *); -static inline struct kset *subsys_get(struct kset *s) -{ - if (s) - return kset_get(s); - return NULL; -} - struct subsys_attribute { struct attribute attr; ssize_t (*show)(struct kset *, char *); diff --git a/lib/kobject.c b/lib/kobject.c index 0aa4e906916..1326041213d 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -679,7 +679,7 @@ int subsys_create_file(struct kset *s, struct subsys_attribute *a) if (!s || !a) return -EINVAL; - if (subsys_get(s)) { + if (kset_get(s)) { error = sysfs_create_file(&s->kobj, &a->attr); kset_put(s); } -- cgit v1.2.3-70-g09d2 From ce2c9cb0259acd2aed184499ebe41ab00da13b25 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: kobject: remove the static array for the name Due to historical reasons, struct kobject contained a static array for the name, and a dynamic pointer in case the name got bigger than the array. That's just dumb, as people didn't always know which variable to reference, even with the accessor for the kobject name. This patch removes the static array, potentially saving a lot of memory as the majority of kobjects do not have a very long name. Thanks to Kay for the idea to do this. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- include/linux/kobject.h | 7 ++--- lib/kobject.c | 79 ++++++++++++++++++++++++------------------------- 2 files changed, 42 insertions(+), 44 deletions(-) (limited to 'include') diff --git a/include/linux/kobject.h b/include/linux/kobject.h index c0fb535d7ac..8b45946e850 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -63,7 +63,6 @@ extern const char *kobject_actions[]; struct kobject { const char * k_name; - char name[KOBJ_NAME_LEN]; struct kref kref; struct list_head entry; struct kobject * parent; @@ -188,18 +187,18 @@ extern struct kobject * kset_find_obj(struct kset *, const char *); * Use this when initializing an embedded kset with no other * fields to initialize. */ -#define set_kset_name(str) .kset = { .kobj = { .name = str } } +#define set_kset_name(str) .kset = { .kobj = { .k_name = str } } #define decl_subsys(_name,_type,_uevent_ops) \ struct kset _name##_subsys = { \ - .kobj = { .name = __stringify(_name) }, \ + .kobj = { .k_name = __stringify(_name) }, \ .ktype = _type, \ .uevent_ops =_uevent_ops, \ } #define decl_subsys_name(_varname,_name,_type,_uevent_ops) \ struct kset _varname##_subsys = { \ - .kobj = { .name = __stringify(_name) }, \ + .kobj = { .k_name = __stringify(_name) }, \ .ktype = _type, \ .uevent_ops =_uevent_ops, \ } diff --git a/lib/kobject.c b/lib/kobject.c index 1326041213d..10ae2ebeaf9 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -170,7 +170,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) if (!(kobj = kobject_get(kobj))) return -ENOENT; if (!kobj->k_name) - kobj->k_name = kobj->name; + kobject_set_name(kobj, "NO_NAME"); if (!*kobj->k_name) { pr_debug("kobject attempted to be registered with no name!\n"); WARN_ON(1); @@ -181,7 +181,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) pr_debug("kobject %s: registering. parent: %s, set: %s\n", kobject_name(kobj), parent ? kobject_name(parent) : "", - kobj->kset ? kobj->kset->kobj.name : "" ); + kobj->kset ? kobject_name(&kobj->kset->kobj) : "" ); if (kobj->kset) { spin_lock(&kobj->kset->list_lock); @@ -255,54 +255,50 @@ int kobject_register(struct kobject * kobj) int kobject_set_name(struct kobject * kobj, const char * fmt, ...) { int error = 0; - int limit = KOBJ_NAME_LEN; + int limit; int need; va_list args; - char * name; + char *name; - /* - * First, try the static array - */ - va_start(args,fmt); - need = vsnprintf(kobj->name,limit,fmt,args); + /* find out how big a buffer we need */ + name = kmalloc(1024, GFP_KERNEL); + if (!name) { + error = -ENOMEM; + goto done; + } + va_start(args, fmt); + need = vsnprintf(name, 1024, fmt, args); va_end(args); - if (need < limit) - name = kobj->name; - else { - /* - * Need more space? Allocate it and try again - */ - limit = need + 1; - name = kmalloc(limit,GFP_KERNEL); - if (!name) { - error = -ENOMEM; - goto Done; - } - va_start(args,fmt); - need = vsnprintf(name,limit,fmt,args); - va_end(args); - - /* Still? Give up. */ - if (need >= limit) { - kfree(name); - error = -EFAULT; - goto Done; - } + kfree(name); + + /* Allocate the new space and copy the string in */ + limit = need + 1; + name = kmalloc(limit, GFP_KERNEL); + if (!name) { + error = -ENOMEM; + goto done; + } + va_start(args, fmt); + need = vsnprintf(name, limit, fmt, args); + va_end(args); + + /* something wrong with the string we copied? */ + if (need >= limit) { + kfree(name); + error = -EFAULT; + goto done; } /* Free the old name, if necessary. */ - if (kobj->k_name && kobj->k_name != kobj->name) - kfree(kobj->k_name); + kfree(kobj->k_name); /* Now, set the new name */ kobj->k_name = name; - Done: +done: return error; } - EXPORT_SYMBOL(kobject_set_name); - /** * kobject_rename - change the name of an object * @kobj: object in question. @@ -477,13 +473,16 @@ void kobject_cleanup(struct kobject * kobj) struct kobj_type * t = get_ktype(kobj); struct kset * s = kobj->kset; struct kobject * parent = kobj->parent; + const char *name = kobj->k_name; pr_debug("kobject %s: cleaning up\n",kobject_name(kobj)); - if (kobj->k_name != kobj->name) - kfree(kobj->k_name); - kobj->k_name = NULL; - if (t && t->release) + if (t && t->release) { t->release(kobj); + /* If we have a release function, we can guess that this was + * not a statically allocated kobject, so we should be safe to + * free the name */ + kfree(name); + } if (s) kset_put(s); kobject_put(parent); -- cgit v1.2.3-70-g09d2 From 2ebefc50161a0a1cdebccd62be749e72abdbec37 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Thu, 2 Aug 2007 18:23:50 -0400 Subject: debugfs: helper for decimal challenged Allows debugfs helper functions to have a hex output, rather than just decimal Signed-off-by: Robin Getz Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/debugfs.h | 27 +++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) (limited to 'include') diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 2e124e0075c..a9b99c0dc2e 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -221,6 +221,42 @@ struct dentry *debugfs_create_u64(const char *name, mode_t mode, } EXPORT_SYMBOL_GPL(debugfs_create_u64); +DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); + +DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n"); + +DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n"); + +/** + * debugfs_create_x8 - create a debugfs file that is used to read and write an unsigned 8-bit value + * debugfs_create_x16 - create a debugfs file that is used to read and write an unsigned 16-bit value + * debugfs_create_x32 - create a debugfs file that is used to read and write an unsigned 32-bit value + * + * These functions are exactly the same as the above functions, (but use a hex + * output for the decimal challenged) for details look at the above unsigned + * decimal functions. + */ +struct dentry *debugfs_create_x8(const char *name, mode_t mode, + struct dentry *parent, u8 *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_x8); +} +EXPORT_SYMBOL_GPL(debugfs_create_x8); + +struct dentry *debugfs_create_x16(const char *name, mode_t mode, + struct dentry *parent, u16 *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_x16); +} +EXPORT_SYMBOL_GPL(debugfs_create_x16); + +struct dentry *debugfs_create_x32(const char *name, mode_t mode, + struct dentry *parent, u32 *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_x32); +} +EXPORT_SYMBOL_GPL(debugfs_create_x32); + static ssize_t read_file_bool(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 104e51e20e1..f592d6de3b9 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -49,6 +49,12 @@ struct dentry *debugfs_create_u32(const char *name, mode_t mode, struct dentry *parent, u32 *value); struct dentry *debugfs_create_u64(const char *name, mode_t mode, struct dentry *parent, u64 *value); +struct dentry *debugfs_create_x8(const char *name, mode_t mode, + struct dentry *parent, u8 *value); +struct dentry *debugfs_create_x16(const char *name, mode_t mode, + struct dentry *parent, u16 *value); +struct dentry *debugfs_create_x32(const char *name, mode_t mode, + struct dentry *parent, u32 *value); struct dentry *debugfs_create_bool(const char *name, mode_t mode, struct dentry *parent, u32 *value); @@ -122,6 +128,27 @@ static inline struct dentry *debugfs_create_u64(const char *name, mode_t mode, return ERR_PTR(-ENODEV); } +static inline struct dentry *debugfs_create_x8(const char *name, mode_t mode, + struct dentry *parent, + u8 *value) +{ + return ERR_PTR(-ENODEV); +} + +static inline struct dentry *debugfs_create_x16(const char *name, mode_t mode, + struct dentry *parent, + u16 *value) +{ + return ERR_PTR(-ENODEV); +} + +static inline struct dentry *debugfs_create_x32(const char *name, mode_t mode, + struct dentry *parent, + u32 *value) +{ + return ERR_PTR(-ENODEV); +} + static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode, struct dentry *parent, u32 *value) -- cgit v1.2.3-70-g09d2 From 90bc61359de0148f8627073d68a22edc7ed9893d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 31 Jul 2007 19:15:08 +0900 Subject: sysfs: Remove first pass at shadow directory support While shadow directories appear to be a good idea, the current scheme of controlling their creation and destruction outside of sysfs appears to be a locking and maintenance nightmare in the face of sysfs directories dynamically coming and going. Which can now occur for directories containing network devices when CONFIG_SYSFS_DEPRECATED is not set. This patch removes everything from the initial shadow directory support that allowed the shadow directory creation to be controlled at a higher level. So except for a few bits of sysfs_rename_dir everything from commit b592fcfe7f06c15ec11774b5be7ce0de3aa86e73 is now gone. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 167 +++++++----------------------------------------- fs/sysfs/group.c | 1 - fs/sysfs/inode.c | 10 --- fs/sysfs/mount.c | 2 +- fs/sysfs/sysfs.h | 6 -- include/linux/kobject.h | 5 -- include/linux/sysfs.h | 27 ++------ lib/kobject.c | 44 ++----------- 8 files changed, 33 insertions(+), 229 deletions(-) (limited to 'include') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 86d75e08de6..837073dbadf 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -569,9 +569,6 @@ static void sysfs_drop_dentry(struct sysfs_dirent *sd) spin_unlock(&dcache_lock); spin_unlock(&sysfs_assoc_lock); - /* 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 */ @@ -723,19 +720,15 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name, /** * sysfs_create_dir - create a directory for an object. * @kobj: object we're creating directory for. - * @shadow_parent: parent object. */ -int sysfs_create_dir(struct kobject *kobj, - struct sysfs_dirent *shadow_parent_sd) +int sysfs_create_dir(struct kobject * kobj) { struct sysfs_dirent *parent_sd, *sd; int error = 0; BUG_ON(!kobj); - if (shadow_parent_sd) - parent_sd = shadow_parent_sd; - else if (kobj->parent) + if (kobj->parent) parent_sd = kobj->parent->sd; else if (sysfs_mount && sysfs_mount->mnt_sb) parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; @@ -890,45 +883,44 @@ void sysfs_remove_dir(struct kobject * kobj) __sysfs_remove_dir(sd); } -int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, - const char *new_name) +int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { - struct sysfs_dirent *sd = kobj->sd; - struct dentry *new_parent = NULL; + struct sysfs_dirent *sd; + struct dentry *parent = NULL; struct dentry *old_dentry = NULL, *new_dentry = NULL; + struct sysfs_dirent *parent_sd; const char *dup_name = NULL; int error; + if (!kobj->parent) + return -EINVAL; + /* get dentries */ + sd = kobj->sd; 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); + parent_sd = kobj->parent->sd; + parent = sysfs_get_dentry(parent_sd); + if (IS_ERR(parent)) { + error = PTR_ERR(parent); goto out_dput; } - /* lock new_parent and get dentry for new name */ - mutex_lock(&new_parent->d_inode->i_mutex); + /* lock parent and get dentry for new name */ + mutex_lock(&parent->d_inode->i_mutex); - new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); + new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); if (IS_ERR(new_dentry)) { error = PTR_ERR(new_dentry); goto out_unlock; } - /* By allowing two different directories with the same - * d_parent we allow this routine to move between different - * shadows of the same directory - */ error = -EINVAL; - if (old_dentry->d_parent->d_inode != new_parent->d_inode || - new_dentry->d_parent->d_inode != new_parent->d_inode || - old_dentry == new_dentry) + if (old_dentry == new_dentry) goto out_unlock; error = -EEXIST; @@ -955,9 +947,9 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, d_move(sd->s_dentry, new_dentry); sysfs_unlink_sibling(sd); - sysfs_get(new_parent_sd); + sysfs_get(parent_sd); sysfs_put(sd->s_parent); - sd->s_parent = new_parent_sd; + sd->s_parent = parent_sd; sysfs_link_sibling(sd); mutex_unlock(&sysfs_mutex); @@ -968,10 +960,10 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, out_drop: d_drop(new_dentry); out_unlock: - mutex_unlock(&new_parent->d_inode->i_mutex); + mutex_unlock(&parent->d_inode->i_mutex); out_dput: kfree(dup_name); - dput(new_parent); + dput(parent); dput(old_dentry); dput(new_dentry); return error; @@ -1192,121 +1184,6 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) return offset; } - -/** - * sysfs_make_shadowed_dir - Setup so a directory can be shadowed - * @kobj: object we're creating shadow of. - */ - -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; - - /* 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) - return -ENOMEM; - - memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op)); - i_op->follow_link = follow_link; - - /* Locking of inode->i_op? - * Since setting i_op is a single word write and they - * are atomic we should be ok here. - */ - inode->i_op = i_op; - return 0; -} - -/** - * sysfs_create_shadow_dir - create a shadow directory for an object. - * @kobj: object we're creating directory for. - * - * sysfs_make_shadowed_dir must already have been called on this - * directory. - */ - -struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) -{ - 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_dput; - - shadow = d_alloc(parent, &dir->d_name); - if (!shadow) - goto nomem; - - sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR); - if (!sd) - goto nomem; - sd->s_elem.dir.kobj = kobj; - - sysfs_addrm_start(&acxt, parent_sd); - - /* add but don't link into children list */ - sysfs_add_one(&acxt, sd); - - /* attach and instantiate dentry */ - sysfs_attach_dentry(sd, shadow); - d_instantiate(shadow, igrab(inode)); - inc_nlink(inode); /* tj: synchronization? */ - - sysfs_addrm_finish(&acxt); - - dget(shadow); /* Extra count - pin the dentry in core */ - - goto out_dput; - - nomem: - dput(shadow); - sd = ERR_PTR(-ENOMEM); - out_dput: - dput(dir); - out: - return sd; -} - -/** - * sysfs_remove_shadow_dir - remove an object's 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 sysfs_dirent *shadow_sd) -{ - __sysfs_remove_dir(shadow_sd); -} - const struct file_operations sysfs_dir_operations = { .open = sysfs_dir_open, .release = sysfs_dir_close, diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index e6b904d7163..d1972374655 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "sysfs.h" diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index aecb6e771e2..45128b79bc6 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -33,16 +33,6 @@ static const struct inode_operations sysfs_inode_operations ={ .setattr = sysfs_setattr, }; -void sysfs_delete_inode(struct inode *inode) -{ - /* Free the shadowed directory inode operations */ - if (sysfs_is_shadowed_inode(inode)) { - kfree(inode->i_op); - inode->i_op = NULL; - } - return generic_delete_inode(inode); -} - int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) { struct inode * inode = dentry->d_inode; diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 69a73ae307f..119f39da1ae 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -20,7 +20,7 @@ struct kmem_cache *sysfs_dir_cachep; static const struct super_operations sysfs_ops = { .statfs = simple_statfs, - .drop_inode = sysfs_delete_inode, + .drop_inode = generic_delete_inode, }; struct sysfs_dirent sysfs_root = { diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6b8c8d76d30..b55e510ea23 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -70,7 +70,6 @@ extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); -extern void sysfs_delete_inode(struct inode *inode); extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); @@ -121,8 +120,3 @@ static inline void sysfs_put(struct sysfs_dirent * sd) if (sd && atomic_dec_and_test(&sd->s_count)) release_sysfs_dirent(sd); } - -static inline int sysfs_is_shadowed_inode(struct inode *inode) -{ - return S_ISDIR(inode->i_mode) && inode->i_op->follow_link; -} diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 8b45946e850..56f5eaf10ea 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -84,14 +84,9 @@ 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 *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 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 be8228e50a2..c16e4c51162 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -17,9 +17,6 @@ struct kobject; struct module; -struct nameidata; -struct dentry; -struct sysfs_dirent; /* FIXME * The *owner field is no longer used, but leave around @@ -94,14 +91,13 @@ 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 *kobj, struct sysfs_dirent *shadow_parent_sd); +sysfs_create_dir(struct kobject *); extern void sysfs_remove_dir(struct kobject *); extern int __must_check -sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, - const char *new_name); +sysfs_rename_dir(struct kobject *kobj, const char *new_name); extern int __must_check sysfs_move_dir(struct kobject *, struct kobject *); @@ -138,12 +134,6 @@ void sysfs_remove_file_from_group(struct kobject *kobj, 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 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); #else /* CONFIG_SYSFS */ @@ -154,8 +144,7 @@ static inline int sysfs_schedule_callback(struct kobject *kobj, return -ENOSYS; } -static inline int sysfs_create_dir(struct kobject *kobj, - struct sysfs_dirent *shadow_parent_sd) +static inline int sysfs_create_dir(struct kobject * kobj) { return 0; } @@ -165,9 +154,7 @@ static inline void sysfs_remove_dir(struct kobject * k) ; } -static inline int sysfs_rename_dir(struct kobject *kobj, - struct sysfs_dirent *new_parent_sd, - const char *new_name) +static inline int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { return 0; } @@ -242,12 +229,6 @@ static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) { } -static inline int sysfs_make_shadowed_dir(struct kobject *kobj, - void * (*follow_link)(struct dentry *, struct nameidata *)) -{ - return 0; -} - static inline int __must_check sysfs_init(void) { return 0; diff --git a/lib/kobject.c b/lib/kobject.c index 10ae2ebeaf9..e8181d3cec3 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -44,11 +44,11 @@ static int populate_dir(struct kobject * kobj) return error; } -static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent) +static int create_dir(struct kobject * kobj) { int error = 0; if (kobject_name(kobj)) { - error = sysfs_create_dir(kobj, shadow_parent); + error = sysfs_create_dir(kobj); if (!error) { if ((error = populate_dir(kobj))) sysfs_remove_dir(kobj); @@ -157,12 +157,11 @@ static void unlink(struct kobject * kobj) } /** - * kobject_shadow_add - add an object to the hierarchy. + * kobject_add - add an object to the hierarchy. * @kobj: object. - * @shadow_parent: sysfs directory to add to. */ -int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) +int kobject_add(struct kobject * kobj) { int error = 0; struct kobject * parent; @@ -194,7 +193,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) kobj->parent = parent; } - error = create_dir(kobj, shadow_parent); + error = create_dir(kobj); if (error) { /* unlink does the kobject_put() for us */ unlink(kobj); @@ -215,16 +214,6 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) return error; } -/** - * kobject_add - add an object to the hierarchy. - * @kobj: object. - */ -int kobject_add(struct kobject * kobj) -{ - return kobject_shadow_add(kobj, NULL); -} - - /** * kobject_register - initialize and add an object. * @kobj: object in question. @@ -334,7 +323,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->sd, new_name); + error = sysfs_rename_dir(kobj, new_name); /* This function is mostly/only used for network interface. * Some hotplug package track interfaces by their name and @@ -350,27 +339,6 @@ out: return error; } -/** - * kobject_rename - change the name of an object - * @kobj: object in question. - * @new_parent: object's new parent - * @new_name: object's new name - */ - -int kobject_shadow_rename(struct kobject *kobj, - struct sysfs_dirent *new_parent, const char *new_name) -{ - int error = 0; - - kobj = kobject_get(kobj); - if (!kobj) - return -EINVAL; - error = sysfs_rename_dir(kobj, new_parent, new_name); - kobject_put(kobj); - - return error; -} - /** * kobject_move - move object to another parent * @kobj: object in question. -- cgit v1.2.3-70-g09d2 From 60043428a561a5d431ad479b7ecb79805ed04efc Mon Sep 17 00:00:00 2001 From: "tonyj@suse.de" Date: Tue, 7 Aug 2007 22:28:47 -0700 Subject: Convert from class_device to device for drivers/video Convert from class_device to device for drivers/video. Signed-off-by: Tony Jones Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/video.c | 4 ++-- drivers/video/output.c | 29 ++++++++++++++++------------- include/linux/video_output.h | 4 ++-- 3 files changed, 20 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index d05891f1628..b8a2095cb5e 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -316,7 +316,7 @@ static int acpi_video_output_get(struct output_device *od) { unsigned long state; struct acpi_video_device *vd = - (struct acpi_video_device *)class_get_devdata(&od->class_dev); + (struct acpi_video_device *)dev_get_drvdata(&od->dev); acpi_video_device_get_state(vd, &state); return (int)state; } @@ -325,7 +325,7 @@ static int acpi_video_output_set(struct output_device *od) { unsigned long state = od->request_state; struct acpi_video_device *vd= - (struct acpi_video_device *)class_get_devdata(&od->class_dev); + (struct acpi_video_device *)dev_get_drvdata(&od->dev); return acpi_video_device_set_state(vd, state); } diff --git a/drivers/video/output.c b/drivers/video/output.c index 1473f2c892d..f2df5519c9c 100644 --- a/drivers/video/output.c +++ b/drivers/video/output.c @@ -31,7 +31,8 @@ MODULE_DESCRIPTION("Display Output Switcher Lowlevel Control Abstraction"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luming Yu "); -static ssize_t video_output_show_state(struct class_device *dev,char *buf) +static ssize_t video_output_show_state(struct device *dev, + struct device_attribute *attr, char *buf) { ssize_t ret_size = 0; struct output_device *od = to_output_device(dev); @@ -40,8 +41,9 @@ static ssize_t video_output_show_state(struct class_device *dev,char *buf) return ret_size; } -static ssize_t video_output_store_state(struct class_device *dev, - const char *buf,size_t count) +static ssize_t video_output_store_state(struct device *dev, + struct device_attribute *attr, + const char *buf,size_t count) { char *endp; struct output_device *od = to_output_device(dev); @@ -60,21 +62,22 @@ static ssize_t video_output_store_state(struct class_device *dev, return count; } -static void video_output_class_release(struct class_device *dev) +static void video_output_release(struct device *dev) { struct output_device *od = to_output_device(dev); kfree(od); } -static struct class_device_attribute video_output_attributes[] = { +static struct device_attribute video_output_attributes[] = { __ATTR(state, 0644, video_output_show_state, video_output_store_state), __ATTR_NULL, }; + static struct class video_output_class = { .name = "video_output", - .release = video_output_class_release, - .class_dev_attrs = video_output_attributes, + .dev_release = video_output_release, + .dev_attrs = video_output_attributes, }; struct output_device *video_output_register(const char *name, @@ -91,11 +94,11 @@ struct output_device *video_output_register(const char *name, goto error_return; } new_dev->props = op; - new_dev->class_dev.class = &video_output_class; - new_dev->class_dev.dev = dev; - strlcpy(new_dev->class_dev.class_id,name,KOBJ_NAME_LEN); - class_set_devdata(&new_dev->class_dev,devdata); - ret_code = class_device_register(&new_dev->class_dev); + new_dev->dev.class = &video_output_class; + new_dev->dev.parent = dev; + strlcpy(new_dev->dev.bus_id,name, BUS_ID_SIZE); + dev_set_drvdata(&new_dev->dev, devdata); + ret_code = device_register(&new_dev->dev); if (ret_code) { kfree(new_dev); goto error_return; @@ -111,7 +114,7 @@ void video_output_unregister(struct output_device *dev) { if (!dev) return; - class_device_unregister(&dev->class_dev); + device_unregister(&dev->dev); } EXPORT_SYMBOL(video_output_unregister); diff --git a/include/linux/video_output.h b/include/linux/video_output.h index e63e0c03ee0..2fb46bc9340 100644 --- a/include/linux/video_output.h +++ b/include/linux/video_output.h @@ -31,9 +31,9 @@ struct output_properties { struct output_device { int request_state; struct output_properties *props; - struct class_device class_dev; + struct device dev; }; -#define to_output_device(obj) container_of(obj, struct output_device, class_dev) +#define to_output_device(obj) container_of(obj, struct output_device, dev) struct output_device *video_output_register(const char *name, struct device *dev, void *devdata, -- cgit v1.2.3-70-g09d2 From 5c5daf657cb5f963a38413f2852279d7a3843144 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 12 Aug 2007 20:43:55 +0200 Subject: Driver core: exclude kobject_uevent.c for !CONFIG_HOTPLUG Move uevent specific logic from the core into kobject_uevent.c, which does no longer require to link the unused string array if hotplug is not compiled in. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 18 ++++------------ include/linux/kobject.h | 10 ++++++--- lib/Makefile | 3 ++- lib/kobject_uevent.c | 57 ++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 57 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/drivers/base/core.c b/drivers/base/core.c index d487c032dc4..65de221e3bf 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -234,13 +234,11 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, /* search the kset, the device belongs to */ top_kobj = &dev->kobj; - if (!top_kobj->kset && top_kobj->parent) { - do { - top_kobj = top_kobj->parent; - } while (!top_kobj->kset && top_kobj->parent); - } + while (!top_kobj->kset && top_kobj->parent) + top_kobj = top_kobj->parent; if (!top_kobj->kset) goto out; + kset = top_kobj->kset; if (!kset->uevent_ops || !kset->uevent_ops->uevent) goto out; @@ -270,17 +268,9 @@ out: static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - size_t len = count; enum kobject_action action; - if (len && buf[len-1] == '\n') - len--; - - for (action = 0; action < KOBJ_MAX; action++) { - if (strncmp(kobject_actions[action], buf, len) != 0) - continue; - if (kobject_actions[action][len] != '\0') - continue; + if (kobject_action_type(buf, count, &action) == 0) { kobject_uevent(&dev->kobj, action); goto out; } diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 56f5eaf10ea..0777b3f57ae 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -58,9 +58,6 @@ enum kobject_action { KOBJ_MAX }; -/* The list of strings defining the valid kobject actions as specified above */ -extern const char *kobject_actions[]; - struct kobject { const char * k_name; struct kref kref; @@ -241,6 +238,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) __attribute__((format (printf, 2, 3))); + +int kobject_action_type(const char *buf, size_t count, + enum kobject_action *type); #else static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action) { return 0; } @@ -251,6 +251,10 @@ static inline int kobject_uevent_env(struct kobject *kobj, static inline int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) { return 0; } + +static inline int kobject_action_type(const char *buf, size_t count, + enum kobject_action *type) +{ return -EINVAL; } #endif #endif /* __KERNEL__ */ diff --git a/lib/Makefile b/lib/Makefile index 4f3f3e25650..6c4ea33bb2c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -10,7 +10,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o -lib-y += kobject.o kref.o kobject_uevent.o klist.o +lib-y += kobject.o kref.o klist.o obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ bust_spinlocks.o hexdump.o kasprintf.o @@ -20,6 +20,7 @@ CFLAGS_kobject.o += -DDEBUG CFLAGS_kobject_uevent.o += -DDEBUG endif +lib-$(CONFIG_HOTPLUG) += kobject_uevent.o obj-$(CONFIG_GENERIC_IOMAP) += iomap.o obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 5ccda460262..a8efb48dca5 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -23,17 +23,6 @@ #include -/* the strings here must match the enum in include/linux/kobject.h */ -const char *kobject_actions[] = { - "add", - "remove", - "change", - "move", - "online", - "offline", -}; - -#if defined(CONFIG_HOTPLUG) u64 uevent_seqnum; char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; static DEFINE_SPINLOCK(sequence_lock); @@ -41,6 +30,50 @@ static DEFINE_SPINLOCK(sequence_lock); static struct sock *uevent_sock; #endif +/* the strings here must match the enum in include/linux/kobject.h */ +static const char *kobject_actions[] = { + [KOBJ_ADD] = "add", + [KOBJ_REMOVE] = "remove", + [KOBJ_CHANGE] = "change", + [KOBJ_MOVE] = "move", + [KOBJ_ONLINE] = "online", + [KOBJ_OFFLINE] = "offline", +}; + +/** + * kobject_action_type - translate action string to numeric type + * + * @buf: buffer containing the action string, newline is ignored + * @len: length of buffer + * @type: pointer to the location to store the action type + * + * Returns 0 if the action string was recognized. + */ +int kobject_action_type(const char *buf, size_t count, + enum kobject_action *type) +{ + enum kobject_action action; + int ret = -EINVAL; + + if (count && buf[count-1] == '\n') + count--; + + if (!count) + goto out; + + for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) { + if (strncmp(kobject_actions[action], buf, count) != 0) + continue; + if (kobject_actions[action][count] != '\0') + continue; + *type = action; + ret = 0; + break; + } +out: + return ret; +} + /** * kobject_uevent_env - send an uevent with environmental data * @@ -270,5 +303,3 @@ static int __init kobject_uevent_init(void) postcore_initcall(kobject_uevent_init); #endif - -#endif /* CONFIG_HOTPLUG */ -- cgit v1.2.3-70-g09d2 From 1359555eb77d240b7c1d7ee75bb07e89e89770e4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 9 Sep 2007 12:54:16 +0200 Subject: Driver core: Make platform_device.id an int While platform_device.id is a u32, platform_device_add() handles "-1" as a special id value. This has potential for confusion and bugs. Making it an int instead should prevent problems from happening in the future. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 7 ++++--- include/linux/platform_device.h | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index a2e3910196e..fb560924148 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -161,7 +161,7 @@ static void platform_device_release(struct device *dev) * Create a platform device object which can have other objects attached * to it, and which will have attached objects freed when it is released. */ -struct platform_device *platform_device_alloc(const char *name, unsigned int id) +struct platform_device *platform_device_alloc(const char *name, int id) { struct platform_object *pa; @@ -245,7 +245,8 @@ int platform_device_add(struct platform_device *pdev) pdev->dev.bus = &platform_bus_type; if (pdev->id != -1) - snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id); + snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name, + pdev->id); else strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE); @@ -359,7 +360,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); * the Linux driver model. In particular, when such drivers are built * as modules, they can't be "hotplugged". */ -struct platform_device *platform_device_register_simple(char *name, unsigned int id, +struct platform_device *platform_device_register_simple(char *name, int id, struct resource *res, unsigned int num) { struct platform_device *pdev; diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 8bbd459eafd..e80804316cd 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -15,7 +15,7 @@ struct platform_device { const char * name; - u32 id; + int id; struct device dev; u32 num_resources; struct resource * resource; @@ -35,9 +35,10 @@ extern struct resource *platform_get_resource_byname(struct platform_device *, u extern int platform_get_irq_byname(struct platform_device *, char *); extern int platform_add_devices(struct platform_device **, int); -extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int); +extern struct platform_device *platform_device_register_simple(char *, int id, + struct resource *, unsigned int); -extern struct platform_device *platform_device_alloc(const char *name, unsigned int id); +extern struct platform_device *platform_device_alloc(const char *name, int id); extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num); extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size); extern int platform_device_add(struct platform_device *pdev); -- cgit v1.2.3-70-g09d2 From dc8c85871c9728c5fddca6854a191fd41eb9438c Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Wed, 15 Aug 2007 12:25:38 +0200 Subject: PTY: add kernel parameter to overwrite legacy pty count Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 4 ++++ drivers/char/pty.c | 9 +++++++-- include/linux/tty.h | 1 - 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index a57c1f216b2..bdddd3cd46d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1430,6 +1430,10 @@ and is between 256 and 4096 characters. It is defined in the file pt. [PARIDE] See Documentation/paride.txt. + pty.legacy_count= + [KNL] Number of legacy pty's. Overwrites compiled-in + default number. + quiet [KNL] Disable most log messages r128= [HW,DRM] diff --git a/drivers/char/pty.c b/drivers/char/pty.c index de14aea34e1..73de77105fe 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -248,14 +248,19 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, return -ENOIOCTLCMD; } +static int legacy_count = CONFIG_LEGACY_PTY_COUNT; +module_param(legacy_count, int, 0); + static void __init legacy_pty_init(void) { + if (legacy_count <= 0) + return; - pty_driver = alloc_tty_driver(NR_PTYS); + pty_driver = alloc_tty_driver(legacy_count); if (!pty_driver) panic("Couldn't allocate pty driver"); - pty_slave_driver = alloc_tty_driver(NR_PTYS); + pty_slave_driver = alloc_tty_driver(legacy_count); if (!pty_slave_driver) panic("Couldn't allocate pty slave driver"); diff --git a/include/linux/tty.h b/include/linux/tty.h index 6570719eafd..60478f6e5dc 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -21,7 +21,6 @@ * (Note: the *_driver.minor_start values 1, 64, 128, 192 are * hardcoded at present.) */ -#define NR_PTYS CONFIG_LEGACY_PTY_COUNT /* Number of legacy ptys */ #define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */ #define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */ #define NR_LDISCS 17 -- cgit v1.2.3-70-g09d2 From 59f69015684b3de7b9472be9a81b1a978f93a496 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 16:05:10 +0900 Subject: sysfs: clean up header files sysfs is about to go through major overhaul making this a pretty good opportunity to clean up (out-of-tree changes and pending patches will need regeneration anyway). Clean up headers. * Kill space between * and symbolname. * Move SYSFS_* type constants and flags into fs/sysfs/sysfs.h. They're internal to sysfs. * Reformat function prototypes and add argument symbol names. * Make dummy function definition order match that of function prototypes. * Add some comments. * Reorganize fs/sysfs/sysfs.h according to which file the declared variable or feature lives in. This patch does not introduce any behavior change. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/sysfs.h | 148 +++++++++++++++++++++++++++++++------------------- include/linux/sysfs.h | 127 +++++++++++++++++++------------------------ 2 files changed, 149 insertions(+), 126 deletions(-) (limited to 'include') diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 791b3ed91a9..63adbecc9ba 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -1,20 +1,24 @@ +/* type-specific structures for sysfs_dirent->s_* union members */ struct sysfs_elem_dir { - struct kobject * kobj; + struct kobject *kobj; }; struct sysfs_elem_symlink { - struct sysfs_dirent * target_sd; + struct sysfs_dirent *target_sd; }; struct sysfs_elem_attr { - struct attribute * attr; + struct attribute *attr; }; struct sysfs_elem_bin_attr { - struct bin_attribute * bin_attr; + struct bin_attribute *bin_attr; }; /* + * sysfs_dirent - the building block of sysfs hierarchy. Each and + * every sysfs node is represented by single sysfs_dirent. + * * As long as s_count reference is held, the sysfs_dirent itself is * accessible. Dereferencing s_elem or any other outer entity * requires s_active reference. @@ -22,10 +26,10 @@ struct sysfs_elem_bin_attr { struct sysfs_dirent { atomic_t s_count; atomic_t s_active; - struct sysfs_dirent * s_parent; - struct sysfs_dirent * s_sibling; - struct sysfs_dirent * s_children; - const char * s_name; + struct sysfs_dirent *s_parent; + struct sysfs_dirent *s_sibling; + struct sysfs_dirent *s_children; + const char *s_name; union { struct sysfs_elem_dir dir; @@ -37,12 +41,31 @@ struct sysfs_dirent { unsigned int s_flags; umode_t s_mode; ino_t s_ino; - struct iattr * s_iattr; + struct iattr *s_iattr; atomic_t s_event; }; -#define SD_DEACTIVATED_BIAS INT_MIN +#define SD_DEACTIVATED_BIAS INT_MIN +#define SYSFS_TYPE_MASK 0x00ff +#define SYSFS_ROOT 0x0001 +#define SYSFS_DIR 0x0002 +#define SYSFS_KOBJ_ATTR 0x0004 +#define SYSFS_KOBJ_BIN_ATTR 0x0008 +#define SYSFS_KOBJ_LINK 0x0020 +#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) + +#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK +#define SYSFS_FLAG_REMOVED 0x0200 + +static inline unsigned int sysfs_type(struct sysfs_dirent *sd) +{ + return sd->s_flags & SYSFS_TYPE_MASK; +} + +/* + * Context structure to be used while adding/removing nodes. + */ struct sysfs_addrm_cxt { struct sysfs_dirent *parent_sd; struct inode *parent_inode; @@ -50,59 +73,47 @@ struct sysfs_addrm_cxt { int cnt; }; +/* + * mount.c + */ extern struct sysfs_dirent sysfs_root; +extern struct super_block *sysfs_sb; extern struct kmem_cache *sysfs_dir_cachep; -extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); -extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); -extern void sysfs_put_active(struct sysfs_dirent *sd); -extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); -extern void sysfs_put_active_two(struct sysfs_dirent *sd); -extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, - struct sysfs_dirent *parent_sd); -extern int sysfs_add_one(struct sysfs_addrm_cxt *acxt, - struct sysfs_dirent *sd); -extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, - struct sysfs_dirent *sd); -extern void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); - -extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); - -extern void release_sysfs_dirent(struct sysfs_dirent * sd); -extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, - const unsigned char *name); -extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, - const unsigned char *name); -extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, - int type); - -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 *kobj, const char *name, - struct sysfs_dirent **p_sd); -extern void sysfs_remove_subdir(struct sysfs_dirent *sd); - -extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); - -extern spinlock_t sysfs_assoc_lock; +/* + * dir.c + */ extern struct mutex sysfs_mutex; extern struct mutex sysfs_rename_mutex; -extern struct super_block * sysfs_sb; +extern spinlock_t sysfs_assoc_lock; + extern const struct file_operations sysfs_dir_operations; -extern const struct file_operations sysfs_file_operations; -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) +struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); +struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); +void sysfs_put_active(struct sysfs_dirent *sd); +struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); +void sysfs_put_active_two(struct sysfs_dirent *sd); +void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, + struct sysfs_dirent *parent_sd); +int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); +void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); +void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); + +struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, + const unsigned char *name); +struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, + const unsigned char *name); +struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); + +void release_sysfs_dirent(struct sysfs_dirent *sd); + +int sysfs_create_subdir(struct kobject *kobj, const char *name, + struct sysfs_dirent **p_sd); +void sysfs_remove_subdir(struct sysfs_dirent *sd); + +static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd) { if (sd) { WARN_ON(!atomic_read(&sd->s_count)); @@ -111,8 +122,33 @@ static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) return sd; } -static inline void sysfs_put(struct sysfs_dirent * sd) +static inline void sysfs_put(struct sysfs_dirent *sd) { if (sd && atomic_dec_and_test(&sd->s_count)) release_sysfs_dirent(sd); } + +/* + * inode.c + */ +struct inode *sysfs_get_inode(struct sysfs_dirent *sd); +int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); +int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); + +/* + * file.c + */ +extern const struct file_operations sysfs_file_operations; + +int sysfs_add_file(struct sysfs_dirent *dir_sd, + const struct attribute *attr, int type); + +/* + * bin.c + */ +extern const struct file_operations bin_fops; + +/* + * symlink.c + */ +extern const struct inode_operations sysfs_symlink_inode_operations; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index c16e4c51162..b393bb44962 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -23,14 +23,14 @@ struct module; * until the tree gets cleaned up fully. */ struct attribute { - const char * name; - struct module * owner; + const char *name; + struct module *owner; mode_t mode; }; struct attribute_group { - const char * name; - struct attribute ** attrs; + const char *name; + struct attribute **attrs; }; @@ -74,65 +74,43 @@ 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 -#define SYSFS_KOBJ_BIN_ATTR 0x0008 -#define SYSFS_KOBJ_LINK 0x0020 -#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) - -#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK -#define SYSFS_FLAG_REMOVED 0x0100 - #ifdef CONFIG_SYSFS -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 *); - -extern void -sysfs_remove_dir(struct kobject *); - -extern int __must_check -sysfs_rename_dir(struct kobject *kobj, const char *new_name); - -extern int __must_check -sysfs_move_dir(struct kobject *, struct kobject *); - -extern int __must_check -sysfs_create_file(struct kobject *, const struct attribute *); - -extern int __must_check -sysfs_update_file(struct kobject *, const struct attribute *); +int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), + void *data, struct module *owner); -extern int __must_check -sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode); +int __must_check sysfs_create_dir(struct kobject *kobj); +void sysfs_remove_dir(struct kobject *kobj); +int __must_check sysfs_rename_dir(struct kobject *kobj, const char *new_name); +int __must_check sysfs_move_dir(struct kobject *kobj, + struct kobject *new_parent_kobj); -extern void -sysfs_remove_file(struct kobject *, const struct attribute *); - -extern int __must_check -sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name); - -extern void -sysfs_remove_link(struct kobject *, const char * name); +int __must_check sysfs_create_file(struct kobject *kobj, + const struct attribute *attr); +int __must_check sysfs_update_file(struct kobject *kobj, + const struct attribute *attr); +int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, + mode_t mode); +void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); int __must_check sysfs_create_bin_file(struct kobject *kobj, - struct bin_attribute *attr); + struct bin_attribute *attr); void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); -int __must_check sysfs_create_group(struct kobject *, - const struct attribute_group *); -void sysfs_remove_group(struct kobject *, const struct attribute_group *); +int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target, + const char *name); +void sysfs_remove_link(struct kobject *kobj, const char *name); + +int __must_check sysfs_create_group(struct kobject *kobj, + const struct attribute_group *grp); +void sysfs_remove_group(struct kobject *kobj, + const struct attribute_group *grp); int sysfs_add_file_to_group(struct kobject *kobj, - const struct attribute *attr, const char *group); + const struct attribute *attr, const char *group); void sysfs_remove_file_from_group(struct kobject *kobj, - const struct attribute *attr, const char *group); + const struct attribute *attr, const char *group); -void sysfs_notify(struct kobject * k, char *dir, char *attr); +void sysfs_notify(struct kobject *kobj, char *dir, char *attr); extern int __must_check sysfs_init(void); @@ -144,72 +122,81 @@ static inline int sysfs_schedule_callback(struct kobject *kobj, return -ENOSYS; } -static inline int sysfs_create_dir(struct kobject * kobj) +static inline int sysfs_create_dir(struct kobject *kobj) { return 0; } -static inline void sysfs_remove_dir(struct kobject * k) +static inline void sysfs_remove_dir(struct kobject *kobj) { ; } -static inline int sysfs_rename_dir(struct kobject * kobj, const char *new_name) +static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name) { return 0; } -static inline int sysfs_move_dir(struct kobject * k, struct kobject * new_parent) +static inline int sysfs_move_dir(struct kobject *kobj, + struct kobject *new_parent_kobj) { return 0; } -static inline int sysfs_create_file(struct kobject * k, const struct attribute * a) +static inline int sysfs_create_file(struct kobject *kobj, + const struct attribute *attr) { return 0; } -static inline int sysfs_update_file(struct kobject * k, const struct attribute * a) +static inline int sysfs_update_file(struct kobject *kobj, + const struct attribute *attr) { return 0; } -static inline int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) +static inline int sysfs_chmod_file(struct kobject *kobj, + struct attribute *attr, mode_t mode) { return 0; } -static inline void sysfs_remove_file(struct kobject * k, const struct attribute * a) +static inline void sysfs_remove_file(struct kobject *kobj, + const struct attribute *attr) { ; } -static inline int sysfs_create_link(struct kobject * k, struct kobject * t, const char * n) +static inline int sysfs_create_bin_file(struct kobject *kobj, + struct bin_attribute *attr) { return 0; } -static inline void sysfs_remove_link(struct kobject * k, const char * name) +static inline int sysfs_remove_bin_file(struct kobject *kobj, + struct bin_attribute *attr) { - ; + return 0; } - -static inline int sysfs_create_bin_file(struct kobject * k, struct bin_attribute * a) +static inline int sysfs_create_link(struct kobject *kobj, + struct kobject *target, const char *name) { return 0; } -static inline int sysfs_remove_bin_file(struct kobject * k, struct bin_attribute * a) +static inline void sysfs_remove_link(struct kobject *kobj, const char *name) { - return 0; + ; } -static inline int sysfs_create_group(struct kobject * k, const struct attribute_group *g) +static inline int sysfs_create_group(struct kobject *kobj, + const struct attribute_group *grp) { return 0; } -static inline void sysfs_remove_group(struct kobject * k, const struct attribute_group * g) +static inline void sysfs_remove_group(struct kobject *kobj, + const struct attribute_group *grp) { ; } @@ -225,7 +212,7 @@ static inline void sysfs_remove_file_from_group(struct kobject *kobj, { } -static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) +static inline void sysfs_notify(struct kobject *kobj, char *dir, char *attr) { } -- cgit v1.2.3-70-g09d2 From 5a7ad7f044941316dc98eda2a087a12a7a50649d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 16:05:10 +0900 Subject: sysfs: kill sysfs_update_file() sysfs_update_file() depends on inode->i_mtime but sysfs iondes are now reclaimable making the reported modification time unreliable. There's only one user (pci hotplug) of this notification mechanism and it reportedly isn't utilized from userland. Kill sysfs_update_file(). Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pci_hotplug_core.c | 60 ---------------------------------- fs/sysfs/file.c | 40 ----------------------- include/linux/sysfs.h | 7 ---- 3 files changed, 107 deletions(-) (limited to 'include') diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index bd433ef6bfc..f0eba534f80 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -694,66 +694,6 @@ int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot, if ((slot == NULL) || (info == NULL)) return -ENODEV; - /* - * check all fields in the info structure, and update timestamps - * for the files referring to the fields that have now changed. - */ - if ((has_power_file(slot) == 0) && - (slot->info->power_status != info->power_status)) { - retval = sysfs_update_file(&slot->kobj, - &hotplug_slot_attr_power.attr); - if (retval) - return retval; - } - - if ((has_attention_file(slot) == 0) && - (slot->info->attention_status != info->attention_status)) { - retval = sysfs_update_file(&slot->kobj, - &hotplug_slot_attr_attention.attr); - if (retval) - return retval; - } - - if ((has_latch_file(slot) == 0) && - (slot->info->latch_status != info->latch_status)) { - retval = sysfs_update_file(&slot->kobj, - &hotplug_slot_attr_latch.attr); - if (retval) - return retval; - } - - if ((has_adapter_file(slot) == 0) && - (slot->info->adapter_status != info->adapter_status)) { - retval = sysfs_update_file(&slot->kobj, - &hotplug_slot_attr_presence.attr); - if (retval) - return retval; - } - - if ((has_address_file(slot) == 0) && - (slot->info->address != info->address)) { - retval = sysfs_update_file(&slot->kobj, - &hotplug_slot_attr_address.attr); - if (retval) - return retval; - } - - if ((has_max_bus_speed_file(slot) == 0) && - (slot->info->max_bus_speed != info->max_bus_speed)) { - retval = sysfs_update_file(&slot->kobj, - &hotplug_slot_attr_max_bus_speed.attr); - if (retval) - return retval; - } - - if ((has_cur_bus_speed_file(slot) == 0) && - (slot->info->cur_bus_speed != info->cur_bus_speed)) { - retval = sysfs_update_file(&slot->kobj, - &hotplug_slot_attr_cur_bus_speed.attr); - if (retval) - return retval; - } - memcpy (slot->info, info, sizeof (struct hotplug_slot_info)); return 0; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 9fdf8dae0dc..61a8c19df7c 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -3,7 +3,6 @@ */ #include -#include #include #include #include @@ -453,44 +452,6 @@ int sysfs_add_file_to_group(struct kobject *kobj, } EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); - -/** - * sysfs_update_file - update the modified timestamp on an object attribute. - * @kobj: object we're acting for. - * @attr: attribute descriptor. - */ -int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) -{ - 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; - - mutex_lock(&sysfs_rename_mutex); - victim = sysfs_get_dentry(victim_sd); - mutex_unlock(&sysfs_rename_mutex); - if (IS_ERR(victim)) { - rc = PTR_ERR(victim); - victim = NULL; - goto out; - } - - 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; -} - - /** * sysfs_chmod_file - update the modified mode value on an object attribute. * @kobj: object we're acting for. @@ -641,4 +602,3 @@ EXPORT_SYMBOL_GPL(sysfs_schedule_callback); EXPORT_SYMBOL_GPL(sysfs_create_file); EXPORT_SYMBOL_GPL(sysfs_remove_file); -EXPORT_SYMBOL_GPL(sysfs_update_file); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index b393bb44962..db5dd2403d0 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -87,8 +87,6 @@ int __must_check sysfs_move_dir(struct kobject *kobj, int __must_check sysfs_create_file(struct kobject *kobj, const struct attribute *attr); -int __must_check sysfs_update_file(struct kobject *kobj, - const struct attribute *attr); int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode); void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); @@ -149,11 +147,6 @@ static inline int sysfs_create_file(struct kobject *kobj, return 0; } -static inline int sysfs_update_file(struct kobject *kobj, - const struct attribute *attr) -{ - return 0; -} static inline int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { -- cgit v1.2.3-70-g09d2 From a4e8b912541d5372ae049a3b7c1979968e52c40b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 16:05:12 +0900 Subject: sysfs: move sysfs file poll implementation to sysfs_open_dirent Sysfs file poll implementation is scattered over sysfs and kobject. Event numbering is done in sysfs_dirent but wait itself is done on kobject. This not only unecessarily bloats both kobject and sysfs_dirent but is also buggy - if a sysfs_dirent is removed while there still are pollers, the associaton betwen the kobject and sysfs_dirent breaks and kobject may be freed with the pollers still sleeping on it. This patch moves whole poll implementation into sysfs_open_dirent. Each time a sysfs_open_dirent is created, event number restarts from 1 and pollers sleep on sysfs_open_dirent. As event sequence number is meaningless without any open file and pollers should have open file and thus sysfs_open_dirent, this ephemeral event counting works and is a saner implementation. This patch fixes the dnagling sleepers bug and reduces the sizes of kobject and sysfs_dirent by one pointer. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 1 - fs/sysfs/file.c | 25 +++++++++++++++++++------ fs/sysfs/sysfs.h | 1 - include/linux/kobject.h | 1 - lib/kobject.c | 1 - 5 files changed, 19 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 4ad9422566a..e301a1207b6 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -318,7 +318,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) atomic_set(&sd->s_count, 1); atomic_set(&sd->s_active, 0); - atomic_set(&sd->s_event, 1); sd->s_name = name; sd->s_mode = mode; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index b13ba94cf8a..c05f9618b2d 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -62,6 +62,8 @@ static spinlock_t sysfs_open_dirent_lock = SPIN_LOCK_UNLOCKED; struct sysfs_open_dirent { atomic_t refcnt; + atomic_t event; + wait_queue_head_t poll; struct list_head buffers; /* goes through sysfs_buffer.list */ }; @@ -104,7 +106,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer if (!sysfs_get_active_two(attr_sd)) return -ENODEV; - buffer->event = atomic_read(&attr_sd->s_event); + buffer->event = atomic_read(&attr_sd->s_attr.open->event); count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page); sysfs_put_active_two(attr_sd); @@ -301,6 +303,8 @@ static int sysfs_get_open_dirent(struct sysfs_dirent *sd, return -ENOMEM; atomic_set(&new_od->refcnt, 0); + atomic_set(&new_od->event, 1); + init_waitqueue_head(&new_od->poll); INIT_LIST_HEAD(&new_od->buffers); goto retry; } @@ -443,17 +447,17 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait) { struct sysfs_buffer * buffer = filp->private_data; struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; - struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; + struct sysfs_open_dirent *od = attr_sd->s_attr.open; /* need parent for the kobj, grab both */ if (!sysfs_get_active_two(attr_sd)) goto trigger; - poll_wait(filp, &kobj->poll, wait); + poll_wait(filp, &od->poll, wait); sysfs_put_active_two(attr_sd); - if (buffer->event != atomic_read(&attr_sd->s_event)) + if (buffer->event != atomic_read(&od->event)) goto trigger; return 0; @@ -474,8 +478,17 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr) if (sd && attr) sd = sysfs_find_dirent(sd, attr); if (sd) { - atomic_inc(&sd->s_event); - wake_up_interruptible(&k->poll); + struct sysfs_open_dirent *od; + + spin_lock(&sysfs_open_dirent_lock); + + od = sd->s_attr.open; + if (od) { + atomic_inc(&od->event); + wake_up_interruptible(&od->poll); + } + + spin_unlock(&sysfs_open_dirent_lock); } mutex_unlock(&sysfs_mutex); diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 3adce7d5e4f..269c845c590 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -46,7 +46,6 @@ struct sysfs_dirent { ino_t s_ino; umode_t s_mode; struct iattr *s_iattr; - atomic_t s_event; }; #define SD_DEACTIVATED_BIAS INT_MIN diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 0777b3f57ae..a8a84fcccbc 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -66,7 +66,6 @@ struct kobject { struct kset * kset; struct kobj_type * ktype; struct sysfs_dirent * sd; - wait_queue_head_t poll; }; extern int kobject_set_name(struct kobject *, const char *, ...) diff --git a/lib/kobject.c b/lib/kobject.c index e8181d3cec3..fc6db6b4bfc 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -131,7 +131,6 @@ void kobject_init(struct kobject * kobj) return; kref_init(&kobj->kref); INIT_LIST_HEAD(&kobj->entry); - init_waitqueue_head(&kobj->poll); kobj->kset = kset_get(kobj->kset); } -- cgit v1.2.3-70-g09d2 From e4bc16621d82ee1fd3685dcbf889a7c49891847b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Sep 2007 11:12:00 -0700 Subject: driver core: remove subsystem_init() There is only one user of it, and it is only a wrapper for kset_init(). Signed-off-by: Greg Kroah-Hartman --- Documentation/kobject.txt | 1 - drivers/base/class.c | 2 +- include/linux/kobject.h | 1 - lib/kobject.c | 5 ----- 4 files changed, 1 insertion(+), 8 deletions(-) (limited to 'include') diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt index 5e7aca26135..ca86a885ad8 100644 --- a/Documentation/kobject.txt +++ b/Documentation/kobject.txt @@ -238,7 +238,6 @@ kobj_set_kset_s(obj,subsys) - Assumes that obj->kobj exists, and is a struct kobject. - Sets the kset of that kobject to the kset . -void subsystem_init(struct kset *s); int subsystem_register(struct kset *s); void subsystem_unregister(struct kset *s); diff --git a/drivers/base/class.c b/drivers/base/class.c index 3e9b04c30fb..5b9cf06eab8 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -861,7 +861,7 @@ int __init classes_init(void) /* ick, this is ugly, the things we go through to keep from showing up * in sysfs... */ - subsystem_init(&class_obj_subsys); + kset_init(&class_obj_subsys); if (!class_obj_subsys.kobj.parent) class_obj_subsys.kobj.parent = &class_obj_subsys.kobj; return 0; diff --git a/include/linux/kobject.h b/include/linux/kobject.h index a8a84fcccbc..05cc5b2ddff 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -217,7 +217,6 @@ extern struct kset hypervisor_subsys; #define kobj_set_kset_s(obj,subsys) \ (obj)->kobj.kset = &(subsys) -extern void subsystem_init(struct kset *); extern int __must_check subsystem_register(struct kset *); extern void subsystem_unregister(struct kset *); diff --git a/lib/kobject.c b/lib/kobject.c index fc6db6b4bfc..b7e0646f797 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -617,11 +617,6 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name) return ret; } -void subsystem_init(struct kset *s) -{ - kset_init(s); -} - int subsystem_register(struct kset *s) { return kset_register(s); -- cgit v1.2.3-70-g09d2 From 6adf7554b9c70eac83251e00aa4a55f7dc830cec Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 27 Sep 2007 14:48:53 -0700 Subject: kset: add some kerneldoc to help describe what these strange things are Signed-off-by: Greg Kroah-Hartman --- include/linux/kobject.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 05cc5b2ddff..973aa7b39e0 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -117,29 +117,30 @@ struct kset_uevent_ops { struct kobj_uevent_env *env); }; -/* - * struct kset - a set of kobjects of a specific type, belonging - * to a specific subsystem. - * - * All kobjects of a kset should be embedded in an identical - * type. This type may have a descriptor, which the kset points - * to. This allows there to exist sets of objects of the same - * type in different subsystems. +/** + * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem. * - * A subsystem does not have to be a list of only one type - * of object; multiple ksets can belong to one subsystem. All - * ksets of a subsystem share the subsystem's lock. + * A kset defines a group of kobjects. They can be individually + * different "types" but overall these kobjects all want to be grouped + * together and operated on in the same manner. ksets are used to + * define the attribute callbacks and other common events that happen to + * a kobject. * - * Each kset can support specific event variables; it can - * supress the event generation or add subsystem specific - * variables carried with the event. + * @ktype: the struct kobj_type for this specific kset + * @list: the list of all kobjects for this kset + * @list_lock: a lock for iterating over the kobjects + * @kobj: the embedded kobject for this kset (recursion, isn't it fun...) + * @uevent_ops: the set of uevent operations for this kset. These are + * called whenever a kobject has something happen to it so that the kset + * can add new environment variables, or filter out the uevents if so + * desired. */ struct kset { - struct kobj_type * ktype; + struct kobj_type *ktype; struct list_head list; spinlock_t list_lock; struct kobject kobj; - struct kset_uevent_ops * uevent_ops; + struct kset_uevent_ops *uevent_ops; }; -- cgit v1.2.3-70-g09d2 From f0e7e1bd77d450ebfa12153b90f93ad46616ab4a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 27 Sep 2007 14:48:53 -0700 Subject: kobject: update the copyrights I've been hacking on these files for a while now, might as well make it official... Signed-off-by: Greg Kroah-Hartman --- include/linux/kobject.h | 6 ++++-- lib/kobject.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 973aa7b39e0..4a0d27f475d 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -1,8 +1,10 @@ /* * kobject.h - generic kernel object infrastructure. * - * Copyright (c) 2002-2003 Patrick Mochel - * Copyright (c) 2002-2003 Open Source Development Labs + * Copyright (c) 2002-2003 Patrick Mochel + * Copyright (c) 2002-2003 Open Source Development Labs + * Copyright (c) 2006-2007 Greg Kroah-Hartman + * Copyright (c) 2006-2007 Novell Inc. * * This file is released under the GPLv2. * diff --git a/lib/kobject.c b/lib/kobject.c index b7e0646f797..03d40360ff1 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -2,6 +2,8 @@ * kobject.c - library routines for handling generic kernel objects * * Copyright (c) 2002-2003 Patrick Mochel + * Copyright (c) 2006-2007 Greg Kroah-Hartman + * Copyright (c) 2006-2007 Novell Inc. * * This file is released under the GPLv2. * -- cgit v1.2.3-70-g09d2 From 6d66f5cd26e4c482e986130b7572f2735a0f7e8b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 17:31:38 +0900 Subject: sysfs: add copyrights Sysfs has gone through considerable amount of reimplementation. Add copyrights. Any objections? :-) Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/bin.c | 8 +++++++- fs/sysfs/dir.c | 10 +++++++++- fs/sysfs/file.c | 10 +++++++++- fs/sysfs/inode.c | 8 ++++++-- fs/sysfs/mount.c | 10 +++++++++- fs/sysfs/symlink.c | 10 +++++++++- fs/sysfs/sysfs.h | 10 ++++++++++ include/linux/sysfs.h | 2 ++ 8 files changed, 61 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 247ea19721c..006fc64227d 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -1,9 +1,15 @@ /* - * bin.c - binary file operations for sysfs. + * fs/sysfs/bin.c - sysfs binary file implementation * * Copyright (c) 2003 Patrick Mochel * Copyright (c) 2003 Matthew Wilcox * Copyright (c) 2004 Silicon Graphics, Inc. + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo + * + * This file is released under the GPLv2. + * + * Please see Documentation/filesystems/sysfs.txt for more information. */ #undef DEBUG diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e301a1207b6..9161db4d6b5 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -1,5 +1,13 @@ /* - * dir.c - Operations for sysfs directories. + * fs/sysfs/dir.c - sysfs core and dir operation implementation + * + * Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo + * + * This file is released under the GPLv2. + * + * Please see Documentation/filesystems/sysfs.txt for more information. */ #undef DEBUG diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index c05f9618b2d..d3be1e7fb48 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -1,5 +1,13 @@ /* - * file.c - operations for regular (text) files. + * fs/sysfs/file.c - sysfs regular (text) file implementation + * + * Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo + * + * This file is released under the GPLv2. + * + * Please see Documentation/filesystems/sysfs.txt for more information. */ #include diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 2210cf0005f..9236635111f 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -1,7 +1,11 @@ /* - * inode.c - basic inode and dentry operations. + * fs/sysfs/inode.c - basic sysfs inode and dentry operations * - * sysfs is Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo + * + * This file is released under the GPLv2. * * Please see Documentation/filesystems/sysfs.txt for more information. */ diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 465902c18d3..c76c540be3c 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -1,5 +1,13 @@ /* - * mount.c - operations for initializing and mounting sysfs. + * fs/sysfs/symlink.c - operations for initializing and mounting sysfs + * + * Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo + * + * This file is released under the GPLv2. + * + * Please see Documentation/filesystems/sysfs.txt for more information. */ #define DEBUG diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index ffa82e9802a..3eac20c63c4 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -1,5 +1,13 @@ /* - * symlink.c - operations for sysfs symlinks. + * fs/sysfs/symlink.c - sysfs symlink implementation + * + * Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo + * + * This file is released under the GPLv2. + * + * Please see Documentation/filesystems/sysfs.txt for more information. */ #include diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 269c845c590..f0326f281d1 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -1,3 +1,13 @@ +/* + * fs/sysfs/sysfs.h - sysfs internal header file + * + * Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo + * + * This file is released under the GPLv2. + */ + struct sysfs_open_dirent; /* type-specific structures for sysfs_dirent->s_* union members */ diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index db5dd2403d0..149ab62329e 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -3,6 +3,8 @@ * * Copyright (c) 2001,2002 Patrick Mochel * Copyright (c) 2004 Silicon Graphics, Inc. + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo * * Please see Documentation/filesystems/sysfs.txt for more information. */ -- cgit v1.2.3-70-g09d2