aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/sysfs/dir.c37
-rw-r--r--fs/sysfs/inode.c24
-rw-r--r--fs/sysfs/sysfs.h2
3 files changed, 37 insertions, 26 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index bbf3525fd222..06dff2c30c9b 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -219,14 +219,16 @@ static int create_dir(struct kobject *kobj, struct dentry *parent,
219 goto out_drop; 219 goto out_drop;
220 sd->s_elem.dir.kobj = kobj; 220 sd->s_elem.dir.kobj = kobj;
221 221
222 inode = sysfs_new_inode(sd); 222 inode = sysfs_get_inode(sd);
223 if (!inode) 223 if (!inode)
224 goto out_sput; 224 goto out_sput;
225 225
226 inode->i_op = &sysfs_dir_inode_operations; 226 if (inode->i_state & I_NEW) {
227 inode->i_fop = &sysfs_dir_operations; 227 inode->i_op = &sysfs_dir_inode_operations;
228 /* directory inodes start off with i_nlink == 2 (for "." entry) */ 228 inode->i_fop = &sysfs_dir_operations;
229 inc_nlink(inode); 229 /* directory inodes start off with i_nlink == 2 (for ".") */
230 inc_nlink(inode);
231 }
230 232
231 /* link in */ 233 /* link in */
232 error = -EEXIST; 234 error = -EEXIST;
@@ -310,20 +312,23 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
310 return NULL; 312 return NULL;
311 313
312 /* attach dentry and inode */ 314 /* attach dentry and inode */
313 inode = sysfs_new_inode(sd); 315 inode = sysfs_get_inode(sd);
314 if (!inode) 316 if (!inode)
315 return ERR_PTR(-ENOMEM); 317 return ERR_PTR(-ENOMEM);
316 318
317 /* initialize inode according to type */ 319 if (inode->i_state & I_NEW) {
318 if (sd->s_type & SYSFS_KOBJ_ATTR) { 320 /* initialize inode according to type */
319 inode->i_size = PAGE_SIZE; 321 if (sd->s_type & SYSFS_KOBJ_ATTR) {
320 inode->i_fop = &sysfs_file_operations; 322 inode->i_size = PAGE_SIZE;
321 } else if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) { 323 inode->i_fop = &sysfs_file_operations;
322 struct bin_attribute *bin_attr = sd->s_elem.bin_attr.bin_attr; 324 } else if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
323 inode->i_size = bin_attr->size; 325 struct bin_attribute *bin_attr =
324 inode->i_fop = &bin_fops; 326 sd->s_elem.bin_attr.bin_attr;
325 } else if (sd->s_type & SYSFS_KOBJ_LINK) 327 inode->i_size = bin_attr->size;
326 inode->i_op = &sysfs_symlink_inode_operations; 328 inode->i_fop = &bin_fops;
329 } else if (sd->s_type & SYSFS_KOBJ_LINK)
330 inode->i_op = &sysfs_symlink_inode_operations;
331 }
327 332
328 sysfs_instantiate(dentry, inode); 333 sysfs_instantiate(dentry, inode);
329 sysfs_attach_dentry(sd, dentry); 334 sysfs_attach_dentry(sd, dentry);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 26d8503c8997..3eab9c46a71b 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -153,10 +153,12 @@ void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
153} 153}
154 154
155/** 155/**
156 * sysfs_new_inode - allocate new inode for sysfs_dirent 156 * sysfs_get_inode - get inode for sysfs_dirent
157 * @sd: sysfs_dirent to allocate inode for 157 * @sd: sysfs_dirent to allocate inode for
158 * 158 *
159 * Allocate inode for @sd and initialize basics. 159 * Get inode for @sd. If such inode doesn't exist, a new inode
160 * is allocated and basics are initialized. New inode is
161 * returned locked.
160 * 162 *
161 * LOCKING: 163 * LOCKING:
162 * Kernel thread context (may sleep). 164 * Kernel thread context (may sleep).
@@ -164,12 +166,12 @@ void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
164 * RETURNS: 166 * RETURNS:
165 * Pointer to allocated inode on success, NULL on failure. 167 * Pointer to allocated inode on success, NULL on failure.
166 */ 168 */
167struct inode * sysfs_new_inode(struct sysfs_dirent *sd) 169struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
168{ 170{
169 struct inode *inode; 171 struct inode *inode;
170 172
171 inode = new_inode(sysfs_sb); 173 inode = iget_locked(sysfs_sb, sd->s_ino);
172 if (inode) 174 if (inode && (inode->i_state & I_NEW))
173 sysfs_init_inode(sd, inode); 175 sysfs_init_inode(sd, inode);
174 176
175 return inode; 177 return inode;
@@ -180,7 +182,7 @@ struct inode * sysfs_new_inode(struct sysfs_dirent *sd)
180 * @dentry: dentry to be instantiated 182 * @dentry: dentry to be instantiated
181 * @inode: inode associated with @sd 183 * @inode: inode associated with @sd
182 * 184 *
183 * Instantiate @dentry with @inode. 185 * Unlock @inode if locked and instantiate @dentry with @inode.
184 * 186 *
185 * LOCKING: 187 * LOCKING:
186 * None. 188 * None.
@@ -189,9 +191,13 @@ void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
189{ 191{
190 BUG_ON(!dentry || dentry->d_inode); 192 BUG_ON(!dentry || dentry->d_inode);
191 193
192 if (dentry->d_parent && dentry->d_parent->d_inode) { 194 if (inode->i_state & I_NEW) {
193 struct inode *p_inode = dentry->d_parent->d_inode; 195 unlock_new_inode(inode);
194 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; 196
197 if (dentry->d_parent && dentry->d_parent->d_inode) {
198 struct inode *p_inode = dentry->d_parent->d_inode;
199 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
200 }
195 } 201 }
196 202
197 d_instantiate(dentry, inode); 203 d_instantiate(dentry, inode);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 143fdbe56c14..627bf3940dfa 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -58,7 +58,7 @@ extern 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 void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode); 60extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
61extern struct inode * sysfs_new_inode(struct sysfs_dirent *sd); 61extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
62extern void sysfs_instantiate(struct dentry *dentry, struct inode *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);