diff options
Diffstat (limited to 'fs/sysfs/inode.c')
| -rw-r--r-- | fs/sysfs/inode.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index e79e38d52c00..1a81ebce20e9 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/backing-dev.h> | 13 | #include <linux/backing-dev.h> |
| 14 | #include <linux/capability.h> | 14 | #include <linux/capability.h> |
| 15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
| 16 | #include <asm/semaphore.h> | ||
| 16 | #include "sysfs.h" | 17 | #include "sysfs.h" |
| 17 | 18 | ||
| 18 | extern struct super_block * sysfs_sb; | 19 | extern struct super_block * sysfs_sb; |
| @@ -209,6 +210,22 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd) | |||
| 209 | return NULL; | 210 | return NULL; |
| 210 | } | 211 | } |
| 211 | 212 | ||
| 213 | static inline void orphan_all_buffers(struct inode *node) | ||
| 214 | { | ||
| 215 | struct sysfs_buffer_collection *set = node->i_private; | ||
| 216 | struct sysfs_buffer *buf; | ||
| 217 | |||
| 218 | mutex_lock(&node->i_mutex); | ||
| 219 | if (node->i_private) { | ||
| 220 | list_for_each_entry(buf, &set->associates, associates) { | ||
| 221 | down(&buf->sem); | ||
| 222 | buf->orphaned = 1; | ||
| 223 | up(&buf->sem); | ||
| 224 | } | ||
| 225 | } | ||
| 226 | mutex_unlock(&node->i_mutex); | ||
| 227 | } | ||
| 228 | |||
| 212 | 229 | ||
| 213 | /* | 230 | /* |
| 214 | * Unhashes the dentry corresponding to given sysfs_dirent | 231 | * Unhashes the dentry corresponding to given sysfs_dirent |
| @@ -217,16 +234,23 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd) | |||
| 217 | void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) | 234 | void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) |
| 218 | { | 235 | { |
| 219 | struct dentry * dentry = sd->s_dentry; | 236 | struct dentry * dentry = sd->s_dentry; |
| 237 | struct inode *inode; | ||
| 220 | 238 | ||
| 221 | if (dentry) { | 239 | if (dentry) { |
| 222 | spin_lock(&dcache_lock); | 240 | spin_lock(&dcache_lock); |
| 223 | spin_lock(&dentry->d_lock); | 241 | spin_lock(&dentry->d_lock); |
| 224 | if (!(d_unhashed(dentry) && dentry->d_inode)) { | 242 | if (!(d_unhashed(dentry) && dentry->d_inode)) { |
| 243 | inode = dentry->d_inode; | ||
| 244 | spin_lock(&inode->i_lock); | ||
| 245 | __iget(inode); | ||
| 246 | spin_unlock(&inode->i_lock); | ||
| 225 | dget_locked(dentry); | 247 | dget_locked(dentry); |
| 226 | __d_drop(dentry); | 248 | __d_drop(dentry); |
| 227 | spin_unlock(&dentry->d_lock); | 249 | spin_unlock(&dentry->d_lock); |
| 228 | spin_unlock(&dcache_lock); | 250 | spin_unlock(&dcache_lock); |
| 229 | simple_unlink(parent->d_inode, dentry); | 251 | simple_unlink(parent->d_inode, dentry); |
| 252 | orphan_all_buffers(inode); | ||
| 253 | iput(inode); | ||
| 230 | } else { | 254 | } else { |
| 231 | spin_unlock(&dentry->d_lock); | 255 | spin_unlock(&dentry->d_lock); |
| 232 | spin_unlock(&dcache_lock); | 256 | spin_unlock(&dcache_lock); |
