From: Mikulas Patocka We must first zero next chunk and then write current chunk. For the purpose of zeroeing, allocate additional bdev_hardsect_size bytes. These bytes will be always zero, they'll be written to the next chunk area. We don't need to clear the whole chunk, just one sector is enough (loading of exceptions stops after seeing the first zero ... it doesn't matter that the rest of the chunk is not cleared). Signed-off-by: Mikulas Patocka Index: linux/drivers/md/dm-exception-store.c =================================================================== --- linux.orig/drivers/md/dm-exception-store.c 2008-07-22 22:01:05.000000000 +0100 +++ linux/drivers/md/dm-exception-store.c 2008-07-22 22:02:17.000000000 +0100 @@ -139,7 +139,12 @@ static int alloc_area(struct pstore *ps) int r = -ENOMEM; size_t len; - len = ps->snap->chunk_size << SECTOR_SHIFT; + /* + * bdev_hardsect_size bytes is always zero and is used to clear + * areas with chunk pointers. + */ + len = (ps->snap->chunk_size << SECTOR_SHIFT) + + bdev_hardsect_size(ps->snap->cow->bdev); /* * Allocate the chunk_size block of memory that will hold @@ -149,6 +154,8 @@ static int alloc_area(struct pstore *ps) if (!ps->area) return r; + memset(ps->area, 0, len); + return 0; } @@ -235,10 +242,28 @@ static int area_io(struct pstore *ps, ch return 0; } -static int zero_area(struct pstore *ps, chunk_t area) +static void zero_memory_area(struct pstore *ps, chunk_t area) { memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); - return area_io(ps, area, WRITE); + ps->current_area = area; +} + +static int zero_disk_area(struct pstore *ps, chunk_t area) +{ + struct dm_io_region where = { + .bdev = ps->snap->cow->bdev, + .sector = ps->snap->chunk_size * area_location(ps, area), + .count = bdev_hardsect_size(ps->snap->cow->bdev) >> SECTOR_SHIFT, + }; + struct dm_io_request io_req = { + .bi_rw = WRITE, + .mem.type = DM_IO_VMA, + .mem.ptr.vma = (char *)ps->area + + (ps->snap->chunk_size << SECTOR_SHIFT), + .client = ps->io_client, + .notify.fn = NULL, + }; + return dm_io(&io_req, 1, &where, NULL); } static int read_header(struct pstore *ps, int *new_snapshot) @@ -486,7 +511,8 @@ static int persistent_read_metadata(stru return r; } - r = zero_area(ps, 0); + zero_memory_area(ps, 0); + r = zero_disk_area(ps, 0); if (r) { DMWARN("zero_area(0) failed"); return r; @@ -576,18 +602,25 @@ static void persistent_commit(struct exc */ if (atomic_dec_and_test(&ps->pending_count) || (ps->current_committed == ps->exceptions_per_area)) { + if (ps->current_committed == ps->exceptions_per_area) { + r = zero_disk_area(ps, ps->current_area + 1); + if (r) { + ps->valid = 0; + goto skip_area_io; + } + } + r = area_io(ps, ps->current_area, WRITE); if (r) ps->valid = 0; +skip_area_io: /* * Have we completely filled the current area ? */ if (ps->current_committed == ps->exceptions_per_area) { ps->current_committed = 0; - r = zero_area(ps, ps->current_area + 1); - if (r) - ps->valid = 0; + zero_memory_area(ps, ps->current_area + 1); } for (i = 0; i < ps->callback_count; i++) {