diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-exception-store.c | 65 | ||||
-rw-r--r-- | drivers/md/dm-snap.c | 6 |
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 | ||
189 | static int zero_area(struct pstore *ps, uint32_t area) | 188 | static 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 | ||
1205 | static struct target_type origin_target = { | 1205 | static 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 | ||
1216 | static struct target_type snapshot_target = { | 1216 | static 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, |