<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">From: Milan Broz &lt;mbroz@redhat.com&gt;

Release memory if snapshot is invalidated.

All I/O operations on the full (invalidated) snapshot will
cause -EIO so no memory is needed anymore.

Snapshot is marked invalid and in workqueue is scheduled its
deallocation.

Signed-off-by: Milan Broz &lt;mbroz@redhat.com&gt;
---

---
 drivers/md/dm-snap.c |   46 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 36 insertions(+), 10 deletions(-)

Index: linux-2.6.22/drivers/md/dm-snap.c
===================================================================
--- linux-2.6.22.orig/drivers/md/dm-snap.c	2007-05-14 17:17:29.000000000 +0200
+++ linux-2.6.22/drivers/md/dm-snap.c	2007-05-14 18:51:47.000000000 +0200
@@ -563,7 +563,7 @@ static int snapshot_ctr(struct dm_target
  bad1:
 	return r;
 }
-
+/*
 static void __free_exceptions(struct dm_snapshot *s)
 {
 	kcopyd_client_destroy(s-&gt;kcopyd_client);
@@ -574,18 +574,31 @@ static void __free_exceptions(struct dm_
 
 	s-&gt;store.destroy(&amp;s-&gt;store);
 }
+*/
+static void __schedule_drop_snapshot(struct dm_snapshot *s)
+{
+	/* invalidated -&gt; already scheduled */
+	if (!s-&gt;valid)
+		return;
+
+	s-&gt;valid = 0;
+
+	queue_work(ksnapd, &amp;s-&gt;queued_bios_work);
+}
 
 static void snapshot_dtr(struct dm_target *ti)
 {
 	struct dm_snapshot *s = (struct dm_snapshot *) ti-&gt;private;
 
-	flush_workqueue(ksnapd);
-
 	/* Prevent further origin writes from using this snapshot. */
 	/* After this returns there can be no new kcopyd jobs. */
 	unregister_snapshot(s);
 
-	__free_exceptions(s);
+	down_write(&amp;s-&gt;lock);
+	__schedule_drop_snapshot(s);
+	up_write(&amp;s-&gt;lock);
+
+	flush_workqueue(ksnapd);
 
 	dm_put_device(ti, s-&gt;origin);
 	dm_put_device(ti, s-&gt;cow);
@@ -612,6 +625,7 @@ static void flush_queued_bios(struct wor
 {
 	struct dm_snapshot *s =
 		container_of(work, struct dm_snapshot, queued_bios_work);
+/*
 	struct bio *queued_bios;
 	unsigned long flags;
 
@@ -620,6 +634,23 @@ static void flush_queued_bios(struct wor
 	spin_unlock_irqrestore(&amp;s-&gt;pe_lock, flags);
 
 	flush_bios(queued_bios);
+*/
+	BUG_ON(!s-&gt;kcopyd_client);
+	BUG_ON(s-&gt;valid);
+
+	kcopyd_client_destroy(s-&gt;kcopyd_client);
+	s-&gt;kcopyd_client = NULL;
+
+//	down_write(&amp;s-&gt;lock);
+	if (s-&gt;store.drop_snapshot)
+		s-&gt;store.drop_snapshot(&amp;s-&gt;store);
+
+	exit_exception_table(&amp;s-&gt;pending, pending_cache);
+	exit_exception_table(&amp;s-&gt;complete, exception_cache);
+
+	s-&gt;store.destroy(&amp;s-&gt;store);
+	dm_table_event(s-&gt;table);
+//	up_write(&amp;s-&gt;lock);
 }
 
 /*
@@ -647,12 +678,7 @@ static void __invalidate_snapshot(struct
 	else if (err == -ENOMEM)
 		DMERR("Invalidating snapshot: Unable to allocate exception.");
 
-	if (s-&gt;store.drop_snapshot)
-		s-&gt;store.drop_snapshot(&amp;s-&gt;store);
-
-	s-&gt;valid = 0;
-
-	dm_table_event(s-&gt;table);
+	__schedule_drop_snapshot(s);
 }
 
 static void get_pending_exception(struct pending_exception *pe)
</pre></body></html>