MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / fs / sysfs / dir.c
blobe2434745d9d35edbbff086a7a1414e878777eaf9
1 /*
2 * dir.c - Operations for sysfs directories.
3 */
5 #undef DEBUG
7 #include <linux/fs.h>
8 #include <linux/mount.h>
9 #include <linux/module.h>
10 #include <linux/kobject.h>
11 #include "sysfs.h"
13 DECLARE_RWSEM(sysfs_rename_sem);
15 static int init_dir(struct inode * inode)
17 inode->i_op = &simple_dir_inode_operations;
18 inode->i_fop = &simple_dir_operations;
20 /* directory inodes start off with i_nlink == 2 (for "." entry) */
21 inode->i_nlink++;
22 return 0;
26 static int create_dir(struct kobject * k, struct dentry * p,
27 const char * n, struct dentry ** d)
29 int error;
30 down(&p->d_inode->i_sem);
31 *d = sysfs_get_dentry(p,n);
32 if (!IS_ERR(*d)) {
33 error = sysfs_create(*d,
34 S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO,
35 init_dir);
36 if (!error) {
37 (*d)->d_fsdata = k;
38 p->d_inode->i_nlink++;
40 dput(*d);
41 } else
42 error = PTR_ERR(*d);
43 up(&p->d_inode->i_sem);
44 return error;
48 int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d)
50 return create_dir(k,k->dentry,n,d);
53 /**
54 * sysfs_create_dir - create a directory for an object.
55 * @parent: parent parent object.
56 * @kobj: object we're creating directory for.
59 int sysfs_create_dir(struct kobject * kobj)
61 struct dentry * dentry = NULL;
62 struct dentry * parent;
63 int error = 0;
65 if (!kobj)
66 return -EINVAL;
68 if (kobj->parent)
69 parent = kobj->parent->dentry;
70 else if (sysfs_mount && sysfs_mount->mnt_sb)
71 parent = sysfs_mount->mnt_sb->s_root;
72 else
73 return -EFAULT;
75 error = create_dir(kobj,parent,kobject_name(kobj),&dentry);
76 if (!error)
77 kobj->dentry = dentry;
78 return error;
82 static void remove_dir(struct dentry * d)
84 struct dentry * parent = dget(d->d_parent);
85 down(&parent->d_inode->i_sem);
86 d_delete(d);
87 if (d->d_inode)
88 simple_rmdir(parent->d_inode,d);
90 pr_debug(" o %s removing done (%d)\n",d->d_name.name,
91 atomic_read(&d->d_count));
93 up(&parent->d_inode->i_sem);
94 dput(parent);
97 void sysfs_remove_subdir(struct dentry * d)
99 remove_dir(d);
104 * sysfs_remove_dir - remove an object's directory.
105 * @kobj: object.
107 * The only thing special about this is that we remove any files in
108 * the directory before we remove the directory, and we've inlined
109 * what used to be sysfs_rmdir() below, instead of calling separately.
112 void sysfs_remove_dir(struct kobject * kobj)
114 struct list_head * node;
115 struct dentry * dentry = dget(kobj->dentry);
117 if (!dentry)
118 return;
120 pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
121 down(&dentry->d_inode->i_sem);
123 spin_lock(&dcache_lock);
124 restart:
125 node = dentry->d_subdirs.next;
126 while (node != &dentry->d_subdirs) {
127 struct dentry * d = list_entry(node,struct dentry,d_child);
129 node = node->next;
130 pr_debug(" o %s (%d): ",d->d_name.name,atomic_read(&d->d_count));
131 if (!d_unhashed(d) && (d->d_inode)) {
132 d = dget_locked(d);
133 pr_debug("removing");
136 * Unlink and unhash.
138 __d_drop(d);
139 spin_unlock(&dcache_lock);
140 /* release the target kobject in case of
141 * a symlink
143 if (S_ISLNK(d->d_inode->i_mode))
144 kobject_put(d->d_fsdata);
146 simple_unlink(dentry->d_inode,d);
147 dput(d);
148 pr_debug(" done\n");
149 spin_lock(&dcache_lock);
150 /* re-acquired dcache_lock, need to restart */
151 goto restart;
154 spin_unlock(&dcache_lock);
155 up(&dentry->d_inode->i_sem);
157 remove_dir(dentry);
159 * Drop reference from dget() on entrance.
161 dput(dentry);
164 int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
166 int error = 0;
167 struct dentry * new_dentry, * parent;
169 if (!strcmp(kobject_name(kobj), new_name))
170 return -EINVAL;
172 if (!kobj->parent)
173 return -EINVAL;
175 down_write(&sysfs_rename_sem);
176 parent = kobj->parent->dentry;
178 down(&parent->d_inode->i_sem);
180 new_dentry = sysfs_get_dentry(parent, new_name);
181 if (!IS_ERR(new_dentry)) {
182 if (!new_dentry->d_inode) {
183 error = kobject_set_name(kobj,new_name);
184 if (!error)
185 d_move(kobj->dentry, new_dentry);
187 dput(new_dentry);
189 up(&parent->d_inode->i_sem);
190 up_write(&sysfs_rename_sem);
192 return error;
195 EXPORT_SYMBOL(sysfs_create_dir);
196 EXPORT_SYMBOL(sysfs_remove_dir);
197 EXPORT_SYMBOL(sysfs_rename_dir);