From patchwork Fri Dec 4 02:23:43 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Snitzer X-Patchwork-Id: 64745 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 nB42NxtI005236 for ; Fri, 4 Dec 2009 02:23: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 738B861C1F9; Thu, 3 Dec 2009 21:23:59 -0500 (EST) Received: from int-mx01.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 nB42NuKM028052 for ; Thu, 3 Dec 2009 21:23:56 -0500 Received: from localhost (dhcp-100-19-150.bos.redhat.com [10.16.19.150]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id nB42Nt1D006658; Thu, 3 Dec 2009 21:23:55 -0500 From: Mike Snitzer To: dm-devel@redhat.com Date: Thu, 3 Dec 2009 21:23:43 -0500 Message-Id: <1259893434-10792-3-git-send-email-snitzer@redhat.com> In-Reply-To: <1259893434-10792-1-git-send-email-snitzer@redhat.com> References: <1259893434-10792-1-git-send-email-snitzer@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-loop: dm-devel@redhat.com Cc: Mikulas Patocka Subject: [dm-devel] [PATCH v5 02/13] dm exception store: add snapshot-merge specific methods 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 diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h index bb88746..534427f 100644 --- a/drivers/md/dm-exception-store.h +++ b/drivers/md/dm-exception-store.h @@ -75,6 +75,22 @@ struct dm_exception_store_type { void *callback_context); /* + * Returns the last chunk in the pointers. (TODO: -ENOPARSE) + * > 0: the number of consecutive chunks that can + * be copied in one shot. + * == 0: the exception store is empty. + * < 0: error. + */ + int (*prepare_merge) (struct dm_exception_store *store, + chunk_t *old_chunk, chunk_t *new_chunk); + + /* + * Clear the last n exceptions. + * n must be <= the value returned by prepare_merge. + */ + int (*commit_merge) (struct dm_exception_store *store, int n); + + /* * The snapshot is invalid, note this in the metadata. */ void (*drop_snapshot) (struct dm_exception_store *store); diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 157999e..1f5752e 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -409,6 +409,15 @@ static void write_exception(struct pstore *ps, 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 @@ -680,6 +689,63 @@ static void persistent_commit_exception(struct dm_exception_store *store, ps->callback_count = 0; } +static int persistent_prepare_merge(struct dm_exception_store *store, + chunk_t *old_chunk, chunk_t *new_chunk) +{ + int r, i; + struct pstore *ps = get_info(store); + struct disk_exception de; + + if (!ps->current_committed) { + if (!ps->current_area) + return 0; + ps->current_area--; + r = area_io(ps, READ); + if (r < 0) + return r; + ps->current_committed = ps->exceptions_per_area; + } + + read_exception(ps, ps->current_committed - 1, &de); + *old_chunk = de.old_chunk; + *new_chunk = de.new_chunk; + + for (i = 1; i < ps->current_committed; i++) { + read_exception(ps, ps->current_committed - 1 - i, &de); + if (de.old_chunk != *old_chunk - i || + de.new_chunk != *new_chunk - i) + break; + } + + return i; +} + +static int persistent_commit_merge(struct dm_exception_store *store, int n) +{ + int r, i; + struct pstore *ps = get_info(store); + + BUG_ON(n > ps->current_committed); + + for (i = 0; i < n; i++) + clear_exception(ps, ps->current_committed - 1 - i); + + r = area_io(ps, WRITE); + if (r < 0) + return r; + + ps->current_committed -= i; + + /* + * ps->next_free cannot really be reliably decreased here (because of + * misordered chunks), so don't do it. We don't even need it, because + * there is no situation where merging snapshot would become + * non-merging. + */ + + return 0; +} + static void persistent_drop_snapshot(struct dm_exception_store *store) { struct pstore *ps = get_info(store); @@ -748,6 +814,8 @@ static struct dm_exception_store_type _persistent_type = { .read_metadata = persistent_read_metadata, .prepare_exception = persistent_prepare_exception, .commit_exception = persistent_commit_exception, + .prepare_merge = persistent_prepare_merge, + .commit_merge = persistent_commit_merge, .drop_snapshot = persistent_drop_snapshot, .usage = persistent_usage, .status = persistent_status, @@ -761,6 +829,8 @@ static struct dm_exception_store_type _persistent_compat_type = { .read_metadata = persistent_read_metadata, .prepare_exception = persistent_prepare_exception, .commit_exception = persistent_commit_exception, + .prepare_merge = persistent_prepare_merge, + .commit_merge = persistent_commit_merge, .drop_snapshot = persistent_drop_snapshot, .usage = persistent_usage, .status = persistent_status,