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>
*/
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;
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";
/*
* 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;
/* Full snapshots are not usable */
if (!s->valid)
- return -1;
+ return -EIO;
+
+ if (unlikely(bio_barrier(bio)))
+ return -EOPNOTSUPP;
/*
* Write to snapshot - higher level takes care of RW/RO
{
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,
/* 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 */
+ if (bio->bi_sector >= dm_table_get_size(snap->table))
continue;
down_write(&snap->lock);
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;
}
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,
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,