diff options
Diffstat (limited to 'fs/ocfs2/dcache.c')
-rw-r--r-- | fs/ocfs2/dcache.c | 46 |
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 | ||
90 | bail: | 101 | bail: |
@@ -310,22 +321,19 @@ out_attach: | |||
310 | return ret; | 321 | return ret; |
311 | } | 322 | } |
312 | 323 | ||
313 | static DEFINE_SPINLOCK(dentry_list_lock); | 324 | DEFINE_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 */ |
320 | void ocfs2_drop_dl_inodes(struct work_struct *work) | 331 | static 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 | |||
347 | void 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 */ | ||
365 | void 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; |