From 99bcf217183e02ebae46373896fba7f12d588001 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 27 Jun 2010 01:02:34 +0000 Subject: device.h drivers/base/core.c Convert dev_ logging macros to functions Reduces an x86 defconfig text and data ~55k, .6% smaller. $ size vmlinux* text data bss dec hex filename 7205273 716016 1366288 9287577 8db799 vmlinux 7258890 719768 1366288 9344946 8e97b2 vmlinux.master Uses %pV and struct va_format Format arguments are verified before printk The dev_info macro is converted to _dev_info because there are existing uses of variables named dev_info in the kernel tree like drivers/net/pcmcia/pcnet_cs.c A dev_info macro is created to call _dev_info Signed-off-by: Joe Perches Acked-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- include/linux/device.h | 112 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 86 insertions(+), 26 deletions(-) (limited to 'include/linux/device.h') diff --git a/include/linux/device.h b/include/linux/device.h index 0713e10571dd..6a8276f683b6 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -638,43 +638,103 @@ extern void sysdev_shutdown(void); /* debugging and troubleshooting/diagnostic helpers. */ extern const char *dev_driver_string(const struct device *dev); -#define dev_printk(level, dev, format, arg...) \ - printk(level "%s %s: " format , dev_driver_string(dev) , \ - dev_name(dev) , ## arg) - -#define dev_emerg(dev, format, arg...) \ - dev_printk(KERN_EMERG , dev , format , ## arg) -#define dev_alert(dev, format, arg...) \ - dev_printk(KERN_ALERT , dev , format , ## arg) -#define dev_crit(dev, format, arg...) \ - dev_printk(KERN_CRIT , dev , format , ## arg) -#define dev_err(dev, format, arg...) \ - dev_printk(KERN_ERR , dev , format , ## arg) -#define dev_warn(dev, format, arg...) \ - dev_printk(KERN_WARNING , dev , format , ## arg) -#define dev_notice(dev, format, arg...) \ - dev_printk(KERN_NOTICE , dev , format , ## arg) -#define dev_info(dev, format, arg...) \ - dev_printk(KERN_INFO , dev , format , ## arg) + + +#ifdef CONFIG_PRINTK + +extern int dev_printk(const char *level, const struct device *dev, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +extern int dev_emerg(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int dev_alert(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int dev_crit(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int dev_err(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int dev_warn(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int dev_notice(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int _dev_info(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +#else + +static inline int dev_printk(const char *level, const struct device *dev, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +static inline int dev_printk(const char *level, const struct device *dev, + const char *fmt, ...) + { return 0; } + +static inline int dev_emerg(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static inline int dev_emerg(const struct device *dev, const char *fmt, ...) + { return 0; } +static inline int dev_crit(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static inline int dev_crit(const struct device *dev, const char *fmt, ...) + { return 0; } +static inline int dev_alert(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static inline int dev_alert(const struct device *dev, const char *fmt, ...) + { return 0; } +static inline int dev_err(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static inline int dev_err(const struct device *dev, const char *fmt, ...) + { return 0; } +static inline int dev_warn(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static inline int dev_warn(const struct device *dev, const char *fmt, ...) + { return 0; } +static inline int dev_notice(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static inline int dev_notice(const struct device *dev, const char *fmt, ...) + { return 0; } +static inline int _dev_info(const struct device *dev, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static inline int _dev_info(const struct device *dev, const char *fmt, ...) + { return 0; } + +#endif + +/* + * Stupid hackaround for existing uses of non-printk uses dev_info + * + * Note that the definition of dev_info below is actually _dev_info + * and a macro is used to avoid redefining dev_info + */ + +#define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg) #if defined(DEBUG) #define dev_dbg(dev, format, arg...) \ - dev_printk(KERN_DEBUG , dev , format , ## arg) + dev_printk(KERN_DEBUG, dev, format, ##arg) #elif defined(CONFIG_DYNAMIC_DEBUG) -#define dev_dbg(dev, format, ...) do { \ +#define dev_dbg(dev, format, ...) \ +do { \ dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \ - } while (0) +} while (0) #else -#define dev_dbg(dev, format, arg...) \ - ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) +#define dev_dbg(dev, format, arg...) \ +({ \ + if (0) \ + dev_printk(KERN_DEBUG, dev, format, ##arg); \ + 0; \ +}) #endif #ifdef VERBOSE_DEBUG #define dev_vdbg dev_dbg #else - -#define dev_vdbg(dev, format, arg...) \ - ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) +#define dev_vdbg(dev, format, arg...) \ +({ \ + if (0) \ + dev_printk(KERN_DEBUG, dev, format, ##arg); \ + 0; \ +}) #endif /* -- cgit v1.2.3 From cc7447a5fa92759b0856d6a83ba2539c6a94e67e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 16 Jun 2010 11:44:18 +0200 Subject: Driver core: Drop __must_check from bus_for_each_drv() There is little rationale for marking bus_for_each_drv() __must_check. It is more of an iteration helper than a real function. You don't know in advance which callback it will be used on, so you have no clue how important it can be to check the returned value. In practice, this helper function can be used for best-effort tasks. As a matter of fact, bus_for_each_dev() is not marked __must_check. So remove it from bus_for_each_drv() as well. This is the same that was done back in October 2006 by Russell King for device_for_each_child(), for exactly the same reasons. Signed-off-by: Jean Delvare Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'include/linux/device.h') diff --git a/include/linux/device.h b/include/linux/device.h index 6a8276f683b6..ddffdf7da393 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -84,9 +84,8 @@ struct device *bus_find_device_by_name(struct bus_type *bus, struct device *start, const char *name); -int __must_check bus_for_each_drv(struct bus_type *bus, - struct device_driver *start, void *data, - int (*fn)(struct device_driver *, void *)); +int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, + void *data, int (*fn)(struct device_driver *, void *)); void bus_sort_breadthfirst(struct bus_type *bus, int (*compare)(const struct device *a, -- cgit v1.2.3 From 45daef0fdcc44f6af86fdebc4fc7eb7c79375398 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 23 Jul 2010 19:56:18 +0900 Subject: Driver core: Add BUS_NOTIFY_BIND_DRIVER Add BUS_NOTIFY_BIND_DRIVER as a bus notifier event. For driver binding/unbinding we with this in place have the following bus notifier events: - BUS_NOTIFY_BIND_DRIVER - before ->probe() - BUS_NOTIFY_BOUND_DRIVER - after ->probe() - BUS_NOTIFY_UNBIND_DRIVER - before ->remove() - BUS_NOTIFY_UNBOUND_DRIVER - after ->remove() The event BUS_NOTIFY_BIND_DRIVER allows bus code to be notified that ->probe() is about to be called. Useful for bus code that needs to setup hardware before the driver gets to run. With this in place platform drivers can be loaded and unloaded as modules and the new BIND event allows bus code to control for instance device clocks that must be enabled before the driver can be executed. Without this patch there is no way for the bus code to get notified that a modular driver is about to be probed. Signed-off-by: Magnus Damm Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 4 ++++ include/linux/device.h | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'include/linux/device.h') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 503c2620bbcc..da57ee9d63fe 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -51,6 +51,10 @@ static int driver_sysfs_add(struct device *dev) { int ret; + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->p->bus_notifier, + BUS_NOTIFY_BIND_DRIVER, dev); + ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj, kobject_name(&dev->kobj)); if (ret == 0) { diff --git a/include/linux/device.h b/include/linux/device.h index ddffdf7da393..0ca24e93304f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -109,10 +109,12 @@ extern int bus_unregister_notifier(struct bus_type *bus, */ #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ #define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ -#define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */ -#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be +#define BUS_NOTIFY_BIND_DRIVER 0x00000003 /* driver about to be + bound */ +#define BUS_NOTIFY_BOUND_DRIVER 0x00000004 /* driver bound to device */ +#define BUS_NOTIFY_UNBIND_DRIVER 0x00000005 /* driver about to be unbound */ -#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000005 /* driver is unbound +#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000006 /* driver is unbound from the device */ extern struct kset *bus_get_kset(struct bus_type *bus); -- cgit v1.2.3 From 6937e8f8c0135f2325194c372ada6dc655499992 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Aug 2010 17:38:18 +0200 Subject: driver core: device_rename's new_name can be const The new_name argument to device_rename() can be const as kobject_rename's new_name argument is. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- include/linux/device.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux/device.h') diff --git a/drivers/base/core.c b/drivers/base/core.c index f8e72724dd4b..d1b2c9adc271 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1599,7 +1599,7 @@ EXPORT_SYMBOL_GPL(device_destroy); * on the same device to ensure that new_name is valid and * won't conflict with other devices. */ -int device_rename(struct device *dev, char *new_name) +int device_rename(struct device *dev, const char *new_name) { char *old_class_name = NULL; char *new_class_name = NULL; diff --git a/include/linux/device.h b/include/linux/device.h index 0ca24e93304f..516fecacf27b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -552,7 +552,7 @@ extern int device_for_each_child(struct device *dev, void *data, int (*fn)(struct device *dev, void *data)); extern struct device *device_find_child(struct device *dev, void *data, int (*match)(struct device *dev, void *data)); -extern int device_rename(struct device *dev, char *new_name); +extern int device_rename(struct device *dev, const char *new_name); extern int device_move(struct device *dev, struct device *new_parent, enum dpm_order dpm_order); extern const char *device_get_devnode(struct device *dev, -- cgit v1.2.3 From e52eec13cd6b7f30ab19081b387813e03e592ae5 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 8 Sep 2010 16:54:17 +0200 Subject: SYSFS: Allow boot time switching between deprecated and modern sysfs layout I have some systems which need legacy sysfs due to old tools that are making assumptions that a directory can never be a symlink to another directory, and it's a big hazzle to compile separate kernels for them. This patch turns CONFIG_SYSFS_DEPRECATED into a run time option that can be switched on/off the kernel command line. This way the same binary can be used in both cases with just a option on the command line. The old CONFIG_SYSFS_DEPRECATED_V2 option is still there to set the default. I kept the weird name to not break existing config files. Also the compat code can be still completely disabled by undefining CONFIG_SYSFS_DEPRECATED_SWITCH -- just the optimizer takes care of this now instead of lots of ifdefs. This makes the code look nicer. v2: This is an updated version on top of Kay's patch to only handle the block devices. I tested it on my old systems and that seems to work. Cc: axboe@kernel.dk Signed-off-by: Andi Kleen Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 9 +++++++++ block/genhd.c | 7 ++----- drivers/base/class.c | 4 ++-- drivers/base/core.c | 26 +++++++++++++++++--------- fs/partitions/check.c | 19 +++++++++---------- include/linux/device.h | 7 +++++++ init/Kconfig | 26 ++++++++++++++++++++++---- 7 files changed, 68 insertions(+), 30 deletions(-) (limited to 'include/linux/device.h') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 3d854c9ae53a..67fa3fdc128f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2365,6 +2365,15 @@ and is between 256 and 4096 characters. It is defined in the file switches= [HW,M68k] + sysfs.deprecated=0|1 [KNL] + Enable/disable old style sysfs layout for old udev + on older distributions. When this option is enabled + very new udev will not work anymore. When this option + is disabled (or CONFIG_SYSFS_DEPRECATED not compiled) + in older udev will not work anymore. + Default depends on CONFIG_SYSFS_DEPRECATED_V2 set in + the kernel configuration. + sysrq_always_enabled [KNL] Ignore sysrq setting - this boot parameter will diff --git a/block/genhd.c b/block/genhd.c index 59a2db6fecef..4e28a840bde0 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -22,9 +22,7 @@ #include "blk.h" static DEFINE_MUTEX(block_class_lock); -#ifndef CONFIG_SYSFS_DEPRECATED struct kobject *block_depr; -#endif /* for extended dynamic devt allocation, currently only one major is used */ #define MAX_EXT_DEVT (1 << MINORBITS) @@ -803,10 +801,9 @@ static int __init genhd_device_init(void) register_blkdev(BLOCK_EXT_MAJOR, "blkext"); -#ifndef CONFIG_SYSFS_DEPRECATED /* create top-level block dir */ - block_depr = kobject_create_and_add("block", NULL); -#endif + if (!sysfs_deprecated) + block_depr = kobject_create_and_add("block", NULL); return 0; } diff --git a/drivers/base/class.c b/drivers/base/class.c index 1078969889fd..9c63a5687d69 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -184,9 +184,9 @@ int __class_register(struct class *cls, struct lock_class_key *key) if (!cls->dev_kobj) cls->dev_kobj = sysfs_dev_char_kobj; -#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK) +#if defined(CONFIG_BLOCK) /* let the block class directory show up in the root of sysfs */ - if (cls != &block_class) + if (!sysfs_deprecated || cls != &block_class) cp->class_subsys.kobj.kset = class_kset; #else cp->class_subsys.kobj.kset = class_kset; diff --git a/drivers/base/core.c b/drivers/base/core.c index 6cf9069f3150..f7f906f0a2f2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -26,6 +26,19 @@ #include "base.h" #include "power/power.h" +#ifdef CONFIG_SYSFS_DEPRECATED +#ifdef CONFIG_SYSFS_DEPRECATED_V2 +long sysfs_deprecated = 1; +#else +long sysfs_deprecated = 0; +#endif +static __init int sysfs_deprecated_setup(char *arg) +{ + return strict_strtol(arg, 10, &sysfs_deprecated); +} +early_param("sysfs.deprecated", sysfs_deprecated_setup); +#endif + int (*platform_notify)(struct device *dev) = NULL; int (*platform_notify_remove)(struct device *dev) = NULL; static struct kobject *dev_kobj; @@ -617,14 +630,13 @@ static struct kobject *get_device_parent(struct device *dev, struct kobject *parent_kobj; struct kobject *k; -#ifdef CONFIG_SYSFS_DEPRECATED /* block disks show up in /sys/block */ - if (dev->class == &block_class) { + if (sysfs_deprecated && dev->class == &block_class) { if (parent && parent->class == &block_class) return &parent->kobj; return &block_class.p->class_subsys.kobj; } -#endif + /* * If we have no parent, we live in "virtual". * Class-devices with a non class-device as parent, live @@ -707,11 +719,9 @@ static int device_add_class_symlinks(struct device *dev) goto out_subsys; } -#ifdef CONFIG_SYSFS_DEPRECATED /* /sys/block has directories and does not need symlinks */ - if (dev->class == &block_class) + if (sysfs_deprecated && dev->class == &block_class) return 0; -#endif /* link in the class directory pointing to the device */ error = sysfs_create_link(&dev->class->p->class_subsys.kobj, @@ -738,10 +748,8 @@ static void device_remove_class_symlinks(struct device *dev) if (dev->parent && device_is_not_partition(dev)) sysfs_remove_link(&dev->kobj, "device"); sysfs_remove_link(&dev->kobj, "subsystem"); -#ifdef CONFIG_SYSFS_DEPRECATED - if (dev->class == &block_class) + if (sysfs_deprecated && dev->class == &block_class) return; -#endif sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev)); } diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 79fbf3f390f0..137bf9787853 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -513,14 +513,14 @@ void register_disk(struct gendisk *disk) if (device_add(ddev)) return; -#ifndef CONFIG_SYSFS_DEPRECATED - err = sysfs_create_link(block_depr, &ddev->kobj, - kobject_name(&ddev->kobj)); - if (err) { - device_del(ddev); - return; + if (!sysfs_deprecated) { + err = sysfs_create_link(block_depr, &ddev->kobj, + kobject_name(&ddev->kobj)); + if (err) { + device_del(ddev); + return; + } } -#endif disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); @@ -737,8 +737,7 @@ void del_gendisk(struct gendisk *disk) kobject_put(disk->part0.holder_dir); kobject_put(disk->slave_dir); disk->driverfs_dev = NULL; -#ifndef CONFIG_SYSFS_DEPRECATED - sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); -#endif + if (!sysfs_deprecated) + sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); device_del(disk_to_dev(disk)); } diff --git a/include/linux/device.h b/include/linux/device.h index 516fecacf27b..dd4895313468 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -751,4 +751,11 @@ do { \ MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor)) #define MODULE_ALIAS_CHARDEV_MAJOR(major) \ MODULE_ALIAS("char-major-" __stringify(major) "-*") + +#ifdef CONFIG_SYSFS_DEPRECATED +extern long sysfs_deprecated; +#else +#define sysfs_deprecated 0 +#endif + #endif /* _DEVICE_H_ */ diff --git a/init/Kconfig b/init/Kconfig index 137609f33ebc..d742b6fca8d2 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -660,8 +660,12 @@ config SYSFS_DEPRECATED depends on SYSFS default n help - This option switches the layout of the "block" class devices, to not - show up in /sys/class/block/, but only in /sys/block/. + This option adds code that switches the layout of the "block" class + devices, to not show up in /sys/class/block/, but only in + /sys/block/. + + This switch is only active when the sysfs.deprecated=1 boot option is + passed or the SYSFS_DEPRECATED_V2 option is set. This option allows new kernels to run on old distributions and tools, which might get confused by /sys/class/block/. Since 2007/2008 all @@ -672,8 +676,22 @@ config SYSFS_DEPRECATED option enabled. Only if you are using a new kernel on an old distribution, you might - need to say Y here. Never say Y, if the original kernel, that came - with your distribution, has not set this option. + need to say Y here. + +config SYSFS_DEPRECATED_V2 + bool "enabled deprecated sysfs features by default" + default n + depends on SYSFS + depends on SYSFS_DEPRECATED + help + Enable deprecated sysfs by default. + + See the CONFIG_SYSFS_DEPRECATED option for more details about this + option. + + Only if you are using a new kernel on an old distribution, you might + need to say Y here. Even then, odds are you would not need it + enabled, you can always pass the boot option if absolutely necessary. config RELAY bool "Kernel->user space relay support (formerly relayfs)" -- cgit v1.2.3