The branch stable/14 has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=97e2915ab98e786f7310d8477aa48d71a5485e44

commit 97e2915ab98e786f7310d8477aa48d71a5485e44
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2025-06-16 20:33:14 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2025-06-24 00:40:22 +0000

    makefs: Implement the collision differentiator for micro ZAPs
    
    In the unlikely event of a hash collision, the collision differentiator
    is used to create a unique lookup key for ZAP entries.  While the fat
    ZAP implementation in makefs implemented this, the micro ZAP
    implementation did not, so it's possible to end up with collisions in
    directory entries.  These are caught deterministically by OpenZFS, but
    the result is a panic.
    
    Implement a simple differentiator by simply assigning a unique value to
    each ZAP entry.  This scheme works since the 16-bit space of
    differentiators is larger than the maximum number of entries in a micro
    ZAP.  (While the on-disk encoding provides 32 bits of space for the
    differentiator, the in-memory representation of micro ZAP entries is
    smaller.)
    
    PR:             287482
    MFC after:      1 week
    
    (cherry picked from commit 64e0b2e8f75286f9f4d85a86fbb6815b435c7096)
---
 usr.sbin/makefs/zfs/zap.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/usr.sbin/makefs/zfs/zap.c b/usr.sbin/makefs/zfs/zap.c
index d01f7527adf9..decf5fc6a473 100644
--- a/usr.sbin/makefs/zfs/zap.c
+++ b/usr.sbin/makefs/zfs/zap.c
@@ -33,6 +33,7 @@
 
 #include <assert.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -201,6 +202,10 @@ zap_micro_write(zfs_opt_t *zfs, zfs_zap_t *zap)
        mzap_phys_t *mzap;
        mzap_ent_phys_t *ment;
        off_t bytes, loc;
+       uint16_t cd;
+
+       _Static_assert(MZAP_ENT_MAX <= UINT16_MAX,
+           "micro ZAP collision differentiator must fit in 16 bits");
 
        memset(zfs->filebuf, 0, sizeof(zfs->filebuf));
        mzap = (mzap_phys_t *)&zfs->filebuf[0];
@@ -211,10 +216,11 @@ zap_micro_write(zfs_opt_t *zfs, zfs_zap_t *zap)
        bytes = sizeof(*mzap) + (zap->kvpcnt - 1) * sizeof(*ment);
        assert(bytes <= (off_t)MZAP_MAX_BLKSZ);
 
+       cd = 0;
        ment = &mzap->mz_chunk[0];
        STAILQ_FOREACH(ent, &zap->kvps, next) {
                memcpy(&ment->mze_value, ent->valp, ent->intsz * ent->intcnt);
-               ment->mze_cd = 0; /* XXX-MJ */
+               ment->mze_cd = cd++;
                strlcpy(ment->mze_name, ent->name, sizeof(ment->mze_name));
                ment++;
        }

Reply via email to