diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-13 17:05:13 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-13 17:05:13 -0500 |
commit | a9f138b0e537de55933335d580ebd38c2bc53c47 (patch) | |
tree | f54235f920d392519bde975d42aa4b4534f9561a | |
parent | 8634c422c1b7e50ca8e346f65afc140d93a3212c (diff) |
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>
-rw-r--r-- | drivers/base/core.c | 17 | ||||
-rw-r--r-- | fs/kernfs/dir.c | 72 | ||||
-rw-r--r-- | fs/sysfs/file.c | 23 | ||||
-rw-r--r-- | include/linux/device.h | 2 | ||||
-rw-r--r-- | include/linux/kernfs.h | 6 | ||||
-rw-r--r-- | include/linux/sysfs.h | 7 |
6 files changed, 0 insertions, 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 | |||
@@ -571,23 +571,6 @@ void device_remove_file(struct device *dev, | |||
571 | EXPORT_SYMBOL_GPL(device_remove_file); | 571 | EXPORT_SYMBOL_GPL(device_remove_file); |
572 | 572 | ||
573 | /** | 573 | /** |
574 | * device_remove_file_self - remove sysfs attribute file from its own method. | ||
575 | * @dev: device. | ||
576 | * @attr: device attribute descriptor. | ||
577 | * | ||
578 | * See kernfs_remove_self() for details. | ||
579 | */ | ||
580 | bool device_remove_file_self(struct device *dev, | ||
581 | const struct device_attribute *attr) | ||
582 | { | ||
583 | if (dev) | ||
584 | return sysfs_remove_file_self(&dev->kobj, &attr->attr); | ||
585 | else | ||
586 | return false; | ||
587 | } | ||
588 | EXPORT_SYMBOL_GPL(device_remove_file_self); | ||
589 | |||
590 | /** | ||
591 | * device_create_bin_file - create sysfs binary attribute file for device. | 574 | * device_create_bin_file - create sysfs binary attribute file for device. |
592 | * @dev: device. | 575 | * @dev: device. |
593 | * @attr: device binary attribute descriptor. | 576 | * @attr: device binary attribute descriptor. |
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) | |||
986 | } | 986 | } |
987 | 987 | ||
988 | /** | 988 | /** |
989 | * kernfs_remove_self - remove a kernfs_node from its own method | ||
990 | * @kn: the self kernfs_node to remove | ||
991 | * | ||
992 | * The caller must be running off of a kernfs operation which is invoked | ||
993 | * with an active reference - e.g. one of kernfs_ops. This can be used to | ||
994 | * implement a file operation which deletes itself. | ||
995 | * | ||
996 | * For example, the "delete" file for a sysfs device directory can be | ||
997 | * implemented by invoking kernfs_remove_self() on the "delete" file | ||
998 | * itself. This function breaks the circular dependency of trying to | ||
999 | * deactivate self while holding an active ref itself. It isn't necessary | ||
1000 | * to modify the usual removal path to use kernfs_remove_self(). The | ||
1001 | * "delete" implementation can simply invoke kernfs_remove_self() on self | ||
1002 | * before proceeding with the usual removal path. kernfs will ignore later | ||
1003 | * kernfs_remove() on self. | ||
1004 | * | ||
1005 | * kernfs_remove_self() can be called multiple times concurrently on the | ||
1006 | * same kernfs_node. Only the first one actually performs removal and | ||
1007 | * returns %true. All others will wait until the kernfs operation which | ||
1008 | * won self-removal finishes and return %false. Note that the losers wait | ||
1009 | * for the completion of not only the winning kernfs_remove_self() but also | ||
1010 | * the whole kernfs_ops which won the arbitration. This can be used to | ||
1011 | * guarantee, for example, all concurrent writes to a "delete" file to | ||
1012 | * finish only after the whole operation is complete. | ||
1013 | */ | ||
1014 | bool kernfs_remove_self(struct kernfs_node *kn) | ||
1015 | { | ||
1016 | bool ret; | ||
1017 | |||
1018 | mutex_lock(&kernfs_mutex); | ||
1019 | __kernfs_deactivate_self(kn); | ||
1020 | |||
1021 | /* | ||
1022 | * SUICIDAL is used to arbitrate among competing invocations. Only | ||
1023 | * the first one will actually perform removal. When the removal | ||
1024 | * is complete, SUICIDED is set and the active ref is restored | ||
1025 | * while holding kernfs_mutex. The ones which lost arbitration | ||
1026 | * waits for SUICDED && drained which can happen only after the | ||
1027 | * enclosing kernfs operation which executed the winning instance | ||
1028 | * of kernfs_remove_self() finished. | ||
1029 | */ | ||
1030 | if (!(kn->flags & KERNFS_SUICIDAL)) { | ||
1031 | kn->flags |= KERNFS_SUICIDAL; | ||
1032 | __kernfs_remove(kn); | ||
1033 | kn->flags |= KERNFS_SUICIDED; | ||
1034 | ret = true; | ||
1035 | } else { | ||
1036 | wait_queue_head_t *waitq = &kernfs_root(kn)->deactivate_waitq; | ||
1037 | DEFINE_WAIT(wait); | ||
1038 | |||
1039 | while (true) { | ||
1040 | prepare_to_wait(waitq, &wait, TASK_UNINTERRUPTIBLE); | ||
1041 | |||
1042 | if ((kn->flags & KERNFS_SUICIDED) && | ||
1043 | atomic_read(&kn->active) == KN_DEACTIVATED_BIAS) | ||
1044 | break; | ||
1045 | |||
1046 | mutex_unlock(&kernfs_mutex); | ||
1047 | schedule(); | ||
1048 | mutex_lock(&kernfs_mutex); | ||
1049 | } | ||
1050 | finish_wait(waitq, &wait); | ||
1051 | WARN_ON_ONCE(!RB_EMPTY_NODE(&kn->rb)); | ||
1052 | ret = false; | ||
1053 | } | ||
1054 | |||
1055 | __kernfs_reactivate_self(kn); | ||
1056 | mutex_unlock(&kernfs_mutex); | ||
1057 | return ret; | ||
1058 | } | ||
1059 | |||
1060 | /** | ||
1061 | * kernfs_remove_by_name_ns - find a kernfs_node by name and remove it | 989 | * kernfs_remove_by_name_ns - find a kernfs_node by name and remove it |
1062 | * @parent: parent of the target | 990 | * @parent: parent of the target |
1063 | * @name: name of the kernfs_node to remove | 991 | * @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, | |||
372 | } | 372 | } |
373 | EXPORT_SYMBOL_GPL(sysfs_remove_file_ns); | 373 | EXPORT_SYMBOL_GPL(sysfs_remove_file_ns); |
374 | 374 | ||
375 | /** | ||
376 | * sysfs_remove_file_self - remove an object attribute from its own method | ||
377 | * @kobj: object we're acting for | ||
378 | * @attr: attribute descriptor | ||
379 | * | ||
380 | * See kernfs_remove_self() for details. | ||
381 | */ | ||
382 | bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr) | ||
383 | { | ||
384 | struct kernfs_node *parent = kobj->sd; | ||
385 | struct kernfs_node *kn; | ||
386 | bool ret; | ||
387 | |||
388 | kn = kernfs_find_and_get(parent, attr->name); | ||
389 | if (WARN_ON_ONCE(!kn)) | ||
390 | return false; | ||
391 | |||
392 | ret = kernfs_remove_self(kn); | ||
393 | |||
394 | kernfs_put(kn); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr) | 375 | void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr) |
399 | { | 376 | { |
400 | int i; | 377 | 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, | |||
560 | const struct device_attribute *entry); | 560 | const struct device_attribute *entry); |
561 | extern void device_remove_file(struct device *dev, | 561 | extern void device_remove_file(struct device *dev, |
562 | const struct device_attribute *attr); | 562 | const struct device_attribute *attr); |
563 | extern bool device_remove_file_self(struct device *dev, | ||
564 | const struct device_attribute *attr); | ||
565 | extern int __must_check device_create_bin_file(struct device *dev, | 563 | extern int __must_check device_create_bin_file(struct device *dev, |
566 | const struct bin_attribute *attr); | 564 | const struct bin_attribute *attr); |
567 | extern void device_remove_bin_file(struct device *dev, | 565 | 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 { | |||
43 | KERNFS_HAS_MMAP = 0x0080, | 43 | KERNFS_HAS_MMAP = 0x0080, |
44 | KERNFS_LOCKDEP = 0x0100, | 44 | KERNFS_LOCKDEP = 0x0100, |
45 | KERNFS_STATIC_NAME = 0x0200, | 45 | KERNFS_STATIC_NAME = 0x0200, |
46 | KERNFS_SUICIDAL = 0x0400, | ||
47 | KERNFS_SUICIDED = 0x0800, | ||
48 | }; | 46 | }; |
49 | 47 | ||
50 | /* type-specific structures for kernfs_node union members */ | 48 | /* type-specific structures for kernfs_node union members */ |
@@ -241,7 +239,6 @@ void kernfs_reactivate(struct kernfs_node *kn); | |||
241 | void kernfs_deactivate_self(struct kernfs_node *kn); | 239 | void kernfs_deactivate_self(struct kernfs_node *kn); |
242 | void kernfs_reactivate_self(struct kernfs_node *kn); | 240 | void kernfs_reactivate_self(struct kernfs_node *kn); |
243 | void kernfs_remove(struct kernfs_node *kn); | 241 | void kernfs_remove(struct kernfs_node *kn); |
244 | bool kernfs_remove_self(struct kernfs_node *kn); | ||
245 | int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, | 242 | int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, |
246 | const void *ns); | 243 | const void *ns); |
247 | int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, | 244 | 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, | |||
299 | 296 | ||
300 | static inline void kernfs_remove(struct kernfs_node *kn) { } | 297 | static inline void kernfs_remove(struct kernfs_node *kn) { } |
301 | 298 | ||
302 | static inline bool kernfs_remove_self(struct kernfs_node *kn) | ||
303 | { return false; } | ||
304 | |||
305 | static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn, | 299 | static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn, |
306 | const char *name, const void *ns) | 300 | const char *name, const void *ns) |
307 | { return -ENOSYS; } | 301 | { 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, | |||
198 | const struct attribute *attr, umode_t mode); | 198 | const struct attribute *attr, umode_t mode); |
199 | void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, | 199 | void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, |
200 | const void *ns); | 200 | const void *ns); |
201 | bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr); | ||
202 | void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); | 201 | void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); |
203 | 202 | ||
204 | int __must_check sysfs_create_bin_file(struct kobject *kobj, | 203 | int __must_check sysfs_create_bin_file(struct kobject *kobj, |
@@ -302,12 +301,6 @@ static inline void sysfs_remove_file_ns(struct kobject *kobj, | |||
302 | { | 301 | { |
303 | } | 302 | } |
304 | 303 | ||
305 | static inline bool sysfs_remove_file_self(struct kobject *kobj, | ||
306 | const struct attribute *attr) | ||
307 | { | ||
308 | return false; | ||
309 | } | ||
310 | |||
311 | static inline void sysfs_remove_files(struct kobject *kobj, | 304 | static inline void sysfs_remove_files(struct kobject *kobj, |
312 | const struct attribute **attr) | 305 | const struct attribute **attr) |
313 | { | 306 | { |