aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/sysfs/inode.c63
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 */
220void sysfs_drop_dentry(struct sysfs_dirent *sd) 220void 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
285int sysfs_hash_and_remove(struct dentry * dir, const char * name) 278int sysfs_hash_and_remove(struct dentry * dir, const char * name)