From: Luis R. Rodriguez Date: Wed, 13 Jan 2010 20:36:32 +0000 (-0800) Subject: Add notes about why debugfs_remove_recursive() cannot be backported X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=c67ff24ace9fe1ce0656a3fcfeb2545ae134209e;p=openwrt%2Fstaging%2Fblogic.git Add notes about why debugfs_remove_recursive() cannot be backported You should just disable debugging for older kernels if this is used. Signed-off-by: Luis R. Rodriguez --- diff --git a/compat/compat-2.6.26.c b/compat/compat-2.6.26.c index 668d658e0084..c20ddd5d4014 100644 --- a/compat/compat-2.6.26.c +++ b/compat/compat-2.6.26.c @@ -1,5 +1,5 @@ /* - * Copyright 2007 Luis R. Rodriguez + * Copyright 2007-2010 Luis R. Rodriguez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -89,5 +89,116 @@ 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. + */ +void debugfs_remove_recursive(struct dentry *dentry) +{ + struct dentry *child; + struct dentry *parent; + + if (!dentry) + return; + + parent = dentry->d_parent; + if (!parent || !parent->d_inode) + return; + + 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); + } + + 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); + } +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 0ea99b1503a7..96459e0b8517 100644 --- a/include/linux/compat-2.6.26.h +++ b/include/linux/compat-2.6.26.h @@ -11,9 +11,22 @@ #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 */