aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-exception-store.c
diff options
context:
space:
mode:
authorMark McLoughlin <markmc@redhat.com>2006-10-03 04:15:25 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-03 11:04:14 -0400
commit4c7e3bf44d0ae227ea1ee87c2197212e65d043d7 (patch)
tree658140b966d78f4709de10cd03e0bfdade6bc13e /drivers/md/dm-exception-store.c
parent92c060a692a0c3482cdfcaf346cb2f7572368895 (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.c124
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)
150static void free_area(struct pstore *ps) 151static 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
272bad2:
273 free_area(ps);
274bad1:
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
550int dm_create_persistent(struct exception_store *store, uint32_t chunk_size) 583int 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
645int dm_create_transient(struct exception_store *store, 661int 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)