[dm-devel] [PATCH 03/10] dm snapshot: Add exception store methods for merging

Mark McLoughlin markmc at redhat.com
Tue Apr 1 07:32:50 UTC 2008


Add prepare_merge() and commit_merge() methods to the exception store to
allow for snapshot chunks to be removed from the exception store as the
chunks are merged back into the origin.

prepare_merge() retrieves the details of the last exception in the store
in preparation for that chunk to be merged back into the origin.

commit_merge() is then later used to remove that same exception from the
store once the merge has completed.

Signed-off-by: Mark McLoughlin <markmc at redhat.com>
---
 drivers/md/dm-exception-store.c |   69 +++++++++++++++++++++++++++++++++++++++
 drivers/md/dm-snap.h            |   12 +++++++
 2 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 02fd3e9..4fd5381 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -624,6 +624,71 @@ static void persistent_commit(struct exception_store *store,
 	}
 }
 
+/* Given an exception index within a certain area, return the
+ * corresponding chunk index.
+ */
+static inline uint32_t exception_to_chunk(uint32_t area,
+					  uint32_t exceptions_per_area,
+					  uint32_t exception)
+{
+	/* Header followed by sets of (metadata chunk, exceptions_per_area chunks)
+	 */
+	return 1 + (area * (1 + exceptions_per_area)) + 1 + exception;
+}
+
+static int persistent_prepare_merge(struct exception_store *store,
+				    struct dm_snap_exception *e,
+				    int *empty)
+{
+	struct pstore *ps = get_info(store);
+	struct disk_exception de;
+	int r;
+
+	*empty = 0;
+
+	if (ps->current_committed == 0) {
+		if (ps->current_area == 0) {
+			*empty = 1;
+			return 0;
+		}
+
+		r = area_io(ps, ps->current_area - 1, READ);
+		if (r)
+			return r;
+
+		ps->current_committed = ps->exceptions_per_area - 1;
+	} else {
+		ps->current_committed--;
+	}
+
+	read_exception(ps, ps->current_committed, &de);
+
+	e->old_chunk = de.old_chunk;
+	e->new_chunk = de.new_chunk;
+
+	ps->next_free = exception_to_chunk(ps->current_area,
+					   ps->exceptions_per_area,
+					   ps->current_committed);
+
+	return 0;
+}
+
+static void persistent_commit_merge(struct exception_store *store)
+{
+	struct pstore *ps = get_info(store);
+	struct disk_exception de;
+	int r;
+
+	read_exception(ps, ps->current_committed, &de);
+
+	de.new_chunk = 0;
+	write_exception(ps, ps->current_committed, &de);
+
+	r = area_io(ps, ps->current_area, WRITE);
+	if (r)
+		ps->valid = 0;
+}
+
 static void persistent_drop(struct exception_store *store)
 {
 	struct pstore *ps = get_info(store);
@@ -664,6 +729,8 @@ int dm_create_persistent(struct exception_store *store)
 	store->read_metadata = persistent_read_metadata;
 	store->prepare_exception = persistent_prepare;
 	store->commit_exception = persistent_commit;
+	store->prepare_merge = persistent_prepare_merge;
+	store->commit_merge = persistent_commit_merge;
 	store->drop_snapshot = persistent_drop;
 	store->fraction_full = persistent_fraction_full;
 	store->context = ps;
@@ -727,6 +794,8 @@ int dm_create_transient(struct exception_store *store)
 	store->read_metadata = transient_read_metadata;
 	store->prepare_exception = transient_prepare;
 	store->commit_exception = transient_commit;
+	store->prepare_merge = NULL;
+	store->commit_merge = NULL;
 	store->drop_snapshot = NULL;
 	store->fraction_full = transient_fraction_full;
 
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 93bce5d..8b02a42 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -115,6 +115,18 @@ struct exception_store {
 				  void *callback_context);
 
 	/*
+	 * Prepare the next exception for merging.
+	 */
+	int (*prepare_merge) (struct exception_store *store,
+			      struct dm_snap_exception *e,
+			      int *empty);
+
+	/*
+	 * Remove the currently merging exception.
+	 */
+	void (*commit_merge) (struct exception_store *store);
+
+	/*
 	 * The snapshot is invalid, note this in the metadata.
 	 */
 	void (*drop_snapshot) (struct exception_store *store);
-- 
1.5.4.1




More information about the dm-devel mailing list