Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2222593/?format=api
{ "id": 2222593, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2222593/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-ext4/patch/20260413065114.730231-2-409411716@gms.tku.edu.tw/", "project": { "id": 8, "url": "http://patchwork.ozlabs.org/api/1.1/projects/8/?format=api", "name": "Linux ext4 filesystem development", "link_name": "linux-ext4", "list_id": "linux-ext4.vger.kernel.org", "list_email": "linux-ext4@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null }, "msgid": "<20260413065114.730231-2-409411716@gms.tku.edu.tw>", "date": "2026-04-13T06:51:13", "name": "[v3,1/2] ext4: add Kunit coverage for directory hash computation", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "5c684d2e4f9d6ac5aa0fee9f293439647ff77845", "submitter": { "id": 92099, "url": "http://patchwork.ozlabs.org/api/1.1/people/92099/?format=api", "name": "Guan-Chun Wu", "email": "409411716@gms.tku.edu.tw" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-ext4/patch/20260413065114.730231-2-409411716@gms.tku.edu.tw/mbox/", "series": [ { "id": 499652, "url": "http://patchwork.ozlabs.org/api/1.1/series/499652/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-ext4/list/?series=499652", "date": "2026-04-13T06:51:13", "name": "ext4: add hash Kunit tests and optimize str2hashbuf", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/499652/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2222593/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2222593/checks/", "tags": {}, "headers": { "Return-Path": "\n <SRS0=c3Jz=CM=vger.kernel.org=linux-ext4+bounces-15802-patchwork-incoming=ozlabs.org@ozlabs.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-ext4@vger.kernel.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "patchwork-incoming@ozlabs.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gms-tku-edu-tw.20251104.gappssmtp.com\n header.i=@gms-tku-edu-tw.20251104.gappssmtp.com header.a=rsa-sha256\n header.s=20251104 header.b=OehaQSmK;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org\n (client-ip=2404:9400:2221:ea00::3; helo=mail.ozlabs.org;\n envelope-from=srs0=c3jz=cm=vger.kernel.org=linux-ext4+bounces-15802-patchwork-incoming=ozlabs.org@ozlabs.org;\n receiver=patchwork.ozlabs.org)", "gandalf.ozlabs.org;\n arc=pass smtp.remote-ip=\"2600:3c04:e001:36c::12fc:5321\"\n arc.chain=subspace.kernel.org", "gandalf.ozlabs.org;\n dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw", "gandalf.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gms-tku-edu-tw.20251104.gappssmtp.com\n header.i=@gms-tku-edu-tw.20251104.gappssmtp.com header.a=rsa-sha256\n header.s=20251104 header.b=OehaQSmK;\n\tdkim-atps=neutral", "gandalf.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-ext4+bounces-15802-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20251104.gappssmtp.com\n header.i=@gms-tku-edu-tw.20251104.gappssmtp.com header.b=\"OehaQSmK\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.214.175", "smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=gms.tku.edu.tw" ], "Received": [ "from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1 raw public key)\n server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fvJ3y24qTz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 13 Apr 2026 16:51:57 +1000 (AEST)", "from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\tby gandalf.ozlabs.org (Postfix) with ESMTP id 4fvJ3q5RrFz4wHp\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 13 Apr 2026 16:51:51 +1000 (AEST)", "by gandalf.ozlabs.org (Postfix)\n\tid 4fvJ3q51P6z4wHk; Mon, 13 Apr 2026 16:51:51 +1000 (AEST)", "from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby gandalf.ozlabs.org (Postfix) with ESMTPS id 4fvJ3l44Vgz4wHp\n\tfor <patchwork-incoming@ozlabs.org>; Mon, 13 Apr 2026 16:51:47 +1000 (AEST)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 268633012C9C\n\tfor <patchwork-incoming@ozlabs.org>; Mon, 13 Apr 2026 06:51:43 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 2EE4E391517;\n\tMon, 13 Apr 2026 06:51:40 +0000 (UTC)", "from mail-pl1-f175.google.com (mail-pl1-f175.google.com\n [209.85.214.175])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B4D6190462\n\tfor <linux-ext4@vger.kernel.org>; Mon, 13 Apr 2026 06:51:36 +0000 (UTC)", "by mail-pl1-f175.google.com with SMTP id\n d9443c01a7336-2ab39b111b9so18595825ad.1\n for <linux-ext4@vger.kernel.org>;\n Sun, 12 Apr 2026 23:51:36 -0700 (PDT)", "from wu-Pro-E500-G6-WS720T..\n ([2001:288:7001:2703:d062:a770:8a34:87a2])\n by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2b2d4dde346sm100107855ad.29.2026.04.12.23.51.33\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Sun, 12 Apr 2026 23:51:35 -0700 (PDT)" ], "ARC-Seal": [ "i=2; a=rsa-sha256; d=ozlabs.org; s=201707; t=1776063111; cv=pass;\n\tb=OkKt4BZNRw3OMxvwOpHttZSMFu1Ey0OIFlp4ZIF4bI7fXEkGq32S5FiyCg7PxxzDfi6qoAyBH71LVri4hkA3kvQPIdfiC690OPgPd5lSuR14n0qAWypv1ucfJrOdCTmSOAmmdTk7sLvVNPWXsvXaAaIJ6Vws/ruBvh7rBMZWeR0K6q6c8k6xc6ceiYhUqOWl3F7VuN417p9h+kk1xn8sXYxWtku9PfctWe94orhuGrn/75DG+DeoZfkSqir56XJHo2EbHNiyfyV5cOIEqdVqnGC6Gd+sGnAC2s/8sPslVLKUBVlG2DDhnq7HBamxAB0flys7393LsTX2YC4iJKab9Q==", "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776063100; cv=none;\n b=l9xcM1TTXKM+JeHD5j5+qKoRd16HMDkVzYJ4+uAaWACeOUprNx9WyxhnvjfFt+eKlZZm8w/I7Yt65SWXHcuH+aaGDb/oNHJdBVZMFR/Q6D2DCf9X0POo6jvmdE8eYZNJQzGwfBXTiy5TCwic/Car+BGzDLrzlBpQQjFexrXWzEI=" ], "ARC-Message-Signature": [ "i=2; a=rsa-sha256; d=ozlabs.org; s=201707;\n\tt=1776063111; c=relaxed/relaxed;\n\tbh=IaJZBskiv7Rb1V4NrQfCtdYsCLSrKzxcTk4n0XYetus=;\n\th=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:\n\t MIME-Version;\n b=j8UTdvBtlds0afYzZN0Hps7fo8djyIr90HbUagWPOgmmOFsysIeGyQnpdITbRvnbfqvbsrYBaGFCwiU7bBUX9p5ggPjaGGKyU81cKy4wSBISPzeVBPWmqVrg9FUL0j3FLubdtVPjsR+2Zhppw6RFW7VaBUY5SximnzKX2TZoADdTiS6lC3iBFC4RaqeL+i4e+/lxlV+ZNBwqfq5bduY9iO/95taOMdxST3OhVhV8XQwsRwyQjOk32HHuitewqdbDWPdpXs4t2whcTmsMns/Pek5suti3C6YNxf+c5bHawDHInpyeSL0ASRdNGuK552bIbpOU8AsnsHQ5kL2EiwIOcQ==", "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776063100; c=relaxed/simple;\n\tbh=HP+Ej0HV+2ncsP88mh6+XiDWyyHr/4TFTjdUK5p+TrM=;\n\th=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:\n\t MIME-Version;\n b=jh5VNCbhhE29ShY2J4PeBPiUydo4Sa/L0yfWCb2HldfAWH8BrvjPGSuNqEel9C3YaELVb2F+J1d2lmZu0Mzzl//4EB2JtKyStbHdZysXLtkpsLI58kGApu9+fua6108Zp+J2d0nvwz2ip9a3MDc9+dKEamiL8nr4Vy0ssZEswng=" ], "ARC-Authentication-Results": [ "i=2; gandalf.ozlabs.org;\n dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw;\n dkim=pass (2048-bit key;\n unprotected) header.d=gms-tku-edu-tw.20251104.gappssmtp.com\n header.i=@gms-tku-edu-tw.20251104.gappssmtp.com header.a=rsa-sha256\n header.s=20251104 header.b=OehaQSmK; dkim-atps=neutral;\n spf=pass (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-ext4+bounces-15802-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org) smtp.mailfrom=vger.kernel.org", "i=1; smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=gms.tku.edu.tw;\n spf=pass smtp.mailfrom=gms.tku.edu.tw;\n dkim=pass (2048-bit key) header.d=gms-tku-edu-tw.20251104.gappssmtp.com\n header.i=@gms-tku-edu-tw.20251104.gappssmtp.com header.b=OehaQSmK;\n arc=none smtp.client-ip=209.85.214.175" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gms-tku-edu-tw.20251104.gappssmtp.com; s=20251104; t=1776063096;\n x=1776667896; darn=vger.kernel.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=IaJZBskiv7Rb1V4NrQfCtdYsCLSrKzxcTk4n0XYetus=;\n b=OehaQSmK7u1tw8ghncdcqjLfXE0IZXelENcclRAGjufTKln+qZ0xM4y/7uJRgmDgkp\n umrEhRRNnlKE7n4j4/cD2d2jD4f0Smc7TQKJpyY3bgMP33NlDUfZBrHNquyGw9MB2pRk\n VITbniSiAZCPb9wgWjTmYvbhIBda1g+Z88+tAGz7rb9/JpPt5PBe0j1zNYuVRU7TJCJO\n ntx7Kilz5ph2q74kJVAB4gSpvhuz9aUcO2eZnd+TQqcajVikeMkgTpk+6YzOLYZcI1Td\n 0dveEbbDV5Vvgp/5+yPGs12Nx+Ey57agwQSAodf4QW+uHIPt78QTrmdr3P8QQ+WXuJIO\n ZbSw==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776063096; x=1776667896;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=IaJZBskiv7Rb1V4NrQfCtdYsCLSrKzxcTk4n0XYetus=;\n b=Z1RSNFYO+Yxq9P3yuc5B/lxBX5/zIB8k9Q5bEUhY41Q0uZL+sXcsj/DgL5DeCxs179\n KbVpOPxgBX7LR8vY4MIMxofbLw2NDWPCGFp4AmHsa63zcUEmB7NPliKtuDF/4kOh2ZWe\n 3YEYun0RPHJpxGl8ZYPJBvUUennnUnAUBf2w2xh8N64738sB0Jf/1RFkIl0NSqhcXH7o\n pVXG0dT4lvjy7K1kY9ggwhUI1GjP70eGRTeHGoJpDtsYNUgEy9yrFPeviskyB9K2omau\n H3aYneCebzRvtwIZkPA9sGBU7ue+16+h7n0BzKb1Lm2RQmZThqZaJ9MRr8ZtdJ15XzVc\n h18A==", "X-Gm-Message-State": "AOJu0YzhD/5b5UhD6e6wAP12oGcDG0zIYNgSIL8aCxAbvWlraxzwh0f+\n\tsS10uEAEbb4eYSyo02Nm7qjWCBJVNLJaPqNURH3zVPftcJMlyS2x5EdnMto/3yVuplo=", "X-Gm-Gg": "AeBDietNqwEkNJZbVSYrgkoC3D4J88LN0ujbVoAfRAiB9rCzZlB9ulOLrCxNSrmSgkO\n\t9J7AFjzmJc1yEY6alb2nfxI6Drv4mpYgHqnBBibihl+ysoUPIcqPuKl6DMpXOOQWH2Ge6Kb/HWR\n\tNui7vkK1mdEimOap1naYGDRQnWFeSFGI+DwRxi+p2N8EbUdGCoqFJqvJ+JljxPfwyFD33zXX5DX\n\t3nYswjDGyg7ynHMSbUr2HmZ4z4pgKKLkUnFti4NzKtfo3hnddFoCD+7za3BIl1KD5KkV9/ZSXaa\n\tG3KgyfZ8qod2vSDgyBKh4ekQE2b9RMBWGvjKTXvRclv9DiW3ExMoaQaDKStHU3H5pWnrDjB1tWI\n\taeySW3nWS+1L71GNNriIyFytg4aZaDMyJQqYvZfwmdy1dtSr5pgNcAeMsWFQfGuN68GSxntQIxY\n\tv1TaGWxBJH3q/Nq2hfiDm6v0kHnHH2TtUO8E24iGCuoTZywds=", "X-Received": "by 2002:a17:903:40cf:b0:2b0:673a:7c90 with SMTP id\n d9443c01a7336-2b2d5a1c860mr124346885ad.28.1776063096180;\n Sun, 12 Apr 2026 23:51:36 -0700 (PDT)", "From": "Guan-Chun Wu <409411716@gms.tku.edu.tw>", "To": "Theodore Ts'o <tytso@mit.edu>,\n\tAndreas Dilger <adilger.kernel@dilger.ca>,\n\tBaokun Li <libaokun@linux.alibaba.com>,\n\tJan Kara <jack@suse.cz>,\n\tOjaswin Mujoo <ojaswin@linux.ibm.com>,\n\tRitesh Harjani <ritesh.list@gmail.com>,\n\tZhang Yi <yi.zhang@huawei.com>", "Cc": "linux-ext4@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\tedward062254@gmail.com,\n\tvisitorckw@gmail.com,\n\tdavid.laight.linux@gmail.com,\n\tGuan-Chun Wu <409411716@gms.tku.edu.tw>", "Subject": "[PATCH v3 1/2] ext4: add Kunit coverage for directory hash\n computation", "Date": "Mon, 13 Apr 2026 14:51:13 +0800", "Message-Id": "<20260413065114.730231-2-409411716@gms.tku.edu.tw>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20260413065114.730231-1-409411716@gms.tku.edu.tw>", "References": "<20260413065114.730231-1-409411716@gms.tku.edu.tw>", "Precedence": "bulk", "X-Mailing-List": "linux-ext4@vger.kernel.org", "List-Id": "<linux-ext4.vger.kernel.org>", "List-Subscribe": "<mailto:linux-ext4+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-ext4+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-Spam-Status": "No, score=-1.1 required=5.0 tests=ARC_SIGNED,ARC_VALID,\n\tDKIM_SIGNED,DKIM_VALID,DMARC_MISSING,HEADER_FROM_DIFFERENT_DOMAINS,\n\tMAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=disabled\n\tversion=4.0.1", "X-Spam-Checker-Version": "SpamAssassin 4.0.1 (2024-03-25) on gandalf.ozlabs.org" }, "content": "Introduce Kunit tests for fs/ext4/hash.c to verify ext4fs_dirhash()\nacross the legacy, half-MD4, and TEA hash variants.\n\nThe tests cover empty, seeded hashing, and non-ASCII name handling.\nThey also verify error paths, including invalid hash versions and\nSipHash without a configured key, and check that the signed and\nunsigned hash variants differ on non-ASCII input as expected.\n\nWhen CONFIG_UNICODE is enabled, the tests further verify casefolded-name\nhashing and the fallback behavior for invalid input.\n\nCo-developed-by: Chen Hao Yu <edward062254@gmail.com>\nSigned-off-by: Chen Hao Yu <edward062254@gmail.com>\nSigned-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw>\n---\n fs/ext4/Makefile | 2 +-\n fs/ext4/hash-test.c | 546 ++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 547 insertions(+), 1 deletion(-)\n create mode 100644 fs/ext4/hash-test.c", "diff": "diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile\nindex 3baee4e7c..3f9fc0eb8 100644\n--- a/fs/ext4/Makefile\n+++ b/fs/ext4/Makefile\n@@ -15,7 +15,7 @@ ext4-y\t:= balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \\\n ext4-$(CONFIG_EXT4_FS_POSIX_ACL)\t+= acl.o\n ext4-$(CONFIG_EXT4_FS_SECURITY)\t\t+= xattr_security.o\n ext4-test-objs\t\t\t\t+= inode-test.o mballoc-test.o \\\n-\t\t\t\t\t extents-test.o\n+\t\t\t\t\t extents-test.o hash-test.o\n obj-$(CONFIG_EXT4_KUNIT_TESTS)\t\t+= ext4-test.o\n ext4-$(CONFIG_FS_VERITY)\t\t+= verity.o\n ext4-$(CONFIG_FS_ENCRYPTION)\t\t+= crypto.o\ndiff --git a/fs/ext4/hash-test.c b/fs/ext4/hash-test.c\nnew file mode 100644\nindex 000000000..a151b5684\n--- /dev/null\n+++ b/fs/ext4/hash-test.c\n@@ -0,0 +1,546 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * KUnit tests for ext4 directory hash computation.\n+ */\n+\n+#include <kunit/test.h>\n+#include <linux/fs.h>\n+#include <linux/string.h>\n+#include <linux/unicode.h>\n+#include \"ext4.h\"\n+\n+static void ext4_hash_init_fake_dir(struct inode *dir, struct super_block *sb)\n+{\n+\tmemset(sb, 0, sizeof(*sb));\n+\tmemset(dir, 0, sizeof(*dir));\n+\tdir->i_sb = sb;\n+\tstrscpy(sb->s_id, \"kunit-ext4\", sizeof(sb->s_id));\n+}\n+\n+static void ext4_hash_init_fake_dir_with_sbi(struct inode *dir,\n+\t\t\t\t\t struct super_block *sb,\n+\t\t\t\t\t struct ext4_sb_info *sbi)\n+{\n+\text4_hash_init_fake_dir(dir, sb);\n+\tmemset(sbi, 0, sizeof(*sbi));\n+\tsb->s_fs_info = sbi;\n+\tsbi->s_sb = sb;\n+}\n+\n+#if IS_ENABLED(CONFIG_UNICODE)\n+static void ext4_hash_init_fake_ext4_dir(struct ext4_inode_info *ei,\n+\t\t\t\t\t struct super_block *sb,\n+\t\t\t\t\t struct ext4_sb_info *sbi)\n+{\n+\tmemset(sb, 0, sizeof(*sb));\n+\tmemset(ei, 0, sizeof(*ei));\n+\tmemset(sbi, 0, sizeof(*sbi));\n+\n+\tinode_init_once(&ei->vfs_inode);\n+\tei->vfs_inode.i_sb = sb;\n+\tei->vfs_inode.i_mode = S_IFDIR;\n+\n+\tstrscpy(sb->s_id, \"kunit-ext4\", sizeof(sb->s_id));\n+\tsb->s_fs_info = sbi;\n+\tsbi->s_sb = sb;\n+}\n+#endif\n+\n+struct ext4_dirhash_test_case {\n+\tconst char *name;\n+\tu32 hash_version;\n+\tconst char *input;\n+\tint len;\n+\tu32 seed[4];\n+\tbool use_seed;\n+\tu32 expected_hash;\n+\tu32 expected_minor_hash;\n+};\n+\n+static const struct ext4_dirhash_test_case ext4_dirhash_test_cases[] = {\n+\t{\n+\t\t.name = \"legacy_abc\",\n+\t\t.hash_version = DX_HASH_LEGACY,\n+\t\t.input = \"abc\",\n+\t\t.len = 3,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0x75afd992,\n+\t\t.expected_minor_hash = 0x00000000,\n+\t},\n+\t{\n+\t\t.name = \"legacy_unsigned_abc\",\n+\t\t.hash_version = DX_HASH_LEGACY_UNSIGNED,\n+\t\t.input = \"abc\",\n+\t\t.len = 3,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0x75afd992,\n+\t\t.expected_minor_hash = 0x00000000,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_abc\",\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t\t.input = \"abc\",\n+\t\t.len = 3,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xd196a868,\n+\t\t.expected_minor_hash = 0xc420eb28,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_unsigned_abc\",\n+\t\t.hash_version = DX_HASH_HALF_MD4_UNSIGNED,\n+\t\t.input = \"abc\",\n+\t\t.len = 3,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xd196a868,\n+\t\t.expected_minor_hash = 0xc420eb28,\n+\t},\n+\t{\n+\t\t.name = \"tea_abc\",\n+\t\t.hash_version = DX_HASH_TEA,\n+\t\t.input = \"abc\",\n+\t\t.len = 3,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xb1435ec4,\n+\t\t.expected_minor_hash = 0x3f7eaa0e,\n+\t},\n+\t{\n+\t\t.name = \"tea_unsigned_abc\",\n+\t\t.hash_version = DX_HASH_TEA_UNSIGNED,\n+\t\t.input = \"abc\",\n+\t\t.len = 3,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xb1435ec4,\n+\t\t.expected_minor_hash = 0x3f7eaa0e,\n+\t},\n+\t{\n+\t\t.name = \"empty_half_md4\",\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t\t.input = \"\",\n+\t\t.len = 0,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xefcdab88,\n+\t\t.expected_minor_hash = 0x98badcfe,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_31bytes\",\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t\t.input = \"1234567890123456789012345678901\",\n+\t\t.len = 31,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xc4db1f78,\n+\t\t.expected_minor_hash = 0xea23921b,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_32bytes\",\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t\t.input = \"12345678901234567890123456789012\",\n+\t\t.len = 32,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xfa6cc63e,\n+\t\t.expected_minor_hash = 0x2f77bd1c,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_33bytes\",\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t\t.input = \"123456789012345678901234567890123\",\n+\t\t.len = 33,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xdc0c2dec,\n+\t\t.expected_minor_hash = 0x5ca23365,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_unsigned_31bytes\",\n+\t\t.hash_version = DX_HASH_HALF_MD4_UNSIGNED,\n+\t\t.input = \"1234567890123456789012345678901\",\n+\t\t.len = 31,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xc4db1f78,\n+\t\t.expected_minor_hash = 0xea23921b,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_unsigned_32bytes\",\n+\t\t.hash_version = DX_HASH_HALF_MD4_UNSIGNED,\n+\t\t.input = \"12345678901234567890123456789012\",\n+\t\t.len = 32,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xfa6cc63e,\n+\t\t.expected_minor_hash = 0x2f77bd1c,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_unsigned_33bytes\",\n+\t\t.hash_version = DX_HASH_HALF_MD4_UNSIGNED,\n+\t\t.input = \"123456789012345678901234567890123\",\n+\t\t.len = 33,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xdc0c2dec,\n+\t\t.expected_minor_hash = 0x5ca23365,\n+\t},\n+\t{\n+\t\t.name = \"tea_15bytes\",\n+\t\t.hash_version = DX_HASH_TEA,\n+\t\t.input = \"123456789abcdef\",\n+\t\t.len = 15,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xa562903a,\n+\t\t.expected_minor_hash = 0x6174a00f,\n+\t},\n+\t{\n+\t\t.name = \"tea_16bytes\",\n+\t\t.hash_version = DX_HASH_TEA,\n+\t\t.input = \"1234567890abcdef\",\n+\t\t.len = 16,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0x8449f258,\n+\t\t.expected_minor_hash = 0x49a16d46,\n+\t},\n+\t{\n+\t\t.name = \"tea_17bytes\",\n+\t\t.hash_version = DX_HASH_TEA,\n+\t\t.input = \"123456789abcdefgh\",\n+\t\t.len = 17,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xf32ec10c,\n+\t\t.expected_minor_hash = 0x58ceae61,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_seeded\",\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t\t.input = \"same-name\",\n+\t\t.len = 9,\n+\t\t.seed = { 0x11111111, 0x22222222, 0x33333333, 0x44444444 },\n+\t\t.use_seed = true,\n+\t\t.expected_hash = 0x8aebf604,\n+\t\t.expected_minor_hash = 0x66ce48fe,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_non_ascii_signed\",\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t\t.input = \"\\x80\\x81\\x82\\x83\\x84\",\n+\t\t.len = 5,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0x8bab0498,\n+\t\t.expected_minor_hash = 0xc326632d,\n+\t},\n+\t{\n+\t\t.name = \"half_md4_non_ascii_unsigned\",\n+\t\t.hash_version = DX_HASH_HALF_MD4_UNSIGNED,\n+\t\t.input = \"\\x80\\x81\\x82\\x83\\x84\",\n+\t\t.len = 5,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0xbc48596e,\n+\t\t.expected_minor_hash = 0xde0fad41,\n+\t},\n+\t{\n+\t\t.name = \"tea_non_ascii_signed\",\n+\t\t.hash_version = DX_HASH_TEA,\n+\t\t.input = \"\\x80\\x81\\x82\\x83\\x84\",\n+\t\t.len = 5,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0x21e3a154,\n+\t\t.expected_minor_hash = 0x90112c3d,\n+\t},\n+\t{\n+\t\t.name = \"tea_non_ascii_unsigned\",\n+\t\t.hash_version = DX_HASH_TEA_UNSIGNED,\n+\t\t.input = \"\\x80\\x81\\x82\\x83\\x84\",\n+\t\t.len = 5,\n+\t\t.use_seed = false,\n+\t\t.expected_hash = 0x9b648616,\n+\t\t.expected_minor_hash = 0x011dd507,\n+\t},\n+};\n+\n+static void test_ext4fs_dirhash_vectors(struct kunit *test)\n+{\n+\tstruct super_block *sb;\n+\tstruct inode *dir;\n+\tint i;\n+\n+\tsb = kunit_kzalloc(test, sizeof(*sb), GFP_KERNEL);\n+\tdir = kunit_kzalloc(test, sizeof(*dir), GFP_KERNEL);\n+\tKUNIT_ASSERT_NOT_NULL(test, sb);\n+\tKUNIT_ASSERT_NOT_NULL(test, dir);\n+\n+\text4_hash_init_fake_dir(dir, sb);\n+\n+\tfor (i = 0; i < ARRAY_SIZE(ext4_dirhash_test_cases); i++) {\n+\t\tconst struct ext4_dirhash_test_case *tc =\n+\t\t\t&ext4_dirhash_test_cases[i];\n+\t\tstruct dx_hash_info hinfo;\n+\t\tint ret;\n+\n+\t\tmemset(&hinfo, 0, sizeof(hinfo));\n+\t\thinfo.hash_version = tc->hash_version;\n+\t\thinfo.seed = tc->use_seed ? (u32 *)tc->seed : NULL;\n+\n+\t\tret = ext4fs_dirhash(dir, tc->input, tc->len, &hinfo);\n+\n+\t\tKUNIT_ASSERT_EQ_MSG(test, ret, 0, \"case=%s\", tc->name);\n+\t\tKUNIT_EXPECT_EQ_MSG(test, hinfo.hash, tc->expected_hash,\n+\t\t\t\t \"case=%s\", tc->name);\n+\t\tKUNIT_EXPECT_EQ_MSG(test, hinfo.minor_hash,\n+\t\t\t\t tc->expected_minor_hash,\n+\t\t\t\t \"case=%s\", tc->name);\n+\t}\n+}\n+\n+static void test_ext4fs_dirhash_seed_changes_result(struct kunit *test)\n+{\n+\tstruct super_block *sb;\n+\tstruct inode *dir;\n+\tu32 seed[4] = { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };\n+\tstruct dx_hash_info plain = {\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t};\n+\tstruct dx_hash_info seeded = {\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t\t.seed = seed,\n+\t};\n+\tint ret_plain, ret_seeded;\n+\n+\tsb = kunit_kzalloc(test, sizeof(*sb), GFP_KERNEL);\n+\tdir = kunit_kzalloc(test, sizeof(*dir), GFP_KERNEL);\n+\tKUNIT_ASSERT_NOT_NULL(test, sb);\n+\tKUNIT_ASSERT_NOT_NULL(test, dir);\n+\n+\text4_hash_init_fake_dir(dir, sb);\n+\n+\tret_plain = ext4fs_dirhash(dir, \"same-name\", 9, &plain);\n+\tret_seeded = ext4fs_dirhash(dir, \"same-name\", 9, &seeded);\n+\n+\tKUNIT_ASSERT_EQ(test, ret_plain, 0);\n+\tKUNIT_ASSERT_EQ(test, ret_seeded, 0);\n+\n+\tKUNIT_EXPECT_TRUE(test,\n+\t\t\t plain.hash != seeded.hash ||\n+\t\t\t plain.minor_hash != seeded.minor_hash);\n+}\n+\n+static void test_ext4fs_dirhash_invalid_version_returns_einval(struct kunit *test)\n+{\n+\tstruct super_block *sb;\n+\tstruct inode *dir;\n+\tstruct ext4_sb_info *sbi;\n+\tstruct dx_hash_info hinfo = {\n+\t\t.hash = 0xdeadbeef,\n+\t\t.minor_hash = 0xcafebabe,\n+\t\t.hash_version = DX_HASH_LAST + 1,\n+\t};\n+\tint ret;\n+\n+\tsb = kunit_kzalloc(test, sizeof(*sb), GFP_KERNEL);\n+\tdir = kunit_kzalloc(test, sizeof(*dir), GFP_KERNEL);\n+\tsbi = kunit_kzalloc(test, sizeof(*sbi), GFP_KERNEL);\n+\tKUNIT_ASSERT_NOT_NULL(test, sb);\n+\tKUNIT_ASSERT_NOT_NULL(test, dir);\n+\tKUNIT_ASSERT_NOT_NULL(test, sbi);\n+\n+\text4_hash_init_fake_dir_with_sbi(dir, sb, sbi);\n+\n+\tret = ext4fs_dirhash(dir, \"abc\", 3, &hinfo);\n+\n+\tKUNIT_EXPECT_EQ(test, ret, -EINVAL);\n+\tKUNIT_EXPECT_EQ(test, hinfo.hash, 0);\n+\tKUNIT_EXPECT_EQ(test, hinfo.minor_hash, 0);\n+}\n+\n+static void test_ext4fs_dirhash_siphash_without_key_returns_einval(struct kunit *test)\n+{\n+\tstruct super_block *sb;\n+\tstruct inode *dir;\n+\tstruct ext4_sb_info *sbi;\n+\tstruct dx_hash_info hinfo = {\n+\t\t.hash_version = DX_HASH_SIPHASH,\n+\t};\n+\tint ret;\n+\n+\tsb = kunit_kzalloc(test, sizeof(*sb), GFP_KERNEL);\n+\tdir = kunit_kzalloc(test, sizeof(*dir), GFP_KERNEL);\n+\tsbi = kunit_kzalloc(test, sizeof(*sbi), GFP_KERNEL);\n+\tKUNIT_ASSERT_NOT_NULL(test, sb);\n+\tKUNIT_ASSERT_NOT_NULL(test, dir);\n+\tKUNIT_ASSERT_NOT_NULL(test, sbi);\n+\n+\text4_hash_init_fake_dir_with_sbi(dir, sb, sbi);\n+\n+\tret = ext4fs_dirhash(dir, \"abc\", 3, &hinfo);\n+\n+\tKUNIT_EXPECT_EQ(test, ret, -EINVAL);\n+}\n+\n+static void test_ext4fs_dirhash_signed_unsigned_differ_on_nonascii(struct kunit *test)\n+{\n+\tstruct super_block *sb;\n+\tstruct inode *dir;\n+\tstatic const char input[] = \"\\x80\\xff\\x81\\xfe\\101bc\";\n+\tstruct dx_hash_info legacy_signed = {\n+\t\t.hash_version = DX_HASH_LEGACY,\n+\t};\n+\tstruct dx_hash_info legacy_unsigned = {\n+\t\t.hash_version = DX_HASH_LEGACY_UNSIGNED,\n+\t};\n+\tstruct dx_hash_info md4_signed = {\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t};\n+\tstruct dx_hash_info md4_unsigned = {\n+\t\t.hash_version = DX_HASH_HALF_MD4_UNSIGNED,\n+\t};\n+\tstruct dx_hash_info tea_signed = {\n+\t\t.hash_version = DX_HASH_TEA,\n+\t};\n+\tstruct dx_hash_info tea_unsigned = {\n+\t\t.hash_version = DX_HASH_TEA_UNSIGNED,\n+\t};\n+\tint ret;\n+\n+\tsb = kunit_kzalloc(test, sizeof(*sb), GFP_KERNEL);\n+\tdir = kunit_kzalloc(test, sizeof(*dir), GFP_KERNEL);\n+\tKUNIT_ASSERT_NOT_NULL(test, sb);\n+\tKUNIT_ASSERT_NOT_NULL(test, dir);\n+\n+\text4_hash_init_fake_dir(dir, sb);\n+\n+\tret = ext4fs_dirhash(dir, input, sizeof(input) - 1, &legacy_signed);\n+\tKUNIT_ASSERT_EQ(test, ret, 0);\n+\tret = ext4fs_dirhash(dir, input, sizeof(input) - 1, &legacy_unsigned);\n+\tKUNIT_ASSERT_EQ(test, ret, 0);\n+\tKUNIT_EXPECT_NE(test, legacy_signed.hash, legacy_unsigned.hash);\n+\n+\tret = ext4fs_dirhash(dir, input, sizeof(input) - 1, &md4_signed);\n+\tKUNIT_ASSERT_EQ(test, ret, 0);\n+\tret = ext4fs_dirhash(dir, input, sizeof(input) - 1, &md4_unsigned);\n+\tKUNIT_ASSERT_EQ(test, ret, 0);\n+\tKUNIT_EXPECT_TRUE(test,\n+\t\t\t md4_signed.hash != md4_unsigned.hash ||\n+\t\t\t md4_signed.minor_hash != md4_unsigned.minor_hash);\n+\n+\tret = ext4fs_dirhash(dir, input, sizeof(input) - 1, &tea_signed);\n+\tKUNIT_ASSERT_EQ(test, ret, 0);\n+\tret = ext4fs_dirhash(dir, input, sizeof(input) - 1, &tea_unsigned);\n+\tKUNIT_ASSERT_EQ(test, ret, 0);\n+\tKUNIT_EXPECT_TRUE(test,\n+\t\t\t tea_signed.hash != tea_unsigned.hash ||\n+\t\t\t tea_signed.minor_hash != tea_unsigned.minor_hash);\n+}\n+\n+#if IS_ENABLED(CONFIG_UNICODE)\n+static void test_ext4fs_dirhash_casefolded_names_hash_consistently(struct kunit *test)\n+{\n+\tstruct super_block *sb;\n+\tstruct ext4_inode_info *ei;\n+\tstruct ext4_sb_info *sbi;\n+\tstruct unicode_map *um;\n+\tstruct dx_hash_info h1 = {\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t};\n+\tstruct dx_hash_info h2 = {\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t};\n+\tint ret1, ret2;\n+\n+\tsb = kunit_kzalloc(test, sizeof(*sb), GFP_KERNEL);\n+\tei = kunit_kzalloc(test, sizeof(*ei), GFP_KERNEL);\n+\tsbi = kunit_kzalloc(test, sizeof(*sbi), GFP_KERNEL);\n+\tKUNIT_ASSERT_NOT_NULL(test, sb);\n+\tKUNIT_ASSERT_NOT_NULL(test, ei);\n+\tKUNIT_ASSERT_NOT_NULL(test, sbi);\n+\n+\tum = utf8_load(UTF8_LATEST);\n+\tif (!um) {\n+\t\tkunit_skip(test, \"utf8_load(UTF8_LATEST) failed\");\n+\t\treturn;\n+\t}\n+\n+\text4_hash_init_fake_ext4_dir(ei, sb, sbi);\n+\tsb->s_encoding = um;\n+\tei->vfs_inode.i_flags |= S_CASEFOLD;\n+\n+\tKUNIT_ASSERT_TRUE(test, IS_CASEFOLDED(&ei->vfs_inode));\n+\n+\tret1 = ext4fs_dirhash(&ei->vfs_inode, \"Alpha\", 5, &h1);\n+\tret2 = ext4fs_dirhash(&ei->vfs_inode, \"aLPHa\", 5, &h2);\n+\n+\tKUNIT_ASSERT_EQ(test, ret1, 0);\n+\tKUNIT_ASSERT_EQ(test, ret2, 0);\n+\tKUNIT_EXPECT_EQ(test, h1.hash, h2.hash);\n+\tKUNIT_EXPECT_EQ(test, h1.minor_hash, h2.minor_hash);\n+\n+\tutf8_unload(um);\n+}\n+\n+static void test_ext4fs_dirhash_casefold_fallback(struct kunit *test)\n+{\n+\tstruct super_block *sb_cf, *sb_plain;\n+\tstruct ext4_inode_info *ei;\n+\tstruct ext4_sb_info *sbi;\n+\tstruct inode *plain_dir;\n+\tstruct unicode_map *um;\n+\tstatic const char invalid_utf8[] = \"\\xc3\\x28\";\n+\tstruct dx_hash_info folded_dir = {\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t};\n+\tstruct dx_hash_info plain = {\n+\t\t.hash_version = DX_HASH_HALF_MD4,\n+\t};\n+\tint ret_cf, ret_plain;\n+\n+\tsb_cf = kunit_kzalloc(test, sizeof(*sb_cf), GFP_KERNEL);\n+\tsb_plain = kunit_kzalloc(test, sizeof(*sb_plain), GFP_KERNEL);\n+\tei = kunit_kzalloc(test, sizeof(*ei), GFP_KERNEL);\n+\tsbi = kunit_kzalloc(test, sizeof(*sbi), GFP_KERNEL);\n+\tplain_dir = kunit_kzalloc(test, sizeof(*plain_dir), GFP_KERNEL);\n+\tKUNIT_ASSERT_NOT_NULL(test, sb_cf);\n+\tKUNIT_ASSERT_NOT_NULL(test, sb_plain);\n+\tKUNIT_ASSERT_NOT_NULL(test, ei);\n+\tKUNIT_ASSERT_NOT_NULL(test, sbi);\n+\tKUNIT_ASSERT_NOT_NULL(test, plain_dir);\n+\n+\tum = utf8_load(UTF8_LATEST);\n+\tif (!um) {\n+\t\tkunit_skip(test, \"utf8_load(UTF8_LATEST) failed\");\n+\t\treturn;\n+\t}\n+\n+\text4_hash_init_fake_ext4_dir(ei, sb_cf, sbi);\n+\tsb_cf->s_encoding = um;\n+\tei->vfs_inode.i_flags |= S_CASEFOLD;\n+\n+\tKUNIT_ASSERT_TRUE(test, IS_CASEFOLDED(&ei->vfs_inode));\n+\n+\text4_hash_init_fake_dir(plain_dir, sb_plain);\n+\n+\tret_cf = ext4fs_dirhash(&ei->vfs_inode, invalid_utf8,\n+\t\t\t\tsizeof(invalid_utf8) - 1, &folded_dir);\n+\tret_plain = ext4fs_dirhash(plain_dir, invalid_utf8,\n+\t\t\t\t sizeof(invalid_utf8) - 1, &plain);\n+\n+\tKUNIT_ASSERT_EQ(test, ret_cf, 0);\n+\tKUNIT_ASSERT_EQ(test, ret_plain, 0);\n+\tKUNIT_EXPECT_EQ(test, folded_dir.hash, plain.hash);\n+\tKUNIT_EXPECT_EQ(test, folded_dir.minor_hash, plain.minor_hash);\n+\n+\tutf8_unload(um);\n+}\n+#endif\n+\n+static struct kunit_case ext4_hash_test_cases[] = {\n+\tKUNIT_CASE(test_ext4fs_dirhash_vectors),\n+\tKUNIT_CASE(test_ext4fs_dirhash_seed_changes_result),\n+\tKUNIT_CASE(test_ext4fs_dirhash_invalid_version_returns_einval),\n+\tKUNIT_CASE(test_ext4fs_dirhash_siphash_without_key_returns_einval),\n+\tKUNIT_CASE(test_ext4fs_dirhash_signed_unsigned_differ_on_nonascii),\n+#if IS_ENABLED(CONFIG_UNICODE)\n+\tKUNIT_CASE(test_ext4fs_dirhash_casefolded_names_hash_consistently),\n+\tKUNIT_CASE(test_ext4fs_dirhash_casefold_fallback),\n+#endif\n+\t{}\n+};\n+\n+static struct kunit_suite ext4_hash_test_suite = {\n+\t.name = \"ext4_hash\",\n+\t.test_cases = ext4_hash_test_cases,\n+};\n+\n+kunit_test_suites(&ext4_hash_test_suite);\n+\n+MODULE_LICENSE(\"GPL\");\n", "prefixes": [ "v3", "1/2" ] }