[PATCH] ppc32/ppc64: cleanup /proc/device-tree

This cleans up the /proc/device-tree representation of the Open Firmware
device-tree on ppc and ppc64. It does the following things:

- Workaround an issue in some Apple device-trees where a property may
exist with the same name as a child node of the parent. We now
simply "drop" the property instead of creating duplicate entries in
/proc with random result...

- Do not try to chop off the "@0" at the end of a node name whose unit
address is 0. This is not useful, inconsistent, and the code was
buggy and didn't always work anyway.

- Do not create symlinks for the short name and unit address parts of a
node. These were never really used, bloated the memory footprint of
the device-tree with useless struct proc_dir_entry and their matching
dentry and inode cache bloat.

This results in smaller code, smaller memory footprint, and a more
accurate view of the tree presented to userland.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Benjamin Herrenschmidt and committed by
Linus Torvalds
5f64f739 f93ea234

+44 -92
-8
arch/ppc64/kernel/pSeries_reconfig.c
··· 47 47 remove_proc_entry(pp->name, np->pde); 48 48 pp = pp->next; 49 49 } 50 - 51 - /* Assuming that symlinks have the same parent directory as 52 - * np->pde. 53 - */ 54 - if (np->name_link) 55 - remove_proc_entry(np->name_link->name, parent->pde); 56 - if (np->addr_link) 57 - remove_proc_entry(np->addr_link->name, parent->pde); 58 50 if (np->pde) 59 51 remove_proc_entry(np->pde->name, parent->pde); 60 52 }
+43 -72
fs/proc/proc_devtree.c
··· 12 12 #include <asm/uaccess.h> 13 13 14 14 #ifndef HAVE_ARCH_DEVTREE_FIXUPS 15 - static inline void set_node_proc_entry(struct device_node *np, struct proc_dir_entry *de) 16 - { 17 - } 18 - 19 - static void inline set_node_name_link(struct device_node *np, struct proc_dir_entry *de) 20 - { 21 - } 22 - 23 - static void inline set_node_addr_link(struct device_node *np, struct proc_dir_entry *de) 15 + static inline void set_node_proc_entry(struct device_node *np, 16 + struct proc_dir_entry *de) 24 17 { 25 18 } 26 19 #endif ··· 51 58 /* 52 59 * Process a node, adding entries for its children and its properties. 53 60 */ 54 - void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *de) 61 + void proc_device_tree_add_node(struct device_node *np, 62 + struct proc_dir_entry *de) 55 63 { 56 64 struct property *pp; 57 65 struct proc_dir_entry *ent; 58 - struct device_node *child, *sib; 59 - const char *p, *at; 60 - int l; 61 - struct proc_dir_entry *list, **lastp, *al; 66 + struct device_node *child; 67 + struct proc_dir_entry *list = NULL, **lastp; 68 + const char *p; 62 69 63 70 set_node_proc_entry(np, de); 64 71 lastp = &list; 72 + for (child = NULL; (child = of_get_next_child(np, child));) { 73 + p = strrchr(child->full_name, '/'); 74 + if (!p) 75 + p = child->full_name; 76 + else 77 + ++p; 78 + ent = proc_mkdir(p, de); 79 + if (ent == 0) 80 + break; 81 + *lastp = ent; 82 + ent->next = NULL; 83 + lastp = &ent->next; 84 + proc_device_tree_add_node(child, ent); 85 + } 86 + of_node_put(child); 65 87 for (pp = np->properties; pp != 0; pp = pp->next) { 88 + /* 89 + * Yet another Apple device-tree bogosity: on some machines, 90 + * they have properties & nodes with the same name. Those 91 + * properties are quite unimportant for us though, thus we 92 + * simply "skip" them here, but we do have to check. 93 + */ 94 + for (ent = list; ent != NULL; ent = ent->next) 95 + if (!strcmp(ent->name, pp->name)) 96 + break; 97 + if (ent != NULL) { 98 + printk(KERN_WARNING "device-tree: property \"%s\" name" 99 + " conflicts with node in %s\n", pp->name, 100 + np->full_name); 101 + continue; 102 + } 103 + 66 104 /* 67 105 * Unfortunately proc_register puts each new entry 68 106 * at the beginning of the list. So we rearrange them. 69 107 */ 70 - ent = create_proc_read_entry(pp->name, strncmp(pp->name, "security-", 9) ? 71 - S_IRUGO : S_IRUSR, de, property_read_proc, pp); 108 + ent = create_proc_read_entry(pp->name, 109 + strncmp(pp->name, "security-", 9) 110 + ? S_IRUGO : S_IRUSR, de, 111 + property_read_proc, pp); 72 112 if (ent == 0) 73 113 break; 74 114 if (!strncmp(pp->name, "security-", 9)) 75 115 ent->size = 0; /* don't leak number of password chars */ 76 116 else 77 117 ent->size = pp->length; 118 + ent->next = NULL; 78 119 *lastp = ent; 79 120 lastp = &ent->next; 80 121 } 81 - child = NULL; 82 - while ((child = of_get_next_child(np, child))) { 83 - p = strrchr(child->full_name, '/'); 84 - if (!p) 85 - p = child->full_name; 86 - else 87 - ++p; 88 - /* chop off '@0' if the name ends with that */ 89 - l = strlen(p); 90 - if (l > 2 && p[l-2] == '@' && p[l-1] == '0') 91 - l -= 2; 92 - ent = proc_mkdir(p, de); 93 - if (ent == 0) 94 - break; 95 - *lastp = ent; 96 - lastp = &ent->next; 97 - proc_device_tree_add_node(child, ent); 98 - 99 - /* 100 - * If we left the address part on the name, consider 101 - * adding symlinks from the name and address parts. 102 - */ 103 - if (p[l] != 0 || (at = strchr(p, '@')) == 0) 104 - continue; 105 - 106 - /* 107 - * If this is the first node with a given name property, 108 - * add a symlink with the name property as its name. 109 - */ 110 - sib = NULL; 111 - while ((sib = of_get_next_child(np, sib)) && sib != child) 112 - if (sib->name && strcmp(sib->name, child->name) == 0) 113 - break; 114 - if (sib == child && strncmp(p, child->name, l) != 0) { 115 - al = proc_symlink(child->name, de, ent->name); 116 - if (al == 0) { 117 - of_node_put(sib); 118 - break; 119 - } 120 - set_node_name_link(child, al); 121 - *lastp = al; 122 - lastp = &al->next; 123 - } 124 - of_node_put(sib); 125 - /* 126 - * Add another directory with the @address part as its name. 127 - */ 128 - al = proc_symlink(at, de, ent->name); 129 - if (al == 0) 130 - break; 131 - set_node_addr_link(child, al); 132 - *lastp = al; 133 - lastp = &al->next; 134 - } 135 - of_node_put(child); 136 - *lastp = NULL; 137 122 de->subdir = list; 138 123 } 139 124
+1 -12
include/asm-ppc64/prom.h
··· 147 147 struct device_node *sibling; 148 148 struct device_node *next; /* next device of same type */ 149 149 struct device_node *allnext; /* next in list of all nodes */ 150 - struct proc_dir_entry *pde; /* this node's proc directory */ 151 - struct proc_dir_entry *name_link; /* name symlink */ 152 - struct proc_dir_entry *addr_link; /* addr symlink */ 150 + struct proc_dir_entry *pde; /* this node's proc directory */ 153 151 struct kref kref; 154 152 unsigned long _flags; 155 153 }; ··· 172 174 dn->pde = de; 173 175 } 174 176 175 - static void inline set_node_name_link(struct device_node *dn, struct proc_dir_entry *de) 176 - { 177 - dn->name_link = de; 178 - } 179 - 180 - static void inline set_node_addr_link(struct device_node *dn, struct proc_dir_entry *de) 181 - { 182 - dn->addr_link = de; 183 - } 184 177 185 178 /* OBSOLETE: Old stlye node lookup */ 186 179 extern struct device_node *find_devices(const char *name);