Received: from mnm [127.0.0.1] by localhost with POP3 (fetchmail-5.9.0) for akpm@localhost (single-drop); Sat, 06 Mar 2004 05:45:35 -0800 (PST) Received: from fire-2.osdl.org (air1.pdx.osdl.net [172.20.0.5]) by mail.osdl.org (8.11.6/8.11.6) with ESMTP id i26DeME07198 for ; Sat, 6 Mar 2004 05:40:22 -0800 Received: from smtp.cistron-office.nl (mail@10fwd.cistron-office.nl [62.216.29.197]) by fire-2.osdl.org (8.12.8/8.12.8) with ESMTP id i26DeK5q022022 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=NO) for ; Sat, 6 Mar 2004 05:40:22 -0800 Received: from subspace.cistron-office.nl ([62.216.29.200]) by smtp.cistron-office.nl with esmtp (Exim 3.35 #1 (Debian)) id 1Azc2M-00078X-00; Sat, 06 Mar 2004 14:40:18 +0100 Received: from miquels by subspace.cistron-office.nl with local (Exim 3.35 #1 (Debian)) id 1Azc2M-0003jd-00; Sat, 06 Mar 2004 14:40:18 +0100 Date: Sat, 6 Mar 2004 14:40:18 +0100 From: Miquel van Smoorenburg To: Andrew Morton Cc: Joe Thornber Subject: Re: [PATCH] dm-rwlock.patch (Re: 2.6.4-rc1-mm1: queue-congestion-dm-implementation patch) Message-ID: <20040306134018.GA13030@cistron.nl> References: <20040302130137.GA9941@cistron.nl> <200403020826.52448.kevcorry@us.ibm.com> <20040303211624.GA11008@cistron.nl> <20040305135544.318de1a6.akpm@osdl.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20040305135544.318de1a6.akpm@osdl.org> X-NCC-RegID: nl.cistron User-Agent: Mutt/1.5.4i Sender: Miquel van Smoorenburg X-MIMEDefang-Filter: osdl$Revision: 1.55 $ X-Scanned-By: MIMEDefang 2.36 X-Spam-Checker-Version: SpamAssassin 2.60 (1.212-2003-09-23-exp) on mnm X-Spam-Level: X-Spam-Status: No, hits=-4.9 required=2.0 tests=BAYES_00 autolearn=ham version=2.60 According to Andrew Morton: > Miquel van Smoorenburg wrote: > > > > I posted a patch in the wrong thread earlier today, and the patch also > > wasn't so good. This should be better, but I'll let Joe be the > > judge of that. At least it survived my testing. > > Joe just sent me a dm update which broke your patch big-time. > > I've dropped a snapshot of my tree at > http://www.zipworld.com.au/~akpm/linux/patches/stuff/x.gz (against rc2). > Would you have time to update and retest the rwlock patch? Sure. I'm taking a new approach, since the rwlock patch was still not correct - sleeping functions could still be called under the rwlock, for example dm-crypt does that in its mapping function. Fixing that would get way too complicated. So: dm-maplock.patch This patch adds a rwlock_t maplock to the struct mapped_device. The ->map member is only updated with that lock held. dm_any_congested takes the lock, and so can be sure that the table under ->map won't change. This patch is much smaller and simpler than dm-rwlock.patch. --- linux-2.6.4-rc2-mmX.orig/drivers/md/dm.c 2004-03-06 04:00:02.000000000 +0100 +++ linux-2.6.4-rc2-mmX/drivers/md/dm.c 2004-03-06 13:24:20.000000000 +0100 @@ -49,6 +49,7 @@ struct mapped_device { struct rw_semaphore lock; + rwlock_t maplock; atomic_t holders; unsigned long flags; @@ -564,9 +565,12 @@ int r; struct mapped_device *md = congested_data; - down_read(&md->lock); - r = dm_table_any_congested(md->map, bdi_bits); - up_read(&md->lock); + read_lock(&md->maplock); + if (md->map == NULL || test_bit(DMF_BLOCK_IO, &md->flags)) + r = bdi_bits; + else + r = dm_table_any_congested(md->map, bdi_bits); + read_unlock(&md->maplock); return r; } @@ -642,6 +646,7 @@ memset(md, 0, sizeof(*md)); init_rwsem(&md->lock); + rwlock_init(&md->maplock); atomic_set(&md->holders, 1); md->queue = blk_alloc_queue(GFP_KERNEL); @@ -741,7 +746,9 @@ if (size == 0) return 0; + write_lock(&md->maplock); md->map = t; + write_unlock(&md->maplock); dm_table_event_callback(md->map, event_callback, md); dm_table_get(t); @@ -751,12 +758,16 @@ static void __unbind(struct mapped_device *md) { - if (!md->map) + struct dm_table *map = md->map; + + if (!map) return; - dm_table_event_callback(md->map, NULL, NULL); - dm_table_put(md->map); + dm_table_event_callback(map, NULL, NULL); + write_lock(&md->maplock); md->map = NULL; + write_unlock(&md->maplock); + dm_table_put(map); } /*