Loading fs/sysfs/dir.c +50 −7 Original line number Diff line number Diff line Loading @@ -45,6 +45,9 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) struct sysfs_dirent *parent_sd = sd->s_parent; struct sysfs_dirent **pos; struct rb_node **p; struct rb_node *parent; BUG_ON(sd->s_sibling); if (sysfs_type(sd) == SYSFS_DIR) Loading @@ -60,6 +63,23 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) } sd->s_sibling = *pos; *pos = sd; p = &parent_sd->s_dir.name_tree.rb_node; parent = NULL; while (*p) { int c; parent = *p; #define node rb_entry(parent, struct sysfs_dirent, name_node) c = strcmp(sd->s_name, node->s_name); if (c < 0) { p = &node->name_node.rb_left; } else { p = &node->name_node.rb_right; } #undef node } rb_link_node(&sd->name_node, parent, p); rb_insert_color(&sd->name_node, &parent_sd->s_dir.name_tree); } /** Loading Loading @@ -87,6 +107,8 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) break; } } rb_erase(&sd->name_node, &sd->s_parent->s_dir.name_tree); } /** Loading Loading @@ -546,15 +568,36 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, const void *ns, const unsigned char *name) { struct sysfs_dirent *sd; for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { if (ns && sd->s_ns && (sd->s_ns != ns)) continue; if (!strcmp(sd->s_name, name)) return sd; struct rb_node *p = parent_sd->s_dir.name_tree.rb_node; struct sysfs_dirent *found = NULL; while (p) { int c; #define node rb_entry(p, struct sysfs_dirent, name_node) c = strcmp(name, node->s_name); if (c < 0) { p = node->name_node.rb_left; } else if (c > 0) { p = node->name_node.rb_right; } else { found = node; p = node->name_node.rb_left; } #undef node } if (found && ns) { while (found->s_ns && found->s_ns != ns) { p = rb_next(&found->name_node); if (!p) return NULL; found = rb_entry(p, struct sysfs_dirent, name_node); if (strcmp(name, found->s_name)) return NULL; } } return found; } /** Loading fs/sysfs/sysfs.h +5 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include <linux/lockdep.h> #include <linux/kobject_ns.h> #include <linux/fs.h> #include <linux/rbtree.h> struct sysfs_open_dirent; Loading @@ -21,6 +22,8 @@ struct sysfs_elem_dir { struct sysfs_dirent *children; unsigned long subdirs; struct rb_root name_tree; }; struct sysfs_elem_symlink { Loading Loading @@ -61,6 +64,8 @@ struct sysfs_dirent { struct sysfs_dirent *s_sibling; const char *s_name; struct rb_node name_node; const void *s_ns; /* namespace tag */ union { struct sysfs_elem_dir s_dir; Loading Loading
fs/sysfs/dir.c +50 −7 Original line number Diff line number Diff line Loading @@ -45,6 +45,9 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) struct sysfs_dirent *parent_sd = sd->s_parent; struct sysfs_dirent **pos; struct rb_node **p; struct rb_node *parent; BUG_ON(sd->s_sibling); if (sysfs_type(sd) == SYSFS_DIR) Loading @@ -60,6 +63,23 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) } sd->s_sibling = *pos; *pos = sd; p = &parent_sd->s_dir.name_tree.rb_node; parent = NULL; while (*p) { int c; parent = *p; #define node rb_entry(parent, struct sysfs_dirent, name_node) c = strcmp(sd->s_name, node->s_name); if (c < 0) { p = &node->name_node.rb_left; } else { p = &node->name_node.rb_right; } #undef node } rb_link_node(&sd->name_node, parent, p); rb_insert_color(&sd->name_node, &parent_sd->s_dir.name_tree); } /** Loading Loading @@ -87,6 +107,8 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) break; } } rb_erase(&sd->name_node, &sd->s_parent->s_dir.name_tree); } /** Loading Loading @@ -546,15 +568,36 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, const void *ns, const unsigned char *name) { struct sysfs_dirent *sd; for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { if (ns && sd->s_ns && (sd->s_ns != ns)) continue; if (!strcmp(sd->s_name, name)) return sd; struct rb_node *p = parent_sd->s_dir.name_tree.rb_node; struct sysfs_dirent *found = NULL; while (p) { int c; #define node rb_entry(p, struct sysfs_dirent, name_node) c = strcmp(name, node->s_name); if (c < 0) { p = node->name_node.rb_left; } else if (c > 0) { p = node->name_node.rb_right; } else { found = node; p = node->name_node.rb_left; } #undef node } if (found && ns) { while (found->s_ns && found->s_ns != ns) { p = rb_next(&found->name_node); if (!p) return NULL; found = rb_entry(p, struct sysfs_dirent, name_node); if (strcmp(name, found->s_name)) return NULL; } } return found; } /** Loading
fs/sysfs/sysfs.h +5 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include <linux/lockdep.h> #include <linux/kobject_ns.h> #include <linux/fs.h> #include <linux/rbtree.h> struct sysfs_open_dirent; Loading @@ -21,6 +22,8 @@ struct sysfs_elem_dir { struct sysfs_dirent *children; unsigned long subdirs; struct rb_root name_tree; }; struct sysfs_elem_symlink { Loading Loading @@ -61,6 +64,8 @@ struct sysfs_dirent { struct sysfs_dirent *s_sibling; const char *s_name; struct rb_node name_node; const void *s_ns; /* namespace tag */ union { struct sysfs_elem_dir s_dir; Loading