From edeb67a5344389f88a6912460fb0cf2e76a32df3 Mon Sep 17 00:00:00 2001 From: Soumya Koduri Date: Wed, 13 Apr 2016 12:50:49 +0530 Subject: inode: Always fetch first entry from the inode lists during inode_table_destroy In inode_table_destroy, we iterate through lru and active lists to move the entries to purge list so that they can be destroyed during inode_table_prune. But if used "list_for_each_entry" or "list_for_each_entry_safe" to iterate, we could end up accessing the entries which may have got moved to different(purge) lists in the process and can result in either infinite loop or crash. The safe approach seems to fetch the first entry of the list in each iteration till it gets empty. Change-Id: I24a18881833bd9419c2d8e5e8807bc71ec396479 BUG: 1326627 Signed-off-by: Soumya Koduri Reviewed-on: http://review.gluster.org/13987 Smoke: Gluster Build System NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System Reviewed-by: Kaleb KEITHLEY Reviewed-by: Niels de Vos Reviewed-by: Jeff Darcy --- libglusterfs/src/inode.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'libglusterfs/src') diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index d66bcb2a038..7f2a102c855 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -1726,7 +1726,7 @@ inode_table_destroy_all (glusterfs_ctx_t *ctx) { void inode_table_destroy (inode_table_t *inode_table) { - inode_t *tmp = NULL, *trav = NULL; + inode_t *trav = NULL; if (inode_table == NULL) return; @@ -1766,15 +1766,15 @@ inode_table_destroy (inode_table_t *inode_table) { * 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); - } + trav = list_first_entry (&inode_table->lru, + inode_t, list); + __inode_forget (trav, 0); + __inode_retire (trav); } - list_for_each_entry_safe (trav, tmp, &inode_table->active, - list) { + while (!list_empty (&inode_table->active)) { + trav = list_first_entry (&inode_table->active, + inode_t, 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 -- cgit