[dm-devel] [PATCH] dm-snapshot.c: Allocate an origin structure in origin_ctr()

Kevin Corry kevcorry at us.ibm.com
Tue Jul 29 15:34:01 UTC 2003


Joe,

We talked on Saturday about adding code in the origin_ctr() path to allocate
an origin structure if one was not already present. This would allow an origin
device to be active without any active snapshots, and thus prevent hitting
the BUG in do_origin. You said you had a patch that did this, but in case
you've misplaced it, I put one together this afternoon. If you do have your
patch available, could you please post it here, and I will test with your version
instead of this one.

Thanks!
-- 
Kevin Corry
kevcorry at us.ibm.com
http://evms.sourceforge.net/


Allocate an origin structure in the origin_ctr path. This prevents us from
hitting the BUG in do_origin() if we have an active origin device with no
active snapshot devices. This patch also creates some common routines to use
in both the snapshot and origin constructors and destructors.

--- a/drivers/md/dm-snapshot.c	4 Jul 2003 19:38:50 -0000
+++ b/drivers/md/dm-snapshot.c	29 Jul 2003 19:47:37 -0000
@@ -155,6 +155,29 @@
 }
 
 /*
+ * Allocate an initialize an origin structure.
+ */
+static struct origin * __alloc_origin(kdev_t dev)
+{
+	struct origin *o = kmalloc(sizeof(*o), GFP_KERNEL);
+	if (o) {
+		o->dev = dev;
+		INIT_LIST_HEAD(&o->hash_list);
+		INIT_LIST_HEAD(&o->snapshots);
+		__insert_origin(o);
+	}
+	return o;
+}
+
+static void __put_origin(struct origin *o)
+{
+	if (list_empty(&o->snapshots)) {
+		list_del(&o->hash_list);
+		kfree(o);
+	}
+}
+
+/*
  * Make a note of the snapshot and its origin so we can look it
  * up when the origin has a write on it.
  */
@@ -168,17 +191,11 @@
 
 	if (!o) {
 		/* New origin */
-		o = kmalloc(sizeof(*o), GFP_KERNEL);
+		o = __alloc_origin(dev);
 		if (!o) {
 			up_write(&_origins_lock);
 			return -ENOMEM;
 		}
-
-		/* Initialise the struct */
-		INIT_LIST_HEAD(&o->snapshots);
-		o->dev = dev;
-
-		__insert_origin(o);
 	}
 
 	list_add_tail(&snap->list, &o->snapshots);
@@ -187,6 +204,26 @@
 	return 0;
 }
 
+static int register_origin(kdev_t dev)
+{
+	struct origin *o;
+
+	down_write(&_origins_lock);
+	o = __lookup_origin(dev);
+
+	if (!o) {
+		/* New origin */
+		o = __alloc_origin(dev);
+		if (!o) {
+			up_write(&_origins_lock);
+			return -ENOMEM;
+		}
+	}
+
+	up_write(&_origins_lock);
+	return 0;
+}
+
 static void unregister_snapshot(struct dm_snapshot *s)
 {
 	struct origin *o;
@@ -195,14 +232,21 @@
 	o = __lookup_origin(s->origin->dev);
 
 	list_del(&s->list);
-	if (list_empty(&o->snapshots)) {
-		list_del(&o->hash_list);
-		kfree(o);
-	}
+	__put_origin(o);
 
 	up_write(&_origins_lock);
 }
 
+static void unregister_origin(kdev_t dev)
+{
+	struct origin *o;
+
+	down_write(&_origins_lock);
+	o = __lookup_origin(dev);
+	__put_origin(o);
+	up_write(&_origins_lock);
+}
+
 /*
  * Implementation of the exception hash tables.
  */
@@ -1050,6 +1094,13 @@
 		return r;
 	}
 
+	r = register_origin(dev->dev);
+	if (r) {
+		ti->error = "Cannot register origin";
+		dm_put_device(ti, dev);
+		return r;
+	}
+
 	ti->private = dev;
 	return 0;
 }
@@ -1057,6 +1108,7 @@
 static void origin_dtr(struct dm_target *ti)
 {
 	struct dm_dev *dev = (struct dm_dev *) ti->private;
+	unregister_origin(dev->dev);
 	dm_put_device(ti, dev);
 }
 





More information about the dm-devel mailing list