@@ -431,6 +431,8 @@ xfs_attr_hashval(
if (attr_flags & XFS_ATTR_PARENT)
return xfs_parent_hashattr(mp, name, namelen, value, valuelen);
+ if (attr_flags & XFS_ATTR_VERITY)
+ return xfs_verity_hashname(name, namelen);
return xfs_attr_hashname(name, namelen);
}
@@ -936,4 +936,10 @@ struct xfs_merkle_key {
#define XFS_VERITY_DESCRIPTOR_NAME "vdesc"
#define XFS_VERITY_DESCRIPTOR_NAME_LEN (sizeof(XFS_VERITY_DESCRIPTOR_NAME) - 1)
+/*
+ * Merkle tree blocks cannot be smaller than 1k in size, so the hash function
+ * can right-shift the merkle offset by this amount without losing anything.
+ */
+#define XFS_VERITY_HASH_SHIFT (10)
+
#endif /* __XFS_DA_FORMAT_H__ */
@@ -56,3 +56,19 @@ xfs_verity_namecheck(
return true;
}
+
+/*
+ * Compute name hash for a verity attribute. For merkle tree blocks, we want
+ * to use the merkle tree block offset as the hash value to avoid collisions
+ * between blocks unless the merkle tree becomes larger than 2^32 blocks.
+ */
+xfs_dahash_t
+xfs_verity_hashname(
+ const uint8_t *name,
+ unsigned int namelen)
+{
+ if (namelen != sizeof(struct xfs_merkle_key))
+ return xfs_attr_hashname(name, namelen);
+
+ return xfs_merkle_key_from_disk(name, namelen) >> XFS_VERITY_HASH_SHIFT;
+}
@@ -9,5 +9,6 @@ void xfs_merkle_key_to_disk(struct xfs_merkle_key *key, uint64_t offset);
uint64_t xfs_merkle_key_from_disk(const void *attr_name, int namelen);
bool xfs_verity_namecheck(unsigned int attr_flags, const void *name,
int namelen);
+xfs_dahash_t xfs_verity_hashname(const uint8_t *name, unsigned int namelen);
#endif /* __XFS_VERITY_H__ */