diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/dir.c | 37 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 24 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 2 |
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 | */ |
167 | struct inode * sysfs_new_inode(struct sysfs_dirent *sd) | 169 | struct 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 | ||
59 | extern void sysfs_delete_inode(struct inode *inode); | 59 | extern void sysfs_delete_inode(struct inode *inode); |
60 | extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode); | 60 | extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode); |
61 | extern struct inode * sysfs_new_inode(struct sysfs_dirent *sd); | 61 | extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); |
62 | extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); | 62 | extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); |
63 | 63 | ||
64 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); | 64 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); |