All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mike Snitzer <snitzer@redhat.com>
To: dm-devel@redhat.com
Subject: [PATCH v2 18/18] dm-exstore-persistent-allow-metadata-reread
Date: Wed, 30 Sep 2009 10:46:04 -0400	[thread overview]
Message-ID: <20090930144604.GC16605@redhat.com> (raw)
In-Reply-To: <1254264823-11538-19-git-send-email-snitzer@redhat.com>

This patch allows the persistent exception store to re-read
exception data from disk without adding duplicate entries
to the cache.  Being able to re-read the metadata is especially
useful when trying to pick-up new data that may have been added.

This means the persistent exception store can be used as the
starting point for a cluster-aware exception store, which leads
to shared-storage cluster-aware snapshots.

Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
---
v2: adjusted slightly to account for dm-snapshot-32bit-chunk-size.patch
---
 drivers/md/dm-snap-persistent.c |  129 ++++++++++++++++++++++++++++++++--------
 1 file changed, 105 insertions(+), 24 deletions(-)

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
@@ -299,7 +299,7 @@ static int zero_disk_area(struct pstore 
 	return chunk_io(ps, ps->zero_area, area_location(ps, area), WRITE, 0);
 }
 
-static int read_header(struct pstore *ps, int *new_snapshot)
+static int initial_read_header(struct pstore *ps, int *new_snapshot)
 {
 	int r;
 	struct disk_header *dh;
@@ -345,7 +345,6 @@ static int read_header(struct pstore *ps
 		goto bad;
 	}
 
-	*new_snapshot = 0;
 	ps->valid = le32_to_cpu(dh->valid);
 	ps->version = le32_to_cpu(dh->version);
 	chunk_size = le32_to_cpu(dh->chunk_size);
@@ -382,6 +381,51 @@ bad:
 	return r;
 }
 
+/*
+ * Re-reading the header is all about checking the 'valid'
+ * field to ensure that this exception store has not been
+ * marked invalid.  We can also do some sanity checks while
+ * we are at it.
+ */
+static int reread_header(struct pstore *ps)
+{
+	int r;
+	struct disk_header *dh;
+
+	r = chunk_io(ps, ps->header_area, 0, READ, 1);
+	if (r)
+		return r;
+
+	dh = (struct disk_header *) ps->header_area;
+
+	/*
+	 * If any of these conditions is true it means that the
+	 * exception store underneath us has changed in ways we
+	 * cannot handle.  What's worse, if we proceed, we can
+	 * corrupt the exception store.
+	 */
+	if ((le32_to_cpu(dh->magic) != SNAP_MAGIC) ||
+	    (ps->version != le32_to_cpu(dh->version)) ||
+	    (ps->store->chunk_size != le32_to_cpu(dh->chunk_size))) {
+		DMERR("Exception store parameters changed while in use.");
+		ps->valid = 0;
+		return -EINVAL;
+	}
+
+	ps->valid = le32_to_cpu(dh->valid);
+
+	return 0;
+}
+
+static int read_header(struct pstore *ps, int *new_snapshot)
+{
+	*new_snapshot = 0;
+	if (ps->io_client)
+		return reread_header(ps);
+
+	return initial_read_header(ps, new_snapshot);
+}
+
 static int write_header(struct pstore *ps)
 {
 	struct disk_header *dh;
@@ -457,7 +501,18 @@ static int insert_exceptions(struct psto
 	/* presume the area is full */
 	*full = 1;
 
-	for (i = 0; i < ps->exceptions_per_area; i++) {
+	/*
+	 * We start the loop at ps->current_committed.  If this is a full
+	 * read of the metadata area, it will be zero until we
+	 * are finished reading.  If this is a partial read to catch
+	 * any updates to the metadata area, then we will start at
+	 * the position that was last known to be empty.  (We must reset
+	 * ps->current_committed, otherwise metadata updates involving
+	 * more than one area will skip over some exceptions.
+	 */
+	i = ps->current_committed;
+	ps->current_committed = 0;
+	for (; i < ps->exceptions_per_area; i++) {
 		read_exception(ps, i, &de);
 
 		/*
@@ -494,10 +549,12 @@ static int read_exceptions(struct pstore
 	int r, full = 1;
 
 	/*
-	 * Keeping reading chunks and inserting exceptions until
-	 * we find a partially full area.
+	 * We start from 'ps->current_area' and keep reading chunks
+	 * and inserting exceptions until we find a partially full
+	 * area.  ('ps->current_area' must be initialized to 0 for the
+	 * first complete read.)
 	 */
-	for (ps->current_area = 0; full; ps->current_area++) {
+	for (; full; ps->current_area++) {
 		r = area_io(ps, READ);
 		if (r)
 			return r;
@@ -543,23 +600,17 @@ static void persistent_dtr(struct dm_exc
 	kfree(ps);
 }
 
-static int persistent_read_metadata(struct dm_exception_store *store)
+static int do_initial_metadata_read(struct dm_exception_store *store,
+				    int new_snapshot)
 {
-	int r, uninitialized_var(new_snapshot);
+	int r;
 	struct pstore *ps = get_info(store);
 
 	/*
-	 * Read the snapshot header.
-	 */
-	r = read_header(ps, &new_snapshot);
-	if (r)
-		return r;
-
-	/*
 	 * Now we know correct chunk_size, complete the initialisation.
 	 */
 	ps->exceptions_per_area = (ps->store->chunk_size << SECTOR_SHIFT) /
-				  sizeof(struct disk_exception);
+		sizeof(struct disk_exception);
 	ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
 			sizeof(*ps->callbacks));
 	if (!ps->callbacks)
@@ -572,24 +623,48 @@ static int persistent_read_metadata(stru
 		r = write_header(ps);
 		if (r) {
 			DMWARN("write_header failed");
-			return r;
+			goto fail;
 		}
 
 		ps->current_area = 0;
 		zero_memory_area(ps);
 		r = zero_disk_area(ps, 0);
-		if (r)
+		if (r) {
 			DMWARN("zero_disk_area(0) failed");
-		return r;
+			goto fail;
+		}
 	}
+
 	/*
 	 * Sanity checks.
 	 */
-	if (ps->version != SNAPSHOT_DISK_VERSION) {
-		DMWARN("unable to handle snapshot disk version %d",
-		       ps->version);
-		return -EINVAL;
-	}
+	if (ps->version == SNAPSHOT_DISK_VERSION)
+		return 0;
+
+	DMWARN("unable to handle snapshot disk version %d",
+	       ps->version);
+	r = -EINVAL;
+
+fail:
+	vfree(ps->callbacks);
+	ps->callbacks = NULL;
+	ps->exceptions_per_area = 0;
+	ps->valid = 0;
+
+	return r;
+}
+
+static int persistent_read_metadata(struct dm_exception_store *store)
+{
+	int r, uninitialized_var(new_snapshot);
+	struct pstore *ps = get_info(store);
+
+	/*
+	 * Read the snapshot header.
+	 */
+	r = read_header(ps, &new_snapshot);
+	if (r)
+		return r;
 
 	/*
 	 * Metadata are valid, but snapshot is invalidated
@@ -597,6 +672,12 @@ static int persistent_read_metadata(stru
 	if (!ps->valid)
 		return 1;
 
+	if (!ps->callbacks) {
+		r = do_initial_metadata_read(store, new_snapshot);
+		if (r)
+			return r;
+	}
+
 	/*
 	 * Read the metadata.
 	 */

      reply	other threads:[~2009-09-30 14:46 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-29 22:53 [PATCH 00/18] Clusterized exception store preparation Mike Snitzer
2009-09-29 22:53 ` [PATCH 01/18] dm-snap-consolidate-insert_exception-functions Mike Snitzer
2009-09-29 22:53 ` [PATCH 02/18] dm-exception-store-generalize-table-args Mike Snitzer
2009-09-30 14:44   ` [PATCH v2 " Mike Snitzer
2009-09-29 22:53 ` [PATCH 03/18] dm-snapshot-new-ctr-table-format Mike Snitzer
2009-09-29 22:53 ` [PATCH 04/18] dm-snapshot-rename-dm_snap_exception-to-dm_exception Mike Snitzer
2009-09-29 22:53 ` [PATCH 05/18] dm-snapshot-rename-exception_table-to-dm_exception_table Mike Snitzer
2009-09-29 22:53 ` [PATCH 06/18] dm-snapshot-rename-exception-functions Mike Snitzer
2009-09-29 22:53 ` [PATCH 07/18] dm-snapshot-use-allocated-exception-tables Mike Snitzer
2009-09-29 22:53 ` [PATCH 08/18] dm-snapshot-exception-function-changes-1 Mike Snitzer
2009-09-29 22:53 ` [PATCH 09/18] dm-snapshot-exception-function-changes-2 Mike Snitzer
2009-09-29 22:53 ` [PATCH 10/18] dm-snapshot-exception-function-changes-3 Mike Snitzer
2009-09-29 22:53 ` [PATCH 11/18] dm-snapshot-exception-function-changes-4 Mike Snitzer
2009-09-29 22:53 ` [PATCH 12/18] dm-snapshot-exception-function-changes-5 Mike Snitzer
2009-09-29 22:53 ` [PATCH 13/18] dm-snapshot-exception-function-changes-6 Mike Snitzer
2009-09-29 22:53 ` [PATCH 14/18] dm-snapshot-move-exception-code-to-new-file Mike Snitzer
2009-09-29 22:53 ` [PATCH 15/18] dm-exception-store-create-local-exception-caches Mike Snitzer
2009-09-29 22:53 ` [PATCH 16/18] dm-exception-store-add-lookup_exception-to-API Mike Snitzer
2009-09-29 22:53 ` [PATCH 17/18] dm-snapshot-remove-completed-exception-cache Mike Snitzer
2009-09-29 22:53 ` [PATCH 18/18] dm-exstore-persistent-allow-metadata-reread Mike Snitzer
2009-09-30 14:46   ` Mike Snitzer [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090930144604.GC16605@redhat.com \
    --to=snitzer@redhat.com \
    --cc=dm-devel@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.