Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm space maps: don't reset space map allocation cursor when committing

Current commit code resets the place where the search for free blocks
will begin back to the start of the metadata device. There are a couple
of repercussions to this:

- The first allocation after the commit is likely to take longer than
normal as it searches for a free block in an area that is likely to
have very few free blocks (if any).

- Any free blocks it finds will have been recently freed. Reusing them
means we have fewer old copies of the metadata to aid recovery from
hardware error.

Fix these issues by leaving the cursor alone, only resetting when the
search hits the end of the metadata device.

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>

authored by

Joe Thornber and committed by
Mike Snitzer
5faafc77 4eafdb15

+16 -2
+8 -1
drivers/md/persistent-data/dm-space-map-disk.c
··· 171 171 * Any block we allocate has to be free in both the old and current ll. 172 172 */ 173 173 r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b); 174 + if (r == -ENOSPC) { 175 + /* 176 + * There's no free block between smd->begin and the end of the metadata device. 177 + * We search before smd->begin in case something has been freed. 178 + */ 179 + r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, 0, smd->begin, b); 180 + } 181 + 174 182 if (r) 175 183 return r; 176 184 ··· 202 194 return r; 203 195 204 196 memcpy(&smd->old_ll, &smd->ll, sizeof(smd->old_ll)); 205 - smd->begin = 0; 206 197 smd->nr_allocated_this_transaction = 0; 207 198 208 199 return 0;
+8 -1
drivers/md/persistent-data/dm-space-map-metadata.c
··· 452 452 * Any block we allocate has to be free in both the old and current ll. 453 453 */ 454 454 r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b); 455 + if (r == -ENOSPC) { 456 + /* 457 + * There's no free block between smm->begin and the end of the metadata device. 458 + * We search before smm->begin in case something has been freed. 459 + */ 460 + r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, 0, smm->begin, b); 461 + } 462 + 455 463 if (r) 456 464 return r; 457 465 ··· 511 503 return r; 512 504 513 505 memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); 514 - smm->begin = 0; 515 506 smm->allocated_this_transaction = 0; 516 507 517 508 return 0;