diff options
author | Tejun Heo <htejun@gmail.com> | 2007-06-13 14:45:15 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-11 19:09:04 -0400 |
commit | 3e5190380ebef77f2b015c9e7a4ca225a3d75021 (patch) | |
tree | 08d17cd0562acf5101063e93c649f5f71f80b3b9 /fs/sysfs | |
parent | 0c096b507f15397da890051ee73de4266d3941fb (diff) |
sysfs: make sysfs_dirent->s_element a union
Make sd->s_element a union of sysfs_elem_{dir|symlink|attr|bin_attr}
and rename it to s_elem. This is to achieve...
* some level of type checking : changing symlink to point to
sysfs_dirent instead of kobject is much safer and less painful now.
* easier / standardized dereferencing
* allow sysfs_elem_* to contain more than one entry
Where possible, pointer is obtained by directly deferencing from sd
instead of going through other entities. This reduces dependencies to
dentry, inode and kobject. to_attr() and to_bin_attr() are unused now
and removed.
This is in preparation of object reference simplification.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/bin.c | 18 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 31 | ||||
-rw-r--r-- | fs/sysfs/file.c | 19 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 2 | ||||
-rw-r--r-- | fs/sysfs/mount.c | 1 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 23 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 56 |
7 files changed, 71 insertions, 79 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 606267a36275..67a0d5030c96 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
@@ -23,7 +23,8 @@ | |||
23 | static int | 23 | static int |
24 | fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) | 24 | fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) |
25 | { | 25 | { |
26 | struct bin_attribute * attr = to_bin_attr(dentry); | 26 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
27 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; | ||
27 | struct kobject * kobj = to_kobj(dentry->d_parent); | 28 | struct kobject * kobj = to_kobj(dentry->d_parent); |
28 | 29 | ||
29 | if (!attr->read) | 30 | if (!attr->read) |
@@ -65,7 +66,8 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) | |||
65 | static int | 66 | static int |
66 | flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) | 67 | flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) |
67 | { | 68 | { |
68 | struct bin_attribute *attr = to_bin_attr(dentry); | 69 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
70 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; | ||
69 | struct kobject *kobj = to_kobj(dentry->d_parent); | 71 | struct kobject *kobj = to_kobj(dentry->d_parent); |
70 | 72 | ||
71 | if (!attr->write) | 73 | if (!attr->write) |
@@ -101,9 +103,9 @@ static ssize_t write(struct file *file, const char __user *userbuf, | |||
101 | 103 | ||
102 | static int mmap(struct file *file, struct vm_area_struct *vma) | 104 | static int mmap(struct file *file, struct vm_area_struct *vma) |
103 | { | 105 | { |
104 | struct dentry *dentry = file->f_path.dentry; | 106 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
105 | struct bin_attribute *attr = to_bin_attr(dentry); | 107 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; |
106 | struct kobject *kobj = to_kobj(dentry->d_parent); | 108 | struct kobject *kobj = to_kobj(file->f_path.dentry->d_parent); |
107 | 109 | ||
108 | if (!attr->mmap) | 110 | if (!attr->mmap) |
109 | return -EINVAL; | 111 | return -EINVAL; |
@@ -114,7 +116,8 @@ static int mmap(struct file *file, struct vm_area_struct *vma) | |||
114 | static int open(struct inode * inode, struct file * file) | 116 | static int open(struct inode * inode, struct file * file) |
115 | { | 117 | { |
116 | struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); | 118 | struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); |
117 | struct bin_attribute * attr = to_bin_attr(file->f_path.dentry); | 119 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
120 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; | ||
118 | int error = -EINVAL; | 121 | int error = -EINVAL; |
119 | 122 | ||
120 | if (!kobj || !attr) | 123 | if (!kobj || !attr) |
@@ -150,7 +153,8 @@ static int open(struct inode * inode, struct file * file) | |||
150 | static int release(struct inode * inode, struct file * file) | 153 | static int release(struct inode * inode, struct file * file) |
151 | { | 154 | { |
152 | struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent); | 155 | struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent); |
153 | struct bin_attribute * attr = to_bin_attr(file->f_path.dentry); | 156 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
157 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; | ||
154 | u8 * buffer = file->private_data; | 158 | u8 * buffer = file->private_data; |
155 | 159 | ||
156 | kobject_put(kobj); | 160 | kobject_put(kobj); |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 6e8d6f54f082..079122695675 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -52,11 +52,8 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) | |||
52 | repeat: | 52 | repeat: |
53 | parent_sd = sd->s_parent; | 53 | parent_sd = sd->s_parent; |
54 | 54 | ||
55 | if (sd->s_type & SYSFS_KOBJ_LINK) { | 55 | if (sd->s_type & SYSFS_KOBJ_LINK) |
56 | struct sysfs_symlink * sl = sd->s_element; | 56 | kobject_put(sd->s_elem.symlink.target_kobj); |
57 | kobject_put(sl->target_kobj); | ||
58 | kfree(sl); | ||
59 | } | ||
60 | if (sd->s_type & SYSFS_COPY_NAME) | 57 | if (sd->s_type & SYSFS_COPY_NAME) |
61 | kfree(sd->s_name); | 58 | kfree(sd->s_name); |
62 | kfree(sd->s_iattr); | 59 | kfree(sd->s_iattr); |
@@ -95,8 +92,7 @@ static struct dentry_operations sysfs_dentry_ops = { | |||
95 | .d_iput = sysfs_d_iput, | 92 | .d_iput = sysfs_d_iput, |
96 | }; | 93 | }; |
97 | 94 | ||
98 | struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element, | 95 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) |
99 | umode_t mode, int type) | ||
100 | { | 96 | { |
101 | char *dup_name = NULL; | 97 | char *dup_name = NULL; |
102 | struct sysfs_dirent *sd = NULL; | 98 | struct sysfs_dirent *sd = NULL; |
@@ -120,7 +116,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element, | |||
120 | INIT_LIST_HEAD(&sd->s_sibling); | 116 | INIT_LIST_HEAD(&sd->s_sibling); |
121 | 117 | ||
122 | sd->s_name = name; | 118 | sd->s_name = name; |
123 | sd->s_element = element; | ||
124 | sd->s_mode = mode; | 119 | sd->s_mode = mode; |
125 | sd->s_type = type; | 120 | sd->s_type = type; |
126 | 121 | ||
@@ -160,7 +155,7 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, | |||
160 | struct sysfs_dirent * sd; | 155 | struct sysfs_dirent * sd; |
161 | 156 | ||
162 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | 157 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { |
163 | if (sd->s_element) { | 158 | if (sd->s_type) { |
164 | if (strcmp(sd->s_name, new)) | 159 | if (strcmp(sd->s_name, new)) |
165 | continue; | 160 | continue; |
166 | else | 161 | else |
@@ -215,9 +210,10 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, | |||
215 | goto out_dput; | 210 | goto out_dput; |
216 | 211 | ||
217 | error = -ENOMEM; | 212 | error = -ENOMEM; |
218 | sd = sysfs_new_dirent(name, kobj, mode, SYSFS_DIR); | 213 | sd = sysfs_new_dirent(name, mode, SYSFS_DIR); |
219 | if (!sd) | 214 | if (!sd) |
220 | goto out_drop; | 215 | goto out_drop; |
216 | sd->s_elem.dir.kobj = kobj; | ||
221 | sysfs_attach_dirent(sd, parent->d_fsdata, dentry); | 217 | sysfs_attach_dirent(sd, parent->d_fsdata, dentry); |
222 | 218 | ||
223 | error = sysfs_create(dentry, mode, init_dir); | 219 | error = sysfs_create(dentry, mode, init_dir); |
@@ -290,10 +286,10 @@ static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry) | |||
290 | int error = 0; | 286 | int error = 0; |
291 | 287 | ||
292 | if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) { | 288 | if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) { |
293 | bin_attr = sd->s_element; | 289 | bin_attr = sd->s_elem.bin_attr.bin_attr; |
294 | attr = &bin_attr->attr; | 290 | attr = &bin_attr->attr; |
295 | } else { | 291 | } else { |
296 | attr = sd->s_element; | 292 | attr = sd->s_elem.attr.attr; |
297 | init = init_file; | 293 | init = init_file; |
298 | } | 294 | } |
299 | 295 | ||
@@ -404,7 +400,7 @@ static void __sysfs_remove_dir(struct dentry *dentry) | |||
404 | mutex_lock(&dentry->d_inode->i_mutex); | 400 | mutex_lock(&dentry->d_inode->i_mutex); |
405 | parent_sd = dentry->d_fsdata; | 401 | parent_sd = dentry->d_fsdata; |
406 | list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { | 402 | list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { |
407 | if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED)) | 403 | if (!sd->s_type || !(sd->s_type & SYSFS_NOT_PINNED)) |
408 | continue; | 404 | continue; |
409 | list_del_init(&sd->s_sibling); | 405 | list_del_init(&sd->s_sibling); |
410 | sysfs_drop_dentry(sd, dentry); | 406 | sysfs_drop_dentry(sd, dentry); |
@@ -556,7 +552,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file) | |||
556 | struct sysfs_dirent * sd; | 552 | struct sysfs_dirent * sd; |
557 | 553 | ||
558 | mutex_lock(&dentry->d_inode->i_mutex); | 554 | mutex_lock(&dentry->d_inode->i_mutex); |
559 | sd = sysfs_new_dirent("_DIR_", NULL, 0, 0); | 555 | sd = sysfs_new_dirent("_DIR_", 0, 0); |
560 | if (sd) | 556 | if (sd) |
561 | sysfs_attach_dirent(sd, parent_sd, NULL); | 557 | sysfs_attach_dirent(sd, parent_sd, NULL); |
562 | mutex_unlock(&dentry->d_inode->i_mutex); | 558 | mutex_unlock(&dentry->d_inode->i_mutex); |
@@ -623,7 +619,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
623 | 619 | ||
624 | next = list_entry(p, struct sysfs_dirent, | 620 | next = list_entry(p, struct sysfs_dirent, |
625 | s_sibling); | 621 | s_sibling); |
626 | if (!next->s_element) | 622 | if (!next->s_type) |
627 | continue; | 623 | continue; |
628 | 624 | ||
629 | name = next->s_name; | 625 | name = next->s_name; |
@@ -671,7 +667,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
671 | struct sysfs_dirent *next; | 667 | struct sysfs_dirent *next; |
672 | next = list_entry(p, struct sysfs_dirent, | 668 | next = list_entry(p, struct sysfs_dirent, |
673 | s_sibling); | 669 | s_sibling); |
674 | if (next->s_element) | 670 | if (next->s_type) |
675 | n--; | 671 | n--; |
676 | p = p->next; | 672 | p = p->next; |
677 | } | 673 | } |
@@ -738,9 +734,10 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) | |||
738 | if (!shadow) | 734 | if (!shadow) |
739 | goto nomem; | 735 | goto nomem; |
740 | 736 | ||
741 | sd = sysfs_new_dirent("_SHADOW_", kobj, inode->i_mode, SYSFS_DIR); | 737 | sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR); |
742 | if (!sd) | 738 | if (!sd) |
743 | goto nomem; | 739 | goto nomem; |
740 | sd->s_elem.dir.kobj = kobj; | ||
744 | /* point to parent_sd but don't attach to it */ | 741 | /* point to parent_sd but don't attach to it */ |
745 | sd->s_parent = sysfs_get(parent_sd); | 742 | sd->s_parent = sysfs_get(parent_sd); |
746 | sysfs_attach_dirent(sd, NULL, shadow); | 743 | sysfs_attach_dirent(sd, NULL, shadow); |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 8240b1687dd0..04f6b0ebc889 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -88,7 +88,6 @@ remove_from_collection(struct sysfs_buffer *buffer, struct inode *node) | |||
88 | static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) | 88 | static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) |
89 | { | 89 | { |
90 | struct sysfs_dirent * sd = dentry->d_fsdata; | 90 | struct sysfs_dirent * sd = dentry->d_fsdata; |
91 | struct attribute * attr = to_attr(dentry); | ||
92 | struct kobject * kobj = to_kobj(dentry->d_parent); | 91 | struct kobject * kobj = to_kobj(dentry->d_parent); |
93 | struct sysfs_ops * ops = buffer->ops; | 92 | struct sysfs_ops * ops = buffer->ops; |
94 | int ret = 0; | 93 | int ret = 0; |
@@ -100,7 +99,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer | |||
100 | return -ENOMEM; | 99 | return -ENOMEM; |
101 | 100 | ||
102 | buffer->event = atomic_read(&sd->s_event); | 101 | buffer->event = atomic_read(&sd->s_event); |
103 | count = ops->show(kobj,attr,buffer->page); | 102 | count = ops->show(kobj, sd->s_elem.attr.attr, buffer->page); |
104 | BUG_ON(count > (ssize_t)PAGE_SIZE); | 103 | BUG_ON(count > (ssize_t)PAGE_SIZE); |
105 | if (count >= 0) { | 104 | if (count >= 0) { |
106 | buffer->needs_read_fill = 0; | 105 | buffer->needs_read_fill = 0; |
@@ -199,11 +198,11 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t | |||
199 | static int | 198 | static int |
200 | flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) | 199 | flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) |
201 | { | 200 | { |
202 | struct attribute * attr = to_attr(dentry); | 201 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
203 | struct kobject * kobj = to_kobj(dentry->d_parent); | 202 | struct kobject * kobj = to_kobj(dentry->d_parent); |
204 | struct sysfs_ops * ops = buffer->ops; | 203 | struct sysfs_ops * ops = buffer->ops; |
205 | 204 | ||
206 | return ops->store(kobj,attr,buffer->page,count); | 205 | return ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count); |
207 | } | 206 | } |
208 | 207 | ||
209 | 208 | ||
@@ -248,7 +247,8 @@ out: | |||
248 | static int sysfs_open_file(struct inode *inode, struct file *file) | 247 | static int sysfs_open_file(struct inode *inode, struct file *file) |
249 | { | 248 | { |
250 | struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); | 249 | struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); |
251 | struct attribute * attr = to_attr(file->f_path.dentry); | 250 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
251 | struct attribute *attr = attr_sd->s_elem.attr.attr; | ||
252 | struct sysfs_buffer_collection *set; | 252 | struct sysfs_buffer_collection *set; |
253 | struct sysfs_buffer * buffer; | 253 | struct sysfs_buffer * buffer; |
254 | struct sysfs_ops * ops = NULL; | 254 | struct sysfs_ops * ops = NULL; |
@@ -341,15 +341,15 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
341 | static int sysfs_release(struct inode * inode, struct file * filp) | 341 | static int sysfs_release(struct inode * inode, struct file * filp) |
342 | { | 342 | { |
343 | struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent); | 343 | struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent); |
344 | struct attribute * attr = to_attr(filp->f_path.dentry); | 344 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; |
345 | struct module * owner = attr->owner; | 345 | struct attribute *attr = attr_sd->s_elem.attr.attr; |
346 | struct sysfs_buffer * buffer = filp->private_data; | 346 | struct sysfs_buffer * buffer = filp->private_data; |
347 | 347 | ||
348 | if (buffer) | 348 | if (buffer) |
349 | remove_from_collection(buffer, inode); | 349 | remove_from_collection(buffer, inode); |
350 | kobject_put(kobj); | 350 | kobject_put(kobj); |
351 | /* After this point, attr should not be accessed. */ | 351 | /* After this point, attr should not be accessed. */ |
352 | module_put(owner); | 352 | module_put(attr->owner); |
353 | 353 | ||
354 | if (buffer) { | 354 | if (buffer) { |
355 | if (buffer->page) | 355 | if (buffer->page) |
@@ -454,11 +454,12 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) | |||
454 | goto out_unlock; | 454 | goto out_unlock; |
455 | } | 455 | } |
456 | 456 | ||
457 | sd = sysfs_new_dirent(attr->name, (void *)attr, mode, type); | 457 | sd = sysfs_new_dirent(attr->name, mode, type); |
458 | if (!sd) { | 458 | if (!sd) { |
459 | error = -ENOMEM; | 459 | error = -ENOMEM; |
460 | goto out_unlock; | 460 | goto out_unlock; |
461 | } | 461 | } |
462 | sd->s_elem.attr.attr = (void *)attr; | ||
462 | sysfs_attach_dirent(sd, parent_sd, NULL); | 463 | sysfs_attach_dirent(sd, parent_sd, NULL); |
463 | 464 | ||
464 | out_unlock: | 465 | out_unlock: |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 5c605b0003a8..617d10cea07d 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -272,7 +272,7 @@ int sysfs_hash_and_remove(struct dentry * dir, const char * name) | |||
272 | parent_sd = dir->d_fsdata; | 272 | parent_sd = dir->d_fsdata; |
273 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); | 273 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); |
274 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | 274 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { |
275 | if (!sd->s_element) | 275 | if (!sd->s_type) |
276 | continue; | 276 | continue; |
277 | if (!strcmp(sd->s_name, name)) { | 277 | if (!strcmp(sd->s_name, name)) { |
278 | list_del_init(&sd->s_sibling); | 278 | list_del_init(&sd->s_sibling); |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 31c1fc67f604..8f6d8b1b211f 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -31,7 +31,6 @@ static struct sysfs_dirent sysfs_root = { | |||
31 | .s_count = ATOMIC_INIT(1), | 31 | .s_count = ATOMIC_INIT(1), |
32 | .s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling), | 32 | .s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling), |
33 | .s_children = LIST_HEAD_INIT(sysfs_root.s_children), | 33 | .s_children = LIST_HEAD_INIT(sysfs_root.s_children), |
34 | .s_element = NULL, | ||
35 | .s_type = SYSFS_ROOT, | 34 | .s_type = SYSFS_ROOT, |
36 | .s_iattr = NULL, | 35 | .s_iattr = NULL, |
37 | .s_ino = 1, | 36 | .s_ino = 1, |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index c72820450e7c..27df635b786a 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -48,30 +48,15 @@ static void fill_object_path(struct kobject * kobj, char * buffer, int length) | |||
48 | static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target) | 48 | static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target) |
49 | { | 49 | { |
50 | struct sysfs_dirent * parent_sd = parent->d_fsdata; | 50 | struct sysfs_dirent * parent_sd = parent->d_fsdata; |
51 | struct sysfs_symlink * sl; | ||
52 | struct sysfs_dirent * sd; | 51 | struct sysfs_dirent * sd; |
53 | int error; | ||
54 | 52 | ||
55 | error = -ENOMEM; | 53 | sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); |
56 | sl = kzalloc(sizeof(*sl), GFP_KERNEL); | ||
57 | if (!sl) | ||
58 | goto err_out; | ||
59 | |||
60 | sl->target_kobj = kobject_get(target); | ||
61 | |||
62 | sd = sysfs_new_dirent(name, sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); | ||
63 | if (!sd) | 54 | if (!sd) |
64 | goto err_out; | 55 | return -ENOMEM; |
65 | sysfs_attach_dirent(sd, parent_sd, NULL); | ||
66 | 56 | ||
57 | sd->s_elem.symlink.target_kobj = kobject_get(target); | ||
58 | sysfs_attach_dirent(sd, parent_sd, NULL); | ||
67 | return 0; | 59 | return 0; |
68 | |||
69 | err_out: | ||
70 | if (sl) { | ||
71 | kobject_put(sl->target_kobj); | ||
72 | kfree(sl); | ||
73 | } | ||
74 | return error; | ||
75 | } | 60 | } |
76 | 61 | ||
77 | /** | 62 | /** |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index d34b008537d5..39ab0481379c 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -1,10 +1,33 @@ | |||
1 | struct sysfs_elem_dir { | ||
2 | struct kobject * kobj; | ||
3 | }; | ||
4 | |||
5 | struct sysfs_elem_symlink { | ||
6 | struct kobject * target_kobj; | ||
7 | }; | ||
8 | |||
9 | struct sysfs_elem_attr { | ||
10 | struct attribute * attr; | ||
11 | }; | ||
12 | |||
13 | struct sysfs_elem_bin_attr { | ||
14 | struct bin_attribute * bin_attr; | ||
15 | }; | ||
16 | |||
1 | struct sysfs_dirent { | 17 | struct sysfs_dirent { |
2 | atomic_t s_count; | 18 | atomic_t s_count; |
3 | struct sysfs_dirent * s_parent; | 19 | struct sysfs_dirent * s_parent; |
4 | struct list_head s_sibling; | 20 | struct list_head s_sibling; |
5 | struct list_head s_children; | 21 | struct list_head s_children; |
6 | const char * s_name; | 22 | const char * s_name; |
7 | void * s_element; | 23 | |
24 | union { | ||
25 | struct sysfs_elem_dir dir; | ||
26 | struct sysfs_elem_symlink symlink; | ||
27 | struct sysfs_elem_attr attr; | ||
28 | struct sysfs_elem_bin_attr bin_attr; | ||
29 | } s_elem; | ||
30 | |||
8 | int s_type; | 31 | int s_type; |
9 | umode_t s_mode; | 32 | umode_t s_mode; |
10 | ino_t s_ino; | 33 | ino_t s_ino; |
@@ -22,8 +45,8 @@ extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); | |||
22 | 45 | ||
23 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); | 46 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); |
24 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); | 47 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); |
25 | extern struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element, | 48 | extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, |
26 | umode_t mode, int type); | 49 | int type); |
27 | extern void sysfs_attach_dirent(struct sysfs_dirent *sd, | 50 | extern void sysfs_attach_dirent(struct sysfs_dirent *sd, |
28 | struct sysfs_dirent *parent_sd, | 51 | struct sysfs_dirent *parent_sd, |
29 | struct dentry *dentry); | 52 | struct dentry *dentry); |
@@ -47,10 +70,6 @@ extern const struct file_operations bin_fops; | |||
47 | extern const struct inode_operations sysfs_dir_inode_operations; | 70 | extern const struct inode_operations sysfs_dir_inode_operations; |
48 | extern const struct inode_operations sysfs_symlink_inode_operations; | 71 | extern const struct inode_operations sysfs_symlink_inode_operations; |
49 | 72 | ||
50 | struct sysfs_symlink { | ||
51 | struct kobject * target_kobj; | ||
52 | }; | ||
53 | |||
54 | struct sysfs_buffer { | 73 | struct sysfs_buffer { |
55 | struct list_head associates; | 74 | struct list_head associates; |
56 | size_t count; | 75 | size_t count; |
@@ -70,19 +89,7 @@ struct sysfs_buffer_collection { | |||
70 | static inline struct kobject * to_kobj(struct dentry * dentry) | 89 | static inline struct kobject * to_kobj(struct dentry * dentry) |
71 | { | 90 | { |
72 | struct sysfs_dirent * sd = dentry->d_fsdata; | 91 | struct sysfs_dirent * sd = dentry->d_fsdata; |
73 | return ((struct kobject *) sd->s_element); | 92 | return sd->s_elem.dir.kobj; |
74 | } | ||
75 | |||
76 | static inline struct attribute * to_attr(struct dentry * dentry) | ||
77 | { | ||
78 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
79 | return ((struct attribute *) sd->s_element); | ||
80 | } | ||
81 | |||
82 | static inline struct bin_attribute * to_bin_attr(struct dentry * dentry) | ||
83 | { | ||
84 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
85 | return ((struct bin_attribute *) sd->s_element); | ||
86 | } | 93 | } |
87 | 94 | ||
88 | static inline struct kobject *sysfs_get_kobject(struct dentry *dentry) | 95 | static inline struct kobject *sysfs_get_kobject(struct dentry *dentry) |
@@ -92,11 +99,10 @@ static inline struct kobject *sysfs_get_kobject(struct dentry *dentry) | |||
92 | spin_lock(&dcache_lock); | 99 | spin_lock(&dcache_lock); |
93 | if (!d_unhashed(dentry)) { | 100 | if (!d_unhashed(dentry)) { |
94 | struct sysfs_dirent * sd = dentry->d_fsdata; | 101 | struct sysfs_dirent * sd = dentry->d_fsdata; |
95 | if (sd->s_type & SYSFS_KOBJ_LINK) { | 102 | if (sd->s_type & SYSFS_KOBJ_LINK) |
96 | struct sysfs_symlink * sl = sd->s_element; | 103 | kobj = kobject_get(sd->s_elem.symlink.target_kobj); |
97 | kobj = kobject_get(sl->target_kobj); | 104 | else |
98 | } else | 105 | kobj = kobject_get(sd->s_elem.dir.kobj); |
99 | kobj = kobject_get(sd->s_element); | ||
100 | } | 106 | } |
101 | spin_unlock(&dcache_lock); | 107 | spin_unlock(&dcache_lock); |
102 | 108 | ||