hammer2 - Increase size of blockref, refactor freemap. master
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 27 May 2015 21:41:36 +0000 (14:41 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 27 May 2015 21:53:12 +0000 (14:53 -0700)
I finally buckled under and increase the size of the blockref from 64 bytes
to 128 bytes.  The negative consequences are relatively minor, and the
positives are many.

Negative consequences

    * 512 blocks per 64KB indirect block instead of 1024.
    * Inode has only 4 built-in blockrefs instead of 8.
    * Indirect block overhead is doubled.
    * Freemap overhead is doubled due to SEGSIZE being 1GB instead of 2GB.
    * Small files will have to push an indirect block sooner (at 256KB).

Positive consequences

    * Freemap overhead is still only 0.40% of the storage.
    * Freemap now uses a 32KB indirect block instead of a 64KB indirect block.

    * Data and inode statistics can be tracked in the blockref.
    * Check code goes from max-192-bits to max-512-bits.
    * Additional fields now available for future filesystem features.

sbin/hammer2/cmd_debug.c
sbin/hammer2/cmd_stat.c
sbin/newfs_hammer2/newfs_hammer2.c
sys/vfs/hammer2/DESIGN
sys/vfs/hammer2/hammer2.h
sys/vfs/hammer2/hammer2_bulkscan.c
sys/vfs/hammer2/hammer2_chain.c
sys/vfs/hammer2/hammer2_disk.h
sys/vfs/hammer2/hammer2_flush.c
sys/vfs/hammer2/hammer2_freemap.c
sys/vfs/hammer2/hammer2_inode.c

index 4ef3379..52010c1 100644 (file)
@@ -643,11 +643,11 @@ show_bref(int fd, int tab, int bi, hammer2_blockref_t *bref, int dofreemap)
                tabprintf(tab, "data_quota  %ju\n",
                          (uintmax_t)media.ipdata.data_quota);
                tabprintf(tab, "data_count  %ju\n",
-                         (uintmax_t)media.ipdata.data_count);
+                         (uintmax_t)bref->data_count);
                tabprintf(tab, "inode_quota %ju\n",
                          (uintmax_t)media.ipdata.inode_quota);
                tabprintf(tab, "inode_count %ju\n",
-                         (uintmax_t)media.ipdata.inode_count);
+                         (uintmax_t)bref->inode_count);
                tabprintf(tab, "attr_tid    0x%016jx\n",
                          (uintmax_t)media.ipdata.attr_tid);
                if (media.ipdata.type == HAMMER2_OBJTYPE_DIRECTORY) {
@@ -689,18 +689,23 @@ show_bref(int fd, int tab, int bi, hammer2_blockref_t *bref, int dofreemap)
                            media.bmdata[i].avail == 0) {
                                continue;
                        }
+#if HAMMER2_BMAP_ELEMENTS != 8
+#error "cmd_debug.c: HAMMER2_BMAP_ELEMENTS expected to be 8"
+#endif
+
                        tabprintf(tab + 4, "%04d.%04x (avail=%7d) "
-                                 "%08x %08x %08x %08x %08x %08x %08x %08x\n",
+                                 "%016jx %016jx %016jx %016jx "
+                                 "%016jx %016jx %016jx %016jx\n",
                                  i, media.bmdata[i].class,
                                  media.bmdata[i].avail,
-                                 media.bmdata[i].bitmap[0],
-                                 media.bmdata[i].bitmap[1],
-                                 media.bmdata[i].bitmap[2],
-                                 media.bmdata[i].bitmap[3],
-                                 media.bmdata[i].bitmap[4],
-                                 media.bmdata[i].bitmap[5],
-                                 media.bmdata[i].bitmap[6],
-                                 media.bmdata[i].bitmap[7]);
+                                 media.bmdata[i].bitmapq[0],
+                                 media.bmdata[i].bitmapq[1],
+                                 media.bmdata[i].bitmapq[2],
+                                 media.bmdata[i].bitmapq[3],
+                                 media.bmdata[i].bitmapq[4],
+                                 media.bmdata[i].bitmapq[5],
+                                 media.bmdata[i].bitmapq[6],
+                                 media.bmdata[i].bitmapq[7]);
                }
                tabprintf(tab, "}\n");
                break;
index 961c8a0..f45f01d 100644 (file)
@@ -75,8 +75,8 @@ cmd_stat(int ac, const char **av)
                }
                printf("%-*.*s ", w, w, av[i]);
                printf("%3d ", ino.ip_data.ncopies);
-               printf("%9s ", sizetostr(ino.ip_data.data_count));
-               printf("%9s ", counttostr(ino.ip_data.inode_count));
+/*             printf("%9s ", sizetostr(ino.ip_data.data_count));*/
+/*             printf("%9s ", counttostr(ino.ip_data.inode_count));*/
                printf("%p ", ino.kdata);
                printf("comp=%s ", compmodestr(ino.ip_data.comp_algo));
                printf("check=%s ", checkmodestr(ino.ip_data.check_algo));
index 0510d9c..bb397bb 100644 (file)
@@ -52,7 +52,7 @@
 #include <err.h>
 #include <uuid.h>
 
-#define MAXLABELS      4
+#define MAXLABELS      HAMMER2_SET_COUNT
 
 #define hammer2_icrc32(buf, size)      iscsi_crc32((buf), (size))
 #define hammer2_icrc32c(buf, size, crc)        iscsi_crc32_ext((buf), (size), (crc))
@@ -142,7 +142,9 @@ main(int ac, char **av)
                                break;
                        }
                        if (NLabels >= MAXLABELS) {
-                               errx(1, "Limit of 3 local labels");
+                               errx(1,
+                                    "Limit of %d local labels",
+                                    MAXLABELS - 1);
                        }
                        Label[NLabels++] = optarg;
                        if (strlen(Label[NLabels-1]) > HAMMER2_INODE_MAXNAME) {
@@ -489,7 +491,7 @@ format_hammer2(int fd, hammer2_off_t total_space, hammer2_off_t free_space)
        hammer2_volume_data_t *vol;
        hammer2_inode_data_t *rawip;
        hammer2_blockref_t sroot_blockref;
-       hammer2_blockref_t root_blockref[MAXLABELS];    /* Max 4 labels */
+       hammer2_blockref_t root_blockref[MAXLABELS];
        uint64_t now;
        hammer2_off_t volu_base = 0;
        hammer2_off_t boot_base = HAMMER2_ZONE_SEG;
@@ -659,10 +661,10 @@ format_hammer2(int fd, hammer2_off_t total_space, hammer2_off_t free_space)
        rawip->pfs_inum = 16;   /* first allocatable inode number */
 
        /*
-        * The super-root has a directory entry pointing to each local
-        * PFS.  To avoid having to deal with indirect blocks we can't load
-        * up more than 8 entries, but NLabels is restricted to 4 entries
-        * to leave room for possible future mandatory PFSs.
+        * Currently newfs_hammer2 just throws the PFS inodes into the
+        * top-level block table at the volume root and doesn't try to
+        * create an indirect block, so we are limited to ~4 at filesystem
+        * creation time.  More can be added after mounting.
         */
        qsort(root_blockref, NLabels, sizeof(root_blockref[0]), blkrefary_cmp);
        for (i = 0; i < NLabels; ++i)
index 5a69f2d..420aede 100644 (file)
@@ -391,7 +391,7 @@ HAMMER2 winds up with very low OS overhead.
                                FREEMAP NOTES
 
 The freemap is stored in the reserved blocks situated in the ~4MB reserved
-area at the baes of every ~2GB level-1 zone.  The current implementation
+area at the baes of every ~1GB level-1 zone.  The current implementation
 reserves 8 copies of every freemap block and cycles through them in order
 to make the freemap operate in a copy-on-write fashion.
 
@@ -407,9 +407,16 @@ goes it is really just a 4-level blockmap.
 
 The freemap radix allocation mechanism is also the same, meaning that it is
 bottom-up and will not allocate unnecessary intermediate levels for smaller
-filesystems.  A 16GB filesystem uses a 2-level blockmap (volume header + one
-level), a 16TB filesystem uses a 3-level blockmap (volume header + two levels),
-and so forth.
+filesystems.  The number of blockmap levels not including the volume header
+for various filesystem sizes is as follows:
+       
+       up-to           #of freemap levels
+       1GB             1-level
+       256GB           2-level
+       64TB            3-level
+       16PB            4-level
+       4EB             5-level
+       16EB            6-level
 
 The Freemap has bitmap granularity down to 16KB and a linear iterator that
 can linearly allocate space down to 1KB.  Due to fragmentation it is possible
index 93e30ff..17728b0 100644 (file)
@@ -327,10 +327,6 @@ struct hammer2_chain {
        struct hammer2_pfs      *pmp;           /* A PFS or super-root (spmp) */
 
        hammer2_xid_t   flush_xid;              /* flush sequencing */
-       hammer2_key_t   data_count;             /* delta's to apply */
-       hammer2_key_t   inode_count;            /* delta's to apply */
-       hammer2_key_t   data_count_up;          /* delta's to apply */
-       hammer2_key_t   inode_count_up;         /* delta's to apply */
        hammer2_io_t    *dio;                   /* physical data buffer */
        u_int           bytes;                  /* physical data size */
        u_int           flags;
index 888db9f..1a2b30f 100644 (file)
@@ -403,32 +403,33 @@ h2_bulkfree_callback(hammer2_chain_t *chain, void *info)
                bmap->linear = (int32_t)data_off + (int32_t)bytes;
 
        /*
-        * Adjust the uint32_t bitmap[8].  2 bits per entry, to code 11.
-        * Shortcut aligned 64KB allocations.
+        * Adjust the hammer2_bitmap_t bitmap[HAMMER2_BMAP_ELEMENTS].
+        * 64-bit entries, 2 bits per entry, to code 11.
         *
         * NOTE: The allocation can be smaller than HAMMER2_FREEMAP_BLOCK_SIZE.
         */
        while (bytes > 0) {
                int bindex;
-               uint32_t bmask;
+               hammer2_bitmap_t bmask;
 
                bindex = (int)data_off >> (HAMMER2_FREEMAP_BLOCK_RADIX +
                                           HAMMER2_BMAP_INDEX_RADIX);
-               bmask = 3 << ((((int)data_off & HAMMER2_BMAP_INDEX_MASK) >>
-                            HAMMER2_FREEMAP_BLOCK_RADIX) << 1);
+               bmask = (hammer2_bitmap_t)3 <<
+                       ((((int)data_off & HAMMER2_BMAP_INDEX_MASK) >>
+                        HAMMER2_FREEMAP_BLOCK_RADIX) << 1);
 
                /*
                 * NOTE! The (avail) calculation is bitmap-granular.  Multiple
                 *       sub-granular records can wind up at the same bitmap
                 *       position.
                 */
-               if ((bmap->bitmap[bindex] & bmask) == 0) {
+               if ((bmap->bitmapq[bindex] & bmask) == 0) {
                        if (bytes < HAMMER2_FREEMAP_BLOCK_SIZE) {
                                bmap->avail -= HAMMER2_FREEMAP_BLOCK_SIZE;
                        } else {
                                bmap->avail -= bytes;
                        }
-                       bmap->bitmap[bindex] |= bmask;
+                       bmap->bitmapq[bindex] |= bmask;
                }
                data_off += HAMMER2_FREEMAP_BLOCK_SIZE;
                if (bytes < HAMMER2_FREEMAP_BLOCK_SIZE)
@@ -538,8 +539,10 @@ h2_bulkfree_sync(hammer2_bulkfree_info_t *cbinfo)
                    live->avail == HAMMER2_FREEMAP_LEVEL0_SIZE) {
                        goto next;
                }
-               if (bcmp(live->bitmap, bmap->bitmap, sizeof(bmap->bitmap)) == 0)
+               if (bcmp(live->bitmapq, bmap->bitmapq,
+                        sizeof(bmap->bitmapq)) == 0) {
                        goto next;
+               }
                if (hammer2_debug & 1)
                kprintf("live %016jx %04d.%04x (avail=%d)\n",
                        data_off, bmapindex, live->class, live->avail);
@@ -567,16 +570,18 @@ h2_bulkfree_sync_adjust(hammer2_bulkfree_info_t *cbinfo,
 {
        int bindex;
        int scount;
-       uint32_t lmask;
-       uint32_t mmask;
+       hammer2_bitmap_t lmask;
+       hammer2_bitmap_t mmask;
 
-       for (bindex = 0; bindex < 8; ++bindex) {
-               lmask = live->bitmap[bindex];
-               mmask = bmap->bitmap[bindex];
+       for (bindex = 0; bindex < HAMMER2_BMAP_ELEMENTS; ++bindex) {
+               lmask = live->bitmapq[bindex];
+               mmask = bmap->bitmapq[bindex];
                if (lmask == mmask)
                        continue;
 
-               for (scount = 0; scount < 32; scount += 2) {
+               for (scount = 0;
+                    scount < HAMMER2_BMAP_BITS_PER_ELEMENT;
+                    scount += 2) {
                        if ((mmask & 3) == 0) {
                                /*
                                 * in-memory 00         live 11 -> 10
@@ -590,7 +595,8 @@ h2_bulkfree_sync_adjust(hammer2_bulkfree_info_t *cbinfo,
                                                "transition m=00/l=01\n");
                                        break;
                                case 2: /* 10 -> 00 */
-                                       live->bitmap[bindex] &= ~(2 << scount);
+                                       live->bitmapq[bindex] &=
+                                           ~((hammer2_bitmap_t)2 << scount);
                                        live->avail +=
                                                HAMMER2_FREEMAP_BLOCK_SIZE;
                                        cbinfo->adj_free +=
@@ -598,7 +604,8 @@ h2_bulkfree_sync_adjust(hammer2_bulkfree_info_t *cbinfo,
                                        ++cbinfo->count_10_00;
                                        break;
                                case 3: /* 11 -> 10 */
-                                       live->bitmap[bindex] &= ~(1 << scount);
+                                       live->bitmapq[bindex] &=
+                                           ~((hammer2_bitmap_t)1 << scount);
                                        ++cbinfo->count_11_10;
                                        break;
                                }
@@ -617,7 +624,8 @@ h2_bulkfree_sync_adjust(hammer2_bulkfree_info_t *cbinfo,
                                                "transition m=11/l=01\n");
                                        break;
                                case 2: /* 10 -> 11 */
-                                       live->bitmap[bindex] |= (1 << scount);
+                                       live->bitmapq[bindex] |=
+                                               ((hammer2_bitmap_t)1 << scount);
                                        ++cbinfo->count_10_11;
                                        break;
                                case 3: /* 11 */
@@ -634,8 +642,8 @@ h2_bulkfree_sync_adjust(hammer2_bulkfree_info_t *cbinfo,
         * fields if so.  Otherwise check to see if we can reduce the linear
         * offset.
         */
-       for (bindex = 7; bindex >= 0; --bindex) {
-               if (live->bitmap[bindex] != 0)
+       for (bindex = HAMMER2_BMAP_ELEMENTS - 1; bindex >= 0; --bindex) {
+               if (live->bitmapq[bindex] != 0)
                        break;
        }
        if (bindex < 0) {
index 58c30bb..2bab0e2 100644 (file)
@@ -1018,7 +1018,6 @@ hammer2_chain_resize(hammer2_trans_t *trans, hammer2_inode_t *ip,
        nbytes = 1U << nradix;
        if (obytes == nbytes)
                return;
-       chain->data_count += (ssize_t)(nbytes - obytes);
 
        /*
         * Make sure the old data is instantiated so we can copy it.  If this
@@ -2286,20 +2285,6 @@ hammer2_chain_create(hammer2_trans_t *trans, hammer2_chain_t **parentp,
                        atomic_set_int(&chain->flags, HAMMER2_CHAIN_INITIAL);
                        break;
                }
-
-               /*
-                * Set statistics for pending updates.  These will be
-                * synchronized by the flush code.
-                */
-               switch(type) {
-               case HAMMER2_BREF_TYPE_INODE:
-                       chain->inode_count = 1;
-                       break;
-               case HAMMER2_BREF_TYPE_DATA:
-               case HAMMER2_BREF_TYPE_INDIRECT:
-                       chain->data_count = chain->bytes;
-                       break;
-               }
        } else {
                /*
                 * We are reattaching a previously deleted chain, possibly
@@ -2454,14 +2439,6 @@ again:
                        hammer2_chain_ref(chain);
                        atomic_set_int(&chain->flags, HAMMER2_CHAIN_UPDATE);
                }
-               if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
-                   (flags & HAMMER2_INSERT_NOSTATS) == 0) {
-                       KKASSERT(chain->data);
-                       chain->inode_count_up +=
-                               chain->data->ipdata.inode_count;
-                       chain->data_count_up +=
-                               chain->data->ipdata.data_count;
-               }
        }
 
        /*
@@ -2668,15 +2645,6 @@ _hammer2_chain_delete_helper(hammer2_trans_t *trans,
                 * undone.  XXX split update possible w/delete in middle?
                 */
                if (base) {
-                       if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
-                           (flags & HAMMER2_DELETE_NOSTATS) == 0) {
-                               KKASSERT(chain->data != NULL);
-                               parent->data_count -=
-                                       chain->data->ipdata.data_count;
-                               parent->inode_count -=
-                                       chain->data->ipdata.inode_count;
-                       }
-
                        int cache_index = -1;
                        hammer2_base_delete(trans, parent, base, count,
                                            &cache_index, chain);
@@ -2693,14 +2661,6 @@ _hammer2_chain_delete_helper(hammer2_trans_t *trans,
                 * inode adjustment statistics which must be undone.
                 */
                hammer2_spin_ex(&parent->core.spin);
-               if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
-                   (flags & HAMMER2_DELETE_NOSTATS) == 0) {
-                       KKASSERT(chain->data != NULL);
-                       chain->data_count_up -=
-                               chain->data->ipdata.data_count;
-                       chain->inode_count_up -=
-                               chain->data->ipdata.inode_count;
-               }
                atomic_set_int(&chain->flags, HAMMER2_CHAIN_DELETED);
                atomic_add_int(&parent->core.live_count, -1);
                ++parent->core.generation;
@@ -3202,6 +3162,9 @@ hammer2_chain_indkey_freemap(hammer2_chain_t *parent, hammer2_key_t *keyp,
                keybits = HAMMER2_FREEMAP_LEVEL4_RADIX;
                break;
        case HAMMER2_FREEMAP_LEVEL4_RADIX:
+               keybits = HAMMER2_FREEMAP_LEVEL5_RADIX;
+               break;
+       case HAMMER2_FREEMAP_LEVEL5_RADIX:
                panic("hammer2_chain_indkey_freemap: level too high");
                break;
        default:
index 8633783..010cba5 100644 (file)
  * fragments might be supported in the future (down to 64 bytes is possible),
  * but probably will not be.
  *
- * A full indirect block use supports 1024 x 64-byte blockrefs in a 64KB
+ * A full indirect block use supports 512 x 128-byte blockrefs in a 64KB
  * buffer.  Indirect blocks down to 1KB are supported to keep small
  * directories small.
  *
- * A maximally sized file (2^64-1 bytes) requires 5 indirect block levels.
- * The hammer2_blockset in the volume header or file inode has another 8
- * entries, giving us 66+3 = 69 bits of address space.  However, some bits
- * are taken up by (potentially) requests for redundant copies.  HAMMER2
- * currently supports up to 8 copies, which brings the address space down
- * to 66 bits and gives us 2 bits of leeway.
+ * A maximally sized file (2^64-1 bytes) requires ~6 indirect block levels
+ * using 64KB indirect blocks (128 byte refs, 512 or radix 9 per indblk).
+ *
+ *     16(datablk) + 9 + 9 + 9 + 9 + 9 + 9 = ~70.
+ *     16(datablk) + 7 + 9 + 9 + 9 + 9 + 9 = ~68.  (smaller top level indblk)
+ *
+ * The actual depth depends on copies redundancy and whether the filesystem
+ * has chosen to use a smaller indirect block size at the top level or not.
  */
 #define HAMMER2_ALLOC_MIN      1024    /* minimum allocation size */
 #define HAMMER2_RADIX_MIN      10      /* minimum allocation size 2^N */
  * Indirect blocks are typically either 4KB (64 blockrefs / ~4MB represented),
  * or 64KB (1024 blockrefs / ~64MB represented).
  */
-#define HAMMER2_SET_COUNT              8       /* direct entries */
-#define HAMMER2_SET_RADIX              3
+#define HAMMER2_SET_RADIX              2       /* radix 2 = 4 entries */
+#define HAMMER2_SET_COUNT              (1 << HAMMER2_SET_RADIX)
 #define HAMMER2_EMBEDDED_BYTES         512     /* inode blockset/dd size */
 #define HAMMER2_EMBEDDED_RADIX         9
 
 #define HAMMER2_ZONE_SEG64             ((hammer2_off_t)HAMMER2_ZONE_SEG)
 #define HAMMER2_ZONE_BLOCKS_SEG                (HAMMER2_ZONE_SEG / HAMMER2_PBUFSIZE)
 
+#define HAMMER2_ZONE_FREEMAP_INC       5       /* 5 deep */
+
 #define HAMMER2_ZONE_VOLHDR            0       /* volume header or backup */
 #define HAMMER2_ZONE_FREEMAP_00                1       /* normal freemap rotation */
-#define HAMMER2_ZONE_FREEMAP_01                5       /* normal freemap rotation */
-#define HAMMER2_ZONE_FREEMAP_02                9       /* normal freemap rotation */
-#define HAMMER2_ZONE_FREEMAP_03                13      /* normal freemap rotation */
-#define HAMMER2_ZONE_FREEMAP_04                17      /* normal freemap rotation */
-#define HAMMER2_ZONE_FREEMAP_05                21      /* normal freemap rotation */
-#define HAMMER2_ZONE_FREEMAP_06                25      /* normal freemap rotation */
-#define HAMMER2_ZONE_FREEMAP_07                29      /* normal freemap rotation */
-#define HAMMER2_ZONE_FREEMAP_END       33      /* (non-inclusive) */
-
-#define HAMMER2_ZONE_UNUSED33          33
-#define HAMMER2_ZONE_UNUSED34          34
-#define HAMMER2_ZONE_UNUSED35          35
-#define HAMMER2_ZONE_UNUSED36          36
-#define HAMMER2_ZONE_UNUSED37          37
-#define HAMMER2_ZONE_UNUSED38          38
-#define HAMMER2_ZONE_UNUSED39          39
-#define HAMMER2_ZONE_UNUSED40          40
+#define HAMMER2_ZONE_FREEMAP_01                6       /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_02                11      /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_03                16      /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_04                21      /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_05                26      /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_06                31      /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_07                36      /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_END       41      /* (non-inclusive) */
+
 #define HAMMER2_ZONE_UNUSED41          41
 #define HAMMER2_ZONE_UNUSED42          42
 #define HAMMER2_ZONE_UNUSED43          43
 #define HAMMER2_NFREEMAPS              8       /* FREEMAP_00 - FREEMAP_07 */
 
                                                /* relative to FREEMAP_x */
-#define HAMMER2_ZONEFM_LEVEL1          0       /* 2GB leafmap */
-#define HAMMER2_ZONEFM_LEVEL2          1       /* 2TB indmap */
-#define HAMMER2_ZONEFM_LEVEL3          2       /* 2PB indmap */
-#define HAMMER2_ZONEFM_LEVEL4          3       /* 2EB indmap */
-/* LEVEL5 is a set of 8 blockrefs in the volume header 16EB */
+#define HAMMER2_ZONEFM_LEVEL1          0       /* 1GB leafmap */
+#define HAMMER2_ZONEFM_LEVEL2          1       /* 256GB indmap */
+#define HAMMER2_ZONEFM_LEVEL3          2       /* 64TB indmap */
+#define HAMMER2_ZONEFM_LEVEL4          3       /* 16PB indmap */
+#define HAMMER2_ZONEFM_LEVEL5          4       /* 4EB indmap */
+/* LEVEL6 is a set of 4 blockrefs in the volume header 16EB */
 
 /*
- * Freemap radix.  Note that the LEVEL 1 blockref points to a 64KB freemap
- * block containing 1024 x LEVEL0 hammer2_bmap_data structures.  LEVEL 0
- * represents one structure.
+ * Freemap radix.  Assumes a set-count of 4, 128-byte blockrefs,
+ * 32KB indirect block for freemap (LEVELN_PSIZE below).
+ *
+ * Leaf entry represents 4MB of storage broken down into a 512-bit
+ * bitmap, 2-bits per entry.  So course bitmap item represents 16KB.
  */
-#define HAMMER2_FREEMAP_LEVEL5_RADIX   64      /* 16EB (end) */
-#define HAMMER2_FREEMAP_LEVEL4_RADIX   61      /* 2EB */
-#define HAMMER2_FREEMAP_LEVEL3_RADIX   51      /* 2PB */
-#define HAMMER2_FREEMAP_LEVEL2_RADIX   41      /* 2TB */
-#define HAMMER2_FREEMAP_LEVEL1_RADIX   31      /* 2GB */
-#define HAMMER2_FREEMAP_LEVEL0_RADIX   21      /* 2MB (entry in l-1 leaf) */
-
-#define HAMMER2_FREEMAP_LEVELN_PSIZE   65536   /* physical bytes */
-
+#if HAMMER2_SET_COUNT != 4
+#error "hammer2_disk.h - freemap assumes SET_COUNT is 4"
+#endif
+#define HAMMER2_FREEMAP_LEVEL6_RADIX   64      /* 16EB (end) */
+#define HAMMER2_FREEMAP_LEVEL5_RADIX   62      /* 4EB */
+#define HAMMER2_FREEMAP_LEVEL4_RADIX   54      /* 16PB */
+#define HAMMER2_FREEMAP_LEVEL3_RADIX   46      /* 64TB */
+#define HAMMER2_FREEMAP_LEVEL2_RADIX   38      /* 256GB */
+#define HAMMER2_FREEMAP_LEVEL1_RADIX   30      /* 1GB */
+#define HAMMER2_FREEMAP_LEVEL0_RADIX   22      /* 4MB (128by in l-1 leaf) */
+
+#define HAMMER2_FREEMAP_LEVELN_PSIZE   32768   /* physical bytes */
+
+#define HAMMER2_FREEMAP_LEVEL5_SIZE    ((hammer2_off_t)1 <<            \
+                                        HAMMER2_FREEMAP_LEVEL5_RADIX)
 #define HAMMER2_FREEMAP_LEVEL4_SIZE    ((hammer2_off_t)1 <<            \
                                         HAMMER2_FREEMAP_LEVEL4_RADIX)
 #define HAMMER2_FREEMAP_LEVEL3_SIZE    ((hammer2_off_t)1 <<            \
 #define HAMMER2_FREEMAP_LEVEL0_SIZE    ((hammer2_off_t)1 <<            \
                                         HAMMER2_FREEMAP_LEVEL0_RADIX)
 
+#define HAMMER2_FREEMAP_LEVEL5_MASK    (HAMMER2_FREEMAP_LEVEL5_SIZE - 1)
 #define HAMMER2_FREEMAP_LEVEL4_MASK    (HAMMER2_FREEMAP_LEVEL4_SIZE - 1)
 #define HAMMER2_FREEMAP_LEVEL3_MASK    (HAMMER2_FREEMAP_LEVEL3_SIZE - 1)
 #define HAMMER2_FREEMAP_LEVEL2_MASK    (HAMMER2_FREEMAP_LEVEL2_SIZE - 1)
 
 #define HAMMER2_FREEMAP_COUNT          (int)(HAMMER2_FREEMAP_LEVELN_PSIZE / \
                                         sizeof(hammer2_bmap_data_t))
+
+/*
+ * 16KB bitmap granularity (x2 bits per entry).
+ */
 #define HAMMER2_FREEMAP_BLOCK_RADIX    14
 #define HAMMER2_FREEMAP_BLOCK_SIZE     (1 << HAMMER2_FREEMAP_BLOCK_RADIX)
 #define HAMMER2_FREEMAP_BLOCK_MASK     (HAMMER2_FREEMAP_BLOCK_SIZE - 1)
 
 /*
- * bitmap[] structure.  2 bits per HAMMER2_FREEMAP_BLOCK_SIZE.  Each bitmap[]
- * element is 32 bits and thus represents 16 blocks (radix 4).
+ * bitmap[] structure.  2 bits per HAMMER2_FREEMAP_BLOCK_SIZE.
+ *
+ * 8 x 64-bit elements, 2 bits per block.
+ * 32 blocks (radix 5) per element.
+ * representing INDEX_SIZE bytes worth of storage per element.
  */
-#define HAMMER2_BMAP_INDEX_RADIX       4
-#define HAMMER2_BMAP_INDEX_SIZE                (HAMMER2_FREEMAP_BLOCK_SIZE * 16)
+
+typedef uint64_t                       hammer2_bitmap_t;
+
+#define HAMMER2_BMAP_ALLONES           ((hammer2_bitmap_t)-1)
+#define HAMMER2_BMAP_ELEMENTS          8
+#define HAMMER2_BMAP_BITS_PER_ELEMENT  64
+#define HAMMER2_BMAP_INDEX_RADIX       5       /* 32 blocks per element */
+#define HAMMER2_BMAP_BLOCKS_PER_ELEMENT        (1 << HAMMER2_BMAP_INDEX_RADIX)
+
+#define HAMMER2_BMAP_INDEX_SIZE                (HAMMER2_FREEMAP_BLOCK_SIZE * \
+                                        HAMMER2_BMAP_BLOCKS_PER_ELEMENT)
 #define HAMMER2_BMAP_INDEX_MASK                (HAMMER2_BMAP_INDEX_SIZE - 1)
 
 /*
@@ -500,7 +522,7 @@ typedef struct dmsg_lnk_hammer2_volconf dmsg_lnk_hammer2_volconf_t;
 
 /*
  * The media block reference structure.  This forms the core of the HAMMER2
- * media topology recursion.  This 64-byte data structure is embedded in the
+ * media topology recursion.  This 128-byte data structure is embedded in the
  * volume header, in inodes (which are also directory entries), and in
  * indirect blocks.
  *
@@ -556,19 +578,30 @@ struct hammer2_blockref {         /* MUST BE EXACTLY 64 BYTES */
        hammer2_tid_t   mirror_tid;     /* media flush topology & freemap */
        hammer2_tid_t   modify_tid;     /* cluster level change / flush */
        hammer2_off_t   data_off;       /* low 6 bits is phys size (radix)*/
+       hammer2_key_t   data_count;     /* statistics aggregation */
+       hammer2_key_t   inode_count;    /* statistics aggregation */
+       hammer2_key_t   reserved38;
        union {                         /* check info */
-               char    buf[24];
+               char    buf[64];
                struct {
                        uint32_t value;
-                       uint32_t unused[5];
+                       uint32_t reserved[15];
                } iscsi32;
                struct {
                        uint64_t value;
-                       uint64_t unused[2];
+                       uint64_t reserved[7];
                } crc64;
                struct {
                        char data[24];
+                       char reserved[40];
                } sha192;
+               struct {
+                       char data[32];
+                       char reserved[32];
+               } sha256;
+               struct {
+                       char data[64];
+               } sha512;
 
                /*
                 * Freemap hints are embedded in addition to the icrc32.
@@ -584,14 +617,14 @@ struct hammer2_blockref {         /* MUST BE EXACTLY 64 BYTES */
                        uint32_t icrc32;
                        uint32_t bigmask;       /* available radixes */
                        uint64_t avail;         /* total available bytes */
-                       uint64_t unused;        /* unused must be 0 */
+                       char reserved[48];
                } freemap;
        } check;
 };
 
 typedef struct hammer2_blockref hammer2_blockref_t;
 
-#define HAMMER2_BLOCKREF_BYTES         64      /* blockref struct in bytes */
+#define HAMMER2_BLOCKREF_BYTES         128     /* blockref struct in bytes */
 
 /*
  * On-media and off-media blockref types.
@@ -653,16 +686,15 @@ typedef struct hammer2_blockref hammer2_blockref_t;
 
 
 /*
- * HAMMER2 block references are collected into sets of 8 blockrefs.  These
+ * HAMMER2 block references are collected into sets of 4 blockrefs.  These
  * sets are fully associative, meaning the elements making up a set are
  * not sorted in any way and may contain duplicate entries, holes, or
  * entries which shortcut multiple levels of indirection.  Sets are used
  * in various ways:
  *
  * (1) When redundancy is desired a set may contain several duplicate
- *     entries pointing to different copies of the same data.  Up to 8 copies
- *     are supported but the set structure becomes a bit inefficient once
- *     you go over 4.
+ *     entries pointing to different copies of the same data.  Up to 4 copies
+ *     are supported.
  *
  * (2) The blockrefs in a set can shortcut multiple levels of indirections
  *     within the bounds imposed by the parent of set.
@@ -699,12 +731,14 @@ typedef struct hammer2_blockset hammer2_blockset_t;
 /*
  * hammer2_bmap_data - A freemap entry in the LEVEL1 block.
  *
- * Each 64-byte entry contains the bitmap and meta-data required to manage
- * a LEVEL0 (2MB) block of storage.  The storage is managed in 128 x 16KB
- * chunks.  Smaller allocation granularity is supported via a linear iterator
- * and/or must otherwise be tracked in ram.
+ * Each 128-byte entry contains the bitmap and meta-data required to manage
+ * a LEVEL0 (128KB) block of storage.  The storage is managed in 128 x 1KB
+ * chunks.
+ *
+ * A smaller allocation granularity is supported via a linear iterator and/or
+ * must otherwise be tracked in ram.
  *
- * (data structure must be 64 bytes exactly)
+ * (data structure must be 128 bytes exactly)
  *
  * linear  - A BYTE linear allocation offset used for sub-16KB allocations
  *          only.  May contain values between 0 and 2MB.  Must be ignored
@@ -730,7 +764,7 @@ typedef struct hammer2_blockset hammer2_blockset_t;
  *          and directory scans.
  *
  * bitmap  - Two bits per 16KB allocation block arranged in arrays of
- *          32-bit elements, 128x2 bits representing ~2MB worth of media
+ *          32-bit elements, 256x2 bits representing ~4MB worth of media
  *          storage.  Bit patterns are as follows:
  *
  *          00 Unallocated
@@ -749,7 +783,9 @@ struct hammer2_bmap_data {
        uint32_t reserved14;    /* 14 */
        uint32_t reserved18;    /* 18 */
        uint32_t avail;         /* 1C */
-       uint32_t bitmap[8];     /* 20-3F 256 bits manages 2MB/16KB/2-bits */
+       uint32_t reserved20[8]; /* 20-3F 256 bits manages 128K/1KB/2-bits */
+                               /* 40-7F 512 bits manages 4MB of storage */
+       hammer2_bitmap_t bitmapq[HAMMER2_BMAP_ELEMENTS];
 };
 
 typedef struct hammer2_bmap_data hammer2_bmap_data_t;
@@ -867,9 +903,9 @@ struct hammer2_inode_data {
         * the sysop and in-memory structures keep track of inheritence.
         */
        hammer2_key_t   data_quota;     /* 00B0 subtree quota in bytes */
-       hammer2_key_t   data_count;     /* 00B8 subtree byte count */
+       hammer2_key_t   unusedB8;       /* 00B8 subtree byte count */
        hammer2_key_t   inode_quota;    /* 00C0 subtree quota inode count */
-       hammer2_key_t   inode_count;    /* 00C8 subtree inode count */
+       hammer2_key_t   unusedC8;       /* 00C8 subtree inode count */
        hammer2_tid_t   attr_tid;       /* 00D0 attributes changed */
        hammer2_tid_t   dirent_tid;     /* 00D8 directory/attr changed */
 
index ad813b0..9d23dd9 100644 (file)
@@ -828,25 +828,6 @@ again:
                                /* can't be mounted as a PFS */
                        }
 
-                       /*
-                        * Update inode statistics.  Pending stats in chain
-                        * are cleared out on UPDATE so expect that bit to
-                        * be set here too or the statistics will not be
-                        * rolled-up properly.
-                        *
-                        * (note: rollup data does not effect modify_tid
-                        *        based synchronization checks and can be
-                        *        different).
-                        */
-                       if (chain->data_count || chain->inode_count) {
-                               hammer2_inode_data_t *ipdata;
-
-                               KKASSERT(chain->flags & HAMMER2_CHAIN_UPDATE);
-                               hammer2_io_setdirty(chain->dio);
-                               ipdata = &chain->data->ipdata;
-                               ipdata->data_count += chain->data_count;
-                               ipdata->inode_count += chain->inode_count;
-                       }
                        KKASSERT((chain->flags & HAMMER2_CHAIN_EMBEDDED) == 0);
                        hammer2_chain_setcheck(chain, chain->data);
                        break;
@@ -1021,14 +1002,6 @@ again:
                        }
                }
                if (base && (chain->flags & HAMMER2_CHAIN_BMAPPED) == 0) {
-                       parent->data_count += chain->data_count +
-                                             chain->data_count_up;
-                       parent->inode_count += chain->inode_count +
-                                              chain->inode_count_up;
-                       chain->data_count = 0;
-                       chain->inode_count = 0;
-                       chain->data_count_up = 0;
-                       chain->inode_count_up = 0;
                        hammer2_spin_ex(&parent->core.spin);
                        hammer2_base_insert(info->trans, parent,
                                            base, count,
index 3213e65..91d2c71 100644 (file)
@@ -95,16 +95,13 @@ hammer2_freemap_reserve(hammer2_trans_t *trans, hammer2_chain_t *chain,
        hammer2_blockref_t *bref = &chain->bref;
        hammer2_off_t off;
        int index;
+       int index_inc;
        size_t bytes;
 
        /*
-        * Physical allocation size -> radix.  Typically either 256 for
-        * a level 0 freemap leaf or 65536 for a level N freemap node.
-        *
-        * NOTE: A 256 byte bitmap represents 256 x 8 x 1024 = 2MB of storage.
-        *       Do not use hammer2_allocsize() here as it has a min cap.
+        * Physical allocation size.
         */
-       bytes = 1 << radix;
+       bytes = (size_t)1 << radix;
 
        /*
         * Calculate block selection index 0..7 of current block.  If this
@@ -132,34 +129,43 @@ hammer2_freemap_reserve(hammer2_trans_t *trans, hammer2_chain_t *chain,
         * point into the 4MB reserved area at the base of the appropriate
         * 2GB zone, once added to the FREEMAP_x selection above.
         */
+       index_inc = index * HAMMER2_ZONE_FREEMAP_INC;
+
        switch(bref->keybits) {
-       /* case HAMMER2_FREEMAP_LEVEL5_RADIX: not applicable */
+       /* case HAMMER2_FREEMAP_LEVEL6_RADIX: not applicable */
+       case HAMMER2_FREEMAP_LEVEL5_RADIX:      /* 2EB */
+               KKASSERT(bref->type == HAMMER2_BREF_TYPE_FREEMAP_NODE);
+               KKASSERT(bytes == HAMMER2_FREEMAP_LEVELN_PSIZE);
+               off = H2FMBASE(bref->key, HAMMER2_FREEMAP_LEVEL5_RADIX) +
+                     (index_inc + HAMMER2_ZONE_FREEMAP_00 +
+                      HAMMER2_ZONEFM_LEVEL5) * HAMMER2_PBUFSIZE;
+               break;
        case HAMMER2_FREEMAP_LEVEL4_RADIX:      /* 2EB */
                KKASSERT(bref->type == HAMMER2_BREF_TYPE_FREEMAP_NODE);
                KKASSERT(bytes == HAMMER2_FREEMAP_LEVELN_PSIZE);
                off = H2FMBASE(bref->key, HAMMER2_FREEMAP_LEVEL4_RADIX) +
-                     (index * 4 + HAMMER2_ZONE_FREEMAP_00 +
+                     (index_inc + HAMMER2_ZONE_FREEMAP_00 +
                       HAMMER2_ZONEFM_LEVEL4) * HAMMER2_PBUFSIZE;
                break;
        case HAMMER2_FREEMAP_LEVEL3_RADIX:      /* 2PB */
                KKASSERT(bref->type == HAMMER2_BREF_TYPE_FREEMAP_NODE);
                KKASSERT(bytes == HAMMER2_FREEMAP_LEVELN_PSIZE);
                off = H2FMBASE(bref->key, HAMMER2_FREEMAP_LEVEL3_RADIX) +
-                     (index * 4 + HAMMER2_ZONE_FREEMAP_00 +
+                     (index_inc + HAMMER2_ZONE_FREEMAP_00 +
                       HAMMER2_ZONEFM_LEVEL3) * HAMMER2_PBUFSIZE;
                break;
        case HAMMER2_FREEMAP_LEVEL2_RADIX:      /* 2TB */
                KKASSERT(bref->type == HAMMER2_BREF_TYPE_FREEMAP_NODE);
                KKASSERT(bytes == HAMMER2_FREEMAP_LEVELN_PSIZE);
                off = H2FMBASE(bref->key, HAMMER2_FREEMAP_LEVEL2_RADIX) +
-                     (index * 4 + HAMMER2_ZONE_FREEMAP_00 +
+                     (index_inc + HAMMER2_ZONE_FREEMAP_00 +
                       HAMMER2_ZONEFM_LEVEL2) * HAMMER2_PBUFSIZE;
                break;
        case HAMMER2_FREEMAP_LEVEL1_RADIX:      /* 2GB */
                KKASSERT(bref->type == HAMMER2_BREF_TYPE_FREEMAP_LEAF);
                KKASSERT(bytes == HAMMER2_FREEMAP_LEVELN_PSIZE);
                off = H2FMBASE(bref->key, HAMMER2_FREEMAP_LEVEL1_RADIX) +
-                     (index * 4 + HAMMER2_ZONE_FREEMAP_00 +
+                     (index_inc + HAMMER2_ZONE_FREEMAP_00 +
                       HAMMER2_ZONEFM_LEVEL1) * HAMMER2_PBUFSIZE;
                break;
        default:
@@ -368,7 +374,8 @@ hammer2_freemap_try_alloc(hammer2_trans_t *trans, hammer2_chain_t **parentp,
                        (intmax_t)bref->data_off,
                        hammer2_error_str(chain->error));
                error = EIO;
-       } else if ((chain->bref.check.freemap.bigmask & (1 << radix)) == 0) {
+       } else if ((chain->bref.check.freemap.bigmask &
+                  ((size_t)1 << radix)) == 0) {
                /*
                 * Already flagged as not having enough space
                 */
@@ -468,8 +475,10 @@ hammer2_freemap_try_alloc(hammer2_trans_t *trans, hammer2_chain_t **parentp,
                                }
                        }
                }
-               if (error == ENOSPC)
-                       chain->bref.check.freemap.bigmask &= ~(1 << radix);
+               if (error == ENOSPC) {
+                       chain->bref.check.freemap.bigmask &=
+                               (uint32_t)~((size_t)1 << radix);
+               }
                /* XXX also scan down from original count */
        }
 
@@ -529,7 +538,7 @@ hammer2_bmap_alloc(hammer2_trans_t *trans, hammer2_dev_t *hmp,
        size_t size;
        size_t bgsize;
        int bmradix;
-       uint32_t bmmask;
+       hammer2_bitmap_t bmmask;
        int offset;
        int error;
        int i;
@@ -544,7 +553,8 @@ hammer2_bmap_alloc(hammer2_trans_t *trans, hammer2_dev_t *hmp,
                bmradix = 2;
                /* (16K) 2 bits per allocation block */
        } else {
-               bmradix = 2 << (radix - HAMMER2_FREEMAP_BLOCK_RADIX);
+               bmradix = (hammer2_bitmap_t)2 <<
+                         (radix - HAMMER2_FREEMAP_BLOCK_RADIX);
                /* (32K-256K) 4, 8, 16, 32 bits per allocation block */
        }
 
@@ -558,7 +568,7 @@ hammer2_bmap_alloc(hammer2_trans_t *trans, hammer2_dev_t *hmp,
         * previous value can still be used for fragments when 16KB+
         * allocations are made).
         *
-        * Beware of hardware artifacts when bmradix == 32 (intermediate
+        * Beware of hardware artifacts when bmradix == 64 (intermediate
         * result can wind up being '1' instead of '0' if hardware masks
         * bit-count & 31).
         *
@@ -578,16 +588,20 @@ hammer2_bmap_alloc(hammer2_trans_t *trans, hammer2_dev_t *hmp,
                offset = bmap->linear;
                i = offset / (HAMMER2_SEGSIZE / 8);
                j = (offset / (HAMMER2_FREEMAP_BLOCK_SIZE / 2)) & 30;
-               bmmask = (bmradix == 32) ?
-                        0xFFFFFFFFU : (1 << bmradix) - 1;
+               bmmask = (bmradix == HAMMER2_BMAP_BITS_PER_ELEMENT) ?
+                        HAMMER2_BMAP_ALLONES :
+                        ((hammer2_bitmap_t)1 << bmradix) - 1;
                bmmask <<= j;
                bmap->linear = offset + size;
        } else {
-               for (i = 0; i < 8; ++i) {
-                       bmmask = (bmradix == 32) ?
-                                0xFFFFFFFFU : (1 << bmradix) - 1;
-                       for (j = 0; j < 32; j += bmradix) {
-                               if ((bmap->bitmap[i] & bmmask) == 0)
+               for (i = 0; i < HAMMER2_BMAP_ELEMENTS; ++i) {
+                       bmmask = (bmradix == HAMMER2_BMAP_BITS_PER_ELEMENT) ?
+                                HAMMER2_BMAP_ALLONES :
+                                ((hammer2_bitmap_t)1 << bmradix) - 1;
+                       for (j = 0;
+                            j < HAMMER2_BMAP_BITS_PER_ELEMENT;
+                            j += bmradix) {
+                               if ((bmap->bitmapq[i] & bmmask) == 0)
                                        goto success;
                                bmmask <<= bmradix;
                        }
@@ -596,13 +610,14 @@ hammer2_bmap_alloc(hammer2_trans_t *trans, hammer2_dev_t *hmp,
                /*KKASSERT(bmap->avail == 0);*/
                return (ENOSPC);
 success:
-               offset = i * (HAMMER2_SEGSIZE / 8) +
+               offset = i * (HAMMER2_SEGSIZE / HAMMER2_BMAP_ELEMENTS) +
                         (j * (HAMMER2_FREEMAP_BLOCK_SIZE / 2));
                if (size & HAMMER2_FREEMAP_BLOCK_MASK)
                        bmap->linear = offset + size;
        }
 
-       KKASSERT(i >= 0 && i < 8);      /* 8 x 16 -> 128 x 16K -> 2MB */
+       /* 8 x (64/2) -> 256 x 16K -> 4MB */
+       KKASSERT(i >= 0 && i < HAMMER2_BMAP_ELEMENTS);
 
        /*
         * Optimize the buffer cache to avoid unnecessary read-before-write
@@ -612,26 +627,29 @@ success:
         * so the actual bitmap test is somewhat more involved.  We have
         * to use a compatible buffer size for this operation.
         */
-       if ((bmap->bitmap[i] & bmmask) == 0 &&
+       if ((bmap->bitmapq[i] & bmmask) == 0 &&
            hammer2_devblksize(size) != size) {
                size_t psize = hammer2_devblksize(size);
                hammer2_off_t pmask = (hammer2_off_t)psize - 1;
-               int pbmradix = 2 << (hammer2_devblkradix(radix) -
-                                    HAMMER2_FREEMAP_BLOCK_RADIX);
-               uint32_t pbmmask;
+               int pbmradix = (hammer2_bitmap_t)2 <<
+                                       (hammer2_devblkradix(radix) -
+                              HAMMER2_FREEMAP_BLOCK_RADIX);
+               hammer2_bitmap_t pbmmask;
                int pradix = hammer2_getradix(psize);
 
-               pbmmask = (pbmradix == 32) ? 0xFFFFFFFFU : (1 << pbmradix) - 1;
+               pbmmask = (pbmradix == HAMMER2_BMAP_BITS_PER_ELEMENT) ?
+                       HAMMER2_BMAP_ALLONES :
+                       ((hammer2_bitmap_t)1 << pbmradix) - 1;
                while ((pbmmask & bmmask) == 0)
                        pbmmask <<= pbmradix;
 
 #if 0
-               kprintf("%016jx mask %08x %08x %08x (%zd/%zd)\n",
-                       *basep + offset, bmap->bitmap[i],
+               kprintf("%016jx mask %016jx %016jx %016jx (%zd/%zd)\n",
+                       *basep + offset, bmap->bitmapq[i],
                        pbmmask, bmmask, size, psize);
 #endif
 
-               if ((bmap->bitmap[i] & pbmmask) == 0) {
+               if ((bmap->bitmapq[i] & pbmmask) == 0) {
                        error = hammer2_io_newq(hmp,
                                                (*basep + (offset & ~pmask)) |
                                                 pradix,
@@ -666,7 +684,7 @@ success:
         * marked allocated it has already been accounted for.
         */
        if (radix < HAMMER2_FREEMAP_BLOCK_RADIX) {
-               if (bmap->bitmap[i] & bmmask)
+               if (bmap->bitmapq[i] & bmmask)
                        bgsize = 0;
                else
                        bgsize = HAMMER2_FREEMAP_BLOCK_SIZE;
@@ -682,7 +700,7 @@ success:
         * avail must reflect the bitmap-granular availability.  The allocator
         * tests will also check the linear iterator.
         */
-       bmap->bitmap[i] |= bmmask;
+       bmap->bitmapq[i] |= bmmask;
        bmap->class = class;
        bmap->avail -= bgsize;
        *basep += offset;
@@ -754,8 +772,8 @@ hammer2_freemap_init(hammer2_trans_t *trans, hammer2_dev_t *hmp,
 
        for (count = 0; count < HAMMER2_FREEMAP_COUNT; ++count) {
                if (key < lokey || key >= hikey) {
-                       memset(bmap->bitmap, -1,
-                              sizeof(bmap->bitmap));
+                       memset(bmap->bitmapq, -1,
+                              sizeof(bmap->bitmapq));
                        bmap->avail = 0;
                        bmap->linear = HAMMER2_SEGSIZE;
                        chain->bref.check.freemap.avail -=
@@ -815,11 +833,11 @@ hammer2_freemap_adjust(hammer2_trans_t *trans, hammer2_dev_t *hmp,
        hammer2_off_t l0size;
        hammer2_off_t l1size;
        hammer2_off_t l1mask;
-       uint32_t *bitmap;
-       const uint32_t bmmask00 = 0;
-       uint32_t bmmask01;
-       uint32_t bmmask10;
-       uint32_t bmmask11;
+       hammer2_bitmap_t *bitmap;
+       const hammer2_bitmap_t bmmask00 = 0;
+       hammer2_bitmap_t bmmask01;
+       hammer2_bitmap_t bmmask10;
+       hammer2_bitmap_t bmmask11;
        size_t bytes;
        uint16_t class;
        int radix;
@@ -923,9 +941,9 @@ hammer2_freemap_adjust(hammer2_trans_t *trans, hammer2_dev_t *hmp,
         * Calculate the bitmask (runs in 2-bit pairs).
         */
        start = ((int)(data_off >> HAMMER2_FREEMAP_BLOCK_RADIX) & 15) * 2;
-       bmmask01 = 1 << start;
-       bmmask10 = 2 << start;
-       bmmask11 = 3 << start;
+       bmmask01 = (hammer2_bitmap_t)1 << start;
+       bmmask10 = (hammer2_bitmap_t)2 << start;
+       bmmask11 = (hammer2_bitmap_t)3 << start;
 
        /*
         * Fixup the bitmap.  Partial blocks cannot be fully freed unless
@@ -949,7 +967,7 @@ hammer2_freemap_adjust(hammer2_trans_t *trans, hammer2_dev_t *hmp,
 again:
        bmap = &chain->data->bmdata[(int)(data_off >> HAMMER2_SEGRADIX) &
                                    (HAMMER2_FREEMAP_COUNT - 1)];
-       bitmap = &bmap->bitmap[(int)(data_off >> (HAMMER2_SEGRADIX - 3)) & 7];
+       bitmap = &bmap->bitmapq[(int)(data_off >> (HAMMER2_SEGRADIX - 3)) & 7];
 
        if (modified)
                bmap->linear = 0;
@@ -1034,18 +1052,21 @@ again:
                bmmask10 <<= 2;
                bmmask11 <<= 2;
        }
+#if HAMMER2_BMAP_ELEMENTS != 8
+#error "hammer2_freemap.c: HAMMER2_BMAP_ELEMENTS expected to be 8"
+#endif
        if (how == HAMMER2_FREEMAP_DOREALFREE && modified) {
                bmap->avail += 1 << radix;
                KKASSERT(bmap->avail <= HAMMER2_SEGSIZE);
                if (bmap->avail == HAMMER2_SEGSIZE &&
-                   bmap->bitmap[0] == 0 &&
-                   bmap->bitmap[1] == 0 &&
-                   bmap->bitmap[2] == 0 &&
-                   bmap->bitmap[3] == 0 &&
-                   bmap->bitmap[4] == 0 &&
-                   bmap->bitmap[5] == 0 &&
-                   bmap->bitmap[6] == 0 &&
-                   bmap->bitmap[7] == 0) {
+                   bmap->bitmapq[0] == 0 &&
+                   bmap->bitmapq[1] == 0 &&
+                   bmap->bitmapq[2] == 0 &&
+                   bmap->bitmapq[3] == 0 &&
+                   bmap->bitmapq[4] == 0 &&
+                   bmap->bitmapq[5] == 0 &&
+                   bmap->bitmapq[6] == 0 &&
+                   bmap->bitmapq[7] == 0) {
                        key = H2FMBASE(data_off, HAMMER2_FREEMAP_LEVEL0_RADIX);
                        kprintf("Freeseg %016jx\n", (intmax_t)key);
                        bmap->class = 0;
index 4dd6958..c513412 100644 (file)
@@ -1799,9 +1799,9 @@ hammer2_hardlink_consolidate(hammer2_trans_t *trans,
                bzero(&wipdata->pfs_clid, sizeof(wipdata->pfs_clid));
                bzero(&wipdata->pfs_fsid, sizeof(wipdata->pfs_fsid));
                wipdata->data_quota = 0;
-               wipdata->data_count = 0;
+               /* wipdata->data_count = 0; */
                wipdata->inode_quota = 0;
-               wipdata->inode_count = 0;
+               /* wipdata->inode_count = 0; */
                wipdata->attr_tid = 0;
                wipdata->dirent_tid = 0;
                bzero(&wipdata->u, sizeof(wipdata->u));