aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/dcache.c')
-rw-r--r--fs/ocfs2/dcache.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index b574431a031d..b4957c7d9fe2 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -85,6 +85,17 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
85 goto bail; 85 goto bail;
86 } 86 }
87 87
88 /*
89 * If the last lookup failed to create dentry lock, let us
90 * redo it.
91 */
92 if (!dentry->d_fsdata) {
93 mlog(0, "Inode %llu doesn't have dentry lock, "
94 "returning false\n",
95 (unsigned long long)OCFS2_I(inode)->ip_blkno);
96 goto bail;
97 }
98
88 ret = 1; 99 ret = 1;
89 100
90bail: 101bail:
@@ -310,22 +321,19 @@ out_attach:
310 return ret; 321 return ret;
311} 322}
312 323
313static DEFINE_SPINLOCK(dentry_list_lock); 324DEFINE_SPINLOCK(dentry_list_lock);
314 325
315/* We limit the number of dentry locks to drop in one go. We have 326/* We limit the number of dentry locks to drop in one go. We have
316 * this limit so that we don't starve other users of ocfs2_wq. */ 327 * this limit so that we don't starve other users of ocfs2_wq. */
317#define DL_INODE_DROP_COUNT 64 328#define DL_INODE_DROP_COUNT 64
318 329
319/* Drop inode references from dentry locks */ 330/* Drop inode references from dentry locks */
320void ocfs2_drop_dl_inodes(struct work_struct *work) 331static void __ocfs2_drop_dl_inodes(struct ocfs2_super *osb, int drop_count)
321{ 332{
322 struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
323 dentry_lock_work);
324 struct ocfs2_dentry_lock *dl; 333 struct ocfs2_dentry_lock *dl;
325 int drop_count = DL_INODE_DROP_COUNT;
326 334
327 spin_lock(&dentry_list_lock); 335 spin_lock(&dentry_list_lock);
328 while (osb->dentry_lock_list && drop_count--) { 336 while (osb->dentry_lock_list && (drop_count < 0 || drop_count--)) {
329 dl = osb->dentry_lock_list; 337 dl = osb->dentry_lock_list;
330 osb->dentry_lock_list = dl->dl_next; 338 osb->dentry_lock_list = dl->dl_next;
331 spin_unlock(&dentry_list_lock); 339 spin_unlock(&dentry_list_lock);
@@ -333,11 +341,32 @@ void ocfs2_drop_dl_inodes(struct work_struct *work)
333 kfree(dl); 341 kfree(dl);
334 spin_lock(&dentry_list_lock); 342 spin_lock(&dentry_list_lock);
335 } 343 }
336 if (osb->dentry_lock_list) 344 spin_unlock(&dentry_list_lock);
345}
346
347void ocfs2_drop_dl_inodes(struct work_struct *work)
348{
349 struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
350 dentry_lock_work);
351
352 __ocfs2_drop_dl_inodes(osb, DL_INODE_DROP_COUNT);
353 /*
354 * Don't queue dropping if umount is in progress. We flush the
355 * list in ocfs2_dismount_volume
356 */
357 spin_lock(&dentry_list_lock);
358 if (osb->dentry_lock_list &&
359 !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
337 queue_work(ocfs2_wq, &osb->dentry_lock_work); 360 queue_work(ocfs2_wq, &osb->dentry_lock_work);
338 spin_unlock(&dentry_list_lock); 361 spin_unlock(&dentry_list_lock);
339} 362}
340 363
364/* Flush the whole work queue */
365void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb)
366{
367 __ocfs2_drop_dl_inodes(osb, -1);
368}
369
341/* 370/*
342 * ocfs2_dentry_iput() and friends. 371 * ocfs2_dentry_iput() and friends.
343 * 372 *
@@ -368,7 +397,8 @@ static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
368 /* We leave dropping of inode reference to ocfs2_wq as that can 397 /* We leave dropping of inode reference to ocfs2_wq as that can
369 * possibly lead to inode deletion which gets tricky */ 398 * possibly lead to inode deletion which gets tricky */
370 spin_lock(&dentry_list_lock); 399 spin_lock(&dentry_list_lock);
371 if (!osb->dentry_lock_list) 400 if (!osb->dentry_lock_list &&
401 !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
372 queue_work(ocfs2_wq, &osb->dentry_lock_work); 402 queue_work(ocfs2_wq, &osb->dentry_lock_work);
373 dl->dl_next = osb->dentry_lock_list; 403 dl->dl_next = osb->dentry_lock_list;
374 osb->dentry_lock_list = dl; 404 osb->dentry_lock_list = dl;