From patchwork Mon Dec 7 15:45:55 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 65535 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 nB7Fjwl7014989 for ; Mon, 7 Dec 2009 15:45:59 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 718958E017C; Mon, 7 Dec 2009 10:45:58 -0500 (EST) Received: from int-mx05.intmail.prod.int.phx2.redhat.com (nat-pool.util.phx.redhat.com [10.8.5.200]) by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id nB7FjuvA031412 for ; Mon, 7 Dec 2009 10:45:56 -0500 Received: from localhost (dhcp-100-19-150.bos.redhat.com [10.16.19.150]) by int-mx05.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id nB7Fjt7e021932; Mon, 7 Dec 2009 10:45:55 -0500 Date: Mon, 7 Dec 2009 10:45:55 -0500 From: Mike Snitzer To: Mikulas Patocka Message-ID: <20091207154555.GC8917@redhat.com> References: <1260037484-20905-1-git-send-email-snitzer@redhat.com> <20091206064338.GA15389@redhat.com> <20091207140145.GA8917@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20091207140145.GA8917@redhat.com> User-Agent: Mutt/1.5.20 (2009-08-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.18 X-loop: dm-devel@redhat.com Cc: dm-devel@redhat.com, Alasdair G Kergon Subject: [dm-devel] dm snapshot: eliminate busy waiting when stopping merge [Was: Re: dm snapshot: stop merging using a completion] 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 Index: linux-rhel6/drivers/md/dm-snap.c =================================================================== --- linux-rhel6.orig/drivers/md/dm-snap.c +++ linux-rhel6/drivers/md/dm-snap.c @@ -102,15 +102,18 @@ struct dm_snapshot { spinlock_t tracked_chunk_lock; struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; - /* Merge operation failed if this is set */ - int merge_failed; + /* Wait for events based on state bits */ + unsigned long bits; /* Merge operation is in progress */ - int merge_running; +#define MERGE_RUNNING 0 /* It is requested to shut down merging */ /* Cleared back to 0 when the merging is stopped */ - int merge_shutdown; +#define SHUTDOWN_MERGE 1 + + /* Merge operation failed if this is set */ + int merge_failed; /* Merging this area --- block any writes */ chunk_t merge_write_interlock; @@ -776,8 +779,8 @@ static void snapshot_merge_process(struc struct dm_io_region src, dest; sector_t io_size; - BUG_ON(!s->merge_running); - if (s->merge_shutdown) + BUG_ON(!test_bit(MERGE_RUNNING, &s->bits)); + if (unlikely(test_bit(SHUTDOWN_MERGE, &s->bits))) goto shut; if (!s->valid) { @@ -849,7 +852,9 @@ test_again: return; shut: - s->merge_running = 0; + clear_bit_unlock(MERGE_RUNNING, &s->bits); + smp_mb__after_clear_bit(); + wake_up_bit(&s->bits, MERGE_RUNNING); } /* This function drops s->lock */ @@ -931,15 +936,21 @@ shut: down_write(&s->lock); s->merge_failed = 1; release_write_interlock(s, 1); - s->merge_running = 0; + clear_bit_unlock(MERGE_RUNNING, &s->bits); + smp_mb__after_clear_bit(); + wake_up_bit(&s->bits, MERGE_RUNNING); } static void start_merge(struct dm_snapshot *s) { - if (!s->merge_running && !s->merge_shutdown) { - s->merge_running = 1; + if (!test_and_set_bit(MERGE_RUNNING, &s->bits)) snapshot_merge_process(s); - } +} + +static int wait_schedule(void *ptr) +{ + schedule(); + return 0; } /* @@ -947,11 +958,10 @@ static void start_merge(struct dm_snapsh */ static void stop_merge(struct dm_snapshot *s) { - while (s->merge_running) { - s->merge_shutdown = 1; - msleep(1); - } - s->merge_shutdown = 0; + set_bit(SHUTDOWN_MERGE, &s->bits); + wait_on_bit(&s->bits, MERGE_RUNNING, wait_schedule, + TASK_UNINTERRUPTIBLE); + clear_bit(SHUTDOWN_MERGE, &s->bits); } /* @@ -1018,9 +1028,8 @@ static int snapshot_ctr(struct dm_target init_rwsem(&s->lock); INIT_LIST_HEAD(&s->list); spin_lock_init(&s->pe_lock); + s->bits = 0; s->merge_failed = 0; - s->merge_running = 0; - s->merge_shutdown = 0; s->merge_write_interlock = 0; s->merge_write_interlock_n = 0; bio_list_init(&s->merge_write_list);