summaryrefslogtreecommitdiffstats
path: root/fs/sysfs/inode.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-06-14 03:45:17 +0900
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-11 16:09:07 -0700
commit8312a8d7c1d19d31027bd4ca127ce671962c23d4 (patch)
treeee28a44611ac2192b265f5f85a74f7da98d2fdef /fs/sysfs/inode.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/inode.c')
-rw-r--r--fs/sysfs/inode.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 26d8503c899..3eab9c46a71 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)
}
/**
- * sysfs_new_inode - allocate new inode for sysfs_dirent
+ * sysfs_get_inode - get inode for sysfs_dirent
* @sd: sysfs_dirent to allocate inode for
*
- * Allocate inode for @sd and initialize basics.
+ * Get inode for @sd. If such inode doesn't exist, a new inode
+ * is allocated and basics are initialized. New inode is
+ * returned locked.
*
* LOCKING:
* Kernel thread context (may sleep).
@@ -164,12 +166,12 @@ void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
* RETURNS:
* Pointer to allocated inode on success, NULL on failure.
*/
-struct inode * sysfs_new_inode(struct sysfs_dirent *sd)
+struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
{
struct inode *inode;
- inode = new_inode(sysfs_sb);
- if (inode)
+ inode = iget_locked(sysfs_sb, sd->s_ino);
+ if (inode && (inode->i_state & I_NEW))
sysfs_init_inode(sd, inode);
return inode;
@@ -180,7 +182,7 @@ struct inode * sysfs_new_inode(struct sysfs_dirent *sd)
* @dentry: dentry to be instantiated
* @inode: inode associated with @sd
*
- * Instantiate @dentry with @inode.
+ * Unlock @inode if locked and instantiate @dentry with @inode.
*
* LOCKING:
* None.
@@ -189,9 +191,13 @@ void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
{
BUG_ON(!dentry || dentry->d_inode);
- if (dentry->d_parent && dentry->d_parent->d_inode) {
- struct inode *p_inode = dentry->d_parent->d_inode;
- p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
+ if (inode->i_state & I_NEW) {
+ unlock_new_inode(inode);
+
+ if (dentry->d_parent && dentry->d_parent->d_inode) {
+ struct inode *p_inode = dentry->d_parent->d_inode;
+ p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
+ }
}
d_instantiate(dentry, inode);