mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
Revert "kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers"
This reverts commit 1ae06819c7
.
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>
This commit is contained in:
parent
8634c422c1
commit
a9f138b0e5
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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; }
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user