2 * dir.c - Operations for sysfs directories.
8 #include <linux/mount.h>
9 #include <linux/module.h>
10 #include <linux/kobject.h>
13 DECLARE_RWSEM(sysfs_rename_sem
);
15 static void sysfs_d_iput(struct dentry
* dentry
, struct inode
* inode
)
17 struct sysfs_dirent
* sd
= dentry
->d_fsdata
;
20 BUG_ON(sd
->s_dentry
!= dentry
);
27 static struct dentry_operations sysfs_dentry_ops
= {
28 .d_iput
= sysfs_d_iput
,
32 * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
34 static struct sysfs_dirent
* sysfs_new_dirent(struct sysfs_dirent
* parent_sd
,
37 struct sysfs_dirent
* sd
;
39 sd
= kmem_cache_alloc(sysfs_dir_cachep
, GFP_KERNEL
);
43 memset(sd
, 0, sizeof(*sd
));
44 atomic_set(&sd
->s_count
, 1);
45 INIT_LIST_HEAD(&sd
->s_children
);
46 list_add(&sd
->s_sibling
, &parent_sd
->s_children
);
47 sd
->s_element
= element
;
52 int sysfs_make_dirent(struct sysfs_dirent
* parent_sd
, struct dentry
* dentry
,
53 void * element
, umode_t mode
, int type
)
55 struct sysfs_dirent
* sd
;
57 sd
= sysfs_new_dirent(parent_sd
, element
);
63 sd
->s_dentry
= dentry
;
65 dentry
->d_fsdata
= sysfs_get(sd
);
66 dentry
->d_op
= &sysfs_dentry_ops
;
72 static int init_dir(struct inode
* inode
)
74 inode
->i_op
= &sysfs_dir_inode_operations
;
75 inode
->i_fop
= &sysfs_dir_operations
;
77 /* directory inodes start off with i_nlink == 2 (for "." entry) */
82 static int init_file(struct inode
* inode
)
84 inode
->i_size
= PAGE_SIZE
;
85 inode
->i_fop
= &sysfs_file_operations
;
89 static int init_symlink(struct inode
* inode
)
91 inode
->i_op
= &sysfs_symlink_inode_operations
;
95 static int create_dir(struct kobject
* k
, struct dentry
* p
,
96 const char * n
, struct dentry
** d
)
99 umode_t mode
= S_IFDIR
| S_IRWXU
| S_IRUGO
| S_IXUGO
;
101 down(&p
->d_inode
->i_sem
);
102 *d
= sysfs_get_dentry(p
,n
);
104 error
= sysfs_make_dirent(p
->d_fsdata
, *d
, k
, mode
, SYSFS_DIR
);
106 error
= sysfs_create(*d
, mode
, init_dir
);
108 p
->d_inode
->i_nlink
++;
109 (*d
)->d_op
= &sysfs_dentry_ops
;
113 if (error
&& (error
!= -EEXIST
)) {
114 sysfs_put((*d
)->d_fsdata
);
120 up(&p
->d_inode
->i_sem
);
125 int sysfs_create_subdir(struct kobject
* k
, const char * n
, struct dentry
** d
)
127 return create_dir(k
,k
->dentry
,n
,d
);
131 * sysfs_create_dir - create a directory for an object.
132 * @parent: parent parent object.
133 * @kobj: object we're creating directory for.
136 int sysfs_create_dir(struct kobject
* kobj
)
138 struct dentry
* dentry
= NULL
;
139 struct dentry
* parent
;
145 parent
= kobj
->parent
->dentry
;
146 else if (sysfs_mount
&& sysfs_mount
->mnt_sb
)
147 parent
= sysfs_mount
->mnt_sb
->s_root
;
151 error
= create_dir(kobj
,parent
,kobject_name(kobj
),&dentry
);
153 kobj
->dentry
= dentry
;
157 /* attaches attribute's sysfs_dirent to the dentry corresponding to the
160 static int sysfs_attach_attr(struct sysfs_dirent
* sd
, struct dentry
* dentry
)
162 struct attribute
* attr
= NULL
;
163 struct bin_attribute
* bin_attr
= NULL
;
164 int (* init
) (struct inode
*) = NULL
;
167 if (sd
->s_type
& SYSFS_KOBJ_BIN_ATTR
) {
168 bin_attr
= sd
->s_element
;
169 attr
= &bin_attr
->attr
;
171 attr
= sd
->s_element
;
175 dentry
->d_fsdata
= sysfs_get(sd
);
176 sd
->s_dentry
= dentry
;
177 error
= sysfs_create(dentry
, (attr
->mode
& S_IALLUGO
) | S_IFREG
, init
);
184 dentry
->d_inode
->i_size
= bin_attr
->size
;
185 dentry
->d_inode
->i_fop
= &bin_fops
;
187 dentry
->d_op
= &sysfs_dentry_ops
;
193 static int sysfs_attach_link(struct sysfs_dirent
* sd
, struct dentry
* dentry
)
197 dentry
->d_fsdata
= sysfs_get(sd
);
198 sd
->s_dentry
= dentry
;
199 err
= sysfs_create(dentry
, S_IFLNK
|S_IRWXUGO
, init_symlink
);
201 dentry
->d_op
= &sysfs_dentry_ops
;
209 static struct dentry
* sysfs_lookup(struct inode
*dir
, struct dentry
*dentry
,
210 struct nameidata
*nd
)
212 struct sysfs_dirent
* parent_sd
= dentry
->d_parent
->d_fsdata
;
213 struct sysfs_dirent
* sd
;
216 list_for_each_entry(sd
, &parent_sd
->s_children
, s_sibling
) {
217 if (sd
->s_type
& SYSFS_NOT_PINNED
) {
218 const unsigned char * name
= sysfs_get_name(sd
);
220 if (strcmp(name
, dentry
->d_name
.name
))
223 if (sd
->s_type
& SYSFS_KOBJ_LINK
)
224 err
= sysfs_attach_link(sd
, dentry
);
226 err
= sysfs_attach_attr(sd
, dentry
);
234 struct inode_operations sysfs_dir_inode_operations
= {
235 .lookup
= sysfs_lookup
,
236 .setattr
= sysfs_setattr
,
239 static void remove_dir(struct dentry
* d
)
241 struct dentry
* parent
= dget(d
->d_parent
);
242 struct sysfs_dirent
* sd
;
244 down(&parent
->d_inode
->i_sem
);
247 list_del_init(&sd
->s_sibling
);
250 simple_rmdir(parent
->d_inode
,d
);
252 pr_debug(" o %s removing done (%d)\n",d
->d_name
.name
,
253 atomic_read(&d
->d_count
));
255 up(&parent
->d_inode
->i_sem
);
259 void sysfs_remove_subdir(struct dentry
* d
)
266 * sysfs_remove_dir - remove an object's directory.
269 * The only thing special about this is that we remove any files in
270 * the directory before we remove the directory, and we've inlined
271 * what used to be sysfs_rmdir() below, instead of calling separately.
274 void sysfs_remove_dir(struct kobject
* kobj
)
276 struct dentry
* dentry
= dget(kobj
->dentry
);
277 struct sysfs_dirent
* parent_sd
;
278 struct sysfs_dirent
* sd
, * tmp
;
283 pr_debug("sysfs %s: removing dir\n",dentry
->d_name
.name
);
284 down(&dentry
->d_inode
->i_sem
);
285 parent_sd
= dentry
->d_fsdata
;
286 list_for_each_entry_safe(sd
, tmp
, &parent_sd
->s_children
, s_sibling
) {
287 if (!sd
->s_element
|| !(sd
->s_type
& SYSFS_NOT_PINNED
))
289 list_del_init(&sd
->s_sibling
);
290 sysfs_drop_dentry(sd
, dentry
);
293 up(&dentry
->d_inode
->i_sem
);
297 * Drop reference from dget() on entrance.
302 int sysfs_rename_dir(struct kobject
* kobj
, const char *new_name
)
305 struct dentry
* new_dentry
, * parent
;
307 if (!strcmp(kobject_name(kobj
), new_name
))
313 down_write(&sysfs_rename_sem
);
314 parent
= kobj
->parent
->dentry
;
316 down(&parent
->d_inode
->i_sem
);
318 new_dentry
= sysfs_get_dentry(parent
, new_name
);
319 if (!IS_ERR(new_dentry
)) {
320 if (!new_dentry
->d_inode
) {
321 error
= kobject_set_name(kobj
, "%s", new_name
);
323 d_add(new_dentry
, NULL
);
324 d_move(kobj
->dentry
, new_dentry
);
332 up(&parent
->d_inode
->i_sem
);
333 up_write(&sysfs_rename_sem
);
338 static int sysfs_dir_open(struct inode
*inode
, struct file
*file
)
340 struct dentry
* dentry
= file
->f_dentry
;
341 struct sysfs_dirent
* parent_sd
= dentry
->d_fsdata
;
343 down(&dentry
->d_inode
->i_sem
);
344 file
->private_data
= sysfs_new_dirent(parent_sd
, NULL
);
345 up(&dentry
->d_inode
->i_sem
);
347 return file
->private_data
? 0 : -ENOMEM
;
351 static int sysfs_dir_close(struct inode
*inode
, struct file
*file
)
353 struct dentry
* dentry
= file
->f_dentry
;
354 struct sysfs_dirent
* cursor
= file
->private_data
;
356 down(&dentry
->d_inode
->i_sem
);
357 list_del_init(&cursor
->s_sibling
);
358 up(&dentry
->d_inode
->i_sem
);
360 release_sysfs_dirent(cursor
);
365 /* Relationship between s_mode and the DT_xxx types */
366 static inline unsigned char dt_type(struct sysfs_dirent
*sd
)
368 return (sd
->s_mode
>> 12) & 15;
371 static int sysfs_readdir(struct file
* filp
, void * dirent
, filldir_t filldir
)
373 struct dentry
*dentry
= filp
->f_dentry
;
374 struct sysfs_dirent
* parent_sd
= dentry
->d_fsdata
;
375 struct sysfs_dirent
*cursor
= filp
->private_data
;
376 struct list_head
*p
, *q
= &cursor
->s_sibling
;
382 ino
= dentry
->d_inode
->i_ino
;
383 if (filldir(dirent
, ".", 1, i
, ino
, DT_DIR
) < 0)
389 ino
= parent_ino(dentry
);
390 if (filldir(dirent
, "..", 2, i
, ino
, DT_DIR
) < 0)
396 if (filp
->f_pos
== 2) {
398 list_add(q
, &parent_sd
->s_children
);
400 for (p
=q
->next
; p
!= &parent_sd
->s_children
; p
=p
->next
) {
401 struct sysfs_dirent
*next
;
405 next
= list_entry(p
, struct sysfs_dirent
,
407 if (!next
->s_element
)
410 name
= sysfs_get_name(next
);
413 ino
= next
->s_dentry
->d_inode
->i_ino
;
415 ino
= iunique(sysfs_sb
, 2);
417 if (filldir(dirent
, name
, len
, filp
->f_pos
, ino
,
430 static loff_t
sysfs_dir_lseek(struct file
* file
, loff_t offset
, int origin
)
432 struct dentry
* dentry
= file
->f_dentry
;
434 down(&dentry
->d_inode
->i_sem
);
437 offset
+= file
->f_pos
;
442 up(&file
->f_dentry
->d_inode
->i_sem
);
445 if (offset
!= file
->f_pos
) {
446 file
->f_pos
= offset
;
447 if (file
->f_pos
>= 2) {
448 struct sysfs_dirent
*sd
= dentry
->d_fsdata
;
449 struct sysfs_dirent
*cursor
= file
->private_data
;
451 loff_t n
= file
->f_pos
- 2;
453 list_del(&cursor
->s_sibling
);
454 p
= sd
->s_children
.next
;
455 while (n
&& p
!= &sd
->s_children
) {
456 struct sysfs_dirent
*next
;
457 next
= list_entry(p
, struct sysfs_dirent
,
463 list_add_tail(&cursor
->s_sibling
, p
);
466 up(&dentry
->d_inode
->i_sem
);
470 struct file_operations sysfs_dir_operations
= {
471 .open
= sysfs_dir_open
,
472 .release
= sysfs_dir_close
,
473 .llseek
= sysfs_dir_lseek
,
474 .read
= generic_read_dir
,
475 .readdir
= sysfs_readdir
,
478 EXPORT_SYMBOL_GPL(sysfs_create_dir
);
479 EXPORT_SYMBOL_GPL(sysfs_remove_dir
);
480 EXPORT_SYMBOL_GPL(sysfs_rename_dir
);