aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r--fs/sysfs/dir.c130
1 files changed, 48 insertions, 82 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index a26e3db89432..bbf3525fd222 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -191,39 +191,18 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
191 return 0; 191 return 0;
192} 192}
193 193
194static int init_dir(struct inode * inode)
195{
196 inode->i_op = &sysfs_dir_inode_operations;
197 inode->i_fop = &sysfs_dir_operations;
198
199 /* directory inodes start off with i_nlink == 2 (for "." entry) */
200 inc_nlink(inode);
201 return 0;
202}
203
204static int init_file(struct inode * inode)
205{
206 inode->i_size = PAGE_SIZE;
207 inode->i_fop = &sysfs_file_operations;
208 return 0;
209}
210
211static int init_symlink(struct inode * inode)
212{
213 inode->i_op = &sysfs_symlink_inode_operations;
214 return 0;
215}
216
217static int create_dir(struct kobject *kobj, struct dentry *parent, 194static int create_dir(struct kobject *kobj, struct dentry *parent,
218 const char *name, struct dentry **p_dentry) 195 const char *name, struct dentry **p_dentry)
219{ 196{
220 int error; 197 int error;
221 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 198 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
222 struct dentry *dentry; 199 struct dentry *dentry;
200 struct inode *inode;
223 struct sysfs_dirent *sd; 201 struct sysfs_dirent *sd;
224 202
225 mutex_lock(&parent->d_inode->i_mutex); 203 mutex_lock(&parent->d_inode->i_mutex);
226 204
205 /* allocate */
227 dentry = lookup_one_len(name, parent, strlen(name)); 206 dentry = lookup_one_len(name, parent, strlen(name));
228 if (IS_ERR(dentry)) { 207 if (IS_ERR(dentry)) {
229 error = PTR_ERR(dentry); 208 error = PTR_ERR(dentry);
@@ -231,7 +210,7 @@ static int create_dir(struct kobject *kobj, struct dentry *parent,
231 } 210 }
232 211
233 error = -EEXIST; 212 error = -EEXIST;
234 if (sysfs_dirent_exist(parent->d_fsdata, name)) 213 if (dentry->d_inode)
235 goto out_dput; 214 goto out_dput;
236 215
237 error = -ENOMEM; 216 error = -ENOMEM;
@@ -240,19 +219,31 @@ static int create_dir(struct kobject *kobj, struct dentry *parent,
240 goto out_drop; 219 goto out_drop;
241 sd->s_elem.dir.kobj = kobj; 220 sd->s_elem.dir.kobj = kobj;
242 221
243 error = sysfs_create(sd, dentry, mode, init_dir); 222 inode = sysfs_new_inode(sd);
244 if (error) 223 if (!inode)
245 goto out_sput; 224 goto out_sput;
246 225
226 inode->i_op = &sysfs_dir_inode_operations;
227 inode->i_fop = &sysfs_dir_operations;
228 /* directory inodes start off with i_nlink == 2 (for "." entry) */
229 inc_nlink(inode);
230
231 /* link in */
232 error = -EEXIST;
233 if (sysfs_dirent_exist(parent->d_fsdata, name))
234 goto out_iput;
235
236 sysfs_instantiate(dentry, inode);
247 inc_nlink(parent->d_inode); 237 inc_nlink(parent->d_inode);
248 sysfs_attach_dirent(sd, parent->d_fsdata, dentry); 238 sysfs_attach_dirent(sd, parent->d_fsdata, dentry);
249 239
250 *p_dentry = dentry; 240 *p_dentry = dentry;
251 error = 0; 241 error = 0;
252 goto out_dput; 242 goto out_unlock; /* pin directory dentry in core */
253 243
244 out_iput:
245 iput(inode);
254 out_sput: 246 out_sput:
255 list_del_init(&sd->s_sibling);
256 sysfs_put(sd); 247 sysfs_put(sd);
257 out_drop: 248 out_drop:
258 d_drop(dentry); 249 d_drop(dentry);
@@ -298,71 +289,46 @@ int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent)
298 return error; 289 return error;
299} 290}
300 291
301/* attaches attribute's sysfs_dirent to the dentry corresponding to the
302 * attribute file
303 */
304static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
305{
306 struct attribute * attr = NULL;
307 struct bin_attribute * bin_attr = NULL;
308 int (* init) (struct inode *) = NULL;
309 int error = 0;
310
311 if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
312 bin_attr = sd->s_elem.bin_attr.bin_attr;
313 attr = &bin_attr->attr;
314 } else {
315 attr = sd->s_elem.attr.attr;
316 init = init_file;
317 }
318
319 error = sysfs_create(sd, dentry,
320 (attr->mode & S_IALLUGO) | S_IFREG, init);
321 if (error)
322 return error;
323
324 if (bin_attr) {
325 dentry->d_inode->i_size = bin_attr->size;
326 dentry->d_inode->i_fop = &bin_fops;
327 }
328
329 sysfs_attach_dentry(sd, dentry);
330
331 return 0;
332}
333
334static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
335{
336 int err;
337
338 err = sysfs_create(sd, dentry, S_IFLNK|S_IRWXUGO, init_symlink);
339 if (!err)
340 sysfs_attach_dentry(sd, dentry);
341
342 return err;
343}
344
345static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, 292static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
346 struct nameidata *nd) 293 struct nameidata *nd)
347{ 294{
348 struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata; 295 struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
349 struct sysfs_dirent * sd; 296 struct sysfs_dirent * sd;
350 int err = 0; 297 struct inode *inode;
298 int found = 0;
351 299
352 list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 300 list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
353 if (sd->s_type & SYSFS_NOT_PINNED) { 301 if ((sd->s_type & SYSFS_NOT_PINNED) &&
354 if (strcmp(sd->s_name, dentry->d_name.name)) 302 !strcmp(sd->s_name, dentry->d_name.name)) {
355 continue; 303 found = 1;
356
357 if (sd->s_type & SYSFS_KOBJ_LINK)
358 err = sysfs_attach_link(sd, dentry);
359 else
360 err = sysfs_attach_attr(sd, dentry);
361 break; 304 break;
362 } 305 }
363 } 306 }
364 307
365 return ERR_PTR(err); 308 /* no such entry */
309 if (!found)
310 return NULL;
311
312 /* attach dentry and inode */
313 inode = sysfs_new_inode(sd);
314 if (!inode)
315 return ERR_PTR(-ENOMEM);
316
317 /* initialize inode according to type */
318 if (sd->s_type & SYSFS_KOBJ_ATTR) {
319 inode->i_size = PAGE_SIZE;
320 inode->i_fop = &sysfs_file_operations;
321 } else if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
322 struct bin_attribute *bin_attr = sd->s_elem.bin_attr.bin_attr;
323 inode->i_size = bin_attr->size;
324 inode->i_fop = &bin_fops;
325 } else if (sd->s_type & SYSFS_KOBJ_LINK)
326 inode->i_op = &sysfs_symlink_inode_operations;
327
328 sysfs_instantiate(dentry, inode);
329 sysfs_attach_dentry(sd, dentry);
330
331 return NULL;
366} 332}
367 333
368const struct inode_operations sysfs_dir_inode_operations = { 334const struct inode_operations sysfs_dir_inode_operations = {