From a6bb340da32f0abf76656be1619fb85150eef61b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 11 Jul 2007 14:53:28 +0200 Subject: debugfs: remove rmdir() non-empty complaint Hi, This patch kills the pointless debugfs rmdir() printk() when called on a non-empty directory. blktrace will sometimes have to call it a few times when forcefully ending a trace, which polutes the log with pointless warnings. Rationale: - It's more code to work-around this "problem" in the debugfs users, and you would have to add code to check for empty directories to do so (or assume that debugfs is using simple_ helpers, but that would be a layering violation). - Other rmdir() implementations don't complain about something this silly. Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/inode.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 1d533a2ec3a6..11be8a325e26 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -345,11 +345,6 @@ void debugfs_remove(struct dentry *dentry) switch (dentry->d_inode->i_mode & S_IFMT) { case S_IFDIR: ret = simple_rmdir(parent->d_inode, dentry); - if (ret) - printk(KERN_ERR - "DebugFS rmdir on %s failed : " - "directory not empty.\n", - dentry->d_name.name); break; case S_IFLNK: kfree(dentry->d_inode->i_private); -- cgit v1.2.3 From 60a96a59569bab85571d0089682109bd3324e896 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 8 Jul 2007 22:29:26 +0200 Subject: Driver core: accept all valid action-strings in uevent-trigger This allows the uevent file to handle any type of uevent action to be triggered by userspace instead of just the "add" uevent. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 23 ++++++++++++++++++++--- include/linux/kobject.h | 25 +++++++++++++++++-------- lib/kobject_uevent.c | 30 ++++++++++-------------------- 3 files changed, 47 insertions(+), 31 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 0455aa78fa13..91a0367d583e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -24,6 +24,8 @@ #include "base.h" #include "power/power.h" +extern const char *kobject_actions[]; + int (*platform_notify)(struct device * dev) = NULL; int (*platform_notify_remove)(struct device * dev) = NULL; @@ -303,10 +305,25 @@ out: static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - if (memcmp(buf, "add", 3) != 0) - dev_err(dev, "uevent: unsupported action-string; this will " - "be ignored in a future kernel version"); + 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; + kobject_uevent(&dev->kobj, action); + goto out; + } + + dev_err(dev, "uevent: unsupported action-string; this will " + "be ignored in a future kernel version\n"); kobject_uevent(&dev->kobj, KOBJ_ADD); +out: return count; } diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 06cbf41d32d2..aa2fe22b1baa 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -36,15 +36,24 @@ extern char uevent_helper[]; /* counter to tag the uevent, read only except for the kobject core */ extern u64 uevent_seqnum; -/* the actions here must match the proper string in lib/kobject_uevent.c */ -typedef int __bitwise kobject_action_t; +/* + * The actions here must match the index to the string array + * in lib/kobject_uevent.c + * + * Do not add new actions here without checking with the driver-core + * maintainers. Action strings are not meant to express subsystem + * or device specific properties. In most cases you want to send a + * kobject_uevent_env(kobj, KOBJ_CHANGE, env) with additional event + * specific variables added to the event environment. + */ enum kobject_action { - KOBJ_ADD = (__force kobject_action_t) 0x01, /* exclusive to core */ - KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* exclusive to core */ - KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* device state change */ - KOBJ_OFFLINE = (__force kobject_action_t) 0x04, /* device offline */ - KOBJ_ONLINE = (__force kobject_action_t) 0x05, /* device online */ - KOBJ_MOVE = (__force kobject_action_t) 0x06, /* device move */ + KOBJ_ADD, + KOBJ_REMOVE, + KOBJ_CHANGE, + KOBJ_MOVE, + KOBJ_ONLINE, + KOBJ_OFFLINE, + KOBJ_MAX }; struct kobject { diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index bd5ecbbafab1..6a80c784a8fb 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -33,25 +33,15 @@ static DEFINE_SPINLOCK(sequence_lock); static struct sock *uevent_sock; #endif -static char *action_to_string(enum kobject_action action) -{ - switch (action) { - case KOBJ_ADD: - return "add"; - case KOBJ_REMOVE: - return "remove"; - case KOBJ_CHANGE: - return "change"; - case KOBJ_OFFLINE: - return "offline"; - case KOBJ_ONLINE: - return "online"; - case KOBJ_MOVE: - return "move"; - default: - return NULL; - } -} +/* the strings here must match the enum in include/linux/kobject.h */ +const char *kobject_actions[] = { + "add", + "remove", + "change", + "move", + "online", + "offline", +}; /** * kobject_uevent_env - send an uevent with environmental data @@ -83,7 +73,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, pr_debug("%s\n", __FUNCTION__); - action_string = action_to_string(action); + action_string = kobject_actions[action]; if (!action_string) { pr_debug("kobject attempted to send uevent without action_string!\n"); return -EINVAL; -- cgit v1.2.3 From 471d0558045fe35f8c5f291c1ee63815eb9c2dcd Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Jul 2007 16:55:07 -0400 Subject: PM: Remove deprecated sysfs files This patch (as932) removes the deprecated sysfs .../power/state attribute files. Signed-off-by: Alan Stern Acked-by: Pavel Machek Signed-off-by: Greg Kroah-Hartman --- Documentation/feature-removal-schedule.txt | 3 +- drivers/base/power/sysfs.c | 66 ------------------------------ kernel/power/Kconfig | 12 ------ 3 files changed, 1 insertion(+), 80 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index d05e6243b4df..9cf9d8346289 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -26,8 +26,7 @@ Who: Hans Verkuil and --------------------------- -What: /sys/devices/.../power/state - dev->power.power_state +What: dev->power.power_state dpm_runtime_{suspend,resume)() When: July 2007 Why: Broken design for runtime control over driver power states, confusing diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 2d47517dbe32..f2ed179cd695 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -7,69 +7,6 @@ #include "power.h" -#ifdef CONFIG_PM_SYSFS_DEPRECATED - -/** - * state - Control current power state of device - * - * show() returns the current power state of the device. '0' indicates - * the device is on. Other values (2) indicate the device is in some low - * power state. - * - * store() sets the current power state, which is an integer valued - * 0, 2, or 3. Devices with bus.suspend_late(), or bus.resume_early() - * methods fail this operation; those methods couldn't be called. - * Otherwise, - * - * - If the recorded dev->power.power_state.event matches the - * target value, nothing is done. - * - If the recorded event code is nonzero, the device is reactivated - * by calling bus.resume() and/or class.resume(). - * - If the target value is nonzero, the device is suspended by - * calling class.suspend() and/or bus.suspend() with event code - * PM_EVENT_SUSPEND. - * - * This mechanism is DEPRECATED and should only be used for testing. - */ - -static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf) -{ - if (dev->power.power_state.event) - return sprintf(buf, "2\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n) -{ - pm_message_t state; - int error = -EINVAL; - - /* disallow incomplete suspend sequences */ - if (dev->bus && (dev->bus->suspend_late || dev->bus->resume_early)) - return error; - - state.event = PM_EVENT_SUSPEND; - /* Older apps expected to write "3" here - confused with PCI D3 */ - if ((n == 1) && !strcmp(buf, "3")) - error = dpm_runtime_suspend(dev, state); - - if ((n == 1) && !strcmp(buf, "2")) - error = dpm_runtime_suspend(dev, state); - - if ((n == 1) && !strcmp(buf, "0")) { - dpm_runtime_resume(dev); - error = 0; - } - - return error ? error : n; -} - -static DEVICE_ATTR(state, 0644, state_show, state_store); - - -#endif /* CONFIG_PM_SYSFS_DEPRECATED */ - /* * wakeup - Report/change current wakeup option for device * @@ -143,9 +80,6 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store); static struct attribute * power_attrs[] = { -#ifdef CONFIG_PM_SYSFS_DEPRECATED - &dev_attr_state.attr, -#endif &dev_attr_wakeup.attr, NULL, }; diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 495b7d4dd330..73328476761c 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -65,18 +65,6 @@ config PM_TRACE CAUTION: this option will cause your machine's real-time clock to be set to an invalid time after a resume. -config PM_SYSFS_DEPRECATED - bool "Driver model /sys/devices/.../power/state files (DEPRECATED)" - depends on PM && SYSFS - default n - help - The driver model started out with a sysfs file intended to provide - a userspace hook for device power management. This feature has never - worked very well, except for limited testing purposes, and so it will - be removed. It's not clear that a generic mechanism could really - handle the wide variability of device power states; any replacements - are likely to be bus or driver specific. - config SOFTWARE_SUSPEND bool "Software Suspend (Hibernation)" depends on PM && SWAP && (((X86 || PPC64_SWSUSP) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)) -- cgit v1.2.3 From 3f8df781fc5f9ee5253a54ba669e1c8872844b86 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Jul 2007 16:57:22 -0400 Subject: PM: remove deprecated dpm_runtime_* routines This patch (as933) removes the deprecated dpm_runtime_suspend() and dpm_runtime_resume() routines from the PM core. The only user of those routines is the PCMCIA ds driver; local replacements are added. Signed-off-by: Alan Stern CC: Dominik Brodowski Signed-off-by: Greg Kroah-Hartman --- Documentation/feature-removal-schedule.txt | 1 - drivers/base/power/Makefile | 2 +- drivers/base/power/power.h | 5 -- drivers/base/power/runtime.c | 85 ------------------------------ drivers/pcmcia/ds.c | 40 +++++++++++--- include/linux/pm.h | 11 ---- 6 files changed, 35 insertions(+), 109 deletions(-) delete mode 100644 drivers/base/power/runtime.c diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 9cf9d8346289..1b5c70758a1a 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -27,7 +27,6 @@ Who: Hans Verkuil and --------------------------- What: dev->power.power_state - dpm_runtime_{suspend,resume)() When: July 2007 Why: Broken design for runtime control over driver power states, confusing driver-internal runtime power management with: mechanisms to support diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 91f230939c1e..fff178007208 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -1,5 +1,5 @@ obj-y := shutdown.o -obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o +obj-$(CONFIG_PM) += main.o suspend.o resume.o sysfs.o obj-$(CONFIG_PM_TRACE) += trace.o ifeq ($(CONFIG_DEBUG_DRIVER),y) diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 2760f25b3ac5..591a0dd5deee 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -62,11 +62,6 @@ extern int resume_device(struct device *); */ extern int suspend_device(struct device *, pm_message_t); - -/* - * runtime.c - */ - #else /* CONFIG_PM */ diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c deleted file mode 100644 index df6174d85866..000000000000 --- a/drivers/base/power/runtime.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * drivers/base/power/runtime.c - Handling dynamic device power management. - * - * Copyright (c) 2003 Patrick Mochel - * Copyright (c) 2003 Open Source Development Lab - * - */ - -#include -#include "power.h" - - -static void runtime_resume(struct device * dev) -{ - dev_dbg(dev, "resuming\n"); - if (!dev->power.power_state.event) - return; - if (!resume_device(dev)) - dev->power.power_state = PMSG_ON; -} - - -/** - * dpm_runtime_resume - Power one device back on. - * @dev: Device. - * - * Bring one device back to the on state by first powering it - * on, then restoring state. We only operate on devices that aren't - * already on. - * FIXME: We need to handle devices that are in an unknown state. - */ - -void dpm_runtime_resume(struct device * dev) -{ - mutex_lock(&dpm_mtx); - runtime_resume(dev); - mutex_unlock(&dpm_mtx); -} -EXPORT_SYMBOL(dpm_runtime_resume); - - -/** - * dpm_runtime_suspend - Put one device in low-power state. - * @dev: Device. - * @state: State to enter. - */ - -int dpm_runtime_suspend(struct device * dev, pm_message_t state) -{ - int error = 0; - - mutex_lock(&dpm_mtx); - if (dev->power.power_state.event == state.event) - goto Done; - - if (dev->power.power_state.event) - runtime_resume(dev); - - if (!(error = suspend_device(dev, state))) - dev->power.power_state = state; - Done: - mutex_unlock(&dpm_mtx); - return error; -} -EXPORT_SYMBOL(dpm_runtime_suspend); - - -#if 0 -/** - * dpm_set_power_state - Update power_state field. - * @dev: Device. - * @state: Power state device is in. - * - * This is an update mechanism for drivers to notify the core - * what power state a device is in. Device probing code may not - * always be able to tell, but we need accurate information to - * work reliably. - */ -void dpm_set_power_state(struct device * dev, pm_message_t state) -{ - mutex_lock(&dpm_mtx); - dev->power.power_state = state; - mutex_unlock(&dpm_mtx); -} -#endif /* 0 */ diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 143c6efc478a..a99607142fc8 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1127,6 +1127,34 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, #endif +/************************ runtime PM support ***************************/ + +static int pcmcia_dev_suspend(struct device *dev, pm_message_t state); +static int pcmcia_dev_resume(struct device *dev); + +static int runtime_suspend(struct device *dev) +{ + int rc; + + down(&dev->sem); + rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND); + up(&dev->sem); + if (!rc) + dev->power.power_state.event = PM_EVENT_SUSPEND; + return rc; +} + +static void runtime_resume(struct device *dev) +{ + int rc; + + down(&dev->sem); + rc = pcmcia_dev_resume(dev); + up(&dev->sem); + if (!rc) + dev->power.power_state.event = PM_EVENT_ON; +} + /************************ per-device sysfs output ***************************/ #define pcmcia_device_attr(field, test, format) \ @@ -1173,9 +1201,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute return -EINVAL; if ((!p_dev->suspended) && !strncmp(buf, "off", 3)) - ret = dpm_runtime_suspend(dev, PMSG_SUSPEND); + ret = runtime_suspend(dev); else if (p_dev->suspended && !strncmp(buf, "on", 2)) - dpm_runtime_resume(dev); + runtime_resume(dev); return ret ? ret : count; } @@ -1312,10 +1340,10 @@ static int pcmcia_bus_suspend_callback(struct device *dev, void * _data) struct pcmcia_socket *skt = _data; struct pcmcia_device *p_dev = to_pcmcia_dev(dev); - if (p_dev->socket != skt) + if (p_dev->socket != skt || p_dev->suspended) return 0; - return dpm_runtime_suspend(dev, PMSG_SUSPEND); + return runtime_suspend(dev); } static int pcmcia_bus_resume_callback(struct device *dev, void * _data) @@ -1323,10 +1351,10 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data) struct pcmcia_socket *skt = _data; struct pcmcia_device *p_dev = to_pcmcia_dev(dev); - if (p_dev->socket != skt) + if (p_dev->socket != skt || !p_dev->suspended) return 0; - dpm_runtime_resume(dev); + runtime_resume(dev); return 0; } diff --git a/include/linux/pm.h b/include/linux/pm.h index 273781c82e4d..2735b7cadd20 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -284,8 +284,6 @@ extern int device_prepare_suspend(pm_message_t state); #define device_may_wakeup(dev) \ (device_can_wakeup(dev) && (dev)->power.should_wakeup) -extern int dpm_runtime_suspend(struct device *, pm_message_t); -extern void dpm_runtime_resume(struct device *); extern void __suspend_report_result(const char *function, void *fn, int ret); #define suspend_report_result(fn, ret) \ @@ -317,15 +315,6 @@ static inline int device_suspend(pm_message_t state) #define device_set_wakeup_enable(dev,val) do{}while(0) #define device_may_wakeup(dev) (0) -static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state) -{ - return 0; -} - -static inline void dpm_runtime_resume(struct device * dev) -{ -} - #define suspend_report_result(fn, ret) do { } while (0) static inline int call_platform_enable_wakeup(struct device *dev, int is_on) -- cgit v1.2.3 From 01da2425f327d7ac673e594bee5655523115970b Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 14 Jul 2007 11:03:35 +0900 Subject: sysfs: avoid kmem_cache_free(NULL) kmem_cache_free() with NULL is not allowed. But it may happen if out of memory error is triggered in sysfs_new_dirent(). This patch fixes that error handling. Signed-off-by: Akinobu Mita Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index aee966c44aac..2e6775a836f2 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -361,20 +361,20 @@ static struct dentry_operations sysfs_dentry_ops = { struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) { char *dup_name = NULL; - struct sysfs_dirent *sd = NULL; + struct sysfs_dirent *sd; if (type & SYSFS_COPY_NAME) { name = dup_name = kstrdup(name, GFP_KERNEL); if (!name) - goto err_out; + return NULL; } sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); if (!sd) - goto err_out; + goto err_out1; if (sysfs_alloc_ino(&sd->s_ino)) - goto err_out; + goto err_out2; atomic_set(&sd->s_count, 1); atomic_set(&sd->s_active, 0); @@ -386,9 +386,10 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) return sd; - err_out: - kfree(dup_name); + err_out2: kmem_cache_free(sysfs_dir_cachep, sd); + err_out1: + kfree(dup_name); return NULL; } -- cgit v1.2.3 From 2c19c49a59ccf2162c0eb999de1ec60c0e07a533 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Tue, 17 Jul 2007 22:09:34 -0700 Subject: Documentation fix devres.txt: lib/iomap.c -> lib/devres.c Signed-off-by: Brandon Philips Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-model/devres.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 6c8d8f27db34..8569072fa387 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -207,7 +207,7 @@ responsibility. This is usually non-issue because bus ops and resource allocations already do the job. For an example of single-instance devres type, read pcim_iomap_table() -in lib/iomap.c. +in lib/devres.c. All devres interface functions can be called without context if the right gfp mask is given. -- cgit v1.2.3 From e080e436f605877e47e4950f5386ed843badbb1b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 18 Jul 2007 14:29:06 +0900 Subject: sysfs: fix sysfs root inode nlink accounting While making sysfs indoes hashed, sysfs root inode was left out. Now that nlink accounting depends on the inode being on the hash, sysfs root inode nlink isn't adjusted properly. Put sysfs root inode on the inode hash by allocating it using sysfs_get_inode() like other sysfs inodes. While at it, massage comments a bit. Signed-off-by: Tejun Heo Acked-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/mount.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 402cc356203c..60714d075c2f 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -43,19 +43,19 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_time_gran = 1; sysfs_sb = sb; - inode = new_inode(sysfs_sb); + /* get root inode, initialize and unlock it */ + inode = sysfs_get_inode(&sysfs_root); if (!inode) { pr_debug("sysfs: could not get root inode\n"); return -ENOMEM; } - sysfs_init_inode(&sysfs_root, inode); - inode->i_op = &sysfs_dir_inode_operations; inode->i_fop = &sysfs_dir_operations; - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inc_nlink(inode); + inc_nlink(inode); /* directory, account for "." */ + unlock_new_inode(inode); + /* instantiate and link root dentry */ root = d_alloc_root(inode); if (!root) { pr_debug("%s: could not get root dentry!\n",__FUNCTION__); -- cgit v1.2.3 From bc37e2830339cbfa42ac8579a7bf62fc4cdd360d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 18 Jul 2007 14:30:28 +0900 Subject: sysfs: make sysfs_init_inode() static With sysfs_fill_super() converted to use sysfs_get_inode(), there is no user of sysfs_init_inode() outside of fs/sysfs/inode.c. Make it static. Signed-off-by: Tejun Heo Acked-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/inode.c | 2 +- fs/sysfs/sysfs.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 3756e152285a..10d1b52899f1 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -133,7 +133,7 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) */ static struct lock_class_key sysfs_inode_imutex_key; -void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) +static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) { inode->i_blocks = 0; inode->i_mapping->a_ops = &sysfs_aops; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6a37f2386a8d..6b8c8d76d308 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -71,7 +71,6 @@ extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); extern void sysfs_delete_inode(struct inode *inode); -extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode); extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); -- cgit v1.2.3 From aebdc3b450a3febf7d7d00cd2235509055ec7082 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 12 Jul 2007 22:08:22 -0700 Subject: dev_vdbg(), available with -DVERBOSE_DEBUG This defines a dev_vdbg() call, which is enabled with -DVERBOSE_DEBUG. When enabled, dev_vdbg() acts just like dev_dbg(). When disabled, it is a NOP ... just like dev_dbg() without -DDEBUG. The specific code was moved out of a USB patch, but lots of drivers have similar support. That is, code can now be written to use an additional level of debug output, selected at compile time. Many driver authors have found this idiom to be very useful. A typical usage model is for "normal" debug messages to focus on fault paths and not be very "chatty", so that those messages can be left on during normal operation without much of a performance or syslog load. On the other hand "verbose" messages would be noisy enough that they wouldn't normally be enabled; they might even affect timings enough to change system or driver behavior. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 7 ------- include/linux/device.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 73c49362cd47..654857493a82 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -29,13 +29,6 @@ #include "hcd.h" #include "usb.h" -#define VERBOSE_DEBUG 0 - -#if VERBOSE_DEBUG -#define dev_vdbg dev_dbg -#else -#define dev_vdbg(dev, fmt, args...) do { } while (0) -#endif #ifdef CONFIG_HOTPLUG diff --git a/include/linux/device.h b/include/linux/device.h index be2debed70d2..d9f0a57f5a2f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -572,6 +572,16 @@ dev_dbg(struct device * dev, const char * fmt, ...) } #endif +#ifdef VERBOSE_DEBUG +#define dev_vdbg dev_dbg +#else +static inline int __attribute__ ((format (printf, 2, 3))) +dev_vdbg(struct device * dev, const char * fmt, ...) +{ + return 0; +} +#endif + #define dev_err(dev, format, arg...) \ dev_printk(KERN_ERR , dev , format , ## arg) #define dev_info(dev, format, arg...) \ -- cgit v1.2.3 From 6b09448ab81e90e59c09cfbc6d0d612dc84a2b1d Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 13 Jul 2007 16:32:09 -0700 Subject: dev_vdbg() documentation Update CodingStyle to talk about "-DDEBUG" message conventions and the new "-DVERBOSE_DEBUG" convention. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/CodingStyle | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index a667eb1fc26e..7f1730f1a1ae 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -633,12 +633,27 @@ covers RTL which is used frequently with assembly language in the kernel. Kernel developers like to be seen as literate. Do mind the spelling of kernel messages to make a good impression. Do not use crippled -words like "dont" and use "do not" or "don't" instead. +words like "dont"; use "do not" or "don't" instead. Make the messages +concise, clear, and unambiguous. Kernel messages do not have to be terminated with a period. Printing numbers in parentheses (%d) adds no value and should be avoided. +There are a number of driver model diagnostic macros in +which you should use to make sure messages are matched to the right device +and driver, and are tagged with the right level: dev_err(), dev_warn(), +dev_info(), and so forth. For messages that aren't associated with a +particular device, defines pr_debug() and pr_info(). + +Coming up with good debugging messages can be quite a challenge; and once +you have them, they can be a huge help for remote troubleshooting. Such +messages should be compiled out when the DEBUG symbol is not defined (that +is, by default they are not included). When you use dev_dbg() or pr_debug(), +that's automatic. Many subsystems have Kconfig options to turn on -DDEBUG. +A related convention uses VERBOSE_DEBUG to add dev_vdbg() messages to the +ones already enabled by DEBUG. + Chapter 14: Allocating memory @@ -790,4 +805,5 @@ Kernel CodingStyle, by greg@kroah.com at OLS 2002: http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ -- -Last updated on 2006-December-06. +Last updated on 2007-July-13. + -- cgit v1.2.3 From be3884943674f8ee7656b1d8b71c087ec900c836 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Mon, 16 Jul 2007 23:55:05 +0200 Subject: HOWTO: Add the knwon_regression URI to the documentation We should let everybody know about where the regression list is hosted. The more is known the more it is used. Signed-off-by: Paolo Ciarrocchi Cc: Li Yang Cc: TripleX Chung Cc: Maggie Chen Cc: WANG Cong Cc: Tsugikazu Shibata Cc: IKEDA Munehiro Signed-off-by: Greg Kroah-Hartman --- Documentation/HOWTO | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/HOWTO b/Documentation/HOWTO index 98e2701c746f..f8cc3f8ed152 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO @@ -249,6 +249,9 @@ process is as follows: release a new -rc kernel every week. - Process continues until the kernel is considered "ready", the process should last around 6 weeks. + - A list of known regressions present in each -rc release is + tracked at the following URI: + http://kernelnewbies.org/known_regressions It is worth mentioning what Andrew Morton wrote on the linux-kernel mailing list about kernel releases: -- cgit v1.2.3 From 2ee97caf0a6602f749ddbfdb1449e383e1212707 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 18 Jul 2007 01:43:47 -0700 Subject: Driver core: check return code of sysfs_create_link() Check for return value of sysfs_create_link() in device_add() and device_rename(). Add helper functions device_add_class_symlinks() and device_remove_class_symlinks() to make the code easier to read. [akpm@linux-foundation.org: fix unused var warnings] Signed-off-by: Cornelia Huck Acked-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 145 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 40 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 91a0367d583e..3599ab2506d2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -660,6 +660,82 @@ static int setup_parent(struct device *dev, struct device *parent) return 0; } +static int device_add_class_symlinks(struct device *dev) +{ + int error; + + if (!dev->class) + return 0; + error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj, + "subsystem"); + if (error) + goto out; + /* + * If this is not a "fake" compatible device, then create the + * symlink from the class to the device. + */ + if (dev->kobj.parent != &dev->class->subsys.kobj) { + error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, + dev->bus_id); + if (error) + goto out_subsys; + } + /* only bus-device parents get a "device"-link */ + if (dev->parent && dev->parent->bus) { + error = sysfs_create_link(&dev->kobj, &dev->parent->kobj, + "device"); + if (error) + goto out_busid; +#ifdef CONFIG_SYSFS_DEPRECATED + { + char * class_name = make_class_name(dev->class->name, + &dev->kobj); + if (class_name) + error = sysfs_create_link(&dev->parent->kobj, + &dev->kobj, class_name); + kfree(class_name); + if (error) + goto out_device; + } +#endif + } + return 0; + +#ifdef CONFIG_SYSFS_DEPRECATED +out_device: + if (dev->parent) + sysfs_remove_link(&dev->kobj, "device"); +#endif +out_busid: + if (dev->kobj.parent != &dev->class->subsys.kobj) + sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); +out_subsys: + sysfs_remove_link(&dev->kobj, "subsystem"); +out: + return error; +} + +static void device_remove_class_symlinks(struct device *dev) +{ + if (!dev->class) + return; + if (dev->parent) { +#ifdef CONFIG_SYSFS_DEPRECATED + char *class_name; + + class_name = make_class_name(dev->class->name, &dev->kobj); + if (class_name) { + sysfs_remove_link(&dev->parent->kobj, class_name); + kfree(class_name); + } +#endif + sysfs_remove_link(&dev->kobj, "device"); + } + if (dev->kobj.parent != &dev->class->subsys.kobj) + sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); + sysfs_remove_link(&dev->kobj, "subsystem"); +} + /** * device_add - add device to device hierarchy. * @dev: device. @@ -674,7 +750,6 @@ static int setup_parent(struct device *dev, struct device *parent) int device_add(struct device *dev) { struct device *parent = NULL; - char *class_name = NULL; struct class_interface *class_intf; int error = -EINVAL; @@ -714,27 +789,9 @@ int device_add(struct device *dev) goto ueventattrError; } - if (dev->class) { - sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj, - "subsystem"); - /* If this is not a "fake" compatible device, then create the - * symlink from the class to the device. */ - if (dev->kobj.parent != &dev->class->subsys.kobj) - sysfs_create_link(&dev->class->subsys.kobj, - &dev->kobj, dev->bus_id); - if (parent) { - sysfs_create_link(&dev->kobj, &dev->parent->kobj, - "device"); -#ifdef CONFIG_SYSFS_DEPRECATED - class_name = make_class_name(dev->class->name, - &dev->kobj); - if (class_name) - sysfs_create_link(&dev->parent->kobj, - &dev->kobj, class_name); -#endif - } - } - + error = device_add_class_symlinks(dev); + if (error) + goto SymlinkError; error = device_add_attrs(dev); if (error) goto AttrsError; @@ -761,7 +818,6 @@ int device_add(struct device *dev) up(&dev->class->sem); } Done: - kfree(class_name); put_device(dev); return error; BusError: @@ -772,6 +828,8 @@ int device_add(struct device *dev) BUS_NOTIFY_DEL_DEVICE, dev); device_remove_attrs(dev); AttrsError: + device_remove_class_symlinks(dev); + SymlinkError: if (MAJOR(dev->devt)) device_remove_file(dev, &devt_attr); @@ -1156,7 +1214,7 @@ int device_rename(struct device *dev, char *new_name) { char *old_class_name = NULL; char *new_class_name = NULL; - char *old_symlink_name = NULL; + char *old_device_name = NULL; int error; dev = get_device(dev); @@ -1170,42 +1228,49 @@ int device_rename(struct device *dev, char *new_name) old_class_name = make_class_name(dev->class->name, &dev->kobj); #endif - if (dev->class) { - old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); - if (!old_symlink_name) { - error = -ENOMEM; - goto out_free_old_class; - } - strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE); + old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); + if (!old_device_name) { + error = -ENOMEM; + goto out; } - + strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE); strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); error = kobject_rename(&dev->kobj, new_name); + if (error) { + strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE); + goto out; + } #ifdef CONFIG_SYSFS_DEPRECATED if (old_class_name) { new_class_name = make_class_name(dev->class->name, &dev->kobj); if (new_class_name) { - sysfs_create_link(&dev->parent->kobj, &dev->kobj, - new_class_name); + error = sysfs_create_link(&dev->parent->kobj, + &dev->kobj, new_class_name); + if (error) + goto out; sysfs_remove_link(&dev->parent->kobj, old_class_name); } } #endif if (dev->class) { - sysfs_remove_link(&dev->class->subsys.kobj, - old_symlink_name); - sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, - dev->bus_id); + sysfs_remove_link(&dev->class->subsys.kobj, old_device_name); + error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, + dev->bus_id); + if (error) { + /* Uh... how to unravel this if restoring can fail? */ + dev_err(dev, "%s: sysfs_create_symlink failed (%d)\n", + __FUNCTION__, error); + } } +out: put_device(dev); kfree(new_class_name); - kfree(old_symlink_name); - out_free_old_class: kfree(old_class_name); + kfree(old_device_name); return error; } -- cgit v1.2.3 From a1da4dfe35bc36c3bc9716d995c85b7983c38a76 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 18 Jul 2007 16:14:45 +0900 Subject: sysfs: kill an extra put in sysfs_create_link() failure path There is a subtle bug in sysfs_create_link() failure path. When symlink creation fails because there's already a node with the same name, the target sysfs_dirent is put twice - once by failure path of sysfs_create_link() and once more when the symlink is released. Fix it by making only the symlink node responsible for putting target_sd. Signed-off-by: Tejun Heo Cc: Gabriel C Cc: Miles Lane Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/symlink.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 2f86e0422290..d056e9695cd6 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -86,7 +86,9 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); if (!sd) goto out_put; + sd->s_elem.symlink.target_sd = target_sd; + target_sd = NULL; /* reference is now owned by the symlink */ sysfs_addrm_start(&acxt, parent_sd); -- cgit v1.2.3 From 967e35dcc9ac194b4a6fad69a5a51f93d69bb0d1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 18 Jul 2007 16:38:11 +0900 Subject: sysfs: cosmetic clean up on node creation failure paths Node addition failure is detected by testing return value of sysfs_addfm_finish() which returns the number of added and removed nodes. As the function is called as the last step of addition right on top of error handling block, the if blocks looked like the following. if (sysfs_addrm_finish(&acxt)) success handling, usually return; /* fall through to error handling */ This is the opposite of usual convention in sysfs and makes the code difficult to understand. This patch inverts the test and makes those blocks look more like others. Signed-off-by: Tejun Heo Cc: Gabriel C Cc: Miles Lane Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 12 +++++++----- fs/sysfs/file.c | 9 +++++---- fs/sysfs/symlink.c | 10 ++++++---- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 2e6775a836f2..048e6054c2fd 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -699,17 +699,19 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, /* link in */ sysfs_addrm_start(&acxt, parent_sd); + if (!sysfs_find_dirent(parent_sd, name)) { sysfs_add_one(&acxt, sd); sysfs_link_sibling(sd); } - if (sysfs_addrm_finish(&acxt)) { - *p_sd = sd; - return 0; + + if (!sysfs_addrm_finish(&acxt)) { + sysfs_put(sd); + return -EEXIST; } - sysfs_put(sd); - return -EEXIST; + *p_sd = sd; + return 0; } int sysfs_create_subdir(struct kobject *kobj, const char *name, diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index cc497994b2a8..3e1cc062a740 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -410,11 +410,12 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, sysfs_link_sibling(sd); } - if (sysfs_addrm_finish(&acxt)) - return 0; + if (!sysfs_addrm_finish(&acxt)) { + sysfs_put(sd); + return -EEXIST; + } - sysfs_put(sd); - return -EEXIST; + return 0; } diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index d056e9695cd6..4ce687f0b5d0 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -97,11 +97,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char sysfs_link_sibling(sd); } - if (sysfs_addrm_finish(&acxt)) - return 0; + if (!sysfs_addrm_finish(&acxt)) { + error = -EEXIST; + goto out_put; + } + + return 0; - error = -EEXIST; - /* fall through */ out_put: sysfs_put(target_sd); sysfs_put(sd); -- cgit v1.2.3