[dm-devel] [PATCH 04/10] dm snapshot: Split snapshot constructor

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


Split parts of snapshot_ctr() into a separate function, snapshot_init()
and parts of snapshot_dtr() into snapshot_destroy().

This is needed by later patches because the merging target re-uses the
dm_snapshot structure, but the merging target doesn't register itself
as a snapshot (i.e. origin writes shouldn't cause an exception), has a
different set of arguments and in some ways behaves more like a
snapshot-origin target.

Signed-off-by: Mark McLoughlin <markmc at redhat.com>
---
 drivers/md/dm-snap.c |  166 +++++++++++++++++++++++++++----------------------
 1 files changed, 91 insertions(+), 75 deletions(-)

diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 3b71f53..20f12a8 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -435,18 +435,9 @@ static ulong round_up(ulong n, ulong size)
 	return (n + size) & ~size;
 }
 
-static int set_chunk_size(struct dm_snapshot *s, const char *chunk_size_arg,
+static int set_chunk_size(struct dm_snapshot *s, unsigned long chunk_size,
 			  char **error)
 {
-	unsigned long chunk_size;
-	char *value;
-
-	chunk_size = simple_strtoul(chunk_size_arg, &value, 10);
-	if (*chunk_size_arg == '\0' || *value != '\0') {
-		*error = "Invalid chunk size";
-		return -EINVAL;
-	}
-
 	if (!chunk_size) {
 		s->chunk_size = s->chunk_mask = s->chunk_shift = 0;
 		return 0;
@@ -477,61 +468,30 @@ static int set_chunk_size(struct dm_snapshot *s, const char *chunk_size_arg,
 	return 0;
 }
 
-/*
- * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
- */
-static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+static int snapshot_init(struct dm_target *ti, struct dm_snapshot *s,
+			 const char *origin_path, int origin_mode,
+			 const char *cow_path, int cow_mode,
+			 char type, unsigned long chunk_size)
 {
-	struct dm_snapshot *s;
-	int r = -EINVAL;
-	char persistent;
-	char *origin_path;
-	char *cow_path;
-
-	if (argc != 4) {
-		ti->error = "requires exactly 4 arguments";
-		r = -EINVAL;
-		goto bad1;
-	}
-
-	origin_path = argv[0];
-	cow_path = argv[1];
-	persistent = toupper(*argv[2]);
-
-	if (persistent != 'P' && persistent != 'N') {
-		ti->error = "Persistent flag is not P or N";
-		r = -EINVAL;
-		goto bad1;
-	}
-
-	s = kmalloc(sizeof(*s), GFP_KERNEL);
-	if (s == NULL) {
-		ti->error = "Cannot allocate snapshot context private "
-		    "structure";
-		r = -ENOMEM;
-		goto bad1;
-	}
+	int r;
 
-	r = dm_get_device(ti, origin_path, 0, ti->len, FMODE_READ, &s->origin);
+	r = dm_get_device(ti, origin_path, 0, ti->len, origin_mode, &s->origin);
 	if (r) {
 		ti->error = "Cannot get origin device";
-		goto bad2;
+		goto bad1;
 	}
 
-	r = dm_get_device(ti, cow_path, 0, 0,
-			  FMODE_READ | FMODE_WRITE, &s->cow);
+	r = dm_get_device(ti, cow_path, 0, 0, cow_mode, &s->cow);
 	if (r) {
-		dm_put_device(ti, s->origin);
 		ti->error = "Cannot get COW device";
 		goto bad2;
 	}
 
-	r = set_chunk_size(s, argv[3], &ti->error);
+	r = set_chunk_size(s, chunk_size, &ti->error);
 	if (r)
 		goto bad3;
 
-	s->type = persistent;
-
+	s->type = type;
 	s->valid = 1;
 	s->active = 0;
 	s->last_percent = 0;
@@ -548,7 +508,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
 	s->store.snap = s;
 
-	if (persistent == 'P')
+	if (s->type == 'P')
 		r = dm_create_persistent(&s->store);
 	else
 		r = dm_create_transient(&s->store);
@@ -578,41 +538,24 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	bio_list_init(&s->queued_bios);
 	INIT_WORK(&s->queued_bios_work, flush_queued_bios);
 
-	/* Add snapshot to the list of snapshots for this origin */
-	/* Exceptions aren't triggered till snapshot_resume() is called */
-	if (register_snapshot(s)) {
-		r = -EINVAL;
-		ti->error = "Cannot register snapshot origin";
-		goto bad6;
-	}
-
-	ti->private = s;
-	ti->split_io = s->chunk_size;
-
 	return 0;
 
  bad6:
 	kcopyd_client_destroy(s->kcopyd_client);
-
  bad5:
 	s->store.destroy(&s->store);
-
  bad4:
 	exit_exception_table(&s->pending, pending_cache);
 	exit_exception_table(&s->complete, exception_cache);
-
  bad3:
 	dm_put_device(ti, s->cow);
-	dm_put_device(ti, s->origin);
-
  bad2:
-	kfree(s);
-
+	dm_put_device(ti, s->origin);
  bad1:
 	return r;
 }
 
-static void __free_exceptions(struct dm_snapshot *s)
+static void snapshot_destroy(struct dm_target *ti, struct dm_snapshot *s)
 {
 	kcopyd_client_destroy(s->kcopyd_client);
 	s->kcopyd_client = NULL;
@@ -621,6 +564,82 @@ static void __free_exceptions(struct dm_snapshot *s)
 	exit_exception_table(&s->complete, exception_cache);
 
 	s->store.destroy(&s->store);
+
+	dm_put_device(ti, s->origin);
+	dm_put_device(ti, s->cow);
+}
+
+/*
+ * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
+ */
+static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+	struct dm_snapshot *s;
+	int r = -EINVAL;
+	char persistent;
+	char *origin_path;
+	char *cow_path;
+	char *chunk_size_arg;
+	unsigned long chunk_size;
+	char *value;
+
+	if (argc != 4) {
+		ti->error = "requires exactly 4 arguments";
+		r = -EINVAL;
+		goto bad1;
+	}
+
+	origin_path = argv[0];
+	cow_path = argv[1];
+	persistent = toupper(*argv[2]);
+	chunk_size_arg = argv[3];
+
+	if (persistent != 'P' && persistent != 'N') {
+		ti->error = "Persistent flag is not P or N";
+		r = -EINVAL;
+		goto bad1;
+	}
+
+	chunk_size = simple_strtoul(chunk_size_arg, &value, 10);
+	if (*chunk_size_arg == '\0' || *value != '\0') {
+		ti->error = "Invalid chunk size";
+		goto bad1;
+	}
+
+	s = kmalloc(sizeof(*s), GFP_KERNEL);
+	if (s == NULL) {
+		ti->error = "Cannot allocate snapshot context private "
+		    "structure";
+		r = -ENOMEM;
+		goto bad1;
+	}
+
+	r = snapshot_init(ti, s,
+			  origin_path, FMODE_READ,
+			  cow_path, FMODE_READ | FMODE_WRITE,
+			  persistent, chunk_size);
+	if (r)
+		goto bad2;
+
+	/* Add snapshot to the list of snapshots for this origin */
+	/* Exceptions aren't triggered till snapshot_resume() is called */
+	if (register_snapshot(s)) {
+		r = -EINVAL;
+		ti->error = "Cannot register snapshot origin";
+		goto bad3;
+	}
+
+	ti->private = s;
+	ti->split_io = s->chunk_size;
+
+	return 0;
+
+ bad3:
+	snapshot_destroy(ti, s);
+ bad2:
+	kfree(s);
+ bad1:
+	return r;
 }
 
 static void snapshot_dtr(struct dm_target *ti)
@@ -633,10 +652,7 @@ static void snapshot_dtr(struct dm_target *ti)
 	/* After this returns there can be no new kcopyd jobs. */
 	unregister_snapshot(s);
 
-	__free_exceptions(s);
-
-	dm_put_device(ti, s->origin);
-	dm_put_device(ti, s->cow);
+	snapshot_destroy(ti, s);
 
 	kfree(s);
 }
-- 
1.5.4.1




More information about the dm-devel mailing list