aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
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
commit8312a8d7c1d19d31027bd4ca127ce671962c23d4 (patch)
treeee28a44611ac2192b265f5f85a74f7da98d2fdef /fs/sysfs/dir.c
parentfc9f54b9982e14e6dbe023425c87ffbfd6992c45 (diff)
sysfs: use iget_locked() instead of new_inode()
After dentry is reclaimed, sysfs always used to allocate new dentry and inode if the file is accessed again. This causes problem with operations which only pin the inode. For example, if inotify watch is added to a sysfs file and the dentry for the file is reclaimed, the next update event creates new dentry and new inode making the inotify watch miss all the events from there on. This patch fixes it by using iget_locked() instead of new_inode(). sysfs_new_inode() is renamed to sysfs_get_inode() and inode is initialized iff the inode is newly allocated. sysfs_instantiate() is responsible for unlocking new inodes. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r--fs/sysfs/dir.c37
1 files changed, 21 insertions, 16 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);