Deleted Added
full compact
activemap.c (223654) activemap.c (225787)
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 14 unchanged lines hidden (view full) ---

23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 14 unchanged lines hidden (view full) ---

23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sbin/hastd/activemap.c 223654 2011-06-28 20:57:54Z trociny $");
31__FBSDID("$FreeBSD: head/sbin/hastd/activemap.c 225787 2011-09-27 08:50:37Z pjd $");
32
33#include <sys/param.h> /* powerof2() */
34#include <sys/queue.h>
35
32
33#include <sys/param.h> /* powerof2() */
34#include <sys/queue.h>
35
36#include <assert.h>
37#include <bitstring.h>
38#include <errno.h>
39#include <stdint.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43
36#include <bitstring.h>
37#include <errno.h>
38#include <stdint.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
44#include <activemap.h>
43#include <pjdlog.h>
45
44
45#include "activemap.h"
46
47#ifndef PJDLOG_ASSERT
48#include <assert.h>
49#define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
50#endif
51
46#define ACTIVEMAP_MAGIC 0xac71e4
47struct activemap {
48 int am_magic; /* Magic value. */
49 off_t am_mediasize; /* Media size in bytes. */
50 uint32_t am_extentsize; /* Extent size in bytes,
51 must be power of 2. */
52 uint8_t am_extentshift;/* 2 ^ extentbits == extentsize */
53 int am_nextents; /* Number of extents. */

--- 34 unchanged lines hidden (view full) ---

88 return (x);
89}
90
91static __inline int
92off2ext(const struct activemap *amp, off_t offset)
93{
94 int extent;
95
52#define ACTIVEMAP_MAGIC 0xac71e4
53struct activemap {
54 int am_magic; /* Magic value. */
55 off_t am_mediasize; /* Media size in bytes. */
56 uint32_t am_extentsize; /* Extent size in bytes,
57 must be power of 2. */
58 uint8_t am_extentshift;/* 2 ^ extentbits == extentsize */
59 int am_nextents; /* Number of extents. */

--- 34 unchanged lines hidden (view full) ---

94 return (x);
95}
96
97static __inline int
98off2ext(const struct activemap *amp, off_t offset)
99{
100 int extent;
101
96 assert(offset >= 0 && offset < amp->am_mediasize);
102 PJDLOG_ASSERT(offset >= 0 && offset < amp->am_mediasize);
97 extent = (offset >> amp->am_extentshift);
103 extent = (offset >> amp->am_extentshift);
98 assert(extent >= 0 && extent < amp->am_nextents);
104 PJDLOG_ASSERT(extent >= 0 && extent < amp->am_nextents);
99 return (extent);
100}
101
102static __inline off_t
103ext2off(const struct activemap *amp, int extent)
104{
105 off_t offset;
106
105 return (extent);
106}
107
108static __inline off_t
109ext2off(const struct activemap *amp, int extent)
110{
111 off_t offset;
112
107 assert(extent >= 0 && extent < amp->am_nextents);
113 PJDLOG_ASSERT(extent >= 0 && extent < amp->am_nextents);
108 offset = ((off_t)extent << amp->am_extentshift);
114 offset = ((off_t)extent << amp->am_extentshift);
109 assert(offset >= 0 && offset < amp->am_mediasize);
115 PJDLOG_ASSERT(offset >= 0 && offset < amp->am_mediasize);
110 return (offset);
111}
112
113/*
114 * Function calculates number of requests needed to synchronize the given
115 * extent.
116 */
117static __inline int
118ext2reqs(const struct activemap *amp, int ext)
119{
120 off_t left;
121
122 if (ext < amp->am_nextents - 1)
123 return (((amp->am_extentsize - 1) / MAXPHYS) + 1);
124
116 return (offset);
117}
118
119/*
120 * Function calculates number of requests needed to synchronize the given
121 * extent.
122 */
123static __inline int
124ext2reqs(const struct activemap *amp, int ext)
125{
126 off_t left;
127
128 if (ext < amp->am_nextents - 1)
129 return (((amp->am_extentsize - 1) / MAXPHYS) + 1);
130
125 assert(ext == amp->am_nextents - 1);
131 PJDLOG_ASSERT(ext == amp->am_nextents - 1);
126 left = amp->am_mediasize % amp->am_extentsize;
127 if (left == 0)
128 left = amp->am_extentsize;
129 return (((left - 1) / MAXPHYS) + 1);
130}
131
132/*
133 * Initialize activemap structure and allocate memory for internal needs.
134 * Function returns 0 on success and -1 if any of the allocations failed.
135 */
136int
137activemap_init(struct activemap **ampp, uint64_t mediasize, uint32_t extentsize,
138 uint32_t sectorsize, uint32_t keepdirty)
139{
140 struct activemap *amp;
141
132 left = amp->am_mediasize % amp->am_extentsize;
133 if (left == 0)
134 left = amp->am_extentsize;
135 return (((left - 1) / MAXPHYS) + 1);
136}
137
138/*
139 * Initialize activemap structure and allocate memory for internal needs.
140 * Function returns 0 on success and -1 if any of the allocations failed.
141 */
142int
143activemap_init(struct activemap **ampp, uint64_t mediasize, uint32_t extentsize,
144 uint32_t sectorsize, uint32_t keepdirty)
145{
146 struct activemap *amp;
147
142 assert(ampp != NULL);
143 assert(mediasize > 0);
144 assert(extentsize > 0);
145 assert(powerof2(extentsize));
146 assert(sectorsize > 0);
147 assert(powerof2(sectorsize));
148 assert(keepdirty > 0);
148 PJDLOG_ASSERT(ampp != NULL);
149 PJDLOG_ASSERT(mediasize > 0);
150 PJDLOG_ASSERT(extentsize > 0);
151 PJDLOG_ASSERT(powerof2(extentsize));
152 PJDLOG_ASSERT(sectorsize > 0);
153 PJDLOG_ASSERT(powerof2(sectorsize));
154 PJDLOG_ASSERT(keepdirty > 0);
149
150 amp = malloc(sizeof(*amp));
151 if (amp == NULL)
152 return (-1);
153
154 amp->am_mediasize = mediasize;
155 amp->am_nkeepdirty_limit = keepdirty;
156 amp->am_extentsize = extentsize;

--- 63 unchanged lines hidden (view full) ---

220 return (false);
221 }
222 /*
223 * Add new element, but first remove the most unused one if
224 * we have too many.
225 */
226 if (amp->am_nkeepdirty >= amp->am_nkeepdirty_limit) {
227 kd = TAILQ_LAST(&amp->am_keepdirty, skeepdirty);
155
156 amp = malloc(sizeof(*amp));
157 if (amp == NULL)
158 return (-1);
159
160 amp->am_mediasize = mediasize;
161 amp->am_nkeepdirty_limit = keepdirty;
162 amp->am_extentsize = extentsize;

--- 63 unchanged lines hidden (view full) ---

226 return (false);
227 }
228 /*
229 * Add new element, but first remove the most unused one if
230 * we have too many.
231 */
232 if (amp->am_nkeepdirty >= amp->am_nkeepdirty_limit) {
233 kd = TAILQ_LAST(&amp->am_keepdirty, skeepdirty);
228 assert(kd != NULL);
234 PJDLOG_ASSERT(kd != NULL);
229 TAILQ_REMOVE(&amp->am_keepdirty, kd, kd_next);
230 amp->am_nkeepdirty--;
235 TAILQ_REMOVE(&amp->am_keepdirty, kd, kd_next);
236 amp->am_nkeepdirty--;
231 assert(amp->am_nkeepdirty > 0);
237 PJDLOG_ASSERT(amp->am_nkeepdirty > 0);
232 }
233 if (kd == NULL)
234 kd = malloc(sizeof(*kd));
235 /* We can ignore allocation failure. */
236 if (kd != NULL) {
237 kd->kd_extent = extent;
238 amp->am_nkeepdirty++;
239 TAILQ_INSERT_HEAD(&amp->am_keepdirty, kd, kd_next);

--- 16 unchanged lines hidden (view full) ---

256{
257 struct keepdirty *kd;
258
259 while ((kd = TAILQ_FIRST(&amp->am_keepdirty)) != NULL) {
260 TAILQ_REMOVE(&amp->am_keepdirty, kd, kd_next);
261 amp->am_nkeepdirty--;
262 free(kd);
263 }
238 }
239 if (kd == NULL)
240 kd = malloc(sizeof(*kd));
241 /* We can ignore allocation failure. */
242 if (kd != NULL) {
243 kd->kd_extent = extent;
244 amp->am_nkeepdirty++;
245 TAILQ_INSERT_HEAD(&amp->am_keepdirty, kd, kd_next);

--- 16 unchanged lines hidden (view full) ---

262{
263 struct keepdirty *kd;
264
265 while ((kd = TAILQ_FIRST(&amp->am_keepdirty)) != NULL) {
266 TAILQ_REMOVE(&amp->am_keepdirty, kd, kd_next);
267 amp->am_nkeepdirty--;
268 free(kd);
269 }
264 assert(amp->am_nkeepdirty == 0);
270 PJDLOG_ASSERT(amp->am_nkeepdirty == 0);
265}
266
267/*
268 * Function frees resources allocated by activemap_init() function.
269 */
270void
271activemap_free(struct activemap *amp)
272{
273
271}
272
273/*
274 * Function frees resources allocated by activemap_init() function.
275 */
276void
277activemap_free(struct activemap *amp)
278{
279
274 assert(amp->am_magic == ACTIVEMAP_MAGIC);
280 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
275
276 amp->am_magic = 0;
277
278 keepdirty_free(amp);
279 free(amp->am_memtab);
280 free(amp->am_diskmap);
281 free(amp->am_memmap);
282 free(amp->am_syncmap);

--- 5 unchanged lines hidden (view full) ---

288 */
289bool
290activemap_write_start(struct activemap *amp, off_t offset, off_t length)
291{
292 bool modified;
293 off_t end;
294 int ext;
295
281
282 amp->am_magic = 0;
283
284 keepdirty_free(amp);
285 free(amp->am_memtab);
286 free(amp->am_diskmap);
287 free(amp->am_memmap);
288 free(amp->am_syncmap);

--- 5 unchanged lines hidden (view full) ---

294 */
295bool
296activemap_write_start(struct activemap *amp, off_t offset, off_t length)
297{
298 bool modified;
299 off_t end;
300 int ext;
301
296 assert(amp->am_magic == ACTIVEMAP_MAGIC);
297 assert(length > 0);
302 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
303 PJDLOG_ASSERT(length > 0);
298
299 modified = false;
300 end = offset + length - 1;
301
302 for (ext = off2ext(amp, offset); ext <= off2ext(amp, end); ext++) {
303 /*
304 * If the number of pending writes is increased from 0,
305 * we have to mark the extent as dirty also in on-disk bitmap.
306 * By returning true we inform the caller that on-disk bitmap
307 * was modified and has to be flushed to disk.
308 */
309 if (amp->am_memtab[ext]++ == 0) {
304
305 modified = false;
306 end = offset + length - 1;
307
308 for (ext = off2ext(amp, offset); ext <= off2ext(amp, end); ext++) {
309 /*
310 * If the number of pending writes is increased from 0,
311 * we have to mark the extent as dirty also in on-disk bitmap.
312 * By returning true we inform the caller that on-disk bitmap
313 * was modified and has to be flushed to disk.
314 */
315 if (amp->am_memtab[ext]++ == 0) {
310 assert(!bit_test(amp->am_memmap, ext));
316 PJDLOG_ASSERT(!bit_test(amp->am_memmap, ext));
311 bit_set(amp->am_memmap, ext);
312 amp->am_ndirty++;
313 }
314 if (keepdirty_add(amp, ext))
315 modified = true;
316 }
317
318 return (modified);

--- 5 unchanged lines hidden (view full) ---

324 */
325bool
326activemap_write_complete(struct activemap *amp, off_t offset, off_t length)
327{
328 bool modified;
329 off_t end;
330 int ext;
331
317 bit_set(amp->am_memmap, ext);
318 amp->am_ndirty++;
319 }
320 if (keepdirty_add(amp, ext))
321 modified = true;
322 }
323
324 return (modified);

--- 5 unchanged lines hidden (view full) ---

330 */
331bool
332activemap_write_complete(struct activemap *amp, off_t offset, off_t length)
333{
334 bool modified;
335 off_t end;
336 int ext;
337
332 assert(amp->am_magic == ACTIVEMAP_MAGIC);
333 assert(length > 0);
338 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
339 PJDLOG_ASSERT(length > 0);
334
335 modified = false;
336 end = offset + length - 1;
337
338 for (ext = off2ext(amp, offset); ext <= off2ext(amp, end); ext++) {
339 /*
340 * If the number of pending writes goes down to 0, we have to
341 * mark the extent as clean also in on-disk bitmap.
342 * By returning true we inform the caller that on-disk bitmap
343 * was modified and has to be flushed to disk.
344 */
340
341 modified = false;
342 end = offset + length - 1;
343
344 for (ext = off2ext(amp, offset); ext <= off2ext(amp, end); ext++) {
345 /*
346 * If the number of pending writes goes down to 0, we have to
347 * mark the extent as clean also in on-disk bitmap.
348 * By returning true we inform the caller that on-disk bitmap
349 * was modified and has to be flushed to disk.
350 */
345 assert(amp->am_memtab[ext] > 0);
346 assert(bit_test(amp->am_memmap, ext));
351 PJDLOG_ASSERT(amp->am_memtab[ext] > 0);
352 PJDLOG_ASSERT(bit_test(amp->am_memmap, ext));
347 if (--amp->am_memtab[ext] == 0) {
348 bit_clear(amp->am_memmap, ext);
349 amp->am_ndirty--;
350 if (keepdirty_find(amp, ext) == NULL)
351 modified = true;
352 }
353 }
354

--- 5 unchanged lines hidden (view full) ---

360 * It returns true if on-disk metadata should be updated.
361 */
362bool
363activemap_extent_complete(struct activemap *amp, int extent)
364{
365 bool modified;
366 int reqs;
367
353 if (--amp->am_memtab[ext] == 0) {
354 bit_clear(amp->am_memmap, ext);
355 amp->am_ndirty--;
356 if (keepdirty_find(amp, ext) == NULL)
357 modified = true;
358 }
359 }
360

--- 5 unchanged lines hidden (view full) ---

366 * It returns true if on-disk metadata should be updated.
367 */
368bool
369activemap_extent_complete(struct activemap *amp, int extent)
370{
371 bool modified;
372 int reqs;
373
368 assert(amp->am_magic == ACTIVEMAP_MAGIC);
369 assert(extent >= 0 && extent < amp->am_nextents);
374 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
375 PJDLOG_ASSERT(extent >= 0 && extent < amp->am_nextents);
370
371 modified = false;
372
373 reqs = ext2reqs(amp, extent);
376
377 modified = false;
378
379 reqs = ext2reqs(amp, extent);
374 assert(amp->am_memtab[extent] >= reqs);
380 PJDLOG_ASSERT(amp->am_memtab[extent] >= reqs);
375 amp->am_memtab[extent] -= reqs;
381 amp->am_memtab[extent] -= reqs;
376 assert(bit_test(amp->am_memmap, extent));
382 PJDLOG_ASSERT(bit_test(amp->am_memmap, extent));
377 if (amp->am_memtab[extent] == 0) {
378 bit_clear(amp->am_memmap, extent);
379 amp->am_ndirty--;
380 modified = true;
381 }
382
383 return (modified);
384}
385
386/*
387 * Function returns number of dirty regions.
388 */
389uint64_t
390activemap_ndirty(const struct activemap *amp)
391{
392
383 if (amp->am_memtab[extent] == 0) {
384 bit_clear(amp->am_memmap, extent);
385 amp->am_ndirty--;
386 modified = true;
387 }
388
389 return (modified);
390}
391
392/*
393 * Function returns number of dirty regions.
394 */
395uint64_t
396activemap_ndirty(const struct activemap *amp)
397{
398
393 assert(amp->am_magic == ACTIVEMAP_MAGIC);
399 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
394
395 return (amp->am_ndirty);
396}
397
398/*
399 * Function compare on-disk bitmap and in-memory bitmap and returns true if
400 * they differ and should be flushed to the disk.
401 */
402bool
403activemap_differ(const struct activemap *amp)
404{
405
400
401 return (amp->am_ndirty);
402}
403
404/*
405 * Function compare on-disk bitmap and in-memory bitmap and returns true if
406 * they differ and should be flushed to the disk.
407 */
408bool
409activemap_differ(const struct activemap *amp)
410{
411
406 assert(amp->am_magic == ACTIVEMAP_MAGIC);
412 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
407
408 return (memcmp(amp->am_diskmap, amp->am_memmap,
409 amp->am_mapsize) != 0);
410}
411
412/*
413 * Function returns number of bytes used by bitmap.
414 */
415size_t
416activemap_size(const struct activemap *amp)
417{
418
413
414 return (memcmp(amp->am_diskmap, amp->am_memmap,
415 amp->am_mapsize) != 0);
416}
417
418/*
419 * Function returns number of bytes used by bitmap.
420 */
421size_t
422activemap_size(const struct activemap *amp)
423{
424
419 assert(amp->am_magic == ACTIVEMAP_MAGIC);
425 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
420
421 return (amp->am_mapsize);
422}
423
424/*
425 * Function returns number of bytes needed for storing on-disk bitmap.
426 * This is the same as activemap_size(), but rounded up to sector size.
427 */
428size_t
429activemap_ondisk_size(const struct activemap *amp)
430{
431
426
427 return (amp->am_mapsize);
428}
429
430/*
431 * Function returns number of bytes needed for storing on-disk bitmap.
432 * This is the same as activemap_size(), but rounded up to sector size.
433 */
434size_t
435activemap_ondisk_size(const struct activemap *amp)
436{
437
432 assert(amp->am_magic == ACTIVEMAP_MAGIC);
438 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
433
434 return (amp->am_diskmapsize);
435}
436
437/*
438 * Function copies the given buffer read from disk to the internal bitmap.
439 */
440void
441activemap_copyin(struct activemap *amp, const unsigned char *buf, size_t size)
442{
443 int ext;
444
439
440 return (amp->am_diskmapsize);
441}
442
443/*
444 * Function copies the given buffer read from disk to the internal bitmap.
445 */
446void
447activemap_copyin(struct activemap *amp, const unsigned char *buf, size_t size)
448{
449 int ext;
450
445 assert(amp->am_magic == ACTIVEMAP_MAGIC);
446 assert(size >= amp->am_mapsize);
451 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
452 PJDLOG_ASSERT(size >= amp->am_mapsize);
447
448 memcpy(amp->am_diskmap, buf, amp->am_mapsize);
449 memcpy(amp->am_memmap, buf, amp->am_mapsize);
450 memcpy(amp->am_syncmap, buf, amp->am_mapsize);
451
452 bit_ffs(amp->am_memmap, amp->am_nextents, &ext);
453 if (ext == -1) {
454 /* There are no dirty extents, so we can leave now. */

--- 21 unchanged lines hidden (view full) ---

476 * Function merges the given bitmap with existing one.
477 */
478void
479activemap_merge(struct activemap *amp, const unsigned char *buf, size_t size)
480{
481 bitstr_t *remmap = __DECONST(bitstr_t *, buf);
482 int ext;
483
453
454 memcpy(amp->am_diskmap, buf, amp->am_mapsize);
455 memcpy(amp->am_memmap, buf, amp->am_mapsize);
456 memcpy(amp->am_syncmap, buf, amp->am_mapsize);
457
458 bit_ffs(amp->am_memmap, amp->am_nextents, &ext);
459 if (ext == -1) {
460 /* There are no dirty extents, so we can leave now. */

--- 21 unchanged lines hidden (view full) ---

482 * Function merges the given bitmap with existing one.
483 */
484void
485activemap_merge(struct activemap *amp, const unsigned char *buf, size_t size)
486{
487 bitstr_t *remmap = __DECONST(bitstr_t *, buf);
488 int ext;
489
484 assert(amp->am_magic == ACTIVEMAP_MAGIC);
485 assert(size >= amp->am_mapsize);
490 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
491 PJDLOG_ASSERT(size >= amp->am_mapsize);
486
487 bit_ffs(remmap, amp->am_nextents, &ext);
488 if (ext == -1) {
489 /* There are no dirty extents, so we can leave now. */
490 return;
491 }
492 /*
493 * We have dirty extents and we want them to stay that way until

--- 22 unchanged lines hidden (view full) ---

516
517/*
518 * Function returns pointer to internal bitmap that should be written to disk.
519 */
520const unsigned char *
521activemap_bitmap(struct activemap *amp, size_t *sizep)
522{
523
492
493 bit_ffs(remmap, amp->am_nextents, &ext);
494 if (ext == -1) {
495 /* There are no dirty extents, so we can leave now. */
496 return;
497 }
498 /*
499 * We have dirty extents and we want them to stay that way until

--- 22 unchanged lines hidden (view full) ---

522
523/*
524 * Function returns pointer to internal bitmap that should be written to disk.
525 */
526const unsigned char *
527activemap_bitmap(struct activemap *amp, size_t *sizep)
528{
529
524 assert(amp->am_magic == ACTIVEMAP_MAGIC);
530 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
525
526 if (sizep != NULL)
527 *sizep = amp->am_diskmapsize;
528 memcpy(amp->am_diskmap, amp->am_memmap, amp->am_mapsize);
529 keepdirty_fill(amp);
530 return ((const unsigned char *)amp->am_diskmap);
531}
532
533/*
534 * Function calculates size needed to store bitmap on disk.
535 */
536size_t
537activemap_calc_ondisk_size(uint64_t mediasize, uint32_t extentsize,
538 uint32_t sectorsize)
539{
540 uint64_t nextents, mapsize;
541
531
532 if (sizep != NULL)
533 *sizep = amp->am_diskmapsize;
534 memcpy(amp->am_diskmap, amp->am_memmap, amp->am_mapsize);
535 keepdirty_fill(amp);
536 return ((const unsigned char *)amp->am_diskmap);
537}
538
539/*
540 * Function calculates size needed to store bitmap on disk.
541 */
542size_t
543activemap_calc_ondisk_size(uint64_t mediasize, uint32_t extentsize,
544 uint32_t sectorsize)
545{
546 uint64_t nextents, mapsize;
547
542 assert(mediasize > 0);
543 assert(extentsize > 0);
544 assert(powerof2(extentsize));
545 assert(sectorsize > 0);
546 assert(powerof2(sectorsize));
548 PJDLOG_ASSERT(mediasize > 0);
549 PJDLOG_ASSERT(extentsize > 0);
550 PJDLOG_ASSERT(powerof2(extentsize));
551 PJDLOG_ASSERT(sectorsize > 0);
552 PJDLOG_ASSERT(powerof2(sectorsize));
547
548 nextents = ((mediasize - 1) / extentsize) + 1;
549 mapsize = sizeof(bitstr_t) * bitstr_size(nextents);
550 return (roundup2(mapsize, sectorsize));
551}
552
553/*
554 * Set synchronization offset to the first dirty extent.
555 */
556void
557activemap_sync_rewind(struct activemap *amp)
558{
559 int ext;
560
553
554 nextents = ((mediasize - 1) / extentsize) + 1;
555 mapsize = sizeof(bitstr_t) * bitstr_size(nextents);
556 return (roundup2(mapsize, sectorsize));
557}
558
559/*
560 * Set synchronization offset to the first dirty extent.
561 */
562void
563activemap_sync_rewind(struct activemap *amp)
564{
565 int ext;
566
561 assert(amp->am_magic == ACTIVEMAP_MAGIC);
567 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
562
563 bit_ffs(amp->am_syncmap, amp->am_nextents, &ext);
564 if (ext == -1) {
565 /* There are no extents to synchronize. */
566 amp->am_syncoff = -2;
567 return;
568 }
569 /*

--- 6 unchanged lines hidden (view full) ---

576 * Return next offset of where we should synchronize.
577 */
578off_t
579activemap_sync_offset(struct activemap *amp, off_t *lengthp, int *syncextp)
580{
581 off_t syncoff, left;
582 int ext;
583
568
569 bit_ffs(amp->am_syncmap, amp->am_nextents, &ext);
570 if (ext == -1) {
571 /* There are no extents to synchronize. */
572 amp->am_syncoff = -2;
573 return;
574 }
575 /*

--- 6 unchanged lines hidden (view full) ---

582 * Return next offset of where we should synchronize.
583 */
584off_t
585activemap_sync_offset(struct activemap *amp, off_t *lengthp, int *syncextp)
586{
587 off_t syncoff, left;
588 int ext;
589
584 assert(amp->am_magic == ACTIVEMAP_MAGIC);
585 assert(lengthp != NULL);
586 assert(syncextp != NULL);
590 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
591 PJDLOG_ASSERT(lengthp != NULL);
592 PJDLOG_ASSERT(syncextp != NULL);
587
588 *syncextp = -1;
589
590 if (amp->am_syncoff == -2)
591 return (-1);
592
593 if (amp->am_syncoff >= 0 &&
594 (amp->am_syncoff + MAXPHYS >= amp->am_mediasize ||

--- 32 unchanged lines hidden (view full) ---

627 syncoff = amp->am_syncoff;
628 left = ext2off(amp, off2ext(amp, syncoff)) +
629 amp->am_extentsize - syncoff;
630 if (syncoff + left > amp->am_mediasize)
631 left = amp->am_mediasize - syncoff;
632 if (left > MAXPHYS)
633 left = MAXPHYS;
634
593
594 *syncextp = -1;
595
596 if (amp->am_syncoff == -2)
597 return (-1);
598
599 if (amp->am_syncoff >= 0 &&
600 (amp->am_syncoff + MAXPHYS >= amp->am_mediasize ||

--- 32 unchanged lines hidden (view full) ---

633 syncoff = amp->am_syncoff;
634 left = ext2off(amp, off2ext(amp, syncoff)) +
635 amp->am_extentsize - syncoff;
636 if (syncoff + left > amp->am_mediasize)
637 left = amp->am_mediasize - syncoff;
638 if (left > MAXPHYS)
639 left = MAXPHYS;
640
635 assert(left >= 0 && left <= MAXPHYS);
636 assert(syncoff >= 0 && syncoff < amp->am_mediasize);
637 assert(syncoff + left >= 0 && syncoff + left <= amp->am_mediasize);
641 PJDLOG_ASSERT(left >= 0 && left <= MAXPHYS);
642 PJDLOG_ASSERT(syncoff >= 0 && syncoff < amp->am_mediasize);
643 PJDLOG_ASSERT(syncoff + left >= 0 &&
644 syncoff + left <= amp->am_mediasize);
638
639 *lengthp = left;
640 return (syncoff);
641}
642
643/*
644 * Mark extent(s) containing the given region for synchronization.
645 * Most likely one of the components is unavailable.
646 */
647bool
648activemap_need_sync(struct activemap *amp, off_t offset, off_t length)
649{
650 bool modified;
651 off_t end;
652 int ext;
653
645
646 *lengthp = left;
647 return (syncoff);
648}
649
650/*
651 * Mark extent(s) containing the given region for synchronization.
652 * Most likely one of the components is unavailable.
653 */
654bool
655activemap_need_sync(struct activemap *amp, off_t offset, off_t length)
656{
657 bool modified;
658 off_t end;
659 int ext;
660
654 assert(amp->am_magic == ACTIVEMAP_MAGIC);
661 PJDLOG_ASSERT(amp->am_magic == ACTIVEMAP_MAGIC);
655
656 modified = false;
657 end = offset + length - 1;
658
659 for (ext = off2ext(amp, offset); ext <= off2ext(amp, end); ext++) {
660 if (bit_test(amp->am_syncmap, ext)) {
661 /* Already marked for synchronization. */
662
663 modified = false;
664 end = offset + length - 1;
665
666 for (ext = off2ext(amp, offset); ext <= off2ext(amp, end); ext++) {
667 if (bit_test(amp->am_syncmap, ext)) {
668 /* Already marked for synchronization. */
662 assert(bit_test(amp->am_memmap, ext));
669 PJDLOG_ASSERT(bit_test(amp->am_memmap, ext));
663 continue;
664 }
665 bit_set(amp->am_syncmap, ext);
666 if (!bit_test(amp->am_memmap, ext)) {
667 bit_set(amp->am_memmap, ext);
668 amp->am_ndirty++;
669 }
670 amp->am_memtab[ext] += ext2reqs(amp, ext);

--- 24 unchanged lines hidden ---
670 continue;
671 }
672 bit_set(amp->am_syncmap, ext);
673 if (!bit_test(amp->am_memmap, ext)) {
674 bit_set(amp->am_memmap, ext);
675 amp->am_ndirty++;
676 }
677 amp->am_memtab[ext] += ext2reqs(amp, ext);

--- 24 unchanged lines hidden ---