diff options
author | Tejun Heo <htejun@gmail.com> | 2007-06-13 15:27:21 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-11 19:09:08 -0400 |
commit | d0bcb5689a521df98bff7549fcb8b17499660a99 (patch) | |
tree | 6f9deb74f4facc5e638b71ba8b99ac2baeed9859 | |
parent | 9d9307dabb3de8140fb3801bf6eb01f231dbd83d (diff) |
sysfs: make sysfs_drop_dentry() access inodes using ilookup()
sysfs_drop_dentry() used to go through sd->s_dentry and
sd->s_parent->s_dentry to access the inodes. This is incorrect
because inode can be cached without dentry.
This patch makes sysfs_drop_dentry() access inodes using ilookup() on
sd->s_ino. This is both correct and simpler.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | fs/sysfs/inode.c | 63 |
1 files changed, 28 insertions, 35 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index ee31bf369a88..63daa06c4194 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -219,9 +219,9 @@ void sysfs_instantiate(struct dentry *dentry, struct inode *inode) | |||
219 | */ | 219 | */ |
220 | void sysfs_drop_dentry(struct sysfs_dirent *sd) | 220 | void sysfs_drop_dentry(struct sysfs_dirent *sd) |
221 | { | 221 | { |
222 | struct dentry *dentry = NULL, *parent = NULL; | 222 | struct dentry *dentry = NULL; |
223 | struct inode *dir; | ||
224 | struct timespec curtime; | 223 | struct timespec curtime; |
224 | struct inode *inode; | ||
225 | 225 | ||
226 | /* We're not holding a reference to ->s_dentry dentry but the | 226 | /* We're not holding a reference to ->s_dentry dentry but the |
227 | * field will stay valid as long as sysfs_lock is held. | 227 | * field will stay valid as long as sysfs_lock is held. |
@@ -229,19 +229,9 @@ void sysfs_drop_dentry(struct sysfs_dirent *sd) | |||
229 | spin_lock(&sysfs_lock); | 229 | spin_lock(&sysfs_lock); |
230 | spin_lock(&dcache_lock); | 230 | spin_lock(&dcache_lock); |
231 | 231 | ||
232 | /* drop dentry if it's there and dput() didn't kill it yet */ | ||
232 | if (sd->s_dentry && sd->s_dentry->d_inode) { | 233 | if (sd->s_dentry && sd->s_dentry->d_inode) { |
233 | /* get dentry if it's there and dput() didn't kill it yet */ | ||
234 | dentry = dget_locked(sd->s_dentry); | 234 | dentry = dget_locked(sd->s_dentry); |
235 | parent = dentry->d_parent; | ||
236 | } else if (sd->s_parent->s_dentry->d_inode) { | ||
237 | /* We need to update the parent even if dentry for the | ||
238 | * victim itself doesn't exist. | ||
239 | */ | ||
240 | parent = dget_locked(sd->s_parent->s_dentry); | ||
241 | } | ||
242 | |||
243 | /* drop */ | ||
244 | if (dentry) { | ||
245 | spin_lock(&dentry->d_lock); | 235 | spin_lock(&dentry->d_lock); |
246 | __d_drop(dentry); | 236 | __d_drop(dentry); |
247 | spin_unlock(&dentry->d_lock); | 237 | spin_unlock(&dentry->d_lock); |
@@ -250,36 +240,39 @@ void sysfs_drop_dentry(struct sysfs_dirent *sd) | |||
250 | spin_unlock(&dcache_lock); | 240 | spin_unlock(&dcache_lock); |
251 | spin_unlock(&sysfs_lock); | 241 | spin_unlock(&sysfs_lock); |
252 | 242 | ||
253 | /* nothing to do if the parent isn't in dcache */ | 243 | dput(dentry); |
254 | if (!parent) | 244 | /* XXX: unpin if directory, this will go away soon */ |
255 | return; | 245 | if (sd->s_type & SYSFS_DIR) |
246 | dput(dentry); | ||
256 | 247 | ||
257 | /* adjust nlink and update timestamp */ | 248 | /* adjust nlink and update timestamp */ |
258 | dir = parent->d_inode; | ||
259 | mutex_lock(&dir->i_mutex); | ||
260 | |||
261 | curtime = CURRENT_TIME; | 249 | curtime = CURRENT_TIME; |
262 | 250 | ||
263 | dir->i_ctime = dir->i_mtime = curtime; | 251 | inode = ilookup(sysfs_sb, sd->s_ino); |
252 | if (inode) { | ||
253 | mutex_lock(&inode->i_mutex); | ||
264 | 254 | ||
265 | if (dentry) { | 255 | inode->i_ctime = curtime; |
266 | dentry->d_inode->i_ctime = curtime; | 256 | drop_nlink(inode); |
267 | drop_nlink(dentry->d_inode); | 257 | if (sd->s_type & SYSFS_DIR) |
268 | if (sd->s_type & SYSFS_DIR) { | 258 | drop_nlink(inode); |
269 | drop_nlink(dentry->d_inode); | 259 | |
270 | drop_nlink(dir); | 260 | mutex_unlock(&inode->i_mutex); |
271 | /* XXX: unpin if directory, this will go away soon */ | 261 | iput(inode); |
272 | dput(dentry); | ||
273 | } | ||
274 | } | 262 | } |
275 | 263 | ||
276 | mutex_unlock(&dir->i_mutex); | 264 | /* adjust nlink and udpate timestamp of the parent */ |
265 | inode = ilookup(sysfs_sb, sd->s_parent->s_ino); | ||
266 | if (inode) { | ||
267 | mutex_lock(&inode->i_mutex); | ||
277 | 268 | ||
278 | /* bye bye */ | 269 | inode->i_ctime = inode->i_mtime = curtime; |
279 | if (dentry) | 270 | if (sd->s_type & SYSFS_DIR) |
280 | dput(dentry); | 271 | drop_nlink(inode); |
281 | else | 272 | |
282 | dput(parent); | 273 | mutex_unlock(&inode->i_mutex); |
274 | iput(inode); | ||
275 | } | ||
283 | } | 276 | } |
284 | 277 | ||
285 | int sysfs_hash_and_remove(struct dentry * dir, const char * name) | 278 | int sysfs_hash_and_remove(struct dentry * dir, const char * name) |