diff options
author | Mark McLoughlin <markmc@redhat.com> | 2006-10-03 04:15:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-03 11:04:14 -0400 |
commit | 4c7e3bf44d0ae227ea1ee87c2197212e65d043d7 (patch) | |
tree | 658140b966d78f4709de10cd03e0bfdade6bc13e /drivers/md/dm-exception-store.c | |
parent | 92c060a692a0c3482cdfcaf346cb2f7572368895 (diff) |
[PATCH] dm snapshot: allow zero chunk_size
The chunk size of snapshots cannot be changed so it is redundant to require it
as a parameter when activating an existing snapshot. Allow a value of zero in
this case and ignore it. For a new snapshot, use a default value if zero is
specified.
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md/dm-exception-store.c')
-rw-r--r-- | drivers/md/dm-exception-store.c | 124 |
1 files changed, 69 insertions, 55 deletions
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index d12379b5cdb5..8b4cd02f75a8 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | 18 | ||
19 | #define DM_MSG_PREFIX "snapshots" | 19 | #define DM_MSG_PREFIX "snapshots" |
20 | #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */ | ||
20 | 21 | ||
21 | /*----------------------------------------------------------------- | 22 | /*----------------------------------------------------------------- |
22 | * Persistent snapshots, by persistent we mean that the snapshot | 23 | * Persistent snapshots, by persistent we mean that the snapshot |
@@ -150,6 +151,7 @@ static int alloc_area(struct pstore *ps) | |||
150 | static void free_area(struct pstore *ps) | 151 | static void free_area(struct pstore *ps) |
151 | { | 152 | { |
152 | vfree(ps->area); | 153 | vfree(ps->area); |
154 | ps->area = NULL; | ||
153 | } | 155 | } |
154 | 156 | ||
155 | /* | 157 | /* |
@@ -198,48 +200,79 @@ static int read_header(struct pstore *ps, int *new_snapshot) | |||
198 | int r; | 200 | int r; |
199 | struct disk_header *dh; | 201 | struct disk_header *dh; |
200 | chunk_t chunk_size; | 202 | chunk_t chunk_size; |
203 | int chunk_size_supplied = 1; | ||
201 | 204 | ||
202 | r = chunk_io(ps, 0, READ); | 205 | /* |
206 | * Use default chunk size (or hardsect_size, if larger) if none supplied | ||
207 | */ | ||
208 | if (!ps->snap->chunk_size) { | ||
209 | ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS, | ||
210 | bdev_hardsect_size(ps->snap->cow->bdev) >> 9); | ||
211 | ps->snap->chunk_mask = ps->snap->chunk_size - 1; | ||
212 | ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1; | ||
213 | chunk_size_supplied = 0; | ||
214 | } | ||
215 | |||
216 | r = dm_io_get(sectors_to_pages(ps->snap->chunk_size)); | ||
203 | if (r) | 217 | if (r) |
204 | return r; | 218 | return r; |
205 | 219 | ||
220 | r = alloc_area(ps); | ||
221 | if (r) | ||
222 | goto bad1; | ||
223 | |||
224 | r = chunk_io(ps, 0, READ); | ||
225 | if (r) | ||
226 | goto bad2; | ||
227 | |||
206 | dh = (struct disk_header *) ps->area; | 228 | dh = (struct disk_header *) ps->area; |
207 | 229 | ||
208 | if (le32_to_cpu(dh->magic) == 0) { | 230 | if (le32_to_cpu(dh->magic) == 0) { |
209 | *new_snapshot = 1; | 231 | *new_snapshot = 1; |
232 | return 0; | ||
233 | } | ||
210 | 234 | ||
211 | } else if (le32_to_cpu(dh->magic) == SNAP_MAGIC) { | 235 | if (le32_to_cpu(dh->magic) != SNAP_MAGIC) { |
212 | *new_snapshot = 0; | 236 | DMWARN("Invalid or corrupt snapshot"); |
213 | ps->valid = le32_to_cpu(dh->valid); | ||
214 | ps->version = le32_to_cpu(dh->version); | ||
215 | chunk_size = le32_to_cpu(dh->chunk_size); | ||
216 | if (ps->snap->chunk_size != chunk_size) { | ||
217 | DMWARN("chunk size %llu in device metadata overrides " | ||
218 | "table chunk size of %llu.", | ||
219 | (unsigned long long)chunk_size, | ||
220 | (unsigned long long)ps->snap->chunk_size); | ||
221 | |||
222 | /* We had a bogus chunk_size. Fix stuff up. */ | ||
223 | dm_io_put(sectors_to_pages(ps->snap->chunk_size)); | ||
224 | free_area(ps); | ||
225 | |||
226 | ps->snap->chunk_size = chunk_size; | ||
227 | ps->snap->chunk_mask = chunk_size - 1; | ||
228 | ps->snap->chunk_shift = ffs(chunk_size) - 1; | ||
229 | |||
230 | r = alloc_area(ps); | ||
231 | if (r) | ||
232 | return r; | ||
233 | |||
234 | r = dm_io_get(sectors_to_pages(chunk_size)); | ||
235 | if (r) | ||
236 | return r; | ||
237 | } | ||
238 | } else { | ||
239 | DMWARN("Invalid/corrupt snapshot"); | ||
240 | r = -ENXIO; | 237 | r = -ENXIO; |
238 | goto bad2; | ||
241 | } | 239 | } |
242 | 240 | ||
241 | *new_snapshot = 0; | ||
242 | ps->valid = le32_to_cpu(dh->valid); | ||
243 | ps->version = le32_to_cpu(dh->version); | ||
244 | chunk_size = le32_to_cpu(dh->chunk_size); | ||
245 | |||
246 | if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size) | ||
247 | return 0; | ||
248 | |||
249 | DMWARN("chunk size %llu in device metadata overrides " | ||
250 | "table chunk size of %llu.", | ||
251 | (unsigned long long)chunk_size, | ||
252 | (unsigned long long)ps->snap->chunk_size); | ||
253 | |||
254 | /* We had a bogus chunk_size. Fix stuff up. */ | ||
255 | dm_io_put(sectors_to_pages(ps->snap->chunk_size)); | ||
256 | free_area(ps); | ||
257 | |||
258 | ps->snap->chunk_size = chunk_size; | ||
259 | ps->snap->chunk_mask = chunk_size - 1; | ||
260 | ps->snap->chunk_shift = ffs(chunk_size) - 1; | ||
261 | |||
262 | r = dm_io_get(sectors_to_pages(chunk_size)); | ||
263 | if (r) | ||
264 | return r; | ||
265 | |||
266 | r = alloc_area(ps); | ||
267 | if (r) | ||
268 | goto bad1; | ||
269 | |||
270 | return 0; | ||
271 | |||
272 | bad2: | ||
273 | free_area(ps); | ||
274 | bad1: | ||
275 | dm_io_put(sectors_to_pages(ps->snap->chunk_size)); | ||
243 | return r; | 276 | return r; |
244 | } | 277 | } |
245 | 278 | ||
@@ -547,32 +580,22 @@ static void persistent_drop(struct exception_store *store) | |||
547 | DMWARN("write header failed"); | 580 | DMWARN("write header failed"); |
548 | } | 581 | } |
549 | 582 | ||
550 | int dm_create_persistent(struct exception_store *store, uint32_t chunk_size) | 583 | int dm_create_persistent(struct exception_store *store) |
551 | { | 584 | { |
552 | int r; | ||
553 | struct pstore *ps; | 585 | struct pstore *ps; |
554 | 586 | ||
555 | r = dm_io_get(sectors_to_pages(chunk_size)); | ||
556 | if (r) | ||
557 | return r; | ||
558 | |||
559 | /* allocate the pstore */ | 587 | /* allocate the pstore */ |
560 | ps = kmalloc(sizeof(*ps), GFP_KERNEL); | 588 | ps = kmalloc(sizeof(*ps), GFP_KERNEL); |
561 | if (!ps) { | 589 | if (!ps) |
562 | r = -ENOMEM; | 590 | return -ENOMEM; |
563 | goto bad; | ||
564 | } | ||
565 | 591 | ||
566 | ps->snap = store->snap; | 592 | ps->snap = store->snap; |
567 | ps->valid = 1; | 593 | ps->valid = 1; |
568 | ps->version = SNAPSHOT_DISK_VERSION; | 594 | ps->version = SNAPSHOT_DISK_VERSION; |
595 | ps->area = NULL; | ||
569 | ps->next_free = 2; /* skipping the header and first area */ | 596 | ps->next_free = 2; /* skipping the header and first area */ |
570 | ps->current_committed = 0; | 597 | ps->current_committed = 0; |
571 | 598 | ||
572 | r = alloc_area(ps); | ||
573 | if (r) | ||
574 | goto bad; | ||
575 | |||
576 | ps->callback_count = 0; | 599 | ps->callback_count = 0; |
577 | atomic_set(&ps->pending_count, 0); | 600 | atomic_set(&ps->pending_count, 0); |
578 | ps->callbacks = NULL; | 601 | ps->callbacks = NULL; |
@@ -586,13 +609,6 @@ int dm_create_persistent(struct exception_store *store, uint32_t chunk_size) | |||
586 | store->context = ps; | 609 | store->context = ps; |
587 | 610 | ||
588 | return 0; | 611 | return 0; |
589 | |||
590 | bad: | ||
591 | dm_io_put(sectors_to_pages(chunk_size)); | ||
592 | if (ps && ps->area) | ||
593 | free_area(ps); | ||
594 | kfree(ps); | ||
595 | return r; | ||
596 | } | 612 | } |
597 | 613 | ||
598 | /*----------------------------------------------------------------- | 614 | /*----------------------------------------------------------------- |
@@ -642,18 +658,16 @@ static void transient_fraction_full(struct exception_store *store, | |||
642 | *denominator = get_dev_size(store->snap->cow->bdev); | 658 | *denominator = get_dev_size(store->snap->cow->bdev); |
643 | } | 659 | } |
644 | 660 | ||
645 | int dm_create_transient(struct exception_store *store, | 661 | int dm_create_transient(struct exception_store *store) |
646 | struct dm_snapshot *s, int blocksize) | ||
647 | { | 662 | { |
648 | struct transient_c *tc; | 663 | struct transient_c *tc; |
649 | 664 | ||
650 | memset(store, 0, sizeof(*store)); | ||
651 | store->destroy = transient_destroy; | 665 | store->destroy = transient_destroy; |
652 | store->read_metadata = transient_read_metadata; | 666 | store->read_metadata = transient_read_metadata; |
653 | store->prepare_exception = transient_prepare; | 667 | store->prepare_exception = transient_prepare; |
654 | store->commit_exception = transient_commit; | 668 | store->commit_exception = transient_commit; |
669 | store->drop_snapshot = NULL; | ||
655 | store->fraction_full = transient_fraction_full; | 670 | store->fraction_full = transient_fraction_full; |
656 | store->snap = s; | ||
657 | 671 | ||
658 | tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL); | 672 | tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL); |
659 | if (!tc) | 673 | if (!tc) |