f4eeb6044b0253f063535705d21bc3cea1eac467
[dragonfly.git] / sys / vfs / hammer2 / hammer2_bulkscan.c
1 /*
2  * Copyright (c) 2013-2015 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@dragonflybsd.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/fcntl.h>
38 #include <sys/buf.h>
39 #include <sys/proc.h>
40 #include <sys/namei.h>
41 #include <sys/mount.h>
42 #include <sys/vnode.h>
43 #include <sys/mountctl.h>
44 #include <vm/vm_kern.h>
45 #include <vm/vm_extern.h>
46
47 #include "hammer2.h"
48
49 /*
50  * breadth-first search
51  */
52 typedef struct hammer2_chain_save {
53         TAILQ_ENTRY(hammer2_chain_save) entry;
54         hammer2_chain_t *parent;
55 } hammer2_chain_save_t;
56
57 TAILQ_HEAD(hammer2_chain_save_list, hammer2_chain_save);
58 typedef struct hammer2_chain_save_list hammer2_chain_save_list_t;
59
60 /*
61  * General bulk scan function with callback.  Called with a referenced
62  * but UNLOCKED parent.  The original parent is returned in the same state.
63  */
64 int
65 hammer2_bulk_scan(hammer2_trans_t *trans, hammer2_chain_t *parent,
66                   int (*func)(hammer2_chain_t *chain, void *info),
67                   void *info)
68 {
69         hammer2_chain_save_list_t list;
70         hammer2_chain_save_t *save;
71         int doabort = 0;
72
73         TAILQ_INIT(&list);
74         hammer2_chain_ref(parent);
75         save = kmalloc(sizeof(*save), M_HAMMER2, M_WAITOK | M_ZERO);
76         save->parent = parent;
77         TAILQ_INSERT_TAIL(&list, save, entry);
78
79         while ((save = TAILQ_FIRST(&list)) != NULL && doabort == 0) {
80                 hammer2_chain_t *chain;
81                 int cache_index;
82
83                 TAILQ_REMOVE(&list, save, entry);
84
85                 parent = save->parent;
86                 save->parent = NULL;
87                 chain = NULL;
88                 cache_index = -1;
89
90                 /*
91                  * lock the parent, the lock eats the ref.
92                  */
93                 hammer2_chain_lock(parent, HAMMER2_RESOLVE_ALWAYS |
94                                            HAMMER2_RESOLVE_SHARED |
95                                            HAMMER2_RESOLVE_NOREF);
96
97                 /*
98                  * Generally loop on the contents if we have not been flagged
99                  * for abort.
100                  */
101                 while ((doabort & HAMMER2_BULK_ABORT) == 0) {
102                         chain = hammer2_chain_scan(parent, chain, &cache_index,
103                                                    HAMMER2_LOOKUP_NODATA |
104                                                    HAMMER2_LOOKUP_SHARED);
105                         if (chain == NULL)
106                                 break;
107                         doabort |= func(chain, info);
108
109                         if (doabort & HAMMER2_BULK_ABORT) {
110                                 hammer2_chain_unlock(chain);
111                                 chain = NULL;
112                                 break;
113                         }
114                         switch(chain->bref.type) {
115                         case HAMMER2_BREF_TYPE_INODE:
116                         case HAMMER2_BREF_TYPE_FREEMAP_NODE:
117                         case HAMMER2_BREF_TYPE_INDIRECT:
118                         case HAMMER2_BREF_TYPE_VOLUME:
119                         case HAMMER2_BREF_TYPE_FREEMAP:
120                                 /*
121                                  * Breadth-first scan.  Chain is referenced
122                                  * to save for later and will be unlocked on
123                                  * our loop (so it isn't left locked while on
124                                  * the list).
125                                  */
126                                 if (save == NULL) {
127                                         save = kmalloc(sizeof(*save),
128                                                        M_HAMMER2,
129                                                        M_WAITOK | M_ZERO);
130                                 }
131                                 hammer2_chain_ref(chain);
132                                 save->parent = chain;
133                                 TAILQ_INSERT_TAIL(&list, save, entry);
134                                 save = NULL;
135                                 break;
136                         default:
137                                 /* does not recurse */
138                                 break;
139                         }
140                 }
141
142                 /*
143                  * Releases the lock and the ref the lock inherited.  Free
144                  * save structure if we didn't recycle it above.
145                  */
146                 hammer2_chain_unlock(parent);
147                 if (save)
148                         kfree(save, M_HAMMER2);
149         }
150
151         /*
152          * Cleanup anything left undone due to an abort
153          */
154         while ((save = TAILQ_FIRST(&list)) != NULL) {
155                 TAILQ_REMOVE(&list, save, entry);
156                 hammer2_chain_drop(save->parent);
157                 kfree(save, M_HAMMER2);
158         }
159
160         return doabort;
161 }
162
163 /*
164  * Bulkfree algorithm -
165  *
166  * DoTwice {
167  *      flush sync
168  *      Scan the whole topology and build the freemap
169  *      ** -> 11 during scan for all elements scanned (and thus not free)
170  *      11 -> 10 after scan if allocated in-topo and free in-memory, mark 10
171  *      10 -> 00 after scan if possibly-free in-topo and free in-memory mark 00
172  * }
173  *
174  * Adjustment of the freemap ->10 and ->00 cannot occur until the topology
175  * scan is complete.  The scan runs concurrentlyt with normal filesystem
176  * operations and any allocation will also remark the freemap bitmap 11.
177  * We handle races by performing two scans and only changing the map to
178  * fully free (00) if both passes believe it is free.
179  *
180  * Temporary memory in multiples of 64KB is required to reconstruct leaf
181  * hammer2_bmap_data blocks so they can later be compared against the live
182  * freemap.  Each 64KB block represents 128 x 16KB x 1024 = ~2 GB of storage.
183  * A 32MB save area thus represents around ~1 TB.  The temporary memory
184  * allocated can be specified.  If it is not sufficient multiple topology
185  * passes will be made.
186  */
187
188 /*
189  * Bulkfree callback info
190  */
191 typedef struct hammer2_bulkfree_info {
192         hammer2_dev_t           *hmp;
193         hammer2_trans_t         *trans;
194         kmem_anon_desc_t        kp;
195         hammer2_off_t           sbase;          /* sub-loop iteration */
196         hammer2_off_t           sstop;
197         hammer2_bmap_data_t     *bmap;
198         long                    count_10_00;
199         long                    count_11_10;
200         long                    count_10_11;
201         long                    count_l0cleans;
202         long                    count_linadjusts;
203         hammer2_off_t           adj_free;
204         time_t                  save_time;
205 } hammer2_bulkfree_info_t;
206
207 static int h2_bulkfree_callback(hammer2_chain_t *chain, void *info);
208 static void h2_bulkfree_sync(hammer2_bulkfree_info_t *cbinfo);
209 static void h2_bulkfree_sync_adjust(hammer2_bulkfree_info_t *cbinfo,
210                         hammer2_bmap_data_t *live, hammer2_bmap_data_t *bmap);
211
212 int
213 hammer2_bulkfree_pass(hammer2_dev_t *hmp, hammer2_ioc_bulkfree_t *bfi)
214 {
215         hammer2_trans_t trans;
216         hammer2_bulkfree_info_t cbinfo;
217         hammer2_off_t incr;
218         size_t size;
219         int doabort = 0;
220
221         /* hammer2_vfs_sync(hmp->mp, MNT_WAIT); XXX */
222
223         bzero(&cbinfo, sizeof(cbinfo));
224         size = (bfi->size + HAMMER2_FREEMAP_LEVELN_PSIZE - 1) &
225                ~(size_t)(HAMMER2_FREEMAP_LEVELN_PSIZE - 1);
226         cbinfo.trans = &trans;
227         cbinfo.hmp = hmp;
228         cbinfo.bmap = kmem_alloc_swapbacked(&cbinfo.kp, size);
229
230         /*
231          * Normalize start point to a 2GB boundary.  We operate on a
232          * 64KB leaf bitmap boundary which represents 2GB of storage.
233          */
234         cbinfo.sbase = bfi->sbase;
235         if (cbinfo.sbase > hmp->voldata.volu_size)
236                 cbinfo.sbase = hmp->voldata.volu_size;
237         cbinfo.sbase &= ~HAMMER2_FREEMAP_LEVEL1_MASK;
238
239         /*
240          * Loop on a full meta-data scan as many times as required to
241          * get through all available storage.
242          */
243         while (cbinfo.sbase < hmp->voldata.volu_size) {
244                 /*
245                  * We have enough ram to represent (incr) bytes of storage.
246                  * Each 64KB of ram represents 2GB of storage.
247                  */
248                 bzero(cbinfo.bmap, size);
249                 incr = size / HAMMER2_FREEMAP_LEVELN_PSIZE *
250                        HAMMER2_FREEMAP_LEVEL1_SIZE;
251                 if (hmp->voldata.volu_size - cbinfo.sbase < incr)
252                         cbinfo.sstop = hmp->voldata.volu_size;
253                 else
254                         cbinfo.sstop = cbinfo.sbase + incr;
255                 kprintf("bulkfree pass %016jx/%jdGB\n",
256                         (intmax_t)cbinfo.sbase,
257                         (intmax_t)incr / HAMMER2_FREEMAP_LEVEL1_SIZE);
258
259                 hammer2_trans_init(&trans, hmp->spmp, 0);
260                 doabort |= hammer2_bulk_scan(&trans, &hmp->vchain,
261                                             h2_bulkfree_callback, &cbinfo);
262
263                 /*
264                  * If complete scan succeeded we can synchronize our
265                  * in-memory freemap against live storage.  If an abort
266                  * did occur we cannot safely synchronize our partially
267                  * filled-out in-memory freemap.
268                  */
269                 if (doabort == 0) {
270                         h2_bulkfree_sync(&cbinfo);
271
272                         hammer2_voldata_lock(hmp);
273                         hammer2_voldata_modify(hmp);
274                         hmp->voldata.allocator_free += cbinfo.adj_free;
275                         hammer2_voldata_unlock(hmp);
276                 }
277
278                 /*
279                  * Cleanup for next loop.
280                  */
281                 hammer2_trans_done(&trans);
282                 if (doabort)
283                         break;
284                 cbinfo.sbase = cbinfo.sstop;
285         }
286         kmem_free_swapbacked(&cbinfo.kp);
287
288         bfi->sstop = cbinfo.sbase;
289
290         incr = bfi->sstop / (hmp->voldata.volu_size / 10000);
291         if (incr > 10000)
292                 incr = 10000;
293
294         kprintf("bulkfree pass statistics (%d.%02d%% storage processed):\n",
295                 (int)incr / 100,
296                 (int)incr % 100);
297
298         kprintf("    transition->free   %ld\n", cbinfo.count_10_00);
299         kprintf("    transition->staged %ld\n", cbinfo.count_11_10);
300         kprintf("    raced on           %ld\n", cbinfo.count_10_11);
301         kprintf("    ~2MB segs cleaned  %ld\n", cbinfo.count_l0cleans);
302         kprintf("    linear adjusts     %ld\n", cbinfo.count_linadjusts);
303
304         return doabort;
305 }
306
307 static int
308 h2_bulkfree_callback(hammer2_chain_t *chain, void *info)
309 {
310         hammer2_bulkfree_info_t *cbinfo = info;
311         hammer2_bmap_data_t *bmap;
312         hammer2_off_t data_off;
313         uint16_t class;
314         size_t bytes;
315         int radix;
316         int error;
317
318         /*
319          * Check for signal and allow yield to userland during scan
320          */
321         if (hammer2_signal_check(&cbinfo->save_time))
322                 return HAMMER2_BULK_ABORT;
323
324 #if 0
325         kprintf("scan chain %016jx %016jx/%-2d type=%02x\n",
326                 (intmax_t)chain->bref.data_off,
327                 (intmax_t)chain->bref.key,
328                 chain->bref.keybits,
329                 chain->bref.type);
330 #endif
331
332         /*
333          * Calculate the data offset and determine if it is within
334          * the current freemap range being gathered.
335          */
336         error = 0;
337         data_off = chain->bref.data_off & ~HAMMER2_OFF_MASK_RADIX;
338         if (data_off < cbinfo->sbase || data_off > cbinfo->sstop)
339                 return 0;
340         if (data_off < chain->hmp->voldata.allocator_beg)
341                 return 0;
342         if (data_off > chain->hmp->voldata.volu_size)
343                 return 0;
344
345         /*
346          * Calculate the information needed to generate the in-memory
347          * freemap record.
348          *
349          * Hammer2 does not allow allocations to cross the L1 (2GB) boundary,
350          * it's a problem if it does.  (Or L0 (2MB) for that matter).
351          */
352         radix = (int)(chain->bref.data_off & HAMMER2_OFF_MASK_RADIX);
353         bytes = (size_t)1 << radix;
354         class = (chain->bref.type << 8) | hammer2_devblkradix(radix);
355
356         if (data_off + bytes > cbinfo->sstop) {
357                 kprintf("hammer2_bulkfree_scan: illegal 2GB boundary "
358                         "%016jx %016jx/%d\n",
359                         (intmax_t)chain->bref.data_off,
360                         (intmax_t)chain->bref.key,
361                         chain->bref.keybits);
362                 bytes = cbinfo->sstop - data_off;       /* XXX */
363         }
364
365         /*
366          * Convert to a storage offset relative to the beginning of the
367          * storage range we are collecting.  Then lookup the level0 bmap entry.
368          */
369         data_off -= cbinfo->sbase;
370         bmap = cbinfo->bmap + (data_off >> HAMMER2_FREEMAP_LEVEL0_RADIX);
371
372         /*
373          * Convert data_off to a bmap-relative value (~2MB storage range).
374          * Adjust linear, class, and avail.
375          *
376          * Hammer2 does not allow allocations to cross the L0 (2MB) boundary,
377          */
378         data_off &= HAMMER2_FREEMAP_LEVEL0_MASK;
379         if (data_off + bytes > HAMMER2_FREEMAP_LEVEL0_SIZE) {
380                 kprintf("hammer2_bulkfree_scan: illegal 2MB boundary "
381                         "%016jx %016jx/%d\n",
382                         (intmax_t)chain->bref.data_off,
383                         (intmax_t)chain->bref.key,
384                         chain->bref.keybits);
385                 bytes = HAMMER2_FREEMAP_LEVEL0_SIZE - data_off;
386         }
387
388         if (bmap->class == 0) {
389                 bmap->class = class;
390                 bmap->avail = HAMMER2_FREEMAP_LEVEL0_SIZE;
391         }
392         if (bmap->class != class) {
393                 kprintf("hammer2_bulkfree_scan: illegal mixed class "
394                         "%016jx %016jx/%d (%04x vs %04x)\n",
395                         (intmax_t)chain->bref.data_off,
396                         (intmax_t)chain->bref.key,
397                         chain->bref.keybits,
398                         class, bmap->class);
399         }
400         if (bmap->linear < (int32_t)data_off + (int32_t)bytes)
401                 bmap->linear = (int32_t)data_off + (int32_t)bytes;
402
403         /*
404          * Adjust the uint32_t bitmap[8].  2 bits per entry, to code 11.
405          * Shortcut aligned 64KB allocations.
406          *
407          * NOTE: The allocation can be smaller than HAMMER2_FREEMAP_BLOCK_SIZE.
408          */
409         while (bytes > 0) {
410                 int bindex;
411                 uint32_t bmask;
412
413                 bindex = (int)data_off >> (HAMMER2_FREEMAP_BLOCK_RADIX +
414                                            HAMMER2_BMAP_INDEX_RADIX);
415                 bmask = 3 << ((((int)data_off & HAMMER2_BMAP_INDEX_MASK) >>
416                              HAMMER2_FREEMAP_BLOCK_RADIX) << 1);
417
418                 /*
419                  * NOTE! The (avail) calculation is bitmap-granular.  Multiple
420                  *       sub-granular records can wind up at the same bitmap
421                  *       position.
422                  */
423                 if ((bmap->bitmap[bindex] & bmask) == 0) {
424                         if (bytes < HAMMER2_FREEMAP_BLOCK_SIZE) {
425                                 bmap->avail -= HAMMER2_FREEMAP_BLOCK_SIZE;
426                         } else {
427                                 bmap->avail -= bytes;
428                         }
429                         bmap->bitmap[bindex] |= bmask;
430                 }
431                 data_off += HAMMER2_FREEMAP_BLOCK_SIZE;
432                 if (bytes < HAMMER2_FREEMAP_BLOCK_SIZE)
433                         bytes = 0;
434                 else
435                         bytes -= HAMMER2_FREEMAP_BLOCK_SIZE;
436         }
437         return error;
438 }
439
440 /*
441  * Synchronize the in-memory bitmap with the live freemap.  This is not a
442  * direct copy.  Instead the bitmaps must be compared:
443  *
444  *      In-memory       Live-freemap
445  *         00             11 -> 10
446  *                        10 -> 00
447  *         11             10 -> 11      handles race against live
448  *                        ** -> 11      nominally warn of corruption
449  * 
450  */
451 static void
452 h2_bulkfree_sync(hammer2_bulkfree_info_t *cbinfo)
453 {
454         hammer2_off_t data_off;
455         hammer2_key_t key;
456         hammer2_key_t key_dummy;
457         hammer2_bmap_data_t *bmap;
458         hammer2_bmap_data_t *live;
459         hammer2_chain_t *live_parent;
460         hammer2_chain_t *live_chain;
461         int cache_index = -1;
462         int bmapindex;
463
464         kprintf("hammer2_bulkfree - range %016jx-%016jx\n",
465                 (intmax_t)cbinfo->sbase,
466                 (intmax_t)cbinfo->sstop);
467                 
468         data_off = cbinfo->sbase;
469         bmap = cbinfo->bmap;
470
471         live_parent = &cbinfo->hmp->fchain;
472         hammer2_chain_lock(live_parent, HAMMER2_RESOLVE_ALWAYS);
473         live_chain = NULL;
474
475         while (data_off < cbinfo->sstop) {
476                 /*
477                  * The freemap is not used below allocator_beg or beyond
478                  * volu_size.
479                  */
480                 if (data_off < cbinfo->hmp->voldata.allocator_beg)
481                         goto next;
482                 if (data_off > cbinfo->hmp->voldata.volu_size)
483                         goto next;
484
485                 /*
486                  * Locate the freemap leaf on the live filesystem
487                  */
488                 key = (data_off & ~HAMMER2_FREEMAP_LEVEL1_MASK);
489                 if (live_chain == NULL || live_chain->bref.key != key) {
490                         if (live_chain)
491                                 hammer2_chain_unlock(live_chain);
492                         live_chain = hammer2_chain_lookup(
493                                             &live_parent,
494                                             &key_dummy,
495                                             key,
496                                             key + HAMMER2_FREEMAP_LEVEL1_MASK,
497                                             &cache_index,
498                                             HAMMER2_LOOKUP_ALWAYS);
499                         if (live_chain)
500                                 kprintf("live_chain %016jx\n", (intmax_t)key);
501                                         
502                 }
503                 if (live_chain == NULL) {
504                         if (bmap->class &&
505                             bmap->avail != HAMMER2_FREEMAP_LEVEL0_SIZE) {
506                                 kprintf("hammer2_bulkfree: cannot locate "
507                                         "live leaf for allocated data "
508                                         "near %016jx\n",
509                                         (intmax_t)data_off);
510                         }
511                         goto next;
512                 }
513
514                 bmapindex = (data_off & HAMMER2_FREEMAP_LEVEL1_MASK) >>
515                             HAMMER2_FREEMAP_LEVEL0_RADIX;
516                 live = &live_chain->data->bmdata[bmapindex];
517
518                 /*
519                  * For now just handle the 11->10, 10->00, and 10->11
520                  * transitions.
521                  */
522                 if (live->class == 0 ||
523                     live->avail == HAMMER2_FREEMAP_LEVEL0_SIZE) {
524                         goto next;
525                 }
526                 if (bcmp(live->bitmap, bmap->bitmap, sizeof(bmap->bitmap)) == 0)
527                         goto next;
528                 kprintf("live %016jx %04d.%04x (avail=%d)\n",
529                         data_off, bmapindex, live->class, live->avail);
530
531                 hammer2_chain_modify(cbinfo->trans, live_chain, 0);
532                 h2_bulkfree_sync_adjust(cbinfo, live, bmap);
533 next:
534                 data_off += HAMMER2_FREEMAP_LEVEL0_SIZE;
535                 ++bmap;
536         }
537         if (live_chain)
538                 hammer2_chain_unlock(live_chain);
539         if (live_parent)
540                 hammer2_chain_unlock(live_parent);
541 }
542
543 static
544 void
545 h2_bulkfree_sync_adjust(hammer2_bulkfree_info_t *cbinfo,
546                         hammer2_bmap_data_t *live, hammer2_bmap_data_t *bmap)
547 {
548         int bindex;
549         int scount;
550         uint32_t lmask;
551         uint32_t mmask;
552
553         for (bindex = 0; bindex < 8; ++bindex) {
554                 lmask = live->bitmap[bindex];
555                 mmask = bmap->bitmap[bindex];
556                 if (lmask == mmask)
557                         continue;
558
559                 for (scount = 0; scount < 32; scount += 2) {
560                         if ((mmask & 3) == 0) {
561                                 /*
562                                  * in-memory 00         live 11 -> 10
563                                  *                      live 10 -> 00
564                                  */
565                                 switch (lmask & 3) {
566                                 case 0: /* 00 */
567                                         break;
568                                 case 1: /* 01 */
569                                         kprintf("hammer2_bulkfree: cannot "
570                                                 "transition m=00/l=01\n");
571                                         break;
572                                 case 2: /* 10 -> 00 */
573                                         live->bitmap[bindex] &= ~(2 << scount);
574                                         live->avail +=
575                                                 HAMMER2_FREEMAP_BLOCK_SIZE;
576                                         cbinfo->adj_free +=
577                                                 HAMMER2_FREEMAP_BLOCK_SIZE;
578                                         ++cbinfo->count_10_00;
579                                         break;
580                                 case 3: /* 11 -> 10 */
581                                         live->bitmap[bindex] &= ~(1 << scount);
582                                         ++cbinfo->count_11_10;
583                                         break;
584                                 }
585                         } else if ((lmask & 3) == 3) {
586                                 /*
587                                  * in-memory 11         live 10 -> 11
588                                  *                      live ** -> 11
589                                  */
590                                 switch (lmask & 3) {
591                                 case 0: /* 00 */
592                                         kprintf("hammer2_bulkfree: cannot "
593                                                 "transition m=11/l=00\n");
594                                         break;
595                                 case 1: /* 01 */
596                                         kprintf("hammer2_bulkfree: cannot "
597                                                 "transition m=11/l=01\n");
598                                         break;
599                                 case 2: /* 10 -> 11 */
600                                         live->bitmap[bindex] |= (1 << scount);
601                                         ++cbinfo->count_10_11;
602                                         break;
603                                 case 3: /* 11 */
604                                         break;
605                                 }
606                         }
607                         mmask >>= 2;
608                         lmask >>= 2;
609                 }
610         }
611
612         /*
613          * Determine if the live bitmap is completely free and reset its
614          * fields if so.  Otherwise check to see if we can reduce the linear
615          * offset.
616          */
617         for (bindex = 7; bindex >= 0; --bindex) {
618                 if (live->bitmap[bindex] != 0)
619                         break;
620         }
621         if (bindex < 0) {
622                 live->avail = HAMMER2_FREEMAP_LEVEL0_SIZE;
623                 live->class = 0;
624                 live->linear = 0;
625                 ++cbinfo->count_l0cleans;
626         } else if (bindex < 7) {
627                 ++bindex;
628                 if (live->linear > bindex * HAMMER2_FREEMAP_BLOCK_SIZE) {
629                         live->linear = bindex * HAMMER2_FREEMAP_BLOCK_SIZE;
630                         ++cbinfo->count_linadjusts;
631                 }
632         }
633
634 #if 0
635         if (bmap->class) {
636                 kprintf("%016jx %04d.%04x (avail=%7d) "
637                         "%08x %08x %08x %08x %08x %08x %08x %08x\n",
638                         (intmax_t)data_off,
639                         (int)((data_off &
640                                HAMMER2_FREEMAP_LEVEL1_MASK) >>
641                               HAMMER2_FREEMAP_LEVEL0_RADIX),
642                         bmap->class,
643                         bmap->avail,
644                         bmap->bitmap[0], bmap->bitmap[1],
645                         bmap->bitmap[2], bmap->bitmap[3],
646                         bmap->bitmap[4], bmap->bitmap[5],
647                         bmap->bitmap[6], bmap->bitmap[7]);
648         }
649 #endif
650 }