Merge git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[powerpc.git] / drivers / md / dm-snap.c
index 7e691ab..4b9dd8f 100644 (file)
@@ -371,6 +371,20 @@ static inline ulong round_up(ulong n, ulong size)
        return (n + size) & ~size;
 }
 
+static void read_snapshot_metadata(struct dm_snapshot *s)
+{
+       if (s->have_metadata)
+               return;
+
+       if (s->store.read_metadata(&s->store)) {
+               down_write(&s->lock);
+               s->valid = 0;
+               up_write(&s->lock);
+       }
+
+       s->have_metadata = 1;
+}
+
 /*
  * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
  */
@@ -777,7 +791,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
 
        /* Full snapshots are not usable */
        if (!s->valid)
-               return -1;
+               return -EIO;
 
        /*
         * Write to snapshot - higher level takes care of RW/RO
@@ -848,16 +862,7 @@ static void snapshot_resume(struct dm_target *ti)
 {
        struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
 
-       if (s->have_metadata)
-               return;
-
-       if (s->store.read_metadata(&s->store)) {
-               down_write(&s->lock);
-               s->valid = 0;
-               up_write(&s->lock);
-       }
-
-       s->have_metadata = 1;
+       read_snapshot_metadata(s);
 }
 
 static int snapshot_status(struct dm_target *ti, status_type_t type,
@@ -931,6 +936,10 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
                if (!snap->valid)
                        continue;
 
+               /* Nothing to do if writing beyond end of snapshot */
+               if (bio->bi_sector >= dm_table_get_size(snap->table))
+                       continue;
+
                down_write(&snap->lock);
 
                /*