Commit c2411045 authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Alasdair G Kergon

dm snapshot: test chunk size against both origin and snapshot

Validate chunk size against both origin and snapshot sector size

Don't allow chunk size smaller than either origin or snapshot logical
sector size. Reading or writing data not aligned to sector size is not
allowed and causes immediate errors.

This requires us to open the origin before initialising the
exception store and to export dm_snap_origin.

Cc: stable@kernel.org
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Reviewed-by: default avatarMike Snitzer <snitzer@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 1e5554c8
...@@ -173,7 +173,9 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store, ...@@ -173,7 +173,9 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
/* Validate the chunk size against the device block size */ /* Validate the chunk size against the device block size */
if (chunk_size % if (chunk_size %
(bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9)) { (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) ||
chunk_size %
(bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) {
*error = "Chunk size is not a multiple of device blocksize"; *error = "Chunk size is not a multiple of device blocksize";
return -EINVAL; return -EINVAL;
} }
......
...@@ -126,8 +126,9 @@ struct dm_exception_store { ...@@ -126,8 +126,9 @@ struct dm_exception_store {
}; };
/* /*
* Obtain the cow device used by a given snapshot. * Obtain the origin or cow device used by a given snapshot.
*/ */
struct dm_dev *dm_snap_origin(struct dm_snapshot *snap);
struct dm_dev *dm_snap_cow(struct dm_snapshot *snap); struct dm_dev *dm_snap_cow(struct dm_snapshot *snap);
/* /*
......
...@@ -148,6 +148,12 @@ struct dm_snapshot { ...@@ -148,6 +148,12 @@ struct dm_snapshot {
#define RUNNING_MERGE 0 #define RUNNING_MERGE 0
#define SHUTDOWN_MERGE 1 #define SHUTDOWN_MERGE 1
struct dm_dev *dm_snap_origin(struct dm_snapshot *s)
{
return s->origin;
}
EXPORT_SYMBOL(dm_snap_origin);
struct dm_dev *dm_snap_cow(struct dm_snapshot *s) struct dm_dev *dm_snap_cow(struct dm_snapshot *s)
{ {
return s->cow; return s->cow;
...@@ -1065,10 +1071,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -1065,10 +1071,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
origin_mode = FMODE_WRITE; origin_mode = FMODE_WRITE;
} }
origin_path = argv[0];
argv++;
argc--;
s = kmalloc(sizeof(*s), GFP_KERNEL); s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s) { if (!s) {
ti->error = "Cannot allocate snapshot context private " ti->error = "Cannot allocate snapshot context private "
...@@ -1077,6 +1079,16 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -1077,6 +1079,16 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad; goto bad;
} }
origin_path = argv[0];
argv++;
argc--;
r = dm_get_device(ti, origin_path, origin_mode, &s->origin);
if (r) {
ti->error = "Cannot get origin device";
goto bad_origin;
}
cow_path = argv[0]; cow_path = argv[0];
argv++; argv++;
argc--; argc--;
...@@ -1097,12 +1109,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -1097,12 +1109,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
argv += args_used; argv += args_used;
argc -= args_used; argc -= args_used;
r = dm_get_device(ti, origin_path, origin_mode, &s->origin);
if (r) {
ti->error = "Cannot get origin device";
goto bad_origin;
}
s->ti = ti; s->ti = ti;
s->valid = 1; s->valid = 1;
s->active = 0; s->active = 0;
...@@ -1212,15 +1218,15 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -1212,15 +1218,15 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
dm_exception_table_exit(&s->complete, exception_cache); dm_exception_table_exit(&s->complete, exception_cache);
bad_hash_tables: bad_hash_tables:
dm_put_device(ti, s->origin);
bad_origin:
dm_exception_store_destroy(s->store); dm_exception_store_destroy(s->store);
bad_store: bad_store:
dm_put_device(ti, s->cow); dm_put_device(ti, s->cow);
bad_cow: bad_cow:
dm_put_device(ti, s->origin);
bad_origin:
kfree(s); kfree(s);
bad: bad:
...@@ -1314,12 +1320,12 @@ static void snapshot_dtr(struct dm_target *ti) ...@@ -1314,12 +1320,12 @@ static void snapshot_dtr(struct dm_target *ti)
mempool_destroy(s->pending_pool); mempool_destroy(s->pending_pool);
dm_put_device(ti, s->origin);
dm_exception_store_destroy(s->store); dm_exception_store_destroy(s->store);
dm_put_device(ti, s->cow); dm_put_device(ti, s->cow);
dm_put_device(ti, s->origin);
kfree(s); kfree(s);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment