[dm-devel] Re: clustered snapshots

Mike Snitzer snitzer at redhat.com
Mon Oct 5 13:38:41 UTC 2009


On Mon, Oct 05 2009 at 12:33am -0400,
Mike Snitzer <snitzer at redhat.com> wrote:

> On Sun, Oct 04 2009 at 10:25pm -0400,
> Mikulas Patocka <mpatocka at redhat.com> wrote:
> 
> > Hi
> > 
> > I don't understand the purpose of this patch. I think it's useless.
> 
> You don't understand it, so you think it's useless.. nice to know where
> I'm starting.
> 
> > - during merge, nothing except the merge process reads the on-disk 
> > exceptions. So it doesn't matter when you clean them. You must clean them 
> > before dropping the interlock, but the order is not important.
> 
> Sure, I thought the same but quickly realized that in practice order
> does matter if you'd like to avoid failing the in-core exception cleanup
> (IFF we allow chunks to be inserted before existing chunks; aka
> "back-merges").
> 
> Your original approach to cleaning all on-disk exceptions then all
> in-core has no hope of working for "back-merges".  Your original
> snapshot-merge completely eliminated insertions before existing chunks.

<snip - my long-winded defensiveness>

> Lesson I learned is that the in-core dm_snap_exception's consecutive
> chunk accounting is _really_ subtle.  And while I agree there should be
> no relation between the proper cleanup of on-disk and in-core
> exceptions; doing the cleanup of each in lock-step appears to be the
> only way forward (that I found).

If I just judge the location of the chunk within the in-core exception
support for back-merges works just as well.  Here is a minimalist patch
the accomplishes the same:

diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index bcfbe85..b271f56 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -790,17 +790,25 @@ static void merge_callback(int read_err, unsigned long write_err, void *context)
         * so that dm_consecutive_chunk_count_dec() accounting works
         */
        for (i = s->merge_write_interlock_n - 1; i >= 0; i--) {
-               e = lookup_exception(&s->complete,
-                                    s->merge_write_interlock + i);
+               chunk_t old_chunk = s->merge_write_interlock + i;
+               e = lookup_exception(&s->complete, old_chunk);
                if (!e) {
                        DMERR("exception for block %llu is on "
                              "disk but not in memory",
-                             (unsigned long long)
-                             s->merge_write_interlock + i);
+                             (unsigned long long)old_chunk);
                        up_write(&s->lock);
                        goto shut;
                }
                if (dm_consecutive_chunk_count(e)) {
+                       if (old_chunk == e->old_chunk) {
+                               e->old_chunk++;
+                               e->new_chunk++;
+                       } else if (old_chunk != e->old_chunk +
+                                  dm_consecutive_chunk_count(e)) {
+                               DMERR("merge from the middle of a chunk range");
+                               up_write(&s->lock);
+                               goto shut;
+                       }
                        dm_consecutive_chunk_count_dec(e);
                } else {
                        remove_exception(e);




More information about the dm-devel mailing list