+++ /dev/null
-From jejb@kernel.org Thu Oct 23 13:10:46 2008
-From: Mikulas Patocka <mpatocka@redhat.com>
-Date: Thu, 23 Oct 2008 17:35:17 GMT
-Subject: dm exception store: fix misordered writes
-To: jejb@kernel.org, stable@kernel.org
-Message-ID: <200810231735.m9NHZHnu008554@hera.kernel.org>
-
-From: Mikulas Patocka <mpatocka@redhat.com>
-
-commit 7acedc5b98a2fcff64f00c21110aae7d3ac2f7df upstream
-
-We must zero the next chunk on disk *before* writing out the current chunk, not
-after. Otherwise if the machine crashes at the wrong time, the "end of metadata"
-marker may be missing.
-
-Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
-Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- drivers/md/dm-exception-store.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
---- a/drivers/md/dm-exception-store.c
-+++ b/drivers/md/dm-exception-store.c
-@@ -603,17 +603,22 @@ static void persistent_commit(struct exc
- return;
-
- /*
-+ * If we completely filled the current area, then wipe the next one.
-+ */
-+ if ((ps->current_committed == ps->exceptions_per_area) &&
-+ zero_disk_area(ps, ps->current_area + 1))
-+ ps->valid = 0;
-+
-+ /*
- * Commit exceptions to disk.
- */
-- if (area_io(ps, WRITE))
-+ if (ps->valid && area_io(ps, WRITE))
- ps->valid = 0;
-
- /*
- * Advance to the next area if this one is full.
- */
- if (ps->current_committed == ps->exceptions_per_area) {
-- if (zero_disk_area(ps, ps->current_area + 1))
-- ps->valid = 0;
- ps->current_committed = 0;
- ps->current_area++;
- zero_memory_area(ps);
+++ /dev/null
-From jejb@kernel.org Thu Oct 23 13:05:28 2008
-From: Alasdair G Kergon <agk@redhat.com>
-Date: Thu, 23 Oct 2008 17:35:19 GMT
-Subject: dm exception store: refactor zero_area
-To: jejb@kernel.org, stable@kernel.org
-Message-ID: <200810231735.m9NHZJcS008600@hera.kernel.org>
-
-From: Alasdair G Kergon <agk@redhat.com>
-
-commit 7c9e6c17325fab380fbe9c9787680ff7d4a51abd upstream
-
-Use a separate buffer for writing zeroes to the on-disk snapshot
-exception store, make the updating of ps->current_area explicit and
-refactor the code in preparation for the fix in the next patch.
-
-No functional change.
-
-Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- drivers/md/dm-exception-store.c | 103 ++++++++++++++++++++++++++--------------
- 1 file changed, 69 insertions(+), 34 deletions(-)
-
---- a/drivers/md/dm-exception-store.c
-+++ b/drivers/md/dm-exception-store.c
-@@ -105,6 +105,11 @@ struct pstore {
- void *area;
-
- /*
-+ * An area of zeros used to clear the next area.
-+ */
-+ void *zero_area;
-+
-+ /*
- * Used to keep track of which metadata area the data in
- * 'chunk' refers to.
- */
-@@ -149,6 +154,13 @@ static int alloc_area(struct pstore *ps)
- if (!ps->area)
- return r;
-
-+ ps->zero_area = vmalloc(len);
-+ if (!ps->zero_area) {
-+ vfree(ps->area);
-+ return r;
-+ }
-+ memset(ps->zero_area, 0, len);
-+
- return 0;
- }
-
-@@ -156,6 +168,8 @@ static void free_area(struct pstore *ps)
- {
- vfree(ps->area);
- ps->area = NULL;
-+ vfree(ps->zero_area);
-+ ps->zero_area = NULL;
- }
-
- struct mdata_req {
-@@ -212,13 +226,13 @@ static int chunk_io(struct pstore *ps, u
- * Read or write a metadata area. Remembering to skip the first
- * chunk which holds the header.
- */
--static int area_io(struct pstore *ps, uint32_t area, int rw)
-+static int area_io(struct pstore *ps, int rw)
- {
- int r;
- uint32_t chunk;
-
- /* convert a metadata area index to a chunk index */
-- chunk = 1 + ((ps->exceptions_per_area + 1) * area);
-+ chunk = area_location(ps, ps->current_area);
-
- r = chunk_io(ps, chunk, rw, 0);
- if (r)
-@@ -228,10 +242,27 @@ static int area_io(struct pstore *ps, ui
- return 0;
- }
-
--static int zero_area(struct pstore *ps, uint32_t area)
-+static void zero_memory_area(struct pstore *ps)
- {
- memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
-- return area_io(ps, area, WRITE);
-+}
-+
-+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 = ps->snap->chunk_size,
-+ };
-+ struct dm_io_request io_req = {
-+ .bi_rw = WRITE,
-+ .mem.type = DM_IO_VMA,
-+ .mem.ptr.vma = ps->zero_area,
-+ .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)
-@@ -404,15 +435,14 @@ static int insert_exceptions(struct psto
-
- static int read_exceptions(struct pstore *ps)
- {
-- uint32_t area;
- int r, full = 1;
-
- /*
- * Keeping reading chunks and inserting exceptions until
- * we find a partially full area.
- */
-- for (area = 0; full; area++) {
-- r = area_io(ps, area, READ);
-+ for (ps->current_area = 0; full; ps->current_area++) {
-+ r = area_io(ps, READ);
- if (r)
- return r;
-
-@@ -421,6 +451,8 @@ static int read_exceptions(struct pstore
- return r;
- }
-
-+ ps->current_area--;
-+
- return 0;
- }
-
-@@ -479,12 +511,13 @@ static int persistent_read_metadata(stru
- return r;
- }
-
-- r = zero_area(ps, 0);
-+ ps->current_area = 0;
-+ zero_memory_area(ps);
-+ r = zero_disk_area(ps, 0);
- if (r) {
-- DMWARN("zero_area(0) failed");
-+ DMWARN("zero_disk_area(0) failed");
- return r;
- }
--
- } else {
- /*
- * Sanity checks.
-@@ -542,7 +575,6 @@ static void persistent_commit(struct exc
- void (*callback) (void *, int success),
- void *callback_context)
- {
-- int r;
- unsigned int i;
- struct pstore *ps = get_info(store);
- struct disk_exception de;
-@@ -563,33 +595,36 @@ static void persistent_commit(struct exc
- cb->context = callback_context;
-
- /*
-- * If there are no more exceptions in flight, or we have
-- * filled this metadata area we commit the exceptions to
-- * disk.
-- */
-- if (atomic_dec_and_test(&ps->pending_count) ||
-- (ps->current_committed == ps->exceptions_per_area)) {
-- r = area_io(ps, ps->current_area, WRITE);
-- if (r)
-- ps->valid = 0;
-+ * If there are exceptions in flight and we have not yet
-+ * filled this metadata area there's nothing more to do.
-+ */
-+ if (!atomic_dec_and_test(&ps->pending_count) &&
-+ (ps->current_committed != ps->exceptions_per_area))
-+ return;
-
-- /*
-- * 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;
-- }
-+ /*
-+ * Commit exceptions to disk.
-+ */
-+ if (area_io(ps, WRITE))
-+ ps->valid = 0;
-
-- for (i = 0; i < ps->callback_count; i++) {
-- cb = ps->callbacks + i;
-- cb->callback(cb->context, r == 0 ? 1 : 0);
-- }
-+ /*
-+ * Advance to the next area if this one is full.
-+ */
-+ if (ps->current_committed == ps->exceptions_per_area) {
-+ if (zero_disk_area(ps, ps->current_area + 1))
-+ ps->valid = 0;
-+ ps->current_committed = 0;
-+ ps->current_area++;
-+ zero_memory_area(ps);
-+ }
-
-- ps->callback_count = 0;
-+ for (i = 0; i < ps->callback_count; i++) {
-+ cb = ps->callbacks + i;
-+ cb->callback(cb->context, ps->valid);
- }
-+
-+ ps->callback_count = 0;
- }
-
- static void persistent_drop(struct exception_store *store)