aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c48
1 files changed, 22 insertions, 26 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 89b9d1f14871..23a3401af2fb 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -352,48 +352,44 @@ repeat:
352 } 352 }
353 } 353 }
354 /* Unreachable? Get rid of it */ 354 /* Unreachable? Get rid of it */
355 if (d_unhashed(dentry)) 355 if (d_unhashed(dentry))
356 goto kill_it; 356 goto kill_it;
357 if (list_empty(&dentry->d_lru)) { 357 if (list_empty(&dentry->d_lru)) {
358 dentry->d_flags |= DCACHE_REFERENCED; 358 dentry->d_flags |= DCACHE_REFERENCED;
359 dentry_lru_add(dentry); 359 dentry_lru_add(dentry);
360 } 360 }
361 spin_unlock(&dentry->d_lock); 361 spin_unlock(&dentry->d_lock);
362 return; 362 return;
363 363
364relock1:
365 spin_lock(&dentry->d_lock);
366kill_it: 364kill_it:
367 inode = dentry->d_inode; 365 inode = dentry->d_inode;
368 if (inode) { 366 if (inode && !spin_trylock(&inode->i_lock))
369 if (!spin_trylock(&inode->i_lock)) { 367 goto retry;
370relock2: 368
371 spin_unlock(&dentry->d_lock);
372 goto relock1;
373 }
374 }
375 parent = dentry->d_parent; 369 parent = dentry->d_parent;
376 if (parent && parent != dentry) { 370 if (parent && parent != dentry && !spin_trylock(&parent->d_lock)) {
377 if (!spin_trylock(&parent->d_lock)) {
378 if (inode)
379 spin_unlock(&inode->i_lock);
380 goto relock2;
381 }
382 }
383 if (atomic_read(&dentry->d_count)) {
384 /* This case should be fine */
385 spin_unlock(&dentry->d_lock);
386 if (parent && parent != dentry)
387 spin_unlock(&parent->d_lock);
388 if (inode) 371 if (inode)
389 spin_unlock(&inode->i_lock); 372 spin_unlock(&inode->i_lock);
390 return; 373 goto retry;
391 } 374 }
375
392 /* if dentry was on the d_lru list delete it from there */ 376 /* if dentry was on the d_lru list delete it from there */
393 dentry_lru_del(dentry); 377 dentry_lru_del(dentry);
394 dentry = d_kill(dentry); 378 dentry = d_kill(dentry);
395 if (dentry) 379 if (dentry)
396 goto repeat; 380 goto repeat;
381 return;
382
383retry:
384 /*
385 * We are about to drop dentry->d_lock. dentry->d_count is 0
386 * so it could be freed by someone else and leave us with a
387 * stale pointer. Prevent this by increasing d_count before
388 * dropping d_lock.
389 */
390 atomic_inc(&dentry->d_count);
391 spin_unlock(&dentry->d_lock);
392 goto repeat;
397} 393}
398 394
399/** 395/**