aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /fs/sysfs
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'fs/sysfs')
-rw-r--r--fs/sysfs/bin.c2
-rw-r--r--fs/sysfs/dir.c335
-rw-r--r--fs/sysfs/file.c66
-rw-r--r--fs/sysfs/group.c8
-rw-r--r--fs/sysfs/inode.c40
-rw-r--r--fs/sysfs/mount.c10
-rw-r--r--fs/sysfs/symlink.c2
-rw-r--r--fs/sysfs/sysfs.h29
8 files changed, 165 insertions, 327 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 614b2b54488..a4759833d62 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -228,8 +228,6 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
228 ret = 0; 228 ret = 0;
229 if (bb->vm_ops->page_mkwrite) 229 if (bb->vm_ops->page_mkwrite)
230 ret = bb->vm_ops->page_mkwrite(vma, vmf); 230 ret = bb->vm_ops->page_mkwrite(vma, vmf);
231 else
232 file_update_time(file);
233 231
234 sysfs_put_active(attr_sd); 232 sysfs_put_active(attr_sd);
235 return ret; 233 return ret;
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 2fbdff6be25..ea9120a830d 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -22,103 +22,48 @@
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/security.h> 24#include <linux/security.h>
25#include <linux/hash.h>
26#include "sysfs.h" 25#include "sysfs.h"
27 26
28DEFINE_MUTEX(sysfs_mutex); 27DEFINE_MUTEX(sysfs_mutex);
29DEFINE_SPINLOCK(sysfs_assoc_lock); 28DEFINE_SPINLOCK(sysfs_assoc_lock);
30 29
31#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb);
32
33static DEFINE_SPINLOCK(sysfs_ino_lock); 30static DEFINE_SPINLOCK(sysfs_ino_lock);
34static DEFINE_IDA(sysfs_ino_ida); 31static DEFINE_IDA(sysfs_ino_ida);
35 32
36/** 33/**
37 * sysfs_name_hash 34 * sysfs_link_sibling - link sysfs_dirent into sibling list
38 * @ns: Namespace tag to hash
39 * @name: Null terminated string to hash
40 *
41 * Returns 31 bit hash of ns + name (so it fits in an off_t )
42 */
43static unsigned int sysfs_name_hash(const void *ns, const char *name)
44{
45 unsigned long hash = init_name_hash();
46 unsigned int len = strlen(name);
47 while (len--)
48 hash = partial_name_hash(*name++, hash);
49 hash = ( end_name_hash(hash) ^ hash_ptr( (void *)ns, 31 ) );
50 hash &= 0x7fffffffU;
51 /* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */
52 if (hash < 1)
53 hash += 2;
54 if (hash >= INT_MAX)
55 hash = INT_MAX - 1;
56 return hash;
57}
58
59static int sysfs_name_compare(unsigned int hash, const void *ns,
60 const char *name, const struct sysfs_dirent *sd)
61{
62 if (hash != sd->s_hash)
63 return hash - sd->s_hash;
64 if (ns != sd->s_ns)
65 return ns - sd->s_ns;
66 return strcmp(name, sd->s_name);
67}
68
69static int sysfs_sd_compare(const struct sysfs_dirent *left,
70 const struct sysfs_dirent *right)
71{
72 return sysfs_name_compare(left->s_hash, left->s_ns, left->s_name,
73 right);
74}
75
76/**
77 * sysfs_link_subling - link sysfs_dirent into sibling rbtree
78 * @sd: sysfs_dirent of interest 35 * @sd: sysfs_dirent of interest
79 * 36 *
80 * Link @sd into its sibling rbtree which starts from 37 * Link @sd into its sibling list which starts from
81 * sd->s_parent->s_dir.children. 38 * sd->s_parent->s_dir.children.
82 * 39 *
83 * Locking: 40 * Locking:
84 * mutex_lock(sysfs_mutex) 41 * mutex_lock(sysfs_mutex)
85 *
86 * RETURNS:
87 * 0 on susccess -EEXIST on failure.
88 */ 42 */
89static int sysfs_link_sibling(struct sysfs_dirent *sd) 43static void sysfs_link_sibling(struct sysfs_dirent *sd)
90{ 44{
91 struct rb_node **node = &sd->s_parent->s_dir.children.rb_node; 45 struct sysfs_dirent *parent_sd = sd->s_parent;
92 struct rb_node *parent = NULL; 46 struct sysfs_dirent **pos;
93 47
94 if (sysfs_type(sd) == SYSFS_DIR) 48 BUG_ON(sd->s_sibling);
95 sd->s_parent->s_dir.subdirs++; 49
96 50 /* Store directory entries in order by ino. This allows
97 while (*node) { 51 * readdir to properly restart without having to add a
98 struct sysfs_dirent *pos; 52 * cursor into the s_dir.children list.
99 int result; 53 */
100 54 for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) {
101 pos = to_sysfs_dirent(*node); 55 if (sd->s_ino < (*pos)->s_ino)
102 parent = *node; 56 break;
103 result = sysfs_sd_compare(sd, pos);
104 if (result < 0)
105 node = &pos->s_rb.rb_left;
106 else if (result > 0)
107 node = &pos->s_rb.rb_right;
108 else
109 return -EEXIST;
110 } 57 }
111 /* add new node and rebalance the tree */ 58 sd->s_sibling = *pos;
112 rb_link_node(&sd->s_rb, parent, node); 59 *pos = sd;
113 rb_insert_color(&sd->s_rb, &sd->s_parent->s_dir.children);
114 return 0;
115} 60}
116 61
117/** 62/**
118 * sysfs_unlink_sibling - unlink sysfs_dirent from sibling rbtree 63 * sysfs_unlink_sibling - unlink sysfs_dirent from sibling list
119 * @sd: sysfs_dirent of interest 64 * @sd: sysfs_dirent of interest
120 * 65 *
121 * Unlink @sd from its sibling rbtree which starts from 66 * Unlink @sd from its sibling list which starts from
122 * sd->s_parent->s_dir.children. 67 * sd->s_parent->s_dir.children.
123 * 68 *
124 * Locking: 69 * Locking:
@@ -126,30 +71,18 @@ static int sysfs_link_sibling(struct sysfs_dirent *sd)
126 */ 71 */
127static void sysfs_unlink_sibling(struct sysfs_dirent *sd) 72static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
128{ 73{
129 if (sysfs_type(sd) == SYSFS_DIR) 74 struct sysfs_dirent **pos;
130 sd->s_parent->s_dir.subdirs--;
131
132 rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children);
133}
134
135#ifdef CONFIG_DEBUG_LOCK_ALLOC
136
137/* Test for attributes that want to ignore lockdep for read-locking */
138static bool ignore_lockdep(struct sysfs_dirent *sd)
139{
140 return sysfs_type(sd) == SYSFS_KOBJ_ATTR &&
141 sd->s_attr.attr->ignore_lockdep;
142}
143 75
144#else 76 for (pos = &sd->s_parent->s_dir.children; *pos;
145 77 pos = &(*pos)->s_sibling) {
146static inline bool ignore_lockdep(struct sysfs_dirent *sd) 78 if (*pos == sd) {
147{ 79 *pos = sd->s_sibling;
148 return true; 80 sd->s_sibling = NULL;
81 break;
82 }
83 }
149} 84}
150 85
151#endif
152
153/** 86/**
154 * sysfs_get_active - get an active reference to sysfs_dirent 87 * sysfs_get_active - get an active reference to sysfs_dirent
155 * @sd: sysfs_dirent to get an active reference to 88 * @sd: sysfs_dirent to get an active reference to
@@ -173,17 +106,15 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
173 return NULL; 106 return NULL;
174 107
175 t = atomic_cmpxchg(&sd->s_active, v, v + 1); 108 t = atomic_cmpxchg(&sd->s_active, v, v + 1);
176 if (likely(t == v)) 109 if (likely(t == v)) {
177 break; 110 rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
111 return sd;
112 }
178 if (t < 0) 113 if (t < 0)
179 return NULL; 114 return NULL;
180 115
181 cpu_relax(); 116 cpu_relax();
182 } 117 }
183
184 if (likely(!ignore_lockdep(sd)))
185 rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
186 return sd;
187} 118}
188 119
189/** 120/**
@@ -195,21 +126,22 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
195 */ 126 */
196void sysfs_put_active(struct sysfs_dirent *sd) 127void sysfs_put_active(struct sysfs_dirent *sd)
197{ 128{
129 struct completion *cmpl;
198 int v; 130 int v;
199 131
200 if (unlikely(!sd)) 132 if (unlikely(!sd))
201 return; 133 return;
202 134
203 if (likely(!ignore_lockdep(sd))) 135 rwsem_release(&sd->dep_map, 1, _RET_IP_);
204 rwsem_release(&sd->dep_map, 1, _RET_IP_);
205 v = atomic_dec_return(&sd->s_active); 136 v = atomic_dec_return(&sd->s_active);
206 if (likely(v != SD_DEACTIVATED_BIAS)) 137 if (likely(v != SD_DEACTIVATED_BIAS))
207 return; 138 return;
208 139
209 /* atomic_dec_return() is a mb(), we'll always see the updated 140 /* atomic_dec_return() is a mb(), we'll always see the updated
210 * sd->u.completion. 141 * sd->s_sibling.
211 */ 142 */
212 complete(sd->u.completion); 143 cmpl = (void *)sd->s_sibling;
144 complete(cmpl);
213} 145}
214 146
215/** 147/**
@@ -223,16 +155,16 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
223 DECLARE_COMPLETION_ONSTACK(wait); 155 DECLARE_COMPLETION_ONSTACK(wait);
224 int v; 156 int v;
225 157
226 BUG_ON(!(sd->s_flags & SYSFS_FLAG_REMOVED)); 158 BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
227 159
228 if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF)) 160 if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF))
229 return; 161 return;
230 162
231 sd->u.completion = (void *)&wait; 163 sd->s_sibling = (void *)&wait;
232 164
233 rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_); 165 rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_);
234 /* atomic_add_return() is a mb(), put_active() will always see 166 /* atomic_add_return() is a mb(), put_active() will always see
235 * the updated sd->u.completion. 167 * the updated sd->s_sibling.
236 */ 168 */
237 v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active); 169 v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
238 170
@@ -241,11 +173,13 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
241 wait_for_completion(&wait); 173 wait_for_completion(&wait);
242 } 174 }
243 175
176 sd->s_sibling = NULL;
177
244 lock_acquired(&sd->dep_map, _RET_IP_); 178 lock_acquired(&sd->dep_map, _RET_IP_);
245 rwsem_release(&sd->dep_map, 1, _RET_IP_); 179 rwsem_release(&sd->dep_map, 1, _RET_IP_);
246} 180}
247 181
248static int sysfs_alloc_ino(unsigned int *pino) 182static int sysfs_alloc_ino(ino_t *pino)
249{ 183{
250 int ino, rc; 184 int ino, rc;
251 185
@@ -264,7 +198,7 @@ static int sysfs_alloc_ino(unsigned int *pino)
264 return rc; 198 return rc;
265} 199}
266 200
267static void sysfs_free_ino(unsigned int ino) 201static void sysfs_free_ino(ino_t ino)
268{ 202{
269 spin_lock(&sysfs_ino_lock); 203 spin_lock(&sysfs_ino_lock);
270 ida_remove(&sysfs_ino_ida, ino); 204 ida_remove(&sysfs_ino_ida, ino);
@@ -300,16 +234,15 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
300static int sysfs_dentry_delete(const struct dentry *dentry) 234static int sysfs_dentry_delete(const struct dentry *dentry)
301{ 235{
302 struct sysfs_dirent *sd = dentry->d_fsdata; 236 struct sysfs_dirent *sd = dentry->d_fsdata;
303 return !(sd && !(sd->s_flags & SYSFS_FLAG_REMOVED)); 237 return !!(sd->s_flags & SYSFS_FLAG_REMOVED);
304} 238}
305 239
306static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) 240static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
307{ 241{
308 struct sysfs_dirent *sd; 242 struct sysfs_dirent *sd;
309 int is_dir; 243 int is_dir;
310 int type;
311 244
312 if (flags & LOOKUP_RCU) 245 if (nd->flags & LOOKUP_RCU)
313 return -ECHILD; 246 return -ECHILD;
314 247
315 sd = dentry->d_fsdata; 248 sd = dentry->d_fsdata;
@@ -327,15 +260,6 @@ static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
327 if (strcmp(dentry->d_name.name, sd->s_name) != 0) 260 if (strcmp(dentry->d_name.name, sd->s_name) != 0)
328 goto out_bad; 261 goto out_bad;
329 262
330 /* The sysfs dirent has been moved to a different namespace */
331 type = KOBJ_NS_TYPE_NONE;
332 if (sd->s_parent) {
333 type = sysfs_ns_type(sd->s_parent);
334 if (type != KOBJ_NS_TYPE_NONE &&
335 sysfs_info(dentry->d_sb)->ns[type] != sd->s_ns)
336 goto out_bad;
337 }
338
339 mutex_unlock(&sysfs_mutex); 263 mutex_unlock(&sysfs_mutex);
340out_valid: 264out_valid:
341 return 1; 265 return 1;
@@ -365,15 +289,18 @@ out_bad:
365 return 0; 289 return 0;
366} 290}
367 291
368static void sysfs_dentry_release(struct dentry *dentry) 292static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode)
369{ 293{
370 sysfs_put(dentry->d_fsdata); 294 struct sysfs_dirent * sd = dentry->d_fsdata;
295
296 sysfs_put(sd);
297 iput(inode);
371} 298}
372 299
373const struct dentry_operations sysfs_dentry_ops = { 300static const struct dentry_operations sysfs_dentry_ops = {
374 .d_revalidate = sysfs_dentry_revalidate, 301 .d_revalidate = sysfs_dentry_revalidate,
375 .d_delete = sysfs_dentry_delete, 302 .d_delete = sysfs_dentry_delete,
376 .d_release = sysfs_dentry_release, 303 .d_iput = sysfs_dentry_iput,
377}; 304};
378 305
379struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) 306struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
@@ -456,21 +383,13 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
456int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) 383int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
457{ 384{
458 struct sysfs_inode_attrs *ps_iattr; 385 struct sysfs_inode_attrs *ps_iattr;
459 int ret;
460 386
461 if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) { 387 if (sysfs_find_dirent(acxt->parent_sd, sd->s_ns, sd->s_name))
462 WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", 388 return -EEXIST;
463 sysfs_ns_type(acxt->parent_sd)? "required": "invalid",
464 acxt->parent_sd->s_name, sd->s_name);
465 return -EINVAL;
466 }
467 389
468 sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
469 sd->s_parent = sysfs_get(acxt->parent_sd); 390 sd->s_parent = sysfs_get(acxt->parent_sd);
470 391
471 ret = sysfs_link_sibling(sd); 392 sysfs_link_sibling(sd);
472 if (ret)
473 return ret;
474 393
475 /* Update timestamps on the parent */ 394 /* Update timestamps on the parent */
476 ps_iattr = acxt->parent_sd->s_iattr; 395 ps_iattr = acxt->parent_sd->s_iattr;
@@ -485,18 +404,20 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
485/** 404/**
486 * sysfs_pathname - return full path to sysfs dirent 405 * sysfs_pathname - return full path to sysfs dirent
487 * @sd: sysfs_dirent whose path we want 406 * @sd: sysfs_dirent whose path we want
488 * @path: caller allocated buffer of size PATH_MAX 407 * @path: caller allocated buffer
489 * 408 *
490 * Gives the name "/" to the sysfs_root entry; any path returned 409 * Gives the name "/" to the sysfs_root entry; any path returned
491 * is relative to wherever sysfs is mounted. 410 * is relative to wherever sysfs is mounted.
411 *
412 * XXX: does no error checking on @path size
492 */ 413 */
493static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) 414static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
494{ 415{
495 if (sd->s_parent) { 416 if (sd->s_parent) {
496 sysfs_pathname(sd->s_parent, path); 417 sysfs_pathname(sd->s_parent, path);
497 strlcat(path, "/", PATH_MAX); 418 strcat(path, "/");
498 } 419 }
499 strlcat(path, sd->s_name, PATH_MAX); 420 strcat(path, sd->s_name);
500 return path; 421 return path;
501} 422}
502 423
@@ -529,11 +450,9 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
529 char *path = kzalloc(PATH_MAX, GFP_KERNEL); 450 char *path = kzalloc(PATH_MAX, GFP_KERNEL);
530 WARN(1, KERN_WARNING 451 WARN(1, KERN_WARNING
531 "sysfs: cannot create duplicate filename '%s'\n", 452 "sysfs: cannot create duplicate filename '%s'\n",
532 (path == NULL) ? sd->s_name 453 (path == NULL) ? sd->s_name :
533 : (sysfs_pathname(acxt->parent_sd, path), 454 strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"),
534 strlcat(path, "/", PATH_MAX), 455 sd->s_name));
535 strlcat(path, sd->s_name, PATH_MAX),
536 path));
537 kfree(path); 456 kfree(path);
538 } 457 }
539 458
@@ -571,7 +490,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
571 } 490 }
572 491
573 sd->s_flags |= SYSFS_FLAG_REMOVED; 492 sd->s_flags |= SYSFS_FLAG_REMOVED;
574 sd->u.removed_list = acxt->removed; 493 sd->s_sibling = acxt->removed;
575 acxt->removed = sd; 494 acxt->removed = sd;
576} 495}
577 496
@@ -595,7 +514,8 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
595 while (acxt->removed) { 514 while (acxt->removed) {
596 struct sysfs_dirent *sd = acxt->removed; 515 struct sysfs_dirent *sd = acxt->removed;
597 516
598 acxt->removed = sd->u.removed_list; 517 acxt->removed = sd->s_sibling;
518 sd->s_sibling = NULL;
599 519
600 sysfs_deactivate(sd); 520 sysfs_deactivate(sd);
601 unmap_bin_file(sd); 521 unmap_bin_file(sd);
@@ -620,28 +540,12 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
620 const void *ns, 540 const void *ns,
621 const unsigned char *name) 541 const unsigned char *name)
622{ 542{
623 struct rb_node *node = parent_sd->s_dir.children.rb_node; 543 struct sysfs_dirent *sd;
624 unsigned int hash;
625
626 if (!!sysfs_ns_type(parent_sd) != !!ns) {
627 WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
628 sysfs_ns_type(parent_sd)? "required": "invalid",
629 parent_sd->s_name, name);
630 return NULL;
631 }
632 544
633 hash = sysfs_name_hash(ns, name); 545 for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) {
634 while (node) { 546 if (ns && sd->s_ns && (sd->s_ns != ns))
635 struct sysfs_dirent *sd; 547 continue;
636 int result; 548 if (!strcmp(sd->s_name, name))
637
638 sd = to_sysfs_dirent(node);
639 result = sysfs_name_compare(hash, ns, name, sd);
640 if (result < 0)
641 node = node->rb_left;
642 else if (result > 0)
643 node = node->rb_right;
644 else
645 return sd; 549 return sd;
646 } 550 }
647 return NULL; 551 return NULL;
@@ -757,9 +661,6 @@ int sysfs_create_dir(struct kobject * kobj)
757 else 661 else
758 parent_sd = &sysfs_root; 662 parent_sd = &sysfs_root;
759 663
760 if (!parent_sd)
761 return -ENOENT;
762
763 if (sysfs_ns_type(parent_sd)) 664 if (sysfs_ns_type(parent_sd))
764 ns = kobj->ktype->namespace(kobj); 665 ns = kobj->ktype->namespace(kobj);
765 type = sysfs_read_ns_type(kobj); 666 type = sysfs_read_ns_type(kobj);
@@ -771,7 +672,7 @@ int sysfs_create_dir(struct kobject * kobj)
771} 672}
772 673
773static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, 674static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
774 unsigned int flags) 675 struct nameidata *nd)
775{ 676{
776 struct dentry *ret = NULL; 677 struct dentry *ret = NULL;
777 struct dentry *parent = dentry->d_parent; 678 struct dentry *parent = dentry->d_parent;
@@ -793,7 +694,6 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
793 ret = ERR_PTR(-ENOENT); 694 ret = ERR_PTR(-ENOENT);
794 goto out_unlock; 695 goto out_unlock;
795 } 696 }
796 dentry->d_fsdata = sysfs_get(sd);
797 697
798 /* attach dentry and inode */ 698 /* attach dentry and inode */
799 inode = sysfs_get_inode(dir->i_sb, sd); 699 inode = sysfs_get_inode(dir->i_sb, sd);
@@ -803,7 +703,16 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
803 } 703 }
804 704
805 /* instantiate and hash dentry */ 705 /* instantiate and hash dentry */
806 ret = d_materialise_unique(dentry, inode); 706 ret = d_find_alias(inode);
707 if (!ret) {
708 d_set_d_op(dentry, &sysfs_dentry_ops);
709 dentry->d_fsdata = sysfs_get(sd);
710 d_add(dentry, inode);
711 } else {
712 d_move(ret, dentry);
713 iput(inode);
714 }
715
807 out_unlock: 716 out_unlock:
808 mutex_unlock(&sysfs_mutex); 717 mutex_unlock(&sysfs_mutex);
809 return ret; 718 return ret;
@@ -835,19 +744,21 @@ void sysfs_remove_subdir(struct sysfs_dirent *sd)
835static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) 744static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
836{ 745{
837 struct sysfs_addrm_cxt acxt; 746 struct sysfs_addrm_cxt acxt;
838 struct rb_node *pos; 747 struct sysfs_dirent **pos;
839 748
840 if (!dir_sd) 749 if (!dir_sd)
841 return; 750 return;
842 751
843 pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); 752 pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
844 sysfs_addrm_start(&acxt, dir_sd); 753 sysfs_addrm_start(&acxt, dir_sd);
845 pos = rb_first(&dir_sd->s_dir.children); 754 pos = &dir_sd->s_dir.children;
846 while (pos) { 755 while (*pos) {
847 struct sysfs_dirent *sd = to_sysfs_dirent(pos); 756 struct sysfs_dirent *sd = *pos;
848 pos = rb_next(pos); 757
849 if (sysfs_type(sd) != SYSFS_DIR) 758 if (sysfs_type(sd) != SYSFS_DIR)
850 sysfs_remove_one(&acxt, sd); 759 sysfs_remove_one(&acxt, sd);
760 else
761 pos = &(*pos)->s_sibling;
851 } 762 }
852 sysfs_addrm_finish(&acxt); 763 sysfs_addrm_finish(&acxt);
853 764
@@ -878,6 +789,7 @@ int sysfs_rename(struct sysfs_dirent *sd,
878 struct sysfs_dirent *new_parent_sd, const void *new_ns, 789 struct sysfs_dirent *new_parent_sd, const void *new_ns,
879 const char *new_name) 790 const char *new_name)
880{ 791{
792 const char *dup_name = NULL;
881 int error; 793 int error;
882 794
883 mutex_lock(&sysfs_mutex); 795 mutex_lock(&sysfs_mutex);
@@ -894,26 +806,28 @@ int sysfs_rename(struct sysfs_dirent *sd,
894 /* rename sysfs_dirent */ 806 /* rename sysfs_dirent */
895 if (strcmp(sd->s_name, new_name) != 0) { 807 if (strcmp(sd->s_name, new_name) != 0) {
896 error = -ENOMEM; 808 error = -ENOMEM;
897 new_name = kstrdup(new_name, GFP_KERNEL); 809 new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
898 if (!new_name) 810 if (!new_name)
899 goto out; 811 goto out;
900 812
901 kfree(sd->s_name); 813 dup_name = sd->s_name;
902 sd->s_name = new_name; 814 sd->s_name = new_name;
903 } 815 }
904 816
905 /* Move to the appropriate place in the appropriate directories rbtree. */ 817 /* Remove from old parent's list and insert into new parent's list. */
906 sysfs_unlink_sibling(sd); 818 if (sd->s_parent != new_parent_sd) {
907 sysfs_get(new_parent_sd); 819 sysfs_unlink_sibling(sd);
908 sysfs_put(sd->s_parent); 820 sysfs_get(new_parent_sd);
821 sysfs_put(sd->s_parent);
822 sd->s_parent = new_parent_sd;
823 sysfs_link_sibling(sd);
824 }
909 sd->s_ns = new_ns; 825 sd->s_ns = new_ns;
910 sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
911 sd->s_parent = new_parent_sd;
912 sysfs_link_sibling(sd);
913 826
914 error = 0; 827 error = 0;
915 out: 828 out:
916 mutex_unlock(&sysfs_mutex); 829 mutex_unlock(&sysfs_mutex);
830 kfree(dup_name);
917 return error; 831 return error;
918} 832}
919 833
@@ -956,37 +870,23 @@ static int sysfs_dir_release(struct inode *inode, struct file *filp)
956} 870}
957 871
958static struct sysfs_dirent *sysfs_dir_pos(const void *ns, 872static struct sysfs_dirent *sysfs_dir_pos(const void *ns,
959 struct sysfs_dirent *parent_sd, loff_t hash, struct sysfs_dirent *pos) 873 struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos)
960{ 874{
961 if (pos) { 875 if (pos) {
962 int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && 876 int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) &&
963 pos->s_parent == parent_sd && 877 pos->s_parent == parent_sd &&
964 hash == pos->s_hash; 878 ino == pos->s_ino;
965 sysfs_put(pos); 879 sysfs_put(pos);
966 if (!valid) 880 if (!valid)
967 pos = NULL; 881 pos = NULL;
968 } 882 }
969 if (!pos && (hash > 1) && (hash < INT_MAX)) { 883 if (!pos && (ino > 1) && (ino < INT_MAX)) {
970 struct rb_node *node = parent_sd->s_dir.children.rb_node; 884 pos = parent_sd->s_dir.children;
971 while (node) { 885 while (pos && (ino > pos->s_ino))
972 pos = to_sysfs_dirent(node); 886 pos = pos->s_sibling;
973
974 if (hash < pos->s_hash)
975 node = node->rb_left;
976 else if (hash > pos->s_hash)
977 node = node->rb_right;
978 else
979 break;
980 }
981 }
982 /* Skip over entries in the wrong namespace */
983 while (pos && pos->s_ns != ns) {
984 struct rb_node *node = rb_next(&pos->s_rb);
985 if (!node)
986 pos = NULL;
987 else
988 pos = to_sysfs_dirent(node);
989 } 887 }
888 while (pos && pos->s_ns && pos->s_ns != ns)
889 pos = pos->s_sibling;
990 return pos; 890 return pos;
991} 891}
992 892
@@ -994,13 +894,10 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns,
994 struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos) 894 struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos)
995{ 895{
996 pos = sysfs_dir_pos(ns, parent_sd, ino, pos); 896 pos = sysfs_dir_pos(ns, parent_sd, ino, pos);
997 if (pos) do { 897 if (pos)
998 struct rb_node *node = rb_next(&pos->s_rb); 898 pos = pos->s_sibling;
999 if (!node) 899 while (pos && pos->s_ns && pos->s_ns != ns)
1000 pos = NULL; 900 pos = pos->s_sibling;
1001 else
1002 pos = to_sysfs_dirent(node);
1003 } while (pos && pos->s_ns != ns);
1004 return pos; 901 return pos;
1005} 902}
1006 903
@@ -1041,7 +938,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
1041 len = strlen(name); 938 len = strlen(name);
1042 ino = pos->s_ino; 939 ino = pos->s_ino;
1043 type = dt_type(pos); 940 type = dt_type(pos);
1044 filp->f_pos = pos->s_hash; 941 filp->f_pos = ino;
1045 filp->private_data = sysfs_get(pos); 942 filp->private_data = sysfs_get(pos);
1046 943
1047 mutex_unlock(&sysfs_mutex); 944 mutex_unlock(&sysfs_mutex);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 602f56db044..1ad8c93c1b8 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -466,6 +466,9 @@ void sysfs_notify(struct kobject *k, const char *dir, const char *attr)
466 mutex_lock(&sysfs_mutex); 466 mutex_lock(&sysfs_mutex);
467 467
468 if (sd && dir) 468 if (sd && dir)
469 /* Only directories are tagged, so no need to pass
470 * a tag explicitly.
471 */
469 sd = sysfs_find_dirent(sd, NULL, dir); 472 sd = sysfs_find_dirent(sd, NULL, dir);
470 if (sd && attr) 473 if (sd && attr)
471 sd = sysfs_find_dirent(sd, NULL, attr); 474 sd = sysfs_find_dirent(sd, NULL, attr);
@@ -485,62 +488,17 @@ const struct file_operations sysfs_file_operations = {
485 .poll = sysfs_poll, 488 .poll = sysfs_poll,
486}; 489};
487 490
488static int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
489 const void **pns)
490{
491 struct sysfs_dirent *dir_sd = kobj->sd;
492 const struct sysfs_ops *ops;
493 const void *ns = NULL;
494 int err;
495
496 if (!dir_sd) {
497 WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n",
498 kobject_name(kobj));
499 return -ENOENT;
500 }
501
502 err = 0;
503 if (!sysfs_ns_type(dir_sd))
504 goto out;
505
506 err = -EINVAL;
507 if (!kobj->ktype)
508 goto out;
509 ops = kobj->ktype->sysfs_ops;
510 if (!ops)
511 goto out;
512 if (!ops->namespace)
513 goto out;
514
515 err = 0;
516 ns = ops->namespace(kobj, attr);
517out:
518 if (err) {
519 WARN(1, KERN_ERR "missing sysfs namespace attribute operation for "
520 "kobject: %s\n", kobject_name(kobj));
521 }
522 *pns = ns;
523 return err;
524}
525
526int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, 491int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
527 const struct attribute *attr, int type, umode_t amode) 492 const struct attribute *attr, int type, mode_t amode)
528{ 493{
529 umode_t mode = (amode & S_IALLUGO) | S_IFREG; 494 umode_t mode = (amode & S_IALLUGO) | S_IFREG;
530 struct sysfs_addrm_cxt acxt; 495 struct sysfs_addrm_cxt acxt;
531 struct sysfs_dirent *sd; 496 struct sysfs_dirent *sd;
532 const void *ns;
533 int rc; 497 int rc;
534 498
535 rc = sysfs_attr_ns(dir_sd->s_dir.kobj, attr, &ns);
536 if (rc)
537 return rc;
538
539 sd = sysfs_new_dirent(attr->name, mode, type); 499 sd = sysfs_new_dirent(attr->name, mode, type);
540 if (!sd) 500 if (!sd)
541 return -ENOMEM; 501 return -ENOMEM;
542
543 sd->s_ns = ns;
544 sd->s_attr.attr = (void *)attr; 502 sd->s_attr.attr = (void *)attr;
545 sysfs_dirent_init_lockdep(sd); 503 sysfs_dirent_init_lockdep(sd);
546 504
@@ -624,21 +582,16 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
624 * 582 *
625 */ 583 */
626int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, 584int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
627 umode_t mode) 585 mode_t mode)
628{ 586{
629 struct sysfs_dirent *sd; 587 struct sysfs_dirent *sd;
630 struct iattr newattrs; 588 struct iattr newattrs;
631 const void *ns;
632 int rc; 589 int rc;
633 590
634 rc = sysfs_attr_ns(kobj, attr, &ns);
635 if (rc)
636 return rc;
637
638 mutex_lock(&sysfs_mutex); 591 mutex_lock(&sysfs_mutex);
639 592
640 rc = -ENOENT; 593 rc = -ENOENT;
641 sd = sysfs_find_dirent(kobj->sd, ns, attr->name); 594 sd = sysfs_find_dirent(kobj->sd, NULL, attr->name);
642 if (!sd) 595 if (!sd)
643 goto out; 596 goto out;
644 597
@@ -663,12 +616,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
663 616
664void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) 617void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
665{ 618{
666 const void *ns; 619 sysfs_hash_and_remove(kobj->sd, NULL, attr->name);
667
668 if (sysfs_attr_ns(kobj, attr, &ns))
669 return;
670
671 sysfs_hash_and_remove(kobj->sd, ns, attr->name);
672} 620}
673 621
674void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) 622void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 2df555c66d5..194414f8298 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -33,7 +33,7 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
33 int error = 0, i; 33 int error = 0, i;
34 34
35 for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) { 35 for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
36 umode_t mode = 0; 36 mode_t mode = 0;
37 37
38 /* in update mode, we're changing the permissions or 38 /* in update mode, we're changing the permissions or
39 * visibility. Do this by first removing then 39 * visibility. Do this by first removing then
@@ -67,11 +67,7 @@ static int internal_create_group(struct kobject *kobj, int update,
67 /* Updates may happen before the object has been instantiated */ 67 /* Updates may happen before the object has been instantiated */
68 if (unlikely(update && !kobj->sd)) 68 if (unlikely(update && !kobj->sd))
69 return -EINVAL; 69 return -EINVAL;
70 if (!grp->attrs) { 70
71 WARN(1, "sysfs: attrs not set by subsystem for group: %s/%s\n",
72 kobj->name, grp->name ? "" : grp->name);
73 return -EINVAL;
74 }
75 if (grp->name) { 71 if (grp->name) {
76 error = sysfs_create_subdir(kobj, grp->name, &sd); 72 error = sysfs_create_subdir(kobj, grp->name, &sd);
77 if (error) 73 if (error)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 0ce3ccf7f40..e3f091a81c7 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -62,8 +62,8 @@ static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd)
62 62
63 /* assign default attributes */ 63 /* assign default attributes */
64 iattrs->ia_mode = sd->s_mode; 64 iattrs->ia_mode = sd->s_mode;
65 iattrs->ia_uid = GLOBAL_ROOT_UID; 65 iattrs->ia_uid = 0;
66 iattrs->ia_gid = GLOBAL_ROOT_GID; 66 iattrs->ia_gid = 0;
67 iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; 67 iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
68 68
69 return attrs; 69 return attrs;
@@ -136,13 +136,12 @@ static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *sec
136 void *old_secdata; 136 void *old_secdata;
137 size_t old_secdata_len; 137 size_t old_secdata_len;
138 138
139 if (!sd->s_iattr) {
140 sd->s_iattr = sysfs_init_inode_attrs(sd);
141 if (!sd->s_iattr)
142 return -ENOMEM;
143 }
144
145 iattrs = sd->s_iattr; 139 iattrs = sd->s_iattr;
140 if (!iattrs)
141 iattrs = sysfs_init_inode_attrs(sd);
142 if (!iattrs)
143 return -ENOMEM;
144
146 old_secdata = iattrs->ia_secdata; 145 old_secdata = iattrs->ia_secdata;
147 old_secdata_len = iattrs->ia_secdata_len; 146 old_secdata_len = iattrs->ia_secdata_len;
148 147
@@ -188,7 +187,7 @@ out:
188 return error; 187 return error;
189} 188}
190 189
191static inline void set_default_inode_attr(struct inode * inode, umode_t mode) 190static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
192{ 191{
193 inode->i_mode = mode; 192 inode->i_mode = mode;
194 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 193 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -203,6 +202,18 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
203 inode->i_ctime = iattr->ia_ctime; 202 inode->i_ctime = iattr->ia_ctime;
204} 203}
205 204
205static int sysfs_count_nlink(struct sysfs_dirent *sd)
206{
207 struct sysfs_dirent *child;
208 int nr = 0;
209
210 for (child = sd->s_dir.children; child; child = child->s_sibling)
211 if (sysfs_type(child) == SYSFS_DIR)
212 nr++;
213
214 return nr + 2;
215}
216
206static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) 217static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
207{ 218{
208 struct sysfs_inode_attrs *iattrs = sd->s_iattr; 219 struct sysfs_inode_attrs *iattrs = sd->s_iattr;
@@ -219,7 +230,7 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
219 } 230 }
220 231
221 if (sysfs_type(sd) == SYSFS_DIR) 232 if (sysfs_type(sd) == SYSFS_DIR)
222 set_nlink(inode, sd->s_dir.subdirs + 2); 233 inode->i_nlink = sysfs_count_nlink(sd);
223} 234}
224 235
225int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 236int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
@@ -310,7 +321,7 @@ void sysfs_evict_inode(struct inode *inode)
310 struct sysfs_dirent *sd = inode->i_private; 321 struct sysfs_dirent *sd = inode->i_private;
311 322
312 truncate_inode_pages(&inode->i_data, 0); 323 truncate_inode_pages(&inode->i_data, 0);
313 clear_inode(inode); 324 end_writeback(inode);
314 sysfs_put(sd); 325 sysfs_put(sd);
315} 326}
316 327
@@ -319,15 +330,14 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const cha
319 struct sysfs_addrm_cxt acxt; 330 struct sysfs_addrm_cxt acxt;
320 struct sysfs_dirent *sd; 331 struct sysfs_dirent *sd;
321 332
322 if (!dir_sd) { 333 if (!dir_sd)
323 WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n",
324 name);
325 return -ENOENT; 334 return -ENOENT;
326 }
327 335
328 sysfs_addrm_start(&acxt, dir_sd); 336 sysfs_addrm_start(&acxt, dir_sd);
329 337
330 sd = sysfs_find_dirent(dir_sd, ns, name); 338 sd = sysfs_find_dirent(dir_sd, ns, name);
339 if (sd && (sd->s_ns != ns))
340 sd = NULL;
331 if (sd) 341 if (sd)
332 sysfs_remove_one(&acxt, sd); 342 sysfs_remove_one(&acxt, sd);
333 343
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index db940a9be04..e34f0d99ea4 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -36,7 +36,7 @@ struct sysfs_dirent sysfs_root = {
36 .s_name = "", 36 .s_name = "",
37 .s_count = ATOMIC_INIT(1), 37 .s_count = ATOMIC_INIT(1),
38 .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT), 38 .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT),
39 .s_mode = S_IFDIR | S_IRUGO | S_IXUGO, 39 .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
40 .s_ino = 1, 40 .s_ino = 1,
41}; 41};
42 42
@@ -61,14 +61,14 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
61 } 61 }
62 62
63 /* instantiate and link root dentry */ 63 /* instantiate and link root dentry */
64 root = d_make_root(inode); 64 root = d_alloc_root(inode);
65 if (!root) { 65 if (!root) {
66 pr_debug("%s: could not get root dentry!\n",__func__); 66 pr_debug("%s: could not get root dentry!\n",__func__);
67 iput(inode);
67 return -ENOMEM; 68 return -ENOMEM;
68 } 69 }
69 root->d_fsdata = &sysfs_root; 70 root->d_fsdata = &sysfs_root;
70 sb->s_root = root; 71 sb->s_root = root;
71 sb->s_d_op = &sysfs_dentry_ops;
72 return 0; 72 return 0;
73} 73}
74 74
@@ -118,12 +118,13 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
118 for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) 118 for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
119 info->ns[type] = kobj_ns_grab_current(type); 119 info->ns[type] = kobj_ns_grab_current(type);
120 120
121 sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info); 121 sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info);
122 if (IS_ERR(sb) || sb->s_fs_info != info) 122 if (IS_ERR(sb) || sb->s_fs_info != info)
123 free_sysfs_super_info(info); 123 free_sysfs_super_info(info);
124 if (IS_ERR(sb)) 124 if (IS_ERR(sb))
125 return ERR_CAST(sb); 125 return ERR_CAST(sb);
126 if (!sb->s_root) { 126 if (!sb->s_root) {
127 sb->s_flags = flags;
127 error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); 128 error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
128 if (error) { 129 if (error) {
129 deactivate_locked_super(sb); 130 deactivate_locked_super(sb);
@@ -149,7 +150,6 @@ static struct file_system_type sysfs_fs_type = {
149 .name = "sysfs", 150 .name = "sysfs",
150 .mount = sysfs_mount, 151 .mount = sysfs_mount,
151 .kill_sb = sysfs_kill_sb, 152 .kill_sb = sysfs_kill_sb,
152 .fs_flags = FS_USERNS_MOUNT,
153}; 153};
154 154
155int __init sysfs_init(void) 155int __init sysfs_init(void)
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 3c9eb5624f5..a7ac78f8e67 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -113,7 +113,7 @@ int sysfs_create_link(struct kobject *kobj, struct kobject *target,
113 * @target: object we're pointing to. 113 * @target: object we're pointing to.
114 * @name: name of the symlink. 114 * @name: name of the symlink.
115 * 115 *
116 * This function does the same as sysfs_create_link(), but it 116 * This function does the same as sysf_create_link(), but it
117 * doesn't warn if the link already exists. 117 * doesn't warn if the link already exists.
118 */ 118 */
119int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, 119int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index d73c0932bbd..845ab3ad229 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -11,17 +11,14 @@
11#include <linux/lockdep.h> 11#include <linux/lockdep.h>
12#include <linux/kobject_ns.h> 12#include <linux/kobject_ns.h>
13#include <linux/fs.h> 13#include <linux/fs.h>
14#include <linux/rbtree.h>
15 14
16struct sysfs_open_dirent; 15struct sysfs_open_dirent;
17 16
18/* type-specific structures for sysfs_dirent->s_* union members */ 17/* type-specific structures for sysfs_dirent->s_* union members */
19struct sysfs_elem_dir { 18struct sysfs_elem_dir {
20 struct kobject *kobj; 19 struct kobject *kobj;
21 20 /* children list starts here and goes through sd->s_sibling */
22 unsigned long subdirs; 21 struct sysfs_dirent *children;
23 /* children rbtree starts here and goes through sd->s_rb */
24 struct rb_root children;
25}; 22};
26 23
27struct sysfs_elem_symlink { 24struct sysfs_elem_symlink {
@@ -59,17 +56,10 @@ struct sysfs_dirent {
59 struct lockdep_map dep_map; 56 struct lockdep_map dep_map;
60#endif 57#endif
61 struct sysfs_dirent *s_parent; 58 struct sysfs_dirent *s_parent;
59 struct sysfs_dirent *s_sibling;
62 const char *s_name; 60 const char *s_name;
63 61
64 struct rb_node s_rb;
65
66 union {
67 struct completion *completion;
68 struct sysfs_dirent *removed_list;
69 } u;
70
71 const void *s_ns; /* namespace tag */ 62 const void *s_ns; /* namespace tag */
72 unsigned int s_hash; /* ns + name hash */
73 union { 63 union {
74 struct sysfs_elem_dir s_dir; 64 struct sysfs_elem_dir s_dir;
75 struct sysfs_elem_symlink s_symlink; 65 struct sysfs_elem_symlink s_symlink;
@@ -77,9 +67,9 @@ struct sysfs_dirent {
77 struct sysfs_elem_bin_attr s_bin_attr; 67 struct sysfs_elem_bin_attr s_bin_attr;
78 }; 68 };
79 69
80 unsigned short s_flags; 70 unsigned int s_flags;
81 umode_t s_mode; 71 unsigned short s_mode;
82 unsigned int s_ino; 72 ino_t s_ino;
83 struct sysfs_inode_attrs *s_iattr; 73 struct sysfs_inode_attrs *s_iattr;
84}; 74};
85 75
@@ -94,11 +84,11 @@ struct sysfs_dirent {
94#define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) 84#define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR)
95 85
96/* identify any namespace tag on sysfs_dirents */ 86/* identify any namespace tag on sysfs_dirents */
97#define SYSFS_NS_TYPE_MASK 0xf00 87#define SYSFS_NS_TYPE_MASK 0xff00
98#define SYSFS_NS_TYPE_SHIFT 8 88#define SYSFS_NS_TYPE_SHIFT 8
99 89
100#define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK) 90#define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK)
101#define SYSFS_FLAG_REMOVED 0x02000 91#define SYSFS_FLAG_REMOVED 0x020000
102 92
103static inline unsigned int sysfs_type(struct sysfs_dirent *sd) 93static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
104{ 94{
@@ -157,7 +147,6 @@ extern struct kmem_cache *sysfs_dir_cachep;
157 */ 147 */
158extern struct mutex sysfs_mutex; 148extern struct mutex sysfs_mutex;
159extern spinlock_t sysfs_assoc_lock; 149extern spinlock_t sysfs_assoc_lock;
160extern const struct dentry_operations sysfs_dentry_ops;
161 150
162extern const struct file_operations sysfs_dir_operations; 151extern const struct file_operations sysfs_dir_operations;
163extern const struct inode_operations sysfs_dir_inode_operations; 152extern const struct inode_operations sysfs_dir_inode_operations;
@@ -229,7 +218,7 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd,
229 const struct attribute *attr, int type); 218 const struct attribute *attr, int type);
230 219
231int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, 220int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
232 const struct attribute *attr, int type, umode_t amode); 221 const struct attribute *attr, int type, mode_t amode);
233/* 222/*
234 * bin.c 223 * bin.c
235 */ 224 */