From: Mike Snitzer <[email-masked]>

Conditionally adjust snapshot usage accounting if snapshot-merge is in
progress.  Care is taken to preserve the established kernel<->userspace
interface.

Signed-off-by: Mike Snitzer <[email-masked]>
Cc: Mikulas Patocka <[email-masked]>

---
 drivers/md/dm-snap-persistent.c |   19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

Index: linux-2.6.32/drivers/md/dm-snap-persistent.c
===================================================================
--- linux-2.6.32.orig/drivers/md/dm-snap-persistent.c
+++ linux-2.6.32/drivers/md/dm-snap-persistent.c
@@ -93,6 +93,7 @@ struct pstore {
 	struct dm_exception_store *store;
 	int version;
 	int valid;
+	int merging;	/* 1 if there is merging going on */
 	uint32_t exceptions_per_area;
 
 	/*
@@ -523,7 +524,20 @@ static void persistent_usage(struct dm_e
 {
 	struct pstore *ps = get_info(store);
 
-	*sectors_allocated = ps->next_free * store->chunk_size;
+	/*
+	 * Must maintain the fact that DM reports all metadata chunks
+	 * in 'sectors_allocated'
+	 * - preserves the established kernel<->userspace interface
+	 * - snapshot-merge must account for the first two metadata
+	 *   chunks in its 'sectors_allocated'
+	 */
+	if (ps->merging)
+		*sectors_allocated =
+		    (area_location(ps, ps->current_area) - 1 +
+		     ps->current_committed + 2) * store->chunk_size;
+	else
+		*sectors_allocated = ps->next_free * store->chunk_size;
+
 	*total_sectors = get_dev_size(dm_snap_cow(store->snap)->bdev);
 
 	/*
@@ -716,6 +730,8 @@ static int persistent_prepare_merge(stru
 	int nr_consecutive;
 	int r;
 
+	ps->merging = 1;
+
 	/*
 	 * When current area is empty, move back to preceding area.
 	 */
@@ -807,6 +823,7 @@ static int persistent_ctr(struct dm_exce
 
 	ps->store = store;
 	ps->valid = 1;
+	ps->merging = 0;
 	ps->version = SNAPSHOT_DISK_VERSION;
 	ps->area = NULL;
 	ps->zero_area = NULL;