aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-06-13 14:45:17 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-11 19:09:07 -0400
commitfc9f54b9982e14e6dbe023425c87ffbfd6992c45 (patch)
tree61b828ac694d9e8decb02022a1056a5367bb1bef
parent7f7cfffe60ed6271c4028ec79ae1c297b44bcb14 (diff)
sysfs: reorganize sysfs_new_indoe() and sysfs_create()
Reorganize/clean up sysfs_new_inode() and sysfs_create(). * sysfs_init_inode() is separated out from sysfs_new_inode() and is responsible for basic initialization. * sysfs_instantiate() replaces the last step of sysfs_create() and is responsible for dentry instantitaion. * type-specific initialization is moved out to the callers. * mode is specified only once when creating a sysfs_dirent. * spurious list_del_init(&sd->s_sibling) dropped from create_dir() This change is to * prepare for inode allocation fix. * separate alloc and init code for synchronization update. * make dentry/inode initialization more flexible for later changes. This patch doesn't introduce visible behavior change. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--fs/sysfs/dir.c130
-rw-r--r--fs/sysfs/inode.c108
-rw-r--r--fs/sysfs/mount.c18
-rw-r--r--fs/sysfs/sysfs.h6
4 files changed, 118 insertions, 144 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 = {
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 6ad47c13b94d..26d8503c8997 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -133,62 +133,68 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
133 */ 133 */
134static struct lock_class_key sysfs_inode_imutex_key; 134static struct lock_class_key sysfs_inode_imutex_key;
135 135
136struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd) 136void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
137{ 137{
138 struct inode * inode = new_inode(sysfs_sb); 138 inode->i_blocks = 0;
139 if (inode) { 139 inode->i_mapping->a_ops = &sysfs_aops;
140 inode->i_blocks = 0; 140 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
141 inode->i_mapping->a_ops = &sysfs_aops; 141 inode->i_op = &sysfs_inode_operations;
142 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; 142 inode->i_ino = sd->s_ino;
143 inode->i_op = &sysfs_inode_operations; 143 lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
144 inode->i_ino = sd->s_ino; 144
145 lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key); 145 if (sd->s_iattr) {
146 146 /* sysfs_dirent has non-default attributes
147 if (sd->s_iattr) { 147 * get them for the new inode from persistent copy
148 /* sysfs_dirent has non-default attributes 148 * in sysfs_dirent
149 * get them for the new inode from persistent copy 149 */
150 * in sysfs_dirent 150 set_inode_attr(inode, sd->s_iattr);
151 */ 151 } else
152 set_inode_attr(inode, sd->s_iattr); 152 set_default_inode_attr(inode, sd->s_mode);
153 } else 153}
154 set_default_inode_attr(inode, mode); 154
155 } 155/**
156 * sysfs_new_inode - allocate new inode for sysfs_dirent
157 * @sd: sysfs_dirent to allocate inode for
158 *
159 * Allocate inode for @sd and initialize basics.
160 *
161 * LOCKING:
162 * Kernel thread context (may sleep).
163 *
164 * RETURNS:
165 * Pointer to allocated inode on success, NULL on failure.
166 */
167struct inode * sysfs_new_inode(struct sysfs_dirent *sd)
168{
169 struct inode *inode;
170
171 inode = new_inode(sysfs_sb);
172 if (inode)
173 sysfs_init_inode(sd, inode);
174
156 return inode; 175 return inode;
157} 176}
158 177
159int sysfs_create(struct sysfs_dirent *sd, struct dentry *dentry, int mode, 178/**
160 int (*init)(struct inode *)) 179 * sysfs_instantiate - instantiate dentry
180 * @dentry: dentry to be instantiated
181 * @inode: inode associated with @sd
182 *
183 * Instantiate @dentry with @inode.
184 *
185 * LOCKING:
186 * None.
187 */
188void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
161{ 189{
162 int error = 0; 190 BUG_ON(!dentry || dentry->d_inode);
163 struct inode * inode = NULL; 191
164 if (dentry) { 192 if (dentry->d_parent && dentry->d_parent->d_inode) {
165 if (!dentry->d_inode) { 193 struct inode *p_inode = dentry->d_parent->d_inode;
166 if ((inode = sysfs_new_inode(mode, sd))) { 194 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
167 if (dentry->d_parent && dentry->d_parent->d_inode) { 195 }
168 struct inode *p_inode = dentry->d_parent->d_inode; 196
169 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; 197 d_instantiate(dentry, inode);
170 }
171 goto Proceed;
172 }
173 else
174 error = -ENOMEM;
175 } else
176 error = -EEXIST;
177 } else
178 error = -ENOENT;
179 goto Done;
180
181 Proceed:
182 if (init)
183 error = init(inode);
184 if (!error) {
185 d_instantiate(dentry, inode);
186 if (S_ISDIR(mode))
187 dget(dentry); /* pin only directory dentry in core */
188 } else
189 iput(inode);
190 Done:
191 return error;
192} 198}
193 199
194/** 200/**
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 37ff9ffc55f0..6d3a6249d21c 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -29,6 +29,7 @@ static struct sysfs_dirent sysfs_root = {
29 .s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling), 29 .s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling),
30 .s_children = LIST_HEAD_INIT(sysfs_root.s_children), 30 .s_children = LIST_HEAD_INIT(sysfs_root.s_children),
31 .s_type = SYSFS_ROOT, 31 .s_type = SYSFS_ROOT,
32 .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
32 .s_iattr = NULL, 33 .s_iattr = NULL,
33 .s_ino = 1, 34 .s_ino = 1,
34}; 35};
@@ -45,18 +46,19 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
45 sb->s_time_gran = 1; 46 sb->s_time_gran = 1;
46 sysfs_sb = sb; 47 sysfs_sb = sb;
47 48
48 inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, 49 inode = new_inode(sysfs_sb);
49 &sysfs_root); 50 if (!inode) {
50 if (inode) {
51 inode->i_op = &sysfs_dir_inode_operations;
52 inode->i_fop = &sysfs_dir_operations;
53 /* directory inodes start off with i_nlink == 2 (for "." entry) */
54 inc_nlink(inode);
55 } else {
56 pr_debug("sysfs: could not get root inode\n"); 51 pr_debug("sysfs: could not get root inode\n");
57 return -ENOMEM; 52 return -ENOMEM;
58 } 53 }
59 54
55 sysfs_init_inode(&sysfs_root, inode);
56
57 inode->i_op = &sysfs_dir_inode_operations;
58 inode->i_fop = &sysfs_dir_operations;
59 /* directory inodes start off with i_nlink == 2 (for "." entry) */
60 inc_nlink(inode);
61
60 root = d_alloc_root(inode); 62 root = d_alloc_root(inode);
61 if (!root) { 63 if (!root) {
62 pr_debug("%s: could not get root dentry!\n",__FUNCTION__); 64 pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index fc6aa863b947..143fdbe56c14 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -57,9 +57,9 @@ extern struct vfsmount * sysfs_mount;
57extern struct kmem_cache *sysfs_dir_cachep; 57extern struct kmem_cache *sysfs_dir_cachep;
58 58
59extern void sysfs_delete_inode(struct inode *inode); 59extern void sysfs_delete_inode(struct inode *inode);
60extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); 60extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
61extern int sysfs_create(struct sysfs_dirent *sd, struct dentry *dentry, 61extern struct inode * sysfs_new_inode(struct sysfs_dirent *sd);
62 int mode, int (*init)(struct inode *)); 62extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
63 63
64extern void release_sysfs_dirent(struct sysfs_dirent * sd); 64extern void release_sysfs_dirent(struct sysfs_dirent * sd);
65extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); 65extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);