···332332 parent = debugfs_mount->mnt_root;333333334334 inode_lock(d_inode(parent));335335- dentry = lookup_one_len(name, parent, strlen(name));335335+ if (unlikely(IS_DEADDIR(d_inode(parent))))336336+ dentry = ERR_PTR(-ENOENT);337337+ else338338+ dentry = lookup_one_len(name, parent, strlen(name));336339 if (!IS_ERR(dentry) && d_really_is_positive(dentry)) {337340 if (d_is_dir(dentry))338341 pr_err("Directory '%s' with parent '%s' already present!\n",···684681 wait_for_completion(&fsd->active_users_drained);685682}686683687687-static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)684684+static void remove_one(struct dentry *victim)688685{689689- int ret = 0;690690-691691- if (simple_positive(dentry)) {692692- dget(dentry);693693- if (d_is_dir(dentry)) {694694- ret = simple_rmdir(d_inode(parent), dentry);695695- if (!ret)696696- fsnotify_rmdir(d_inode(parent), dentry);697697- } else {698698- simple_unlink(d_inode(parent), dentry);699699- fsnotify_unlink(d_inode(parent), dentry);700700- }701701- if (!ret)702702- d_delete(dentry);703703- if (d_is_reg(dentry))704704- __debugfs_file_removed(dentry);705705- dput(dentry);706706- }707707- return ret;686686+ if (d_is_reg(victim))687687+ __debugfs_file_removed(victim);688688+ simple_release_fs(&debugfs_mount, &debugfs_mount_count);708689}709690710691/**711711- * debugfs_remove - removes a file or directory from the debugfs filesystem712712- * @dentry: a pointer to a the dentry of the file or directory to be713713- * removed. If this parameter is NULL or an error value, nothing714714- * will be done.715715- *716716- * This function removes a file or directory in debugfs that was previously717717- * created with a call to another debugfs function (like718718- * debugfs_create_file() or variants thereof.)719719- *720720- * This function is required to be called in order for the file to be721721- * removed, no automatic cleanup of files will happen when a module is722722- * removed, you are responsible here.723723- */724724-void debugfs_remove(struct dentry *dentry)725725-{726726- struct dentry *parent;727727- int ret;728728-729729- if (IS_ERR_OR_NULL(dentry))730730- return;731731-732732- parent = dentry->d_parent;733733- inode_lock(d_inode(parent));734734- ret = __debugfs_remove(dentry, parent);735735- inode_unlock(d_inode(parent));736736- if (!ret)737737- simple_release_fs(&debugfs_mount, &debugfs_mount_count);738738-}739739-EXPORT_SYMBOL_GPL(debugfs_remove);740740-741741-/**742742- * debugfs_remove_recursive - recursively removes a directory692692+ * debugfs_remove - recursively removes a directory743693 * @dentry: a pointer to a the dentry of the directory to be removed. If this744694 * parameter is NULL or an error value, nothing will be done.745695 *···704748 * removed, no automatic cleanup of files will happen when a module is705749 * removed, you are responsible here.706750 */707707-void debugfs_remove_recursive(struct dentry *dentry)751751+void debugfs_remove(struct dentry *dentry)708752{709709- struct dentry *child, *parent;710710-711753 if (IS_ERR_OR_NULL(dentry))712754 return;713755714714- parent = dentry;715715- down:716716- inode_lock(d_inode(parent));717717- loop:718718- /*719719- * The parent->d_subdirs is protected by the d_lock. Outside that720720- * lock, the child can be unlinked and set to be freed which can721721- * use the d_u.d_child as the rcu head and corrupt this list.722722- */723723- spin_lock(&parent->d_lock);724724- list_for_each_entry(child, &parent->d_subdirs, d_child) {725725- if (!simple_positive(child))726726- continue;727727-728728- /* perhaps simple_empty(child) makes more sense */729729- if (!list_empty(&child->d_subdirs)) {730730- spin_unlock(&parent->d_lock);731731- inode_unlock(d_inode(parent));732732- parent = child;733733- goto down;734734- }735735-736736- spin_unlock(&parent->d_lock);737737-738738- if (!__debugfs_remove(child, parent))739739- simple_release_fs(&debugfs_mount, &debugfs_mount_count);740740-741741- /*742742- * The parent->d_lock protects agaist child from unlinking743743- * from d_subdirs. When releasing the parent->d_lock we can744744- * no longer trust that the next pointer is valid.745745- * Restart the loop. We'll skip this one with the746746- * simple_positive() check.747747- */748748- goto loop;749749- }750750- spin_unlock(&parent->d_lock);751751-752752- inode_unlock(d_inode(parent));753753- child = parent;754754- parent = parent->d_parent;755755- inode_lock(d_inode(parent));756756-757757- if (child != dentry)758758- /* go up */759759- goto loop;760760-761761- if (!__debugfs_remove(child, parent))762762- simple_release_fs(&debugfs_mount, &debugfs_mount_count);763763- inode_unlock(d_inode(parent));756756+ simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count);757757+ simple_recursive_removal(dentry, remove_one);758758+ simple_release_fs(&debugfs_mount, &debugfs_mount_count);764759}765765-EXPORT_SYMBOL_GPL(debugfs_remove_recursive);760760+EXPORT_SYMBOL_GPL(debugfs_remove);766761767762/**768763 * debugfs_rename - rename a file/directory in the debugfs filesystem
···330330 parent = tracefs_mount->mnt_root;331331332332 inode_lock(parent->d_inode);333333- dentry = lookup_one_len(name, parent, strlen(name));333333+ if (unlikely(IS_DEADDIR(parent->d_inode)))334334+ dentry = ERR_PTR(-ENOENT);335335+ else336336+ dentry = lookup_one_len(name, parent, strlen(name));334337 if (!IS_ERR(dentry) && dentry->d_inode) {335338 dput(dentry);336339 dentry = ERR_PTR(-EEXIST);···502499 return dentry;503500}504501505505-static int __tracefs_remove(struct dentry *dentry, struct dentry *parent)502502+static void remove_one(struct dentry *victim)506503{507507- int ret = 0;508508-509509- if (simple_positive(dentry)) {510510- if (dentry->d_inode) {511511- dget(dentry);512512- switch (dentry->d_inode->i_mode & S_IFMT) {513513- case S_IFDIR:514514- ret = simple_rmdir(parent->d_inode, dentry);515515- if (!ret)516516- fsnotify_rmdir(parent->d_inode, dentry);517517- break;518518- default:519519- simple_unlink(parent->d_inode, dentry);520520- fsnotify_unlink(parent->d_inode, dentry);521521- break;522522- }523523- if (!ret)524524- d_delete(dentry);525525- dput(dentry);526526- }527527- }528528- return ret;504504+ simple_release_fs(&tracefs_mount, &tracefs_mount_count);529505}530506531507/**532532- * tracefs_remove - removes a file or directory from the tracefs filesystem533533- * @dentry: a pointer to a the dentry of the file or directory to be534534- * removed.535535- *536536- * This function removes a file or directory in tracefs that was previously537537- * created with a call to another tracefs function (like538538- * tracefs_create_file() or variants thereof.)539539- */540540-void tracefs_remove(struct dentry *dentry)541541-{542542- struct dentry *parent;543543- int ret;544544-545545- if (IS_ERR_OR_NULL(dentry))546546- return;547547-548548- parent = dentry->d_parent;549549- inode_lock(parent->d_inode);550550- ret = __tracefs_remove(dentry, parent);551551- inode_unlock(parent->d_inode);552552- if (!ret)553553- simple_release_fs(&tracefs_mount, &tracefs_mount_count);554554-}555555-556556-/**557557- * tracefs_remove_recursive - recursively removes a directory508508+ * tracefs_remove - recursively removes a directory558509 * @dentry: a pointer to a the dentry of the directory to be removed.559510 *560511 * This function recursively removes a directory tree in tracefs that561512 * was previously created with a call to another tracefs function562513 * (like tracefs_create_file() or variants thereof.)563514 */564564-void tracefs_remove_recursive(struct dentry *dentry)515515+void tracefs_remove(struct dentry *dentry)565516{566566- struct dentry *child, *parent;567567-568517 if (IS_ERR_OR_NULL(dentry))569518 return;570519571571- parent = dentry;572572- down:573573- inode_lock(parent->d_inode);574574- loop:575575- /*576576- * The parent->d_subdirs is protected by the d_lock. Outside that577577- * lock, the child can be unlinked and set to be freed which can578578- * use the d_u.d_child as the rcu head and corrupt this list.579579- */580580- spin_lock(&parent->d_lock);581581- list_for_each_entry(child, &parent->d_subdirs, d_child) {582582- if (!simple_positive(child))583583- continue;584584-585585- /* perhaps simple_empty(child) makes more sense */586586- if (!list_empty(&child->d_subdirs)) {587587- spin_unlock(&parent->d_lock);588588- inode_unlock(parent->d_inode);589589- parent = child;590590- goto down;591591- }592592-593593- spin_unlock(&parent->d_lock);594594-595595- if (!__tracefs_remove(child, parent))596596- simple_release_fs(&tracefs_mount, &tracefs_mount_count);597597-598598- /*599599- * The parent->d_lock protects agaist child from unlinking600600- * from d_subdirs. When releasing the parent->d_lock we can601601- * no longer trust that the next pointer is valid.602602- * Restart the loop. We'll skip this one with the603603- * simple_positive() check.604604- */605605- goto loop;606606- }607607- spin_unlock(&parent->d_lock);608608-609609- inode_unlock(parent->d_inode);610610- child = parent;611611- parent = parent->d_parent;612612- inode_lock(parent->d_inode);613613-614614- if (child != dentry)615615- /* go up */616616- goto loop;617617-618618- if (!__tracefs_remove(child, parent))619619- simple_release_fs(&tracefs_mount, &tracefs_mount_count);620620- inode_unlock(parent->d_inode);520520+ simple_pin_fs(&trace_fs_type, &tracefs_mount, &tracefs_mount_count);521521+ simple_recursive_removal(dentry, remove_one);522522+ simple_release_fs(&tracefs_mount, &tracefs_mount_count);621523}622524623525/**