aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/inode.c')
-rw-r--r--fs/sysfs/inode.c24
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
18extern struct super_block * sysfs_sb; 19extern 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
213static 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)
217void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) 234void 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);