From patchwork Sun Oct 4 03:48:44 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 51573 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 n943mnZs026182 for ; Sun, 4 Oct 2009 03:48:49 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 0D2B261BC8B; Sat, 3 Oct 2009 23:48:48 -0400 (EDT) Received: from int-mx04.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 n943mkve030828 for ; Sat, 3 Oct 2009 23:48:46 -0400 Received: from localhost (vpn-11-138.rdu.redhat.com [10.11.11.138]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id n943mj8m026672; Sat, 3 Oct 2009 23:48:45 -0400 Date: Sat, 3 Oct 2009 23:48:44 -0400 From: Mike Snitzer To: Mikulas Patocka Message-ID: <20091004034843.GC25374@redhat.com> References: <20091002172656.GA13491@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20091002172656.GA13491@redhat.com> User-Agent: Mutt/1.5.19 (2009-01-05) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.17 X-loop: dm-devel@redhat.com Cc: dm-devel@redhat.com, Alasdair G Kergon Subject: [dm-devel] Re: clustered snapshots 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-2.6/drivers/md/dm-exception-store.h =================================================================== --- linux-2.6.orig/drivers/md/dm-exception-store.h +++ linux-2.6/drivers/md/dm-exception-store.h @@ -91,8 +91,11 @@ struct dm_exception_store_type { /* * Clear the last n exceptions. * n must be <= the value returned by prepare_merge. + * callback is used to clear in-core exceptions. */ - int (*commit_merge) (struct dm_exception_store *store, int n); + int (*commit_merge) (struct dm_exception_store *store, int n, + int (*callback) (void *, chunk_t old, chunk_t new), + void *callback_context); /* * The snapshot is invalid, note this in the metadata. Index: linux-2.6/drivers/md/dm-snap-persistent.c =================================================================== --- linux-2.6.orig/drivers/md/dm-snap-persistent.c +++ linux-2.6/drivers/md/dm-snap-persistent.c @@ -410,15 +410,6 @@ static void write_exception(struct pstor e->new_chunk = cpu_to_le64(de->new_chunk); } -static void clear_exception(struct pstore *ps, uint32_t index) -{ - struct disk_exception *e = get_exception(ps, index); - - /* clear it */ - e->old_chunk = 0; - e->new_chunk = 0; -} - /* * Registers the exceptions that are present in the current area. * 'full' is filled in to indicate if the area has been @@ -726,15 +717,30 @@ static int persistent_prepare_merge(stru return i; } -static int persistent_commit_merge(struct dm_exception_store *store, int n) +static int persistent_commit_merge(struct dm_exception_store *store, int n, + int (*callback) (void *, + chunk_t old, chunk_t new), + void *callback_context) { int r, i; struct pstore *ps = get_info(store); BUG_ON(n > ps->current_committed); + BUG_ON(!callback); - for (i = 0; i < n; i++) - clear_exception(ps, ps->current_committed - 1 - i); + for (i = 0; i < n; i++) { + struct disk_exception *de = + get_exception(ps, ps->current_committed - 1 - i); + + /* clear in-core exception */ + r = callback(callback_context, de->old_chunk, de->new_chunk); + if (r < 0) + return r; + + /* clear disk exception */ + de->old_chunk = 0; + de->new_chunk = 0; + } r = area_io(ps, WRITE); if (r < 0) Index: linux-2.6/drivers/md/dm-snap.c =================================================================== --- linux-2.6.orig/drivers/md/dm-snap.c +++ linux-2.6/drivers/md/dm-snap.c @@ -764,11 +764,50 @@ static inline void release_write_interlo error_bios(b); } +static int clear_merged_exception(struct dm_snap_exception *e, + chunk_t old_chunk, chunk_t new_chunk) +{ + if (dm_consecutive_chunk_count(e)) { + if ((old_chunk == e->old_chunk) && + (new_chunk == dm_chunk_number(e->new_chunk))) { + e->old_chunk++; + e->new_chunk++; + } else if (old_chunk != e->old_chunk + + dm_consecutive_chunk_count(e) && + new_chunk != dm_chunk_number(e->new_chunk) + + dm_consecutive_chunk_count(e)) { + DMERR("merge from the middle of a chunk range"); + return -1; + } + dm_consecutive_chunk_count_dec(e); + } else { + remove_exception(e); + free_exception(e); + } + + return 0; +} + +static int merge_clear_exception_callback(void *context, + chunk_t old_chunk, chunk_t new_chunk) +{ + struct dm_snap_exception *e; + struct exception_table *complete_et = context; + + e = lookup_exception(complete_et, old_chunk); + if (!e) { + DMERR("exception for block %llu is on disk but not in memory", + (unsigned long long)old_chunk); + return -1; + } + + return clear_merged_exception(e, old_chunk, new_chunk); +} + static void merge_callback(int read_err, unsigned long write_err, void *context) { - int r, i; + int r; struct dm_snapshot *s = context; - struct dm_snap_exception *e; if (read_err || write_err) { if (read_err) @@ -778,35 +817,15 @@ static void merge_callback(int read_err, goto shut; } - r = s->store->type->commit_merge(s->store, s->merge_write_interlock_n); + r = s->store->type->commit_merge(s->store, s->merge_write_interlock_n, + merge_clear_exception_callback, + &s->complete); if (r < 0) { DMERR("Write error in exception store, shutting down merge"); goto shut; } down_write(&s->lock); - /* - * Must process chunks (and associated exceptions) in reverse - * so that dm_consecutive_chunk_count_dec() accounting works - */ - for (i = s->merge_write_interlock_n - 1; i >= 0; i--) { - e = lookup_exception(&s->complete, - s->merge_write_interlock + i); - if (!e) { - DMERR("exception for block %llu is on " - "disk but not in memory", - (unsigned long long) - s->merge_write_interlock + i); - up_write(&s->lock); - goto shut; - } - if (dm_consecutive_chunk_count(e)) { - dm_consecutive_chunk_count_dec(e); - } else { - remove_exception(e); - free_exception(e); - } - } release_write_interlock(s, 0); snapshot_merge_process(s);