diff options
Diffstat (limited to 'fs/sysfs/inode.c')
-rw-r--r-- | fs/sysfs/inode.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 38bbe071cc15..5266eec15f6e 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -246,9 +246,23 @@ static inline void orphan_all_buffers(struct inode *node) | |||
246 | */ | 246 | */ |
247 | void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) | 247 | void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) |
248 | { | 248 | { |
249 | struct dentry * dentry = sd->s_dentry; | 249 | struct dentry *dentry = NULL; |
250 | struct inode *inode; | 250 | struct inode *inode; |
251 | 251 | ||
252 | /* We're not holding a reference to ->s_dentry dentry but the | ||
253 | * field will stay valid as long as sysfs_lock is held. | ||
254 | */ | ||
255 | spin_lock(&sysfs_lock); | ||
256 | spin_lock(&dcache_lock); | ||
257 | |||
258 | /* dget dentry if it's still alive */ | ||
259 | if (sd->s_dentry && sd->s_dentry->d_inode) | ||
260 | dentry = dget_locked(sd->s_dentry); | ||
261 | |||
262 | spin_unlock(&dcache_lock); | ||
263 | spin_unlock(&sysfs_lock); | ||
264 | |||
265 | /* drop dentry */ | ||
252 | if (dentry) { | 266 | if (dentry) { |
253 | spin_lock(&dcache_lock); | 267 | spin_lock(&dcache_lock); |
254 | spin_lock(&dentry->d_lock); | 268 | spin_lock(&dentry->d_lock); |
@@ -268,6 +282,8 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) | |||
268 | spin_unlock(&dentry->d_lock); | 282 | spin_unlock(&dentry->d_lock); |
269 | spin_unlock(&dcache_lock); | 283 | spin_unlock(&dcache_lock); |
270 | } | 284 | } |
285 | |||
286 | dput(dentry); | ||
271 | } | 287 | } |
272 | } | 288 | } |
273 | 289 | ||