aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2010-08-11 23:13:51 -0400
committerAlasdair G Kergon <agk@redhat.com>2010-08-11 23:13:51 -0400
commitc24110450650f17f7d3ba4fbe01f01ac5a115456 (patch)
tree8b5bff17f77c995099d93b2b4a32bc306962a0bf
parent1e5554c8428bc7209a83e2d07ca724be4d981ce3 (diff)
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: Mikulas Patocka <mpatocka@redhat.com> Reviewed-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r--drivers/md/dm-exception-store.c4
-rw-r--r--drivers/md/dm-exception-store.h3
-rw-r--r--drivers/md/dm-snap.c36
3 files changed, 26 insertions, 17 deletions
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 2b7907b6dd09..0bdb201c2c2a 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -173,7 +173,9 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
173 173
174 /* Validate the chunk size against the device block size */ 174 /* Validate the chunk size against the device block size */
175 if (chunk_size % 175 if (chunk_size %
176 (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9)) { 176 (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) ||
177 chunk_size %
178 (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) {
177 *error = "Chunk size is not a multiple of device blocksize"; 179 *error = "Chunk size is not a multiple of device blocksize";
178 return -EINVAL; 180 return -EINVAL;
179 } 181 }
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
index e8dfa06af3ba..0b2536247cf5 100644
--- a/drivers/md/dm-exception-store.h
+++ b/drivers/md/dm-exception-store.h
@@ -126,8 +126,9 @@ struct dm_exception_store {
126}; 126};
127 127
128/* 128/*
129 * Obtain the cow device used by a given snapshot. 129 * Obtain the origin or cow device used by a given snapshot.
130 */ 130 */
131struct dm_dev *dm_snap_origin(struct dm_snapshot *snap);
131struct dm_dev *dm_snap_cow(struct dm_snapshot *snap); 132struct dm_dev *dm_snap_cow(struct dm_snapshot *snap);
132 133
133/* 134/*
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index a6ab98920cc3..a1f2ab553b92 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -148,6 +148,12 @@ struct dm_snapshot {
148#define RUNNING_MERGE 0 148#define RUNNING_MERGE 0
149#define SHUTDOWN_MERGE 1 149#define SHUTDOWN_MERGE 1
150 150
151struct dm_dev *dm_snap_origin(struct dm_snapshot *s)
152{
153 return s->origin;
154}
155EXPORT_SYMBOL(dm_snap_origin);
156
151struct dm_dev *dm_snap_cow(struct dm_snapshot *s) 157struct dm_dev *dm_snap_cow(struct dm_snapshot *s)
152{ 158{
153 return s->cow; 159 return s->cow;
@@ -1065,10 +1071,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
1065 origin_mode = FMODE_WRITE; 1071 origin_mode = FMODE_WRITE;
1066 } 1072 }
1067 1073
1068 origin_path = argv[0];
1069 argv++;
1070 argc--;
1071
1072 s = kmalloc(sizeof(*s), GFP_KERNEL); 1074 s = kmalloc(sizeof(*s), GFP_KERNEL);
1073 if (!s) { 1075 if (!s) {
1074 ti->error = "Cannot allocate snapshot context private " 1076 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 goto bad; 1079 goto bad;
1078 } 1080 }
1079 1081
1082 origin_path = argv[0];
1083 argv++;
1084 argc--;
1085
1086 r = dm_get_device(ti, origin_path, origin_mode, &s->origin);
1087 if (r) {
1088 ti->error = "Cannot get origin device";
1089 goto bad_origin;
1090 }
1091
1080 cow_path = argv[0]; 1092 cow_path = argv[0];
1081 argv++; 1093 argv++;
1082 argc--; 1094 argc--;
@@ -1097,12 +1109,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
1097 argv += args_used; 1109 argv += args_used;
1098 argc -= args_used; 1110 argc -= args_used;
1099 1111
1100 r = dm_get_device(ti, origin_path, origin_mode, &s->origin);
1101 if (r) {
1102 ti->error = "Cannot get origin device";
1103 goto bad_origin;
1104 }
1105
1106 s->ti = ti; 1112 s->ti = ti;
1107 s->valid = 1; 1113 s->valid = 1;
1108 s->active = 0; 1114 s->active = 0;
@@ -1212,15 +1218,15 @@ bad_kcopyd:
1212 dm_exception_table_exit(&s->complete, exception_cache); 1218 dm_exception_table_exit(&s->complete, exception_cache);
1213 1219
1214bad_hash_tables: 1220bad_hash_tables:
1215 dm_put_device(ti, s->origin);
1216
1217bad_origin:
1218 dm_exception_store_destroy(s->store); 1221 dm_exception_store_destroy(s->store);
1219 1222
1220bad_store: 1223bad_store:
1221 dm_put_device(ti, s->cow); 1224 dm_put_device(ti, s->cow);
1222 1225
1223bad_cow: 1226bad_cow:
1227 dm_put_device(ti, s->origin);
1228
1229bad_origin:
1224 kfree(s); 1230 kfree(s);
1225 1231
1226bad: 1232bad:
@@ -1314,12 +1320,12 @@ static void snapshot_dtr(struct dm_target *ti)
1314 1320
1315 mempool_destroy(s->pending_pool); 1321 mempool_destroy(s->pending_pool);
1316 1322
1317 dm_put_device(ti, s->origin);
1318
1319 dm_exception_store_destroy(s->store); 1323 dm_exception_store_destroy(s->store);
1320 1324
1321 dm_put_device(ti, s->cow); 1325 dm_put_device(ti, s->cow);
1322 1326
1327 dm_put_device(ti, s->origin);
1328
1323 kfree(s); 1329 kfree(s);
1324} 1330}
1325 1331