diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-13 14:05:13 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-13 14:05:13 -0800 |
commit | a9f138b0e537de55933335d580ebd38c2bc53c47 (patch) | |
tree | f54235f920d392519bde975d42aa4b4534f9561a /fs | |
parent | 8634c422c1b7e50ca8e346f65afc140d93a3212c (diff) | |
download | linux-stable-a9f138b0e537de55933335d580ebd38c2bc53c47.tar.gz linux-stable-a9f138b0e537de55933335d580ebd38c2bc53c47.tar.bz2 linux-stable-a9f138b0e537de55933335d580ebd38c2bc53c47.zip |
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 <tj@kernel.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/kernfs/dir.c | 72 | ||||
-rw-r--r-- | fs/sysfs/file.c | 23 |
2 files changed, 0 insertions, 95 deletions
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 @@ -986,78 +986,6 @@ void kernfs_remove(struct kernfs_node *kn) } /** - * 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 * @name: name of the kernfs_node to remove 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; |