Make fraction_full() return a percentage of the amount of actual data the device can hold, rather than of the amount of data+metadata it can hold. Index: linux-2.6.16.i686/drivers/md/dm-exception-store.c =================================================================== --- linux-2.6.16.i686.orig/drivers/md/dm-exception-store.c 2006-04-14 12:53:12.000000000 -0400 +++ linux-2.6.16.i686/drivers/md/dm-exception-store.c 2006-04-14 13:21:25.000000000 -0400 @@ -397,11 +397,42 @@ static inline struct pstore *get_info(st return (struct pstore *) store->context; } +/* + * Calculate the number of chunks of data we can store in @n_chunks, + * given that each metadata area can store @exceptions_per_area + * exceptions. + */ +static inline uint32_t calc_n_data_chunks(uint32_t n_chunks, + uint32_t exceptions_per_area) +{ + uint32_t stride, full_areas, leftovers; + + /* we can't use the header */ + if (--n_chunks <= 0) + return 0; + + stride = exceptions_per_area + 1; + + /* how many metadata areas would we completely fill? */ + full_areas = n_chunks / stride; + + /* how many chunks could we fit after the full areas? */ + if ((leftovers = (n_chunks % stride) - 1) < 0) + leftovers = 0; + + return (full_areas * exceptions_per_area) + leftovers; +} + static void persistent_fraction_full(struct exception_store *store, sector_t *numerator, sector_t *denominator) { - *numerator = get_info(store)->next_free * store->snap->chunk_size; - *denominator = get_dev_size(store->snap->cow->bdev); + struct pstore *ps = get_info(store); + uint32_t n_chunks; + + n_chunks = get_dev_size(ps->snap->cow->bdev) >> ps->snap->chunk_shift; + + *numerator = calc_n_data_chunks (ps->next_free, ps->exceptions_per_area); + *denominator = calc_n_data_chunks (n_chunks, ps->exceptions_per_area); } static void persistent_destroy(struct exception_store *store)