summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libglusterfs/src/inode.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c
index 26e0194a761..d66bcb2a038 100644
--- a/libglusterfs/src/inode.c
+++ b/libglusterfs/src/inode.c
@@ -1755,13 +1755,40 @@ inode_table_destroy (inode_table_t *inode_table) {
*/
pthread_mutex_lock (&inode_table->lock);
{
- list_for_each_entry_safe (trav, tmp, &inode_table->active, list) {
- __inode_ref_reduce_by_n (trav, 0);
+ /* Process lru list first as we need to unset their dentry
+ * entries (the ones which may not be unset during
+ * '__inode_passivate' as they were hashed) which in turn
+ * shall unref their parent
+ *
+ * These parent inodes when unref'ed may well again fall
+ * into lru list and if we are at the end of traversing
+ * the list, we may miss to delete/retire that entry. Hence
+ * traverse the lru list till it gets empty.
+ */
+ while (!list_empty (&inode_table->lru)) {
+ list_for_each_entry_safe (trav, tmp, &inode_table->lru,
+ list) {
+ __inode_forget (trav, 0);
+ __inode_retire (trav);
+ }
}
- list_for_each_entry_safe (trav, tmp, &inode_table->lru, list) {
+ list_for_each_entry_safe (trav, tmp, &inode_table->active,
+ list) {
+ /* forget and unref the inode to retire and add it to
+ * purge list. By this time there should not be any
+ * inodes present in the active list except for root
+ * inode. Its a ref_leak otherwise. */
+ if (trav != inode_table->root)
+ gf_msg_callingfn (THIS->name, GF_LOG_WARNING, 0,
+ LG_MSG_REF_COUNT,
+ "Active inode(%p) with refcount"
+ "(%d) found during cleanup",
+ trav, trav->ref);
__inode_forget (trav, 0);
+ __inode_ref_reduce_by_n (trav, 0);
}
+
}
pthread_mutex_unlock (&inode_table->lock);