this is especially useful after /sys/slab introduced, for example: $ ls -l /sys/slab/mm_struct lrwxrwxrwx 1 root root 0 2007-10-31 17:40 /sys/slab/mm_struct -> :0000448
instead of: $ ls -l /sys/slab/mm_struct lrwxrwxrwx 1 root root 0 2007-10-31 17:40 /sys/slab/mm_struct -> ../slab/:0000448 Signed-off-by: Denis Cheng <[EMAIL PROTECTED]> --- fs/sysfs/symlink.c | 38 +++++++++++++++++++++++++++----------- 1 files changed, 27 insertions(+), 11 deletions(-) diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 3eac20c..230a925 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -19,30 +19,41 @@ #include "sysfs.h" -static int object_depth(struct sysfs_dirent *sd) +static struct sysfs_dirent *object_base(struct sysfs_dirent *parent, + struct sysfs_dirent *sd) +{ + for (; sd->s_parent; sd = sd->s_parent) + if (sd->s_parent == parent) + return parent; + return NULL; +} + +static int object_depth(struct sysfs_dirent *base, struct sysfs_dirent *sd) { int depth = 0; - for (; sd->s_parent; sd = sd->s_parent) + for (; sd->s_parent && sd != base; sd = sd->s_parent) depth++; return depth; } -static int object_path_length(struct sysfs_dirent * sd) +static int object_path_length(struct sysfs_dirent *base, + struct sysfs_dirent *sd) { int length = 1; - for (; sd->s_parent; sd = sd->s_parent) + for (; sd->s_parent && sd != base; sd = sd->s_parent) length += strlen(sd->s_name) + 1; return length; } -static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length) +static void fill_object_path(struct sysfs_dirent *base, + struct sysfs_dirent *sd, char *buffer, int length) { --length; - for (; sd->s_parent; sd = sd->s_parent) { + for (; sd->s_parent && sd != base; sd = sd->s_parent) { int cur = strlen(sd->s_name); /* back up enough to print this bus id with '/' */ @@ -129,18 +140,23 @@ static int sysfs_get_target_path(struct sysfs_dirent * parent_sd, { char * s; int depth, size; + struct sysfs_dirent *base; - depth = object_depth(parent_sd); - size = object_path_length(target_sd) + depth * 3 - 1; + base = object_base(parent_sd, target_sd); + depth = object_depth(base, parent_sd); + size = object_path_length(base, target_sd) + depth * 3 - 1; if (size > PATH_MAX) return -ENAMETOOLONG; - pr_debug("%s: depth = %d, size = %d\n", __FUNCTION__, depth, size); + pr_debug("%s: base = %s, depth = %d, size = %d\n", + __FUNCTION__, + base ? base->s_name : "/sys", + depth, size); for (s = path; depth--; s += 3) - strcpy(s,"../"); + strcpy(s, "../"); - fill_object_path(target_sd, path, size); + fill_object_path(base, target_sd, path, size); pr_debug("%s: path = '%s'\n", __FUNCTION__, path); return 0; -- 1.5.3.4 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/