compat: backport debugfs_remove_recursive()
authorPavel Roskin <proski@gnu.org>
Thu, 18 Feb 2010 17:45:37 +0000 (09:45 -0800)
committerLuis R. Rodriguez <lrodriguez@atheros.com>
Thu, 18 Feb 2010 17:45:37 +0000 (09:45 -0800)
This avoids using the internal globals by the internal
kernel debugfs implementation.

Signed-off-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
compat/compat-2.6.26.c
include/linux/compat-2.6.26.h

index c20ddd5..82134c2 100644 (file)
@@ -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) */
 
index 360f8e0..498fe44 100644 (file)
 #include <linux/jiffies.h>
 #include <net/sock.h>
 #include <linux/fs.h>
+#include <linux/debugfs.h>
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
 #include <net/net_namespace.h>
 #endif
 #include <linux/fs.h>
 #include <linux/types.h>
 
-#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 */