hammer2 - Make the CRC check code programmable
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 5 Aug 2014 06:58:14 +0000 (23:58 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 5 Aug 2014 07:00:05 +0000 (00:00 -0700)
* Add infrastructure to allow a CRC check code method request to be stored
  in an inode.  The method will be inherited by anything created under the
  inode.

* Refactor the check_algo and comp_algo encoding to make the distinction
  between the requests in ipdata fields and the actual specification stored
  in bref.methods.

* Make sure that the hidden directory inherits the iroot's algorithm
  specifications for consistency.

sys/vfs/hammer2/FREEMAP
sys/vfs/hammer2/TODO
sys/vfs/hammer2/hammer2.h
sys/vfs/hammer2/hammer2_chain.c
sys/vfs/hammer2/hammer2_cluster.c
sys/vfs/hammer2/hammer2_disk.h
sys/vfs/hammer2/hammer2_inode.c
sys/vfs/hammer2/hammer2_ioctl.c
sys/vfs/hammer2/hammer2_vfsops.c

index d8ae1e1..b315305 100644 (file)
     simplify the algorithm and to ensure freemap locality to the blocks
     under management.
 
-    Level 1 - (radix 10 + 21) 16KB blockmap representing 2GB.  There are 1024
-             entries representing ~2MB worth of media storage per entry.
+    Level 1 - (radix 10 + 21) 64KB representing 2GB.  This is represented
+             by a hammer2_bmap_data[1024] array.  Each entry represents
+             2MB worth of media storage x 1024 entries to represent 2GB.
              Each entry contains a 128x2 bit bitmap representing 16KB
-             of storage in 2 bits.
+             of storage in 2 bits (128 x 16KB = 2MB).
 
     Level 2 - (radix 10) 64KB blockmap representing 2TB (~2GB per entry)
     Level 3 - (radix 10) 64KB blockmap representing 2PB (~2TB per entry)
index 0308f00..3c497d6 100644 (file)
@@ -1,4 +1,9 @@
 
+* Currently the check code (bref.methods / crc, sha, etc) is being checked
+  every single blasted time a chain is locked, even if the underlying buffer
+  was previously checked for that chain.  This needs an optimization to
+  (significantly) improve performance.
+
 * flush synchronization boundary crossing check and current flush chain
   interlock needed.
 
index 145c24d..61d8ab3 100644 (file)
@@ -980,6 +980,8 @@ void hammer2_cluster_set_chainflags(hammer2_cluster_t *cluster, uint32_t flags);
 void hammer2_cluster_bref(hammer2_cluster_t *cluster, hammer2_blockref_t *bref);
 void hammer2_cluster_setflush(hammer2_trans_t *trans,
                        hammer2_cluster_t *cluster);
+void hammer2_cluster_setmethod_check(hammer2_trans_t *trans,
+                       hammer2_cluster_t *cluster, int check_algo);
 hammer2_cluster_t *hammer2_cluster_alloc(hammer2_pfsmount_t *pmp,
                        hammer2_trans_t *trans,
                        hammer2_blockref_t *bref);
index 9c0cb8f..242b815 100644 (file)
@@ -3855,6 +3855,8 @@ hammer2_chain_setcheck(hammer2_chain_t *chain, void *bdata)
        switch(HAMMER2_DEC_CHECK(chain->bref.methods)) {
        case HAMMER2_CHECK_NONE:
                break;
+       case HAMMER2_CHECK_DISABLED:
+               break;
        case HAMMER2_CHECK_ISCSI32:
                chain->bref.check.iscsi32.value =
                        hammer2_icrc32(bdata, chain->bytes);
@@ -3903,6 +3905,9 @@ hammer2_chain_testcheck(hammer2_chain_t *chain, void *bdata)
        case HAMMER2_CHECK_NONE:
                r = 1;
                break;
+       case HAMMER2_CHECK_DISABLED:
+               r = 1;
+               break;
        case HAMMER2_CHECK_ISCSI32:
                r = (chain->bref.check.iscsi32.value ==
                     hammer2_icrc32(bdata, chain->bytes));
index 56866e0..2386053 100644 (file)
@@ -140,6 +140,24 @@ hammer2_cluster_setflush(hammer2_trans_t *trans, hammer2_cluster_t *cluster)
        }
 }
 
+void
+hammer2_cluster_setmethod_check(hammer2_trans_t *trans,
+                               hammer2_cluster_t *cluster,
+                               int check_algo)
+{
+       hammer2_chain_t *chain;
+       int i;
+
+       for (i = 0; i < cluster->nchains; ++i) {
+               chain = cluster->array[i];
+               if (chain) {
+                       KKASSERT(chain->flags & HAMMER2_CHAIN_MODIFIED);
+                       chain->bref.methods &= ~HAMMER2_ENC_CHECK(-1);
+                       chain->bref.methods |= HAMMER2_ENC_CHECK(check_algo);
+               }
+       }
+}
+
 /*
  * Create a cluster with one ref from the specified chain.  The chain
  * is not further referenced.  The caller typically supplies a locked
index bc9c0d4..e14f729 100644 (file)
@@ -553,18 +553,35 @@ typedef struct hammer2_blockref hammer2_blockref_t;
 #define HAMMER2_BREF_FLAG_PFSROOT      0x01    /* see also related opflag */
 #define HAMMER2_BREF_FLAG_ZERO         0x02
 
-#define HAMMER2_ENC_CHECK(n)           ((n) << 4)
+/*
+ * Encode/decode check mode and compression mode for
+ * bref.methods.  The compression level is not encoded in
+ * bref.methods.
+ */
+#define HAMMER2_ENC_CHECK(n)           (((n) & 15) << 4)
 #define HAMMER2_DEC_CHECK(n)           (((n) >> 4) & 15)
+#define HAMMER2_ENC_COMP(n)            ((n) & 15)
+#define HAMMER2_DEC_COMP(n)            ((n) & 15)
 
 #define HAMMER2_CHECK_NONE             0
-#define HAMMER2_CHECK_ISCSI32          1
-#define HAMMER2_CHECK_CRC64            2
-#define HAMMER2_CHECK_SHA192           3
-#define HAMMER2_CHECK_FREEMAP          4
+#define HAMMER2_CHECK_DISABLED         1
+#define HAMMER2_CHECK_ISCSI32          2
+#define HAMMER2_CHECK_CRC64            3
+#define HAMMER2_CHECK_SHA192           4
+#define HAMMER2_CHECK_FREEMAP          5
+
+/* user-specifiable check modes only */
+#define HAMMER2_CHECK_STRINGS          { "none", "disabled", "crc32", \
+                                         "crc64", "sha192" }
+#define HAMMER2_CHECK_STRINGS_COUNT    5
 
-#define HAMMER2_ENC_COMP(n)            (n)
+/*
+ * Encode/decode check or compression algorithm request in
+ * ipdata->check_algo and ipdata->comp_algo.
+ */
+#define HAMMER2_ENC_ALGO(n)            (n)
+#define HAMMER2_DEC_ALGO(n)            ((n) & 15)
 #define HAMMER2_ENC_LEVEL(n)           ((n) << 4)
-#define HAMMER2_DEC_COMP(n)            ((n) & 15)
 #define HAMMER2_DEC_LEVEL(n)           (((n) >> 4) & 15)
 
 #define HAMMER2_COMP_NONE              0
@@ -778,7 +795,7 @@ struct hammer2_inode_data {
         *       registration in the cluster.
         */
        uint8_t         target_type;    /* 0084 hardlink target type */
-       uint8_t         reserved85;     /* 0085 */
+       uint8_t         check_algo;     /* 0085 check code request & algo */
        uint8_t         pfs_nmasters;   /* 0086 (if PFSROOT) if multi-master */
        uint8_t         pfs_type;       /* 0087 (if PFSROOT) node type */
        uint64_t        pfs_inum;       /* 0088 (if PFSROOT) inum allocator */
index f03e5df..5f79d3c 100644 (file)
@@ -606,7 +606,8 @@ hammer2_inode_create(hammer2_trans_t *trans, hammer2_inode_t *dip,
        uuid_t dip_uid;
        uuid_t dip_gid;
        uint32_t dip_mode;
-       uint8_t dip_algo;
+       uint8_t dip_comp_algo;
+       uint8_t dip_check_algo;
        int ddflag;
 
        lhc = hammer2_dirhash(name, name_len);
@@ -625,7 +626,8 @@ retry:
        dip_uid = dipdata->uid;
        dip_gid = dipdata->gid;
        dip_mode = dipdata->mode;
-       dip_algo = dipdata->comp_algo;
+       dip_comp_algo = dipdata->comp_algo;
+       dip_check_algo = dipdata->check_algo;
 
        error = 0;
        while (error == 0) {
@@ -714,7 +716,8 @@ retry:
        
        /* Inherit parent's inode compression mode. */
        nip->comp_heuristic = 0;
-       nipdata->comp_algo = dip_algo;
+       nipdata->comp_algo = dip_comp_algo;
+       nipdata->check_algo = dip_check_algo;
        nipdata->version = HAMMER2_INODE_VERSION_ONE;
        hammer2_update_time(&nipdata->ctime);
        nipdata->mtime = nipdata->ctime;
@@ -1396,12 +1399,15 @@ hammer2_inode_install_hidden(hammer2_pfsmount_t *pmp)
        hammer2_cluster_t *cparent;
        hammer2_cluster_t *cluster;
        hammer2_cluster_t *scan;
+       const hammer2_inode_data_t *ripdata;
        hammer2_inode_data_t *wipdata;
        hammer2_key_t key_dummy;
        hammer2_key_t key_next;
        int ddflag;
        int error;
        int count;
+       int dip_check_algo;
+       int dip_comp_algo;
 
        if (pmp->ihidden)
                return;
@@ -1412,7 +1418,22 @@ hammer2_inode_install_hidden(hammer2_pfsmount_t *pmp)
        bzero(&key_dummy, sizeof(key_dummy));
        hammer2_trans_init(&trans, pmp, 0);
 
+       /*
+        * Setup for lookup, retrieve iroot's check and compression
+        * algorithm request which was likely generated by newfs_hammer2.
+        *
+        * The check/comp fields will probably never be used since inodes
+        * are renamed into the hidden directory and not created relative to
+        * the hidden directory, chain creation inherits from bref.methods,
+        * and data chains inherit from their respective file inode *_algo
+        * fields.
+        */
        cparent = hammer2_inode_lock_ex(pmp->iroot);
+       ripdata = &hammer2_cluster_data(cparent)->ipdata;
+       dip_check_algo = ripdata->check_algo;
+       dip_comp_algo = ripdata->comp_algo;
+       ripdata = NULL;
+
        cluster = hammer2_cluster_lookup(cparent, &key_dummy,
                                         HAMMER2_INODE_HIDDENDIR,
                                         HAMMER2_INODE_HIDDENDIR,
@@ -1466,6 +1487,8 @@ hammer2_inode_install_hidden(hammer2_pfsmount_t *pmp)
        wipdata->type = HAMMER2_OBJTYPE_DIRECTORY;
        wipdata->inum = HAMMER2_INODE_HIDDENDIR;
        wipdata->nlinks = 1;
+       wipdata->comp_algo = dip_comp_algo;
+       wipdata->check_algo = dip_check_algo;
        hammer2_cluster_modsync(cluster);
        kprintf("hammer2: PFS root missing hidden directory, creating\n");
 
@@ -1606,6 +1629,7 @@ hammer2_hardlink_consolidate(hammer2_trans_t *trans,
 
                /* wipdata->comp_algo = ripdata->comp_algo; */
                wipdata->comp_algo = 0;
+               wipdata->check_algo = 0;
                wipdata->version = HAMMER2_INODE_VERSION_ONE;
                wipdata->inum = ripdata->inum;
                wipdata->target_type = ripdata->type;
index eb27c1a..ad79d54 100644 (file)
@@ -550,7 +550,8 @@ hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data)
                 * "boot", the boot loader can't decompress (yet).
                 */
                if (strcmp(pfs->name, "boot") == 0)
-                       nipdata->comp_algo = HAMMER2_COMP_AUTOZERO;
+                       nipdata->comp_algo = HAMMER2_ENC_ALGO(
+                                                       HAMMER2_COMP_AUTOZERO);
                hammer2_cluster_modsync(ncluster);
                hammer2_inode_unlock_ex(nip, ncluster);
        }
@@ -645,6 +646,14 @@ hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data)
        cparent = hammer2_inode_lock_ex(ip);
        ripdata = &hammer2_cluster_data(cparent)->ipdata;
 
+       if (ino->ip_data.check_algo != ripdata->check_algo) {
+               wipdata = hammer2_cluster_modify_ip(&trans, ip, cparent, 0);
+               wipdata->check_algo = ino->ip_data.check_algo;
+               ripdata = wipdata; /* safety */
+               hammer2_cluster_setmethod_check(&trans, cparent,
+                                               wipdata->check_algo);
+               dosync = 1;
+       }
        if (ino->ip_data.comp_algo != ripdata->comp_algo) {
                wipdata = hammer2_cluster_modify_ip(&trans, ip, cparent, 0);
                wipdata->comp_algo = ino->ip_data.comp_algo;
index bcb6031..2eeb318 100644 (file)
@@ -219,13 +219,15 @@ static void hammer2_compress_and_write(struct buf *bp, hammer2_trans_t *trans,
                                const hammer2_inode_data_t *ipdata,
                                hammer2_cluster_t *cparent,
                                hammer2_key_t lbase, int ioflag,
-                               int pblksize, int *errorp, int comp_algo);
+                               int pblksize, int *errorp,
+                               int comp_algo, int check_algo);
 static void hammer2_zero_check_and_write(struct buf *bp,
                                hammer2_trans_t *trans, hammer2_inode_t *ip,
                                const hammer2_inode_data_t *ipdata,
                                hammer2_cluster_t *cparent,
                                hammer2_key_t lbase,
-                               int ioflag, int pblksize, int *errorp);
+                               int ioflag, int pblksize, int *errorp,
+                               int check_algo);
 static int test_block_zeros(const char *buf, size_t bytes);
 static void zero_write(struct buf *bp, hammer2_trans_t *trans,
                                hammer2_inode_t *ip,
@@ -234,7 +236,8 @@ static void zero_write(struct buf *bp, hammer2_trans_t *trans,
                                hammer2_key_t lbase,
                                int *errorp);
 static void hammer2_write_bp(hammer2_cluster_t *cluster, struct buf *bp,
-                               int ioflag, int pblksize, int *errorp);
+                               int ioflag, int pblksize, int *errorp,
+                               int check_algo);
 
 static int hammer2_rcvdmsg(kdmsg_msg_t *msg);
 static void hammer2_autodmsg(kdmsg_msg_t *msg);
@@ -1108,7 +1111,7 @@ hammer2_write_file_core(struct buf *bp, hammer2_trans_t *trans,
 {
        hammer2_cluster_t *cluster;
 
-       switch(HAMMER2_DEC_COMP(ipdata->comp_algo)) {
+       switch(HAMMER2_DEC_ALGO(ipdata->comp_algo)) {
        case HAMMER2_COMP_NONE:
                /*
                 * We have to assign physical storage to the buffer
@@ -1121,7 +1124,8 @@ hammer2_write_file_core(struct buf *bp, hammer2_trans_t *trans,
                cluster = hammer2_assign_physical(trans, ip, cparent,
                                                lbase, pblksize,
                                                errorp);
-               hammer2_write_bp(cluster, bp, ioflag, pblksize, errorp);
+               hammer2_write_bp(cluster, bp, ioflag, pblksize, errorp,
+                                ipdata->check_algo);
                if (cluster)
                        hammer2_cluster_unlock(cluster);
                break;
@@ -1131,7 +1135,8 @@ hammer2_write_file_core(struct buf *bp, hammer2_trans_t *trans,
                 */
                hammer2_zero_check_and_write(bp, trans, ip,
                                    ipdata, cparent, lbase,
-                                   ioflag, pblksize, errorp);
+                                   ioflag, pblksize, errorp,
+                                   ipdata->check_algo);
                break;
        case HAMMER2_COMP_LZ4:
        case HAMMER2_COMP_ZLIB:
@@ -1143,7 +1148,8 @@ hammer2_write_file_core(struct buf *bp, hammer2_trans_t *trans,
                                           ipdata, cparent,
                                           lbase, ioflag,
                                           pblksize, errorp,
-                                          ipdata->comp_algo);
+                                          ipdata->comp_algo,
+                                          ipdata->check_algo);
                break;
        }
 }
@@ -1159,7 +1165,7 @@ hammer2_compress_and_write(struct buf *bp, hammer2_trans_t *trans,
        hammer2_inode_t *ip, const hammer2_inode_data_t *ipdata,
        hammer2_cluster_t *cparent,
        hammer2_key_t lbase, int ioflag, int pblksize,
-       int *errorp, int comp_algo)
+       int *errorp, int comp_algo, int check_algo)
 {
        hammer2_cluster_t *cluster;
        hammer2_chain_t *chain;
@@ -1183,7 +1189,7 @@ hammer2_compress_and_write(struct buf *bp, hammer2_trans_t *trans,
                int comp_level;
                int ret;
 
-               switch(HAMMER2_DEC_COMP(comp_algo)) {
+               switch(HAMMER2_DEC_ALGO(comp_algo)) {
                case HAMMER2_COMP_LZ4:
                        comp_buffer = objcache_get(cache_buffer_write,
                                                   M_INTWAIT);
@@ -1284,7 +1290,6 @@ hammer2_compress_and_write(struct buf *bp, hammer2_trans_t *trans,
        for (i = 0; i < cluster->nchains; ++i) {
                hammer2_io_t *dio;
                char *bdata;
-               int temp_check;
 
                chain = cluster->array[i];
                KKASSERT(chain->flags & HAMMER2_CHAIN_MODIFIED);
@@ -1298,8 +1303,6 @@ hammer2_compress_and_write(struct buf *bp, hammer2_trans_t *trans,
                              HAMMER2_EMBEDDED_BYTES);
                        break;
                case HAMMER2_BREF_TYPE_DATA:
-                       temp_check = HAMMER2_DEC_CHECK(chain->bref.methods);
-
                        /*
                         * Optimize out the read-before-write
                         * if possible.
@@ -1323,7 +1326,7 @@ hammer2_compress_and_write(struct buf *bp, hammer2_trans_t *trans,
                        if (comp_size) {
                                chain->bref.methods =
                                        HAMMER2_ENC_COMP(comp_algo) +
-                                       HAMMER2_ENC_CHECK(temp_check);
+                                       HAMMER2_ENC_CHECK(check_algo);
                                bcopy(comp_buffer, bdata, comp_size);
                                if (comp_size != comp_block_size) {
                                        bzero(bdata + comp_size,
@@ -1333,7 +1336,7 @@ hammer2_compress_and_write(struct buf *bp, hammer2_trans_t *trans,
                                chain->bref.methods =
                                        HAMMER2_ENC_COMP(
                                                HAMMER2_COMP_NONE) +
-                                       HAMMER2_ENC_CHECK(temp_check);
+                                       HAMMER2_ENC_CHECK(check_algo);
                                bcopy(bp->b_data, bdata, pblksize);
                        }
 
@@ -1392,7 +1395,8 @@ void
 hammer2_zero_check_and_write(struct buf *bp, hammer2_trans_t *trans,
        hammer2_inode_t *ip, const hammer2_inode_data_t *ipdata,
        hammer2_cluster_t *cparent,
-       hammer2_key_t lbase, int ioflag, int pblksize, int *errorp)
+       hammer2_key_t lbase, int ioflag, int pblksize, int *errorp,
+       int check_algo)
 {
        hammer2_cluster_t *cluster;
 
@@ -1401,7 +1405,8 @@ hammer2_zero_check_and_write(struct buf *bp, hammer2_trans_t *trans,
        } else {
                cluster = hammer2_assign_physical(trans, ip, cparent,
                                                  lbase, pblksize, errorp);
-               hammer2_write_bp(cluster, bp, ioflag, pblksize, errorp);
+               hammer2_write_bp(cluster, bp, ioflag, pblksize, errorp,
+                                check_algo);
                if (cluster)
                        hammer2_cluster_unlock(cluster);
        }
@@ -1467,22 +1472,19 @@ zero_write(struct buf *bp, hammer2_trans_t *trans,
 static
 void
 hammer2_write_bp(hammer2_cluster_t *cluster, struct buf *bp, int ioflag,
-                               int pblksize, int *errorp)
+                               int pblksize, int *errorp, int check_algo)
 {
        hammer2_chain_t *chain;
        hammer2_io_t *dio;
        char *bdata;
        int error;
        int i;
-       int temp_check;
 
        error = 0;      /* XXX TODO below */
 
        for (i = 0; i < cluster->nchains; ++i) {
                chain = cluster->array[i];
 
-               temp_check = HAMMER2_DEC_CHECK(chain->bref.methods);
-
                KKASSERT(chain->flags & HAMMER2_CHAIN_MODIFIED);
 
                switch(chain->bref.type) {
@@ -1508,7 +1510,7 @@ hammer2_write_bp(hammer2_cluster_t *cluster, struct buf *bp, int ioflag,
 
                        chain->bref.methods = HAMMER2_ENC_COMP(
                                                        HAMMER2_COMP_NONE) +
-                                             HAMMER2_ENC_CHECK(temp_check);
+                                             HAMMER2_ENC_CHECK(check_algo);
                        bcopy(bp->b_data, bdata, chain->bytes);
 
                        /*