From a9f138b0e537de55933335d580ebd38c2bc53c47 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 13 Jan 2014 14:05:13 -0800 Subject: [PATCH] Revert "kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers" This reverts commit 1ae06819c77cff1ea2833c94f8c093fe8a5c79db. Tejun writes: I'm sorry but can you please revert the whole series? get_active() waiting while a node is deactivated has potential to lead to deadlock and that deactivate/reactivate interface is something fundamentally flawed and that cgroup will have to work with the remove_self() like everybody else. IOW, I think the first posting was correct. Cc: Tejun Heo Cc: Alan Stern Cc: kbuild test robot Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 17 ---------- fs/kernfs/dir.c | 72 ------------------------------------------ fs/sysfs/file.c | 23 -------------- include/linux/device.h | 2 -- include/linux/kernfs.h | 6 ---- include/linux/sysfs.h | 7 ---- 6 files changed, 127 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 9db57afcf81f..2b567177ef78 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -570,23 +570,6 @@ void device_remove_file(struct device *dev, } EXPORT_SYMBOL_GPL(device_remove_file); -/** - * device_remove_file_self - remove sysfs attribute file from its own method. - * @dev: device. - * @attr: device attribute descriptor. - * - * See kernfs_remove_self() for details. - */ -bool device_remove_file_self(struct device *dev, - const struct device_attribute *attr) -{ - if (dev) - return sysfs_remove_file_self(&dev->kobj, &attr->attr); - else - return false; -} -EXPORT_SYMBOL_GPL(device_remove_file_self); - /** * device_create_bin_file - create sysfs binary attribute file for device. * @dev: device. diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index a8028be6cdb7..1aeb57969bff 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -985,78 +985,6 @@ void kernfs_remove(struct kernfs_node *kn) mutex_unlock(&kernfs_mutex); } -/** - * kernfs_remove_self - remove a kernfs_node from its own method - * @kn: the self kernfs_node to remove - * - * The caller must be running off of a kernfs operation which is invoked - * with an active reference - e.g. one of kernfs_ops. This can be used to - * implement a file operation which deletes itself. - * - * For example, the "delete" file for a sysfs device directory can be - * implemented by invoking kernfs_remove_self() on the "delete" file - * itself. This function breaks the circular dependency of trying to - * deactivate self while holding an active ref itself. It isn't necessary - * to modify the usual removal path to use kernfs_remove_self(). The - * "delete" implementation can simply invoke kernfs_remove_self() on self - * before proceeding with the usual removal path. kernfs will ignore later - * kernfs_remove() on self. - * - * kernfs_remove_self() can be called multiple times concurrently on the - * same kernfs_node. Only the first one actually performs removal and - * returns %true. All others will wait until the kernfs operation which - * won self-removal finishes and return %false. Note that the losers wait - * for the completion of not only the winning kernfs_remove_self() but also - * the whole kernfs_ops which won the arbitration. This can be used to - * guarantee, for example, all concurrent writes to a "delete" file to - * finish only after the whole operation is complete. - */ -bool kernfs_remove_self(struct kernfs_node *kn) -{ - bool ret; - - mutex_lock(&kernfs_mutex); - __kernfs_deactivate_self(kn); - - /* - * SUICIDAL is used to arbitrate among competing invocations. Only - * the first one will actually perform removal. When the removal - * is complete, SUICIDED is set and the active ref is restored - * while holding kernfs_mutex. The ones which lost arbitration - * waits for SUICDED && drained which can happen only after the - * enclosing kernfs operation which executed the winning instance - * of kernfs_remove_self() finished. - */ - if (!(kn->flags & KERNFS_SUICIDAL)) { - kn->flags |= KERNFS_SUICIDAL; - __kernfs_remove(kn); - kn->flags |= KERNFS_SUICIDED; - ret = true; - } else { - wait_queue_head_t *waitq = &kernfs_root(kn)->deactivate_waitq; - DEFINE_WAIT(wait); - - while (true) { - prepare_to_wait(waitq, &wait, TASK_UNINTERRUPTIBLE); - - if ((kn->flags & KERNFS_SUICIDED) && - atomic_read(&kn->active) == KN_DEACTIVATED_BIAS) - break; - - mutex_unlock(&kernfs_mutex); - schedule(); - mutex_lock(&kernfs_mutex); - } - finish_wait(waitq, &wait); - WARN_ON_ONCE(!RB_EMPTY_NODE(&kn->rb)); - ret = false; - } - - __kernfs_reactivate_self(kn); - mutex_unlock(&kernfs_mutex); - return ret; -} - /** * kernfs_remove_by_name_ns - find a kernfs_node by name and remove it * @parent: parent of the target diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1b8b91b67fdb..810cf6e613e5 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -372,29 +372,6 @@ void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, } EXPORT_SYMBOL_GPL(sysfs_remove_file_ns); -/** - * sysfs_remove_file_self - remove an object attribute from its own method - * @kobj: object we're acting for - * @attr: attribute descriptor - * - * See kernfs_remove_self() for details. - */ -bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr) -{ - struct kernfs_node *parent = kobj->sd; - struct kernfs_node *kn; - bool ret; - - kn = kernfs_find_and_get(parent, attr->name); - if (WARN_ON_ONCE(!kn)) - return false; - - ret = kernfs_remove_self(kn); - - kernfs_put(kn); - return ret; -} - void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr) { int i; diff --git a/include/linux/device.h b/include/linux/device.h index 1ff3f1697513..952b01033c32 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -560,8 +560,6 @@ extern int device_create_file(struct device *device, const struct device_attribute *entry); extern void device_remove_file(struct device *dev, const struct device_attribute *attr); -extern bool device_remove_file_self(struct device *dev, - const struct device_attribute *attr); extern int __must_check device_create_bin_file(struct device *dev, const struct bin_attribute *attr); extern void device_remove_bin_file(struct device *dev, diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index 0b7b7cc352eb..ac8693027058 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h @@ -43,8 +43,6 @@ enum kernfs_node_flag { KERNFS_HAS_MMAP = 0x0080, KERNFS_LOCKDEP = 0x0100, KERNFS_STATIC_NAME = 0x0200, - KERNFS_SUICIDAL = 0x0400, - KERNFS_SUICIDED = 0x0800, }; /* type-specific structures for kernfs_node union members */ @@ -241,7 +239,6 @@ void kernfs_reactivate(struct kernfs_node *kn); void kernfs_deactivate_self(struct kernfs_node *kn); void kernfs_reactivate_self(struct kernfs_node *kn); void kernfs_remove(struct kernfs_node *kn); -bool kernfs_remove_self(struct kernfs_node *kn); int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, const void *ns); int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, @@ -299,9 +296,6 @@ kernfs_create_link(struct kernfs_node *parent, const char *name, static inline void kernfs_remove(struct kernfs_node *kn) { } -static inline bool kernfs_remove_self(struct kernfs_node *kn) -{ return false; } - static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn, const char *name, const void *ns) { return -ENOSYS; } diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index bd96c603ab6c..30b2ebee6439 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -198,7 +198,6 @@ int __must_check sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, umode_t mode); void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, const void *ns); -bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr); void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); int __must_check sysfs_create_bin_file(struct kobject *kobj, @@ -302,12 +301,6 @@ static inline void sysfs_remove_file_ns(struct kobject *kobj, { } -static inline bool sysfs_remove_file_self(struct kobject *kobj, - const struct attribute *attr) -{ - return false; -} - static inline void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr) {