From 5acb4d977a0c49411033414a8ba179e7b10cdb2b Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 18 Feb 2010 09:45:37 -0800 Subject: [PATCH] compat: backport debugfs_remove_recursive() This avoids using the internal globals by the internal kernel debugfs implementation. Signed-off-by: Pavel Roskin Signed-off-by: Luis R. Rodriguez --- compat/compat-2.6.26.c | 121 ++++++---------------------------- include/linux/compat-2.6.26.h | 4 +- 2 files changed, 22 insertions(+), 103 deletions(-) diff --git a/compat/compat-2.6.26.c b/compat/compat-2.6.26.c index c20ddd5d4014..82134c21235b 100644 --- a/compat/compat-2.6.26.c +++ b/compat/compat-2.6.26.c @@ -89,116 +89,37 @@ int dev_set_name(struct device *dev, const char *fmt, ...) } EXPORT_SYMBOL_GPL(dev_set_name); -#if 0 /* - * Below was an attempt to backport debugfs_remove_recursive() but as - * can be seen if enabled it cannot be backported since it relies on - * two static variables from fs/debugfs/inode.c . If you need backport - * this consider instead just disabling debugfs for drivers that use - * this for kernels < 2.6.26 - */ -static inline int debugfs_positive(struct dentry *dentry) -{ - return dentry->d_inode && !d_unhashed(dentry); -} - -static void __debugfs_remove(struct dentry *dentry, struct dentry *parent) -{ - int ret = 0; - - if (debugfs_positive(dentry)) { - if (dentry->d_inode) { - dget(dentry); - switch (dentry->d_inode->i_mode & S_IFMT) { - case S_IFDIR: - ret = simple_rmdir(parent->d_inode, dentry); - break; - case S_IFLNK: - kfree(dentry->d_inode->i_private); - /* fall through */ - default: - simple_unlink(parent->d_inode, dentry); - break; - } - if (!ret) - d_delete(dentry); - dput(dentry); - } - } -} - -/** - * debugfs_remove_recursive - recursively removes a directory - * @dentry: a pointer to a the dentry of the directory to be removed. - * - * This function recursively removes a directory tree in debugfs that - * was previously created with a call to another debugfs function - * (like debugfs_create_file() or variants thereof.) - * - * This function is required to be called in order for the file to be - * removed, no automatic cleanup of files will happen when a module is - * removed, you are responsible here. + * Backport of debugfs_remove_recursive() without using the internals globals + * which are used by the kernel's version with: + * simple_release_fs(&debugfs_mount, &debugfs_mount_count); */ void debugfs_remove_recursive(struct dentry *dentry) { - struct dentry *child; - struct dentry *parent; + struct dentry *last = NULL; - if (!dentry) + /* Sanity checks */ + if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode) return; - parent = dentry->d_parent; - if (!parent || !parent->d_inode) - return; + while (dentry != last) { + struct dentry *child = dentry; - parent = dentry; - mutex_lock(&parent->d_inode->i_mutex); - - while (1) { - /* - * When all dentries under "parent" has been removed, - * walk up the tree until we reach our starting point. - */ - if (list_empty(&parent->d_subdirs)) { - mutex_unlock(&parent->d_inode->i_mutex); - if (parent == dentry) - break; - parent = parent->d_parent; - mutex_lock(&parent->d_inode->i_mutex); - } - child = list_entry(parent->d_subdirs.next, struct dentry, - d_u.d_child); - - /* - * If "child" isn't empty, walk down the tree and - * remove all its descendants first. - */ - if (!list_empty(&child->d_subdirs)) { - mutex_unlock(&parent->d_inode->i_mutex); - parent = child; - mutex_lock(&parent->d_inode->i_mutex); - continue; - } - __debugfs_remove(child, parent); - if (parent->d_subdirs.next == &child->d_u.d_child) { - /* - * Avoid infinite loop if we fail to remove - * one dentry. - */ - mutex_unlock(&parent->d_inode->i_mutex); - break; - } - simple_release_fs(&debugfs_mount, &debugfs_mount_count); - } + /* Find a child without children */ + while (!list_empty(&child->d_subdirs)) + child = list_entry(child->d_subdirs.next, + struct dentry, + d_u.d_child); - parent = dentry->d_parent; - mutex_lock(&parent->d_inode->i_mutex); - __debugfs_remove(dentry, parent); - mutex_unlock(&parent->d_inode->i_mutex); - simple_release_fs(&debugfs_mount, &debugfs_mount_count); - } + /* Bail out if we already tried to remove that entry */ + if (child == last) + return; + + last = child; + debugfs_remove(child); + } +} EXPORT_SYMBOL_GPL(debugfs_remove_recursive); -#endif #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) */ diff --git a/include/linux/compat-2.6.26.h b/include/linux/compat-2.6.26.h index 360f8e02c5a4..498fe44cff3d 100644 --- a/include/linux/compat-2.6.26.h +++ b/include/linux/compat-2.6.26.h @@ -11,21 +11,19 @@ #include #include #include +#include #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)) #include #endif #include #include -#if 0 -/* This cannot be backported :( */ #if defined(CONFIG_DEBUG_FS) void debugfs_remove_recursive(struct dentry *dentry); #else static inline void debugfs_remove_recursive(struct dentry *dentry) { } #endif -#endif /* These jiffie helpers added as of 2.6.26 */ -- 2.30.2