From mboxrd@z Thu Jan 1 00:00:00 1970 From: Masasyoshi MIZUMA Subject: [PATCH][BUG] Lack of mutex_lock in drop_pagecache_sb() Date: Wed, 18 Mar 2009 17:13:35 +0900 Message-ID: <20090318170237.8F6C.61FB500B@jp.fujitsu.com> Mime-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit To: linux-fsdevel@vger.kernel.org Return-path: Received: from fgwmail7.fujitsu.co.jp ([192.51.44.37]:36314 "EHLO fgwmail7.fujitsu.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752072AbZCRINR (ORCPT ); Wed, 18 Mar 2009 04:13:17 -0400 Received: from m6.gw.fujitsu.co.jp ([10.0.50.76]) by fgwmail7.fujitsu.co.jp (Fujitsu Gateway) with ESMTP id n2I8DEuE021236 for (envelope-from m.mizuma@jp.fujitsu.com); Wed, 18 Mar 2009 17:13:14 +0900 Received: from smail (m6 [127.0.0.1]) by outgoing.m6.gw.fujitsu.co.jp (Postfix) with ESMTP id 02C4845DD72 for ; Wed, 18 Mar 2009 17:13:14 +0900 (JST) Received: from s6.gw.fujitsu.co.jp (s6.gw.fujitsu.co.jp [10.0.50.96]) by m6.gw.fujitsu.co.jp (Postfix) with ESMTP id F0FBB45DE5C for ; Wed, 18 Mar 2009 17:13:12 +0900 (JST) Received: from s6.gw.fujitsu.co.jp (localhost.localdomain [127.0.0.1]) by s6.gw.fujitsu.co.jp (Postfix) with ESMTP id B62971DB8038 for ; Wed, 18 Mar 2009 17:13:12 +0900 (JST) Received: from m106.s.css.fujitsu.com (m106.s.css.fujitsu.com [10.249.87.106]) by s6.gw.fujitsu.co.jp (Postfix) with ESMTP id 6319AE3800C for ; Wed, 18 Mar 2009 17:13:10 +0900 (JST) Received: from m106.css.fujitsu.com (m106 [127.0.0.1]) by m106.s.css.fujitsu.com (Postfix) with ESMTP id 32BA15B8607 for ; Wed, 18 Mar 2009 17:13:10 +0900 (JST) Received: from [10.124.101.91] (gabell.soft.fujitsu.com [10.124.101.91]) by m106.s.css.fujitsu.com (Postfix) with ESMTP id 0C0BC5B8621 for ; Wed, 18 Mar 2009 17:13:09 +0900 (JST) Sender: linux-fsdevel-owner@vger.kernel.org List-ID: I create the patch which fixes lack of mutex_lock in drop_pagecache_sb(). Please check the bug and the patch (below). ---------------------------------------------------------------------- When drop_pagecache_sb() frees inodes, it doesn't get mutex_lock of iprune_mutex. Therefore, if it races the process which frees inodes (ex. prune_icache()), OS panic may happen. An example of the panic flow is the following: ---------------------------------------------------------------------- [process A] | [process B] | | | shrink_icache_memory() | | | | | V | | prune_icache() | drop_pagecache() | mutex_lock(&iprune_mutex) | | | spin_lock(&inode_lock) | | | | | V | | | drop_pagecache_sb() | | | | | V | V | spin_unlock(&inode_lock) | spin_lock(&inode_lock) | | | | | | | | | V | V | dispose_list() | __iget() | list_del() | | | | | | | V | V | spin_lock(&inode_lock) | list_move() <----- PANIC !! | | V | (time) ---------------------------------------------------------------------- If the inode which Process B do list_move() with is the same as the one which Process A did list_del() with, OS may panic. Fixing this bug requires the following: - Adding mutex_lock of iprune_mutex to drop_pagecache_sb(). - Changing iprune_mutex from static to global. Signed-off-by: Masayoshi Mizuma --- fs/drop_caches.c | 2 ++ fs/inode.c | 2 +- include/linux/writeback.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff -Nurp linux-2.6.29-rc7.orig/fs/drop_caches.c linux-2.6.29-rc7/fs/drop_caches.c --- linux-2.6.29-rc7.orig/fs/drop_caches.c 2009-03-10 06:38:17.137283010 +0900 +++ linux-2.6.29-rc7/fs/drop_caches.c 2009-03-11 04:04:29.705284864 +0900 @@ -16,6 +16,7 @@ static void drop_pagecache_sb(struct sup { struct inode *inode, *toput_inode = NULL; + mutex_lock(&iprune_mutex); spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { if (inode->i_state & (I_FREEING|I_WILL_FREE)) @@ -31,6 +32,7 @@ static void drop_pagecache_sb(struct sup } spin_unlock(&inode_lock); iput(toput_inode); + mutex_unlock(&iprune_mutex); } static void drop_pagecache(void) diff -Nurp linux-2.6.29-rc7.orig/fs/inode.c linux-2.6.29-rc7/fs/inode.c --- linux-2.6.29-rc7.orig/fs/inode.c 2009-03-10 06:38:22.404282773 +0900 +++ linux-2.6.29-rc7/fs/inode.c 2009-03-18 07:17:31.032284423 +0900 @@ -91,7 +91,7 @@ DEFINE_SPINLOCK(inode_lock); * from its final dispose_list, the struct super_block they refer to * (for inode->i_sb->s_op) may already have been freed and reused. */ -static DEFINE_MUTEX(iprune_mutex); +DEFINE_MUTEX(iprune_mutex); /* * Statistics gathering.. diff -Nurp linux-2.6.29-rc7.orig/include/linux/writeback.h linux-2.6.29-rc7/include/linux/writeback.h --- linux-2.6.29-rc7.orig/include/linux/writeback.h 2009-03-10 06:38:27.133285255 +0900 +++ linux-2.6.29-rc7/include/linux/writeback.h 2009-03-11 05:27:43.679283477 +0900 @@ -10,6 +10,7 @@ struct backing_dev_info; extern spinlock_t inode_lock; +extern struct mutex iprune_mutex; extern struct list_head inode_in_use; extern struct list_head inode_unused;