{"id":2229420,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2229420/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-ext4/patch/20260428083332.768693-5-aalbersh@kernel.org/","project":{"id":8,"url":"http://patchwork.ozlabs.org/api/1.1/projects/8/?format=json","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":"<20260428083332.768693-5-aalbersh@kernel.org>","date":"2026-04-28T08:33:10","name":"[v9,04/22] fsverity: generate and store zero-block hash","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"9c466512dfecbecfe048d5fe4983a46c9bc0c06a","submitter":{"id":92821,"url":"http://patchwork.ozlabs.org/api/1.1/people/92821/?format=json","name":"Andrey Albershteyn","email":"aalbersh@kernel.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-ext4/patch/20260428083332.768693-5-aalbersh@kernel.org/mbox/","series":[{"id":501796,"url":"http://patchwork.ozlabs.org/api/1.1/series/501796/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-ext4/list/?series=501796","date":"2026-04-28T08:33:09","name":"[v9,01/22] fsverity: report validation errors through fserror to fsnotify","version":9,"mbox":"http://patchwork.ozlabs.org/series/501796/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2229420/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2229420/checks/","tags":{},"headers":{"Return-Path":"\n <SRS0=D15T=C3=vger.kernel.org=linux-ext4+bounces-16150-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=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=sHlNCPMT;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org\n (client-ip=150.107.74.76; helo=mail.ozlabs.org;\n envelope-from=srs0=d15t=c3=vger.kernel.org=linux-ext4+bounces-16150-patchwork-incoming=ozlabs.org@ozlabs.org;\n receiver=patchwork.ozlabs.org)","gandalf.ozlabs.org;\n arc=pass smtp.remote-ip=\"2600:3c09:e001:a7::12fc:5321\"\n arc.chain=subspace.kernel.org","gandalf.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=kernel.org","gandalf.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=sHlNCPMT;\n\tdkim-atps=neutral","gandalf.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c09:e001:a7::12fc:5321; helo=sto.lore.kernel.org;\n envelope-from=linux-ext4+bounces-16150-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"sHlNCPMT\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"],"Received":["from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76])\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 4g4Ym60vW6z1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 18:40:22 +1000 (AEST)","from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\tby gandalf.ozlabs.org (Postfix) with ESMTP id 4g4Ym60jf3z4wL8\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 18:40:22 +1000 (AEST)","by gandalf.ozlabs.org (Postfix)\n\tid 4g4Ym60ZThz4wLP; Tue, 28 Apr 2026 18:40:22 +1000 (AEST)","from sto.lore.kernel.org (sto.lore.kernel.org\n [IPv6:2600:3c09:e001:a7::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 4g4Ym22llqz4wL8\n\tfor <patchwork-incoming@ozlabs.org>; Tue, 28 Apr 2026 18:40:18 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sto.lore.kernel.org (Postfix) with ESMTP id AC10630807CA\n\tfor <patchwork-incoming@ozlabs.org>; Tue, 28 Apr 2026 08:34:25 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 7E60F3D47A4;\n\tTue, 28 Apr 2026 08:34:07 +0000 (UTC)","from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 3DF832DCC01;\n\tTue, 28 Apr 2026 08:34:07 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id 731BDC2BCAF;\n\tTue, 28 Apr 2026 08:34:04 +0000 (UTC)"],"ARC-Seal":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707; t=1777365622; cv=pass;\n\tb=JZndIoyxDuj+83xGWd3d0UL9VnSKUqRafyBwMyciTjsZLQ3wpOPqIYVPZhCjJfvMTmxjTp28yXAdc2YIhuaitMDzz7ozvzv3DpG+o3cvQBZvTSQqbsTTxua/mHj6FzQ0Q4va22pbA88b/G+83v2iX95fFNYEFfW0RhQY1ivO1d+zPKw/69g1hGczuhHlW2J1Ht7hz9V44AYNI8wpiRBPU8UBTbzSNSGHM5x+oQfH4gmSNzqXAPE1m8G7zlON+6awV8XVo2ED4vFG8L6GXjInRgfwN0kEVd4Jvp8LKSfELTnaeqOl4dmaukQx4ZwIm7MlWWcTa+qqZPULN8HqDFldLg==","i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1777365247; cv=none;\n b=FYplx/SdrSmSbiNY2sIShaFQLxlZGNtDloegLI1YUF6ahysBpVs41mkpPYY3gddw43lPDt4IFAj0SN2oHxyf/e6txTg9yWN0NSPrnewjH9Jqs0ZYcxLgzNP7iSOiGqZSwq5B0uz4oBD6l2gG73y201YxrygQUFof3qF+KxolP7U="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707;\n\tt=1777365622; c=relaxed/relaxed;\n\tbh=2W/huMs5akZB5W5rF4xsjMB8NN0kUDnKQc173nD7tcM=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=IpsjC7mlEb4ZnuU+9PqLRY+XhyQAWt3gI6yYtmS7bqgfnPpjR15NU6uNMNy9oOv5KWF3yl0GJftBhlgMef+rl7UqIsKNJLY+chcAjIlf809kWpVTS0zMfYLeRexNFMR21FwmUZN6sT83hgGaQm+KpHXb8mmpOXMKNe1O9CZhXnDLwcaLdH01KRuB1OhGoLtsyRVUcIvje85bWOtCn9HXYY6Z37YxZht7f6Yf7B9lo13fWX7h/pZii+pOEZ6OmMqFetxtXQez9LBq4u1QvDzoK2yt+A6R/bVSpi/DuDnrauonY/IP1LKvnoRC3fuXgIwpkcBD3yITEFV3MjM/VNwC8Q==","i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1777365247; c=relaxed/simple;\n\tbh=nUhG1extIwuU0/MW8Rh2m8eKBR8Qhj6c/9kAlQIdHFo=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=LookvJZ/o1bsFXxfvGlm567A2IHpIR8t15u0I6X9W8jSebslQ+hQ643mzqZx3YffLi3mqkMhFGbK2ZyzjRrkbChfbRPYtLvH26VJESSuj2bLJcWkymjJiqPxVqqPEX1Rhi1Aen7QP2bVBnCdPPjMwfwQV6Gdfd9JuT+KTDVomzQ="],"ARC-Authentication-Results":["i=2; gandalf.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=kernel.org;\n dkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=sHlNCPMT; dkim-atps=neutral;\n spf=pass (client-ip=2600:3c09:e001:a7::12fc:5321; helo=sto.lore.kernel.org;\n envelope-from=linux-ext4+bounces-16150-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org) smtp.mailfrom=vger.kernel.org","i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=sHlNCPMT; arc=none smtp.client-ip=10.30.226.201"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1777365246;\n\tbh=nUhG1extIwuU0/MW8Rh2m8eKBR8Qhj6c/9kAlQIdHFo=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=sHlNCPMT36Sbn5B+H9QVrzcBxkjzy7iZn5HX5MpWsmwwXW8D8UhZ8dgxwTlkHTKEC\n\t P3x9ALvNWDIzYI0agg88rym3rzbwbdUKufZo5ccECcTg4TnL6QfISvRCOJkvcb/XY4\n\t YP3751K99isuKhoxEn0NciWNhAMRnj1NboFTtLxQitbANeinPxGjI04XFaxDBxQbyN\n\t ho1ZVmNPgL0RtQo7X3NA+uZ2LrRfsIt6faTae78Q6tazyJ0+miErKM/Py+6ieNR/Vi\n\t Y6wK4IZDOdFGD7Px03o4qQJUukC2JQxyZlub853h0KGRXB08u7/xp211M2mf9JboFn\n\t +pTUoSN/c4tSw==","From":"Andrey Albershteyn <aalbersh@kernel.org>","To":"linux-xfs@vger.kernel.org,\n\tfsverity@lists.linux.dev,\n\tlinux-fsdevel@vger.kernel.org,\n\tebiggers@kernel.org","Cc":"Andrey Albershteyn <aalbersh@kernel.org>,\n\thch@lst.de,\n\tlinux-ext4@vger.kernel.org,\n\tlinux-f2fs-devel@lists.sourceforge.net,\n\tlinux-btrfs@vger.kernel.org,\n\tlinux-unionfs@vger.kernel.org,\n\tdjwong@kernel.org","Subject":"[PATCH v9 04/22] fsverity: generate and store zero-block hash","Date":"Tue, 28 Apr 2026 10:33:10 +0200","Message-ID":"<20260428083332.768693-5-aalbersh@kernel.org>","X-Mailer":"git-send-email 2.51.2","In-Reply-To":"<20260428083332.768693-1-aalbersh@kernel.org>","References":"<20260428083332.768693-1-aalbersh@kernel.org>","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.2 required=5.0 tests=ARC_SIGNED,ARC_VALID,\n\tDKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DMARC_PASS,\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":"Compute the hash of one filesystem block's worth of zeros. A filesystem\nimplementation can decide to elide merkle tree blocks containing only\nthis hash and synthesize the contents at read time.\n\nLet's pretend that there's a file containing 131 data block and whose\nmerkle tree looks roughly like this:\n\nroot\n +--leaf0\n |   +--data0\n |   +--data1\n |   +--...\n |   `--data128\n `--leaf1\n     +--data129\n     +--data130\n     `--data131\n\nIf data[0-128] are sparse holes, then leaf0 will contain a repeating\nsequence of @zero_digest.  Therefore, leaf0 need not be written to disk\nbecause its contents can be synthesized.\n\nA subsequent xfs patch will use this to reduce the size of the merkle\ntree when dealing with sparse gold master disk images and the like.\n\nNote that this works only on the first-level (data holes). fsverity\ndoesn't store/generate zero_digest for any higher levels.\n\nAdd a helper to pre-fill folio with hashes of empty blocks. This will be\nused by iomap to synthesize blocks full of zero hashes on the fly.\n\nSigned-off-by: Darrick J. Wong <djwong@kernel.org>\nAcked-by: Eric Biggers <ebiggers@kernel.org>\nSigned-off-by: Andrey Albershteyn <aalbersh@kernel.org>\n---\n fs/verity/fsverity_private.h |  3 +++\n fs/verity/measure.c          |  4 ++--\n fs/verity/open.c             |  3 +++\n fs/verity/pagecache.c        | 22 ++++++++++++++++++++++\n include/linux/fsverity.h     |  8 ++++++++\n 5 files changed, 38 insertions(+), 2 deletions(-)","diff":"diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h\nindex 6e6854c19078..881d46f25e08 100644\n--- a/fs/verity/fsverity_private.h\n+++ b/fs/verity/fsverity_private.h\n@@ -53,6 +53,9 @@ struct merkle_tree_params {\n \tu64 tree_size;\t\t\t/* Merkle tree size in bytes */\n \tunsigned long tree_pages;\t/* Merkle tree size in pages */\n \n+\t/* the hash of an all-zeroes block */\n+\tu8 zero_digest[FS_VERITY_MAX_DIGEST_SIZE];\n+\n \t/*\n \t * Starting block index for each tree level, ordered from leaf level (0)\n \t * to root level ('num_levels - 1')\ndiff --git a/fs/verity/measure.c b/fs/verity/measure.c\nindex 6a35623ebdf0..818083507885 100644\n--- a/fs/verity/measure.c\n+++ b/fs/verity/measure.c\n@@ -68,8 +68,8 @@ EXPORT_SYMBOL_GPL(fsverity_ioctl_measure);\n  * @alg: (out) the digest's algorithm, as a FS_VERITY_HASH_ALG_* value\n  * @halg: (out) the digest's algorithm, as a HASH_ALGO_* value\n  *\n- * Retrieves the fsverity digest of the given file.  The file must have been\n- * opened at least once since the inode was last loaded into the inode cache;\n+ * Retrieves the fsverity digest of the given file. The\n+ * fsverity_ensure_verity_info() must be called on the inode beforehand;\n  * otherwise this function will not recognize when fsverity is enabled.\n  *\n  * The file's fsverity digest consists of @raw_digest in combination with either\ndiff --git a/fs/verity/open.c b/fs/verity/open.c\nindex d32d0899df25..875e8850ccba 100644\n--- a/fs/verity/open.c\n+++ b/fs/verity/open.c\n@@ -153,6 +153,9 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,\n \t\tgoto out_err;\n \t}\n \n+\tfsverity_hash_block(params, page_address(ZERO_PAGE(0)),\n+\t\t\t    params->zero_digest);\n+\n \tparams->tree_size = offset << log_blocksize;\n \tparams->tree_pages = PAGE_ALIGN(params->tree_size) >> PAGE_SHIFT;\n \treturn 0;\ndiff --git a/fs/verity/pagecache.c b/fs/verity/pagecache.c\nindex 1819314ecaa3..99f5f53eea98 100644\n--- a/fs/verity/pagecache.c\n+++ b/fs/verity/pagecache.c\n@@ -2,6 +2,7 @@\n /*\n  * Copyright 2019 Google LLC\n  */\n+#include \"fsverity_private.h\"\n \n #include <linux/export.h>\n #include <linux/fsverity.h>\n@@ -56,3 +57,24 @@ void generic_readahead_merkle_tree(struct inode *inode, pgoff_t index,\n \t\tfolio_put(folio);\n }\n EXPORT_SYMBOL_GPL(generic_readahead_merkle_tree);\n+\n+/**\n+ * fsverity_fill_zerohash() - fill folio with hashes of zero data block\n+ * @folio:\tfolio to fill\n+ * @offset:\toffset in the folio to start\n+ * @len:\tlength of the range to fill with hashes\n+ * @vi:\t\tfsverity info\n+ */\n+void fsverity_fill_zerohash(struct folio *folio, size_t offset, size_t len,\n+\t\t\t      struct fsverity_info *vi)\n+{\n+\tsize_t off = offset;\n+\n+\tWARN_ON_ONCE(!IS_ALIGNED(offset, vi->tree_params.digest_size));\n+\tWARN_ON_ONCE(!IS_ALIGNED(len, vi->tree_params.digest_size));\n+\n+\tfor (; off < (offset + len); off += vi->tree_params.digest_size)\n+\t\tmemcpy_to_folio(folio, off, vi->tree_params.zero_digest,\n+\t\t\t\tvi->tree_params.digest_size);\n+}\n+EXPORT_SYMBOL_GPL(fsverity_fill_zerohash);\ndiff --git a/include/linux/fsverity.h b/include/linux/fsverity.h\nindex 5562271bd628..3c3250f6f272 100644\n--- a/include/linux/fsverity.h\n+++ b/include/linux/fsverity.h\n@@ -201,6 +201,8 @@ bool fsverity_verify_blocks(struct fsverity_info *vi, struct folio *folio,\n \t\t\t    size_t len, size_t offset);\n void fsverity_verify_bio(struct fsverity_info *vi, struct bio *bio);\n void fsverity_enqueue_verify_work(struct work_struct *work);\n+void fsverity_fill_zerohash(struct folio *folio, size_t offset, size_t len,\n+\t\t\t    struct fsverity_info *vi);\n \n #else /* !CONFIG_FS_VERITY */\n \n@@ -281,6 +283,12 @@ static inline void fsverity_enqueue_verify_work(struct work_struct *work)\n \tWARN_ON_ONCE(1);\n }\n \n+static inline void fsverity_fill_zerohash(struct folio *folio, size_t offset,\n+\t\tsize_t len, struct fsverity_info *vi)\n+{\n+\tWARN_ON_ONCE(1);\n+}\n+\n #endif\t/* !CONFIG_FS_VERITY */\n \n static inline bool fsverity_verify_folio(struct fsverity_info *vi,\n","prefixes":["v9","04/22"]}