Revert "eventfs: Use simple_recursive_removal() to clean up dentries"
This reverts commit 055907ad2c14838c90d63297f7bab8d180a5d844. The eventfs was not designed properly and may have some hidden bugs in it. Linus rewrote it properly and I trust his version more than this one. Revert the backported patches for 6.6 and re-apply all the changes to make it equivalent to Linus's version. Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
5e9fb47619
commit
601daf7e31
@ -54,10 +54,12 @@ struct eventfs_file {
|
||||
/*
|
||||
* Union - used for deletion
|
||||
* @llist: for calling dput() if needed after RCU
|
||||
* @del_list: list of eventfs_file to delete
|
||||
* @rcu: eventfs_file to delete in RCU
|
||||
*/
|
||||
union {
|
||||
struct llist_node llist;
|
||||
struct list_head del_list;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
void *data;
|
||||
@ -274,6 +276,7 @@ static void free_ef(struct eventfs_file *ef)
|
||||
*/
|
||||
void eventfs_set_ef_status_free(struct tracefs_inode *ti, struct dentry *dentry)
|
||||
{
|
||||
struct tracefs_inode *ti_parent;
|
||||
struct eventfs_inode *ei;
|
||||
struct eventfs_file *ef;
|
||||
|
||||
@ -294,6 +297,10 @@ void eventfs_set_ef_status_free(struct tracefs_inode *ti, struct dentry *dentry)
|
||||
|
||||
mutex_lock(&eventfs_mutex);
|
||||
|
||||
ti_parent = get_tracefs(dentry->d_parent->d_inode);
|
||||
if (!ti_parent || !(ti_parent->flags & TRACEFS_EVENT_INODE))
|
||||
goto out;
|
||||
|
||||
ef = dentry->d_fsdata;
|
||||
if (!ef)
|
||||
goto out;
|
||||
@ -866,29 +873,30 @@ static void unhook_dentry(struct dentry *dentry)
|
||||
{
|
||||
if (!dentry)
|
||||
return;
|
||||
/*
|
||||
* Need to add a reference to the dentry that is expected by
|
||||
* simple_recursive_removal(), which will include a dput().
|
||||
*/
|
||||
|
||||
/* Keep the dentry from being freed yet (see eventfs_workfn()) */
|
||||
dget(dentry);
|
||||
|
||||
/*
|
||||
* Also add a reference for the dput() in eventfs_workfn().
|
||||
* That is required as that dput() will free the ei after
|
||||
* the SRCU grace period is over.
|
||||
*/
|
||||
dget(dentry);
|
||||
dentry->d_fsdata = NULL;
|
||||
d_invalidate(dentry);
|
||||
mutex_lock(&eventfs_mutex);
|
||||
/* dentry should now have at least a single reference */
|
||||
WARN_ONCE((int)d_count(dentry) < 1,
|
||||
"dentry %px (%s) less than one reference (%d) after invalidate\n",
|
||||
dentry, dentry->d_name.name, d_count(dentry));
|
||||
mutex_unlock(&eventfs_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* eventfs_remove_rec - remove eventfs dir or file from list
|
||||
* @ef: eventfs_file to be removed.
|
||||
* @head: to create list of eventfs_file to be deleted
|
||||
* @level: to check recursion depth
|
||||
*
|
||||
* The helper function eventfs_remove_rec() is used to clean up and free the
|
||||
* associated data from eventfs for both of the added functions.
|
||||
*/
|
||||
static void eventfs_remove_rec(struct eventfs_file *ef, int level)
|
||||
static void eventfs_remove_rec(struct eventfs_file *ef, struct list_head *head, int level)
|
||||
{
|
||||
struct eventfs_file *ef_child;
|
||||
|
||||
@ -908,16 +916,14 @@ static void eventfs_remove_rec(struct eventfs_file *ef, int level)
|
||||
/* search for nested folders or files */
|
||||
list_for_each_entry_srcu(ef_child, &ef->ei->e_top_files, list,
|
||||
lockdep_is_held(&eventfs_mutex)) {
|
||||
eventfs_remove_rec(ef_child, level + 1);
|
||||
eventfs_remove_rec(ef_child, head, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
ef->is_freed = 1;
|
||||
|
||||
unhook_dentry(ef->dentry);
|
||||
|
||||
list_del_rcu(&ef->list);
|
||||
call_srcu(&eventfs_srcu, &ef->rcu, free_rcu_ef);
|
||||
list_add_tail(&ef->del_list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -928,22 +934,28 @@ static void eventfs_remove_rec(struct eventfs_file *ef, int level)
|
||||
*/
|
||||
void eventfs_remove(struct eventfs_file *ef)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
struct eventfs_file *tmp;
|
||||
LIST_HEAD(ef_del_list);
|
||||
|
||||
if (!ef)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Move the deleted eventfs_inodes onto the ei_del_list
|
||||
* which will also set the is_freed value. Note, this has to be
|
||||
* done under the eventfs_mutex, but the deletions of
|
||||
* the dentries must be done outside the eventfs_mutex.
|
||||
* Hence moving them to this temporary list.
|
||||
*/
|
||||
mutex_lock(&eventfs_mutex);
|
||||
dentry = ef->dentry;
|
||||
eventfs_remove_rec(ef, 0);
|
||||
eventfs_remove_rec(ef, &ef_del_list, 0);
|
||||
mutex_unlock(&eventfs_mutex);
|
||||
|
||||
/*
|
||||
* If any of the ei children has a dentry, then the ei itself
|
||||
* must have a dentry.
|
||||
*/
|
||||
if (dentry)
|
||||
simple_recursive_removal(dentry, NULL);
|
||||
list_for_each_entry_safe(ef, tmp, &ef_del_list, del_list) {
|
||||
unhook_dentry(ef->dentry);
|
||||
list_del(&ef->del_list);
|
||||
call_srcu(&eventfs_srcu, &ef->rcu, free_rcu_ef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -954,8 +966,6 @@ void eventfs_remove(struct eventfs_file *ef)
|
||||
*/
|
||||
void eventfs_remove_events_dir(struct dentry *dentry)
|
||||
{
|
||||
struct eventfs_file *ef_child;
|
||||
struct eventfs_inode *ei;
|
||||
struct tracefs_inode *ti;
|
||||
|
||||
if (!dentry || !dentry->d_inode)
|
||||
@ -965,11 +975,6 @@ void eventfs_remove_events_dir(struct dentry *dentry)
|
||||
if (!ti || !(ti->flags & TRACEFS_EVENT_INODE))
|
||||
return;
|
||||
|
||||
mutex_lock(&eventfs_mutex);
|
||||
ei = ti->private;
|
||||
list_for_each_entry_srcu(ef_child, &ei->e_top_files, list,
|
||||
lockdep_is_held(&eventfs_mutex)) {
|
||||
eventfs_remove_rec(ef_child, 0);
|
||||
}
|
||||
mutex_unlock(&eventfs_mutex);
|
||||
d_invalidate(dentry);
|
||||
dput(dentry);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user