|
@@ -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
|