From 29adf166aa5f15202c5fe49369ad4f11df799c5b Mon Sep 17 00:00:00 2001 From: Soumya Koduri Date: Thu, 31 Dec 2015 13:53:54 +0530 Subject: inode: Retire the inodes from the lru list in inode_table_destroy Inodes from the lru list are not moved to purge list unless they are retired. Also process the lru list first to unset their parent 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 inodes which could be in active list. 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. This is backport of the below patch - http://review.gluster.org/13125 Change-Id: Ib7666e235e9b9644144a7c7933afb5e407e506ca BUG: 1311441 Signed-off-by: Soumya Koduri Reviewed-on: http://review.gluster.org/13125 Reviewed-by: Kaleb KEITHLEY Reviewed-by: Raghavendra G Reviewed-on: http://review.gluster.org/13527 Smoke: Gluster Build System NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System --- libglusterfs/src/inode.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'libglusterfs/src') diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index 6c3d6e13093..097b6d3ccdf 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -1760,13 +1760,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); -- cgit