aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/sysfs/dir.c82
-rw-r--r--fs/sysfs/file.c21
-rw-r--r--fs/sysfs/symlink.c7
-rw-r--r--fs/sysfs/sysfs.h7
4 files changed, 50 insertions, 67 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 90bed5df254f..f16aa7e3eafc 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -85,10 +85,7 @@ static struct dentry_operations sysfs_dentry_ops = {
85 .d_iput = sysfs_d_iput, 85 .d_iput = sysfs_d_iput,
86}; 86};
87 87
88/* 88struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, int type)
89 * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
90 */
91static struct sysfs_dirent * __sysfs_new_dirent(void * element)
92{ 89{
93 struct sysfs_dirent * sd; 90 struct sysfs_dirent * sd;
94 91
@@ -105,25 +102,25 @@ static struct sysfs_dirent * __sysfs_new_dirent(void * element)
105 atomic_set(&sd->s_event, 1); 102 atomic_set(&sd->s_event, 1);
106 INIT_LIST_HEAD(&sd->s_children); 103 INIT_LIST_HEAD(&sd->s_children);
107 INIT_LIST_HEAD(&sd->s_sibling); 104 INIT_LIST_HEAD(&sd->s_sibling);
105
108 sd->s_element = element; 106 sd->s_element = element;
107 sd->s_mode = mode;
108 sd->s_type = type;
109 109
110 return sd; 110 return sd;
111} 111}
112 112
113static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd, 113void sysfs_attach_dirent(struct sysfs_dirent *sd,
114 struct sysfs_dirent *sd) 114 struct sysfs_dirent *parent_sd, struct dentry *dentry)
115{ 115{
116 if (sd) 116 if (dentry) {
117 list_add(&sd->s_sibling, &parent_sd->s_children); 117 sd->s_dentry = dentry;
118} 118 dentry->d_fsdata = sysfs_get(sd);
119 dentry->d_op = &sysfs_dentry_ops;
120 }
119 121
120static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd, 122 if (parent_sd)
121 void * element) 123 list_add(&sd->s_sibling, &parent_sd->s_children);
122{
123 struct sysfs_dirent *sd;
124 sd = __sysfs_new_dirent(element);
125 __sysfs_list_dirent(parent_sd, sd);
126 return sd;
127} 124}
128 125
129/* 126/*
@@ -151,39 +148,6 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
151 return 0; 148 return 0;
152} 149}
153 150
154
155static struct sysfs_dirent *
156__sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type)
157{
158 struct sysfs_dirent * sd;
159
160 sd = __sysfs_new_dirent(element);
161 if (!sd)
162 goto out;
163
164 sd->s_mode = mode;
165 sd->s_type = type;
166 sd->s_dentry = dentry;
167 if (dentry) {
168 dentry->d_fsdata = sysfs_get(sd);
169 dentry->d_op = &sysfs_dentry_ops;
170 }
171
172out:
173 return sd;
174}
175
176int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
177 void * element, umode_t mode, int type)
178{
179 struct sysfs_dirent *sd;
180
181 sd = __sysfs_make_dirent(dentry, element, mode, type);
182 __sysfs_list_dirent(parent_sd, sd);
183
184 return sd ? 0 : -ENOMEM;
185}
186
187static int init_dir(struct inode * inode) 151static int init_dir(struct inode * inode)
188{ 152{
189 inode->i_op = &sysfs_dir_inode_operations; 153 inode->i_op = &sysfs_dir_inode_operations;
@@ -227,10 +191,11 @@ static int create_dir(struct kobject *kobj, struct dentry *parent,
227 if (sysfs_dirent_exist(parent->d_fsdata, name)) 191 if (sysfs_dirent_exist(parent->d_fsdata, name))
228 goto out_dput; 192 goto out_dput;
229 193
230 error = sysfs_make_dirent(parent->d_fsdata, dentry, kobj, mode, 194 error = -ENOMEM;
231 SYSFS_DIR); 195 sd = sysfs_new_dirent(kobj, mode, SYSFS_DIR);
232 if (error) 196 if (!sd)
233 goto out_drop; 197 goto out_drop;
198 sysfs_attach_dirent(sd, parent->d_fsdata, dentry);
234 199
235 error = sysfs_create(dentry, mode, init_dir); 200 error = sysfs_create(dentry, mode, init_dir);
236 if (error) 201 if (error)
@@ -245,7 +210,6 @@ static int create_dir(struct kobject *kobj, struct dentry *parent,
245 goto out_dput; 210 goto out_dput;
246 211
247 out_sput: 212 out_sput:
248 sd = dentry->d_fsdata;
249 list_del_init(&sd->s_sibling); 213 list_del_init(&sd->s_sibling);
250 sysfs_put(sd); 214 sysfs_put(sd);
251 out_drop: 215 out_drop:
@@ -557,13 +521,16 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
557{ 521{
558 struct dentry * dentry = file->f_path.dentry; 522 struct dentry * dentry = file->f_path.dentry;
559 struct sysfs_dirent * parent_sd = dentry->d_fsdata; 523 struct sysfs_dirent * parent_sd = dentry->d_fsdata;
524 struct sysfs_dirent * sd;
560 525
561 mutex_lock(&dentry->d_inode->i_mutex); 526 mutex_lock(&dentry->d_inode->i_mutex);
562 file->private_data = sysfs_new_dirent(parent_sd, NULL); 527 sd = sysfs_new_dirent(NULL, 0, 0);
528 if (sd)
529 sysfs_attach_dirent(sd, parent_sd, NULL);
563 mutex_unlock(&dentry->d_inode->i_mutex); 530 mutex_unlock(&dentry->d_inode->i_mutex);
564 531
565 return file->private_data ? 0 : -ENOMEM; 532 file->private_data = sd;
566 533 return sd ? 0 : -ENOMEM;
567} 534}
568 535
569static int sysfs_dir_close(struct inode *inode, struct file *file) 536static int sysfs_dir_close(struct inode *inode, struct file *file)
@@ -736,9 +703,10 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
736 if (!shadow) 703 if (!shadow)
737 goto nomem; 704 goto nomem;
738 705
739 sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR); 706 sd = sysfs_new_dirent(kobj, inode->i_mode, SYSFS_DIR);
740 if (!sd) 707 if (!sd)
741 goto nomem; 708 goto nomem;
709 sysfs_attach_dirent(sd, NULL, shadow);
742 710
743 d_instantiate(shadow, igrab(inode)); 711 d_instantiate(shadow, igrab(inode));
744 inc_nlink(inode); 712 inc_nlink(inode);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index b502c7197ec0..fd4b6dc03d2d 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -444,14 +444,25 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
444{ 444{
445 struct sysfs_dirent * parent_sd = dir->d_fsdata; 445 struct sysfs_dirent * parent_sd = dir->d_fsdata;
446 umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; 446 umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
447 int error = -EEXIST; 447 struct sysfs_dirent *sd;
448 int error = 0;
448 449
449 mutex_lock(&dir->d_inode->i_mutex); 450 mutex_lock(&dir->d_inode->i_mutex);
450 if (!sysfs_dirent_exist(parent_sd, attr->name))
451 error = sysfs_make_dirent(parent_sd, NULL, (void *)attr,
452 mode, type);
453 mutex_unlock(&dir->d_inode->i_mutex);
454 451
452 if (sysfs_dirent_exist(parent_sd, attr->name)) {
453 error = -EEXIST;
454 goto out_unlock;
455 }
456
457 sd = sysfs_new_dirent((void *)attr, mode, type);
458 if (!sd) {
459 error = -ENOMEM;
460 goto out_unlock;
461 }
462 sysfs_attach_dirent(sd, parent_sd, NULL);
463
464 out_unlock:
465 mutex_unlock(&dir->d_inode->i_mutex);
455 return error; 466 return error;
456} 467}
457 468
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index b463f17f6638..d96bb9cbc9d4 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -49,6 +49,7 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj
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; 51 struct sysfs_symlink * sl;
52 struct sysfs_dirent * sd;
52 int error; 53 int error;
53 54
54 error = -ENOMEM; 55 error = -ENOMEM;
@@ -63,10 +64,10 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj
63 strcpy(sl->link_name, name); 64 strcpy(sl->link_name, name);
64 sl->target_kobj = kobject_get(target); 65 sl->target_kobj = kobject_get(target);
65 66
66 error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO, 67 sd = sysfs_new_dirent(sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
67 SYSFS_KOBJ_LINK); 68 if (!sd)
68 if (error)
69 goto err_out; 69 goto err_out;
70 sysfs_attach_dirent(sd, parent_sd, NULL);
70 71
71 return 0; 72 return 0;
72 73
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index f4fdbbffd571..f8f49cc5c852 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -20,8 +20,11 @@ extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
20 20
21extern void release_sysfs_dirent(struct sysfs_dirent * sd); 21extern void release_sysfs_dirent(struct sysfs_dirent * sd);
22extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); 22extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
23extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, 23extern struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode,
24 umode_t, int); 24 int type);
25extern void sysfs_attach_dirent(struct sysfs_dirent *sd,
26 struct sysfs_dirent *parent_sd,
27 struct dentry *dentry);
25 28
26extern int sysfs_add_file(struct dentry *, const struct attribute *, int); 29extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
27extern int sysfs_hash_and_remove(struct dentry * dir, const char * name); 30extern int sysfs_hash_and_remove(struct dentry * dir, const char * name);