From patchwork Thu Feb 5 12:51:01 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junichi Nomura X-Patchwork-Id: 5640 X-Patchwork-Delegate: agk@redhat.com Received: from hormel.redhat.com (hormel1.redhat.com [209.132.177.33]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n15CpIE7016118 for ; Thu, 5 Feb 2009 12:51:18 GMT Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110]) by hormel.redhat.com (Postfix) with ESMTP id 75B7D619707; Thu, 5 Feb 2009 07:51:17 -0500 (EST) Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id n15CpGt4005532 for ; Thu, 5 Feb 2009 07:51:16 -0500 Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n15CpGbH019551 for ; Thu, 5 Feb 2009 07:51:17 -0500 Received: from tyo201.gate.nec.co.jp (TYO201.gate.nec.co.jp [202.32.8.193]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n15Cp0IZ006381 for ; Thu, 5 Feb 2009 07:51:01 -0500 Received: from mailgate3.nec.co.jp ([10.7.69.193]) by tyo201.gate.nec.co.jp (8.13.8/8.13.4) with ESMTP id n15CoxIU018226 for ; Thu, 5 Feb 2009 21:50:59 +0900 (JST) Received: (from root@localhost) by mailgate3.nec.co.jp (8.11.7/3.7W-MAILGATE-NEC) id n15Coxs27302 for dm-devel@redhat.com; Thu, 5 Feb 2009 21:50:59 +0900 (JST) Received: from mailsv.linux.bs1.fc.nec.co.jp (mailsv.linux.bs1.fc.nec.co.jp [10.34.125.2]) by mailsv3.nec.co.jp (8.13.8/8.13.4) with ESMTP id n15Cowuq020202 for ; Thu, 5 Feb 2009 21:50:58 +0900 (JST) Received: from ronnie.linux.bs1.fc.nec.co.jp (ronnie.linux.bs1.fc.nec.co.jp [10.34.125.103]) by mailsv.linux.bs1.fc.nec.co.jp (Postfix) with ESMTP id B4D77E4823B; Thu, 5 Feb 2009 21:50:58 +0900 (JST) Message-ID: <498AE0B5.5050709@ce.jp.nec.com> Date: Thu, 05 Feb 2009 21:51:01 +0900 From: "Jun'ichi Nomura" User-Agent: Thunderbird 2.0.0.19 (X11/20090105) MIME-Version: 1.0 To: device-mapper development X-RedHat-Spam-Score: -0.8 X-Scanned-By: MIMEDefang 2.58 on 172.16.52.254 X-Scanned-By: MIMEDefang 2.63 on 172.16.48.31 X-loop: dm-devel@redhat.com Cc: Kiyoshi Ueda Subject: [dm-devel] [PATCH] dm-path-selector: fix refcount corruption X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.5 Precedence: junk Reply-To: device-mapper development List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com Hi, Refcounting of path-selector module is not safe in SMP environment. The counter may corrupt and trigger BUG() like this: kernel BUG at linux-2.6.29-rc3/drivers/md/dm-path-selector.c:90! though it's rare under normal usage. The bug is here: void dm_put_path_selector(struct path_selector_type *pst) { ... down_read(&_ps_lock); psi = __find_path_selector_type(pst->name); if (!psi) goto out; if (--psi->use == 0) module_put(psi->pst.module); BUG_ON(psi->use < 0); The code manipulates the counter without exclusive lock or atomic ops. So if 2 processors come in, the counter may corrupt. While it could be fixed using atomic ops for the counter manipulation, we can just drop the 'use' counter like Cheng Renquan did for dm-target: https://www.redhat.com/archives/dm-devel/2008-December/msg00075.html (Actually, without his patch, dm-target.c hits the same problem.) This is a simple reproducer. Change "dev" for your environment. (In my experiment, it used to take hours to reproduce the problem.) ------------------------------------------------------------------- #!/bin/sh dev=/dev/sda11 tab1="0 100 multipath 0 0 1 1 round-robin 0 1 1 $dev 10" tab2="0 100 multipath 0 0 1 1 round-robin 0 1 1 $dev 20" function runtest() { local map=$1 echo $tab1 | dmsetup create $map while true; do echo $tab2 | dmsetup load $map dmsetup resume $map echo $tab1 | dmsetup load $map dmsetup resume $map done } runtest m1 & runtest m1 & ------------------------------------------------------------------- Index: linux-2.6.29-rc2/drivers/md/dm-path-selector.c =================================================================== --- linux-2.6.29-rc2.orig/drivers/md/dm-path-selector.c +++ linux-2.6.29-rc2/drivers/md/dm-path-selector.c @@ -17,9 +17,7 @@ struct ps_internal { struct path_selector_type pst; - struct list_head list; - long use; }; #define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst) @@ -45,12 +43,8 @@ static struct ps_internal *get_path_sele down_read(&_ps_lock); psi = __find_path_selector_type(name); - if (psi) { - if ((psi->use == 0) && !try_module_get(psi->pst.module)) - psi = NULL; - else - psi->use++; - } + if (psi && !try_module_get(psi->pst.module)) + psi = NULL; up_read(&_ps_lock); return psi; @@ -84,11 +78,7 @@ void dm_put_path_selector(struct path_se if (!psi) goto out; - if (--psi->use == 0) - module_put(psi->pst.module); - - BUG_ON(psi->use < 0); - + module_put(psi->pst.module); out: up_read(&_ps_lock); } @@ -136,11 +126,6 @@ int dm_unregister_path_selector(struct p return -EINVAL; } - if (psi->use) { - up_write(&_ps_lock); - return -ETXTBSY; - } - list_del(&psi->list); up_write(&_ps_lock);