aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-exception-store.c65
-rw-r--r--drivers/md/dm-snap.c6
2 files changed, 45 insertions, 26 deletions
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index cc07bbebbb1..34a75939a0c 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -91,7 +91,6 @@ struct pstore {
91 struct dm_snapshot *snap; /* up pointer to my snapshot */ 91 struct dm_snapshot *snap; /* up pointer to my snapshot */
92 int version; 92 int version;
93 int valid; 93 int valid;
94 uint32_t chunk_size;
95 uint32_t exceptions_per_area; 94 uint32_t exceptions_per_area;
96 95
97 /* 96 /*
@@ -133,7 +132,7 @@ static int alloc_area(struct pstore *ps)
133 int r = -ENOMEM; 132 int r = -ENOMEM;
134 size_t len; 133 size_t len;
135 134
136 len = ps->chunk_size << SECTOR_SHIFT; 135 len = ps->snap->chunk_size << SECTOR_SHIFT;
137 136
138 /* 137 /*
139 * Allocate the chunk_size block of memory that will hold 138 * Allocate the chunk_size block of memory that will hold
@@ -160,8 +159,8 @@ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
160 unsigned long bits; 159 unsigned long bits;
161 160
162 where.bdev = ps->snap->cow->bdev; 161 where.bdev = ps->snap->cow->bdev;
163 where.sector = ps->chunk_size * chunk; 162 where.sector = ps->snap->chunk_size * chunk;
164 where.count = ps->chunk_size; 163 where.count = ps->snap->chunk_size;
165 164
166 return dm_io_sync_vm(1, &where, rw, ps->area, &bits); 165 return dm_io_sync_vm(1, &where, rw, ps->area, &bits);
167} 166}
@@ -188,7 +187,7 @@ static int area_io(struct pstore *ps, uint32_t area, int rw)
188 187
189static int zero_area(struct pstore *ps, uint32_t area) 188static int zero_area(struct pstore *ps, uint32_t area)
190{ 189{
191 memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT); 190 memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
192 return area_io(ps, area, WRITE); 191 return area_io(ps, area, WRITE);
193} 192}
194 193
@@ -196,6 +195,7 @@ static int read_header(struct pstore *ps, int *new_snapshot)
196{ 195{
197 int r; 196 int r;
198 struct disk_header *dh; 197 struct disk_header *dh;
198 chunk_t chunk_size;
199 199
200 r = chunk_io(ps, 0, READ); 200 r = chunk_io(ps, 0, READ);
201 if (r) 201 if (r)
@@ -210,8 +210,29 @@ static int read_header(struct pstore *ps, int *new_snapshot)
210 *new_snapshot = 0; 210 *new_snapshot = 0;
211 ps->valid = le32_to_cpu(dh->valid); 211 ps->valid = le32_to_cpu(dh->valid);
212 ps->version = le32_to_cpu(dh->version); 212 ps->version = le32_to_cpu(dh->version);
213 ps->chunk_size = le32_to_cpu(dh->chunk_size); 213 chunk_size = le32_to_cpu(dh->chunk_size);
214 214 if (ps->snap->chunk_size != chunk_size) {
215 DMWARN("chunk size %llu in device metadata overrides "
216 "table chunk size of %llu.",
217 (unsigned long long)chunk_size,
218 (unsigned long long)ps->snap->chunk_size);
219
220 /* We had a bogus chunk_size. Fix stuff up. */
221 dm_io_put(sectors_to_pages(ps->snap->chunk_size));
222 free_area(ps);
223
224 ps->snap->chunk_size = chunk_size;
225 ps->snap->chunk_mask = chunk_size - 1;
226 ps->snap->chunk_shift = ffs(chunk_size) - 1;
227
228 r = alloc_area(ps);
229 if (r)
230 return r;
231
232 r = dm_io_get(sectors_to_pages(chunk_size));
233 if (r)
234 return r;
235 }
215 } else { 236 } else {
216 DMWARN("Invalid/corrupt snapshot"); 237 DMWARN("Invalid/corrupt snapshot");
217 r = -ENXIO; 238 r = -ENXIO;
@@ -224,13 +245,13 @@ static int write_header(struct pstore *ps)
224{ 245{
225 struct disk_header *dh; 246 struct disk_header *dh;
226 247
227 memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT); 248 memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
228 249
229 dh = (struct disk_header *) ps->area; 250 dh = (struct disk_header *) ps->area;
230 dh->magic = cpu_to_le32(SNAP_MAGIC); 251 dh->magic = cpu_to_le32(SNAP_MAGIC);
231 dh->valid = cpu_to_le32(ps->valid); 252 dh->valid = cpu_to_le32(ps->valid);
232 dh->version = cpu_to_le32(ps->version); 253 dh->version = cpu_to_le32(ps->version);
233 dh->chunk_size = cpu_to_le32(ps->chunk_size); 254 dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
234 255
235 return chunk_io(ps, 0, WRITE); 256 return chunk_io(ps, 0, WRITE);
236} 257}
@@ -365,7 +386,7 @@ static void persistent_destroy(struct exception_store *store)
365{ 386{
366 struct pstore *ps = get_info(store); 387 struct pstore *ps = get_info(store);
367 388
368 dm_io_put(sectors_to_pages(ps->chunk_size)); 389 dm_io_put(sectors_to_pages(ps->snap->chunk_size));
369 vfree(ps->callbacks); 390 vfree(ps->callbacks);
370 free_area(ps); 391 free_area(ps);
371 kfree(ps); 392 kfree(ps);
@@ -384,6 +405,16 @@ static int persistent_read_metadata(struct exception_store *store)
384 return r; 405 return r;
385 406
386 /* 407 /*
408 * Now we know correct chunk_size, complete the initialisation.
409 */
410 ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /
411 sizeof(struct disk_exception);
412 ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
413 sizeof(*ps->callbacks));
414 if (!ps->callbacks)
415 return -ENOMEM;
416
417 /*
387 * Do we need to setup a new snapshot ? 418 * Do we need to setup a new snapshot ?
388 */ 419 */
389 if (new_snapshot) { 420 if (new_snapshot) {
@@ -533,9 +564,6 @@ int dm_create_persistent(struct exception_store *store, uint32_t chunk_size)
533 ps->snap = store->snap; 564 ps->snap = store->snap;
534 ps->valid = 1; 565 ps->valid = 1;
535 ps->version = SNAPSHOT_DISK_VERSION; 566 ps->version = SNAPSHOT_DISK_VERSION;
536 ps->chunk_size = chunk_size;
537 ps->exceptions_per_area = (chunk_size << SECTOR_SHIFT) /
538 sizeof(struct disk_exception);
539 ps->next_free = 2; /* skipping the header and first area */ 567 ps->next_free = 2; /* skipping the header and first area */
540 ps->current_committed = 0; 568 ps->current_committed = 0;
541 569
@@ -543,18 +571,9 @@ int dm_create_persistent(struct exception_store *store, uint32_t chunk_size)
543 if (r) 571 if (r)
544 goto bad; 572 goto bad;
545 573
546 /*
547 * Allocate space for all the callbacks.
548 */
549 ps->callback_count = 0; 574 ps->callback_count = 0;
550 atomic_set(&ps->pending_count, 0); 575 atomic_set(&ps->pending_count, 0);
551 ps->callbacks = dm_vcalloc(ps->exceptions_per_area, 576 ps->callbacks = NULL;
552 sizeof(*ps->callbacks));
553
554 if (!ps->callbacks) {
555 r = -ENOMEM;
556 goto bad;
557 }
558 577
559 store->destroy = persistent_destroy; 578 store->destroy = persistent_destroy;
560 store->read_metadata = persistent_read_metadata; 579 store->read_metadata = persistent_read_metadata;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 08312b46463..b84bc1aae35 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -530,7 +530,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
530 } 530 }
531 531
532 ti->private = s; 532 ti->private = s;
533 ti->split_io = chunk_size; 533 ti->split_io = s->chunk_size;
534 534
535 return 0; 535 return 0;
536 536
@@ -1204,7 +1204,7 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result,
1204 1204
1205static struct target_type origin_target = { 1205static struct target_type origin_target = {
1206 .name = "snapshot-origin", 1206 .name = "snapshot-origin",
1207 .version = {1, 1, 0}, 1207 .version = {1, 4, 0},
1208 .module = THIS_MODULE, 1208 .module = THIS_MODULE,
1209 .ctr = origin_ctr, 1209 .ctr = origin_ctr,
1210 .dtr = origin_dtr, 1210 .dtr = origin_dtr,
@@ -1215,7 +1215,7 @@ static struct target_type origin_target = {
1215 1215
1216static struct target_type snapshot_target = { 1216static struct target_type snapshot_target = {
1217 .name = "snapshot", 1217 .name = "snapshot",
1218 .version = {1, 1, 0}, 1218 .version = {1, 4, 0},
1219 .module = THIS_MODULE, 1219 .module = THIS_MODULE,
1220 .ctr = snapshot_ctr, 1220 .ctr = snapshot_ctr,
1221 .dtr = snapshot_dtr, 1221 .dtr = snapshot_dtr,