]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/md/dm-snap.c
[SCSI] lpfc 8.1.2: Fixed a race condition in the PLOGI retry logic.
[linux-2.6-omap-h63xx.git] / drivers / md / dm-snap.c
index ab54f99b7c3b27cfd40a023bae56f9e0ed0b0f18..f3759dd7828e585ed81b0819e9908fbf546da543 100644 (file)
@@ -371,6 +371,15 @@ static inline ulong round_up(ulong n, ulong size)
        return (n + size) & ~size;
 }
 
+static void read_snapshot_metadata(struct dm_snapshot *s)
+{
+       if (s->store.read_metadata(&s->store)) {
+               down_write(&s->lock);
+               s->valid = 0;
+               up_write(&s->lock);
+       }
+}
+
 /*
  * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
  */
@@ -457,7 +466,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        s->chunk_shift = ffs(chunk_size) - 1;
 
        s->valid = 1;
-       s->have_metadata = 0;
+       s->active = 0;
        s->last_percent = 0;
        init_rwsem(&s->lock);
        s->table = ti->table;
@@ -492,7 +501,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad5;
        }
 
+       /* Metadata must only be loaded into one table at once */
+       read_snapshot_metadata(s);
+
        /* 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";
@@ -677,7 +690,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context)
 /*
  * Dispatches the copy operation to kcopyd.
  */
-static inline void start_copy(struct pending_exception *pe)
+static void start_copy(struct pending_exception *pe)
 {
        struct dm_snapshot *s = pe->snap;
        struct io_region src, dest;
@@ -779,6 +792,9 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
        if (!s->valid)
                return -EIO;
 
+       if (unlikely(bio_barrier(bio)))
+               return -EOPNOTSUPP;
+
        /*
         * Write to snapshot - higher level takes care of RW/RO
         * flags so we should only get this if we are
@@ -848,16 +864,9 @@ 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;
+       down_write(&s->lock);
+       s->active = 1;
+       up_write(&s->lock);
 }
 
 static int snapshot_status(struct dm_target *ti, status_type_t type,
@@ -927,8 +936,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
        /* Do all the snapshots on this origin */
        list_for_each_entry (snap, snapshots, list) {
 
-               /* Only deal with valid snapshots */
-               if (!snap->valid)
+               /* Only deal with valid and active snapshots */
+               if (!snap->valid || !snap->active)
                        continue;
 
                /* Nothing to do if writing beyond end of snapshot */
@@ -1052,6 +1061,9 @@ static int origin_map(struct dm_target *ti, struct bio *bio,
        struct dm_dev *dev = (struct dm_dev *) ti->private;
        bio->bi_bdev = dev->bdev;
 
+       if (unlikely(bio_barrier(bio)))
+               return -EOPNOTSUPP;
+
        /* Only tell snapshots if this is a write */
        return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1;
 }
@@ -1099,7 +1111,7 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result,
 
 static struct target_type origin_target = {
        .name    = "snapshot-origin",
-       .version = {1, 0, 1},
+       .version = {1, 1, 0},
        .module  = THIS_MODULE,
        .ctr     = origin_ctr,
        .dtr     = origin_dtr,
@@ -1110,7 +1122,7 @@ static struct target_type origin_target = {
 
 static struct target_type snapshot_target = {
        .name    = "snapshot",
-       .version = {1, 0, 1},
+       .version = {1, 1, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,