From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 790A22E2DD2; Fri, 6 Feb 2026 05:01:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354114; cv=none; b=Qs8eZcuJ7l7um783eD8ZZGl9e8M1t0ZHwEdejYUs4cJ2sbEw+kPmZCtJb05t20xKbpHwK13fiDUz1ee7gAwi1lWvEKGKFExZfQgrTjiyWb0KJlUvFb3By6WUxgDdD+VDK/AXiQrsqo+XlxeVjpX9pTVzq5hX0qXynGQPbEHPusc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354114; c=relaxed/simple; bh=awsnYHluhMYiSyOtcwgGx116nbhXaUrMrdS3ZQpowTk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ReQ0Fecd0QzWmPS31Zc/vmB7R7B8GNFuxfzcCprDK45dHO7zlsETQnvCqx5fTwIIRcVVpYODoVxABsTHJ0eXGr7WTpU0t3bSGl4IUdIe73K5/2FVUibma3ryokvtsWuK7eq1ezg7xavl+jyleWvBuw/B27rS1R0EFI+0/mNlsVI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KukJk880; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KukJk880" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1745DC16AAE; Fri, 6 Feb 2026 05:01:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354114; bh=awsnYHluhMYiSyOtcwgGx116nbhXaUrMrdS3ZQpowTk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KukJk880K6NnbRiGcQFsNjp8X07faD28UcXBZDbAECOYIy/jSDdG7AEYTGhh9YFaf alGeSBJN8Wl4Dyu/dHP/uC8l5nFTn6Xb7mhRcAyHppQ2kZ9VBak/5JO+/050vv+V2/ VgAC+cOTUrkWCifdB6c5W/IFJuqbHhpUWFHhbNHvMsnYtsO56EHhBgPpGsKOXJHic7 7lExmnphPv0JVb0mrSMbIq4Tx3t2FnASQTMZVlLQqq7EjtAHPJjw0KhBGuFtEnbrt5 NtTbQsJeIWjaJ9pnE9yshT+nhImeGNOaZr5WirjathqMwuOSjTPWtkj7toivfcDJGC PAnP0YedhLT+A== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers , stable@vger.kernel.org Subject: [PATCH 01/22] dm-verity-fec: correctly reject too-small FEC devices Date: Thu, 5 Feb 2026 20:59:20 -0800 Message-ID: <20260206045942.52965-2-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Fix verity_fec_ctr() to reject too-small FEC devices by correctly computing the number of parity blocks as 'f->rounds * f->roots'. Previously it incorrectly used 'div64_u64(f->rounds * f->roots, v->fec->roots << SECTOR_SHIFT)' which is a much smaller value. Note that the units of 'rounds' are blocks, not bytes. This matches the units of the value returned by dm_bufio_get_device_size(), which are also blocks. A later commit will give 'rounds' a clearer name. Fixes: a739ff3f543a ("dm verity: add support for forward error correction") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 7583607a8aa62..5c276d0fc20c0 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -623,11 +623,11 @@ int verity_fec_ctr_alloc(struct dm_verity *v) */ int verity_fec_ctr(struct dm_verity *v) { struct dm_verity_fec *f =3D v->fec; struct dm_target *ti =3D v->ti; - u64 hash_blocks, fec_blocks; + u64 hash_blocks; int ret; =20 if (!verity_fec_is_enabled(v)) { verity_fec_dtr(v); return 0; @@ -704,12 +704,11 @@ int verity_fec_ctr(struct dm_verity *v) return PTR_ERR(f->bufio); } =20 dm_bufio_set_sector_offset(f->bufio, f->start << (v->data_dev_block_bits = - SECTOR_SHIFT)); =20 - fec_blocks =3D div64_u64(f->rounds * f->roots, v->fec->roots << SECTOR_SH= IFT); - if (dm_bufio_get_device_size(f->bufio) < fec_blocks) { + if (dm_bufio_get_device_size(f->bufio) < f->rounds * f->roots) { ti->error =3D "FEC device is too small"; return -E2BIG; } =20 f->data_bufio =3D dm_bufio_client_create(v->data_dev->bdev, --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E35FC338599; Fri, 6 Feb 2026 05:01:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354115; cv=none; b=sWe2gpIftWLYUHkjItdrQgOYqUSeogrXY4dy/I8/vxX82ICZipm+Kly8WAqlz3Cb6bzx0t7ckOJF8uN/Wufbw3ognrFwLHZI8ksOVFsf4WLGXXLVlJUznwD4z3BV0sElOuNs/r0nN5AbAeupmJ6LY1py6JTt27XMpp6AH+4VNCU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354115; c=relaxed/simple; bh=5d5HjKM+DeqQTaH+goXutkoNBKAF0dufO9VZmmDqK+Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lnblK1KFAfWFg5h2vp4FpWs9HO/uFZ71dY8VtJwugEmxQu14Clafm9mKsxyKAts8lrgXxaCtC3rCiXcN3SV/tYzA9nv6Y9tmbdMCL9MFKfHW1Lb/pRgd7tPmfAgzov+6ev1/vP2GoNId5cJVTqrcKQO5KoMwg9f456ZTQ9wEJkg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=t9TDjzNp; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="t9TDjzNp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7E5A4C19422; Fri, 6 Feb 2026 05:01:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354114; bh=5d5HjKM+DeqQTaH+goXutkoNBKAF0dufO9VZmmDqK+Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t9TDjzNplqNANTMSyynLoOfJfnx+vQlgXycvKw7GSvZTq4MdaCb/LarTpiNoD+hpC YKHI3ABqtf/QRud2LG99rIFYP7AsLp3mbC60HSaE6auUEUjjIpwrw40DZa1nRFSmpr ptTkLhxp8MedWfKryI/7pSN62L9GVmUMluhOLZuyDt5wnClkKmveHE4/xySk992ffU i/5e6CxkHYleXtbFXv4v8Q2/B85ec8YwaHgBlUfvJi7jDJc37nKlR9OInmgl2MZPui j2KlFOB4MSz9kYbofNGFptatuCBIqodoV1h3HNq6vAMBWpciTw+Jek08CW8MQBr8vo 6vYj8fjvZ7zdw== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers , stable@vger.kernel.org Subject: [PATCH 02/22] dm-verity-fec: correctly reject too-small hash devices Date: Thu, 5 Feb 2026 20:59:21 -0800 Message-ID: <20260206045942.52965-3-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Fix verity_fec_ctr() to reject too-small hash devices by correctly taking hash_start into account. Note that this is necessary because dm-verity doesn't call dm_bufio_set_sector_offset() on the hash device's bufio client (v->bufio). Thus, dm_bufio_get_device_size(v->bufio) returns a size relative to 0 rather than hash_start. An alternative fix would be to call dm_bufio_set_sector_offset() on v->bufio, but then all the code that reads from the hash device would have to be adjusted accordingly. Fixes: a739ff3f543a ("dm verity: add support for forward error correction") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 5c276d0fc20c0..9f06bd66bae31 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -686,11 +686,12 @@ int verity_fec_ctr(struct dm_verity *v) /* * Metadata is accessed through the hash device, so we require * it to be large enough. */ f->hash_blocks =3D f->blocks - v->data_blocks; - if (dm_bufio_get_device_size(v->bufio) < f->hash_blocks) { + if (dm_bufio_get_device_size(v->bufio) < + v->hash_start + f->hash_blocks) { ti->error =3D "Hash device is too small for " DM_VERITY_OPT_FEC_BLOCKS; return -E2BIG; } =20 --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7762133A010; Fri, 6 Feb 2026 05:01:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354115; cv=none; b=NdaV5GGWIF9gptTGRjUtEXyaXeGnCoaXJjsmIxk4ThM2t4kXzNBbAeWsmOTYTgqwTqraXfND8fqXYGODGMp+SWV11ewV8wwZ39jPjeknVPZKOgxPvXdwi5dFCf/HtqBFri2lC4Wsbz/PpSzyzy8yuyqF8hqyYKFl+UOEFcudOKY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354115; c=relaxed/simple; bh=0OIDTxwWeNBq0cYgnVu7ObvDTWCwxCqc2kk3dLvqHMk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ip8XvdmpjLYFjYdHhX2DH6Yu3BuTfsAhnoWxwuSrtdgipxt3NRswWTMsUr1n0rARHaM53/5T3fkmKOdszfwdA28C/VIBNa9EpkVN9IUYUzZomREOO6SdD9Dn+1CUifDB+MapLIGN+JtbDZh/2qKVSi73pTaVYlfMEWLgN87mA98= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=G3bVDuxt; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="G3bVDuxt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E5248C2BC86; Fri, 6 Feb 2026 05:01:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354115; bh=0OIDTxwWeNBq0cYgnVu7ObvDTWCwxCqc2kk3dLvqHMk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G3bVDuxtDrhc9oo6PruKrovP7oUwjWE7HQX6gOVmtRiv+jq+LIJz/6pfjZqKmnNZW UyX/9PrOvTjgDNqNZxNGmAMBHSbFry4bNOdFPVhtfsGRVutAzJQNdTz0Hx4lTjGW6j UMZJk0HuVq00BrE+S4kaKvAkMXia4NvNYIVU5pjZ7r9k6D4q7CqSMSXmDK8u1LaeS0 rMmSHbQsVb+EjrT7OejZS44+cVpagIvAyfKHplGsQCRM3T7x9oJsSfPfkgjEJPgzio GyNIXnidx7wXGPZYKt89r22qk37pMVow+zvJQCDZDAdJ3YX3I3SkyOcyCCwhrq5c6g q8upBFR3ju4eQ== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers , Shubhankar Mishra , stable@vger.kernel.org Subject: [PATCH 03/22] dm-verity-fec: fix corrected block count stat Date: Thu, 5 Feb 2026 20:59:22 -0800 Message-ID: <20260206045942.52965-4-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" dm_verity_fec::corrected seems to have been intended to count the number of corrected blocks. However, it actually counted the number of calls to fec_decode_bufs() that corrected at least one error. That's not the same thing. For example, in low-memory situations correcting a single block can require many calls to fec_decode_bufs(). Fix it to count corrected blocks instead. Fixes: ae97648e14f7 ("dm verity fec: Expose corrected block count via statu= s") Cc: Shubhankar Mishra Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 9f06bd66bae31..d4a9367a2fee6 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -161,15 +161,13 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, dm_bufio_release(buf); =20 if (r < 0 && neras) DMERR_LIMIT("%s: FEC %llu: failed to correct: %d", v->data_dev->name, (unsigned long long)rsb, r); - else if (r > 0) { + else if (r > 0) DMWARN_LIMIT("%s: FEC %llu: corrected %d errors", v->data_dev->name, (unsigned long long)rsb, r); - atomic64_inc(&v->fec->corrected); - } =20 return r; } =20 /* @@ -437,10 +435,11 @@ int verity_fec_decode(struct dm_verity *v, struct dm_= verity_io *io, if (r < 0) goto done; } =20 memcpy(dest, fio->output, 1 << v->data_dev_block_bits); + atomic64_inc(&v->fec->corrected); =20 done: fio->level--; return r; } --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CBB6933A71A; Fri, 6 Feb 2026 05:01:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354115; cv=none; b=jVXrj05J3VzlxzSKGzp5jokXmLpSrTDCYCIqyELtDwZ/FFVroeIcePqVy9HoN0Id4ZnLJSt9OcCflKP8FgM2MgVllj5KLHxba8zMFCyUT7YBbbKLXPpzGPr0cgyBWHPFd58e5pHajopMaNr8OjApOFhFeyIUVV7jh1PuMVR9P6M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354115; c=relaxed/simple; bh=MVzAcLB7GStHyBxjs1SgTFNmn9t0HihbC+rOJgEnDzo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qZKefwtk7tUXaluvyvCId5+OZ7VKtFM/EP+IP0DxcOmg3mrCJasJDD4PtnN8ojVH3c/thdDqXxpNBkVRLJZsaH2cslw9SZDxfLxgX0HK0YFETSLek6W15NyIlbwb+I/tc8FSI4KUyKETuwihKQp89Sl6cUH8B70GsspHLk9Z0TY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=X0/uH2QL; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="X0/uH2QL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5FF1FC16AAE; Fri, 6 Feb 2026 05:01:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354115; bh=MVzAcLB7GStHyBxjs1SgTFNmn9t0HihbC+rOJgEnDzo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=X0/uH2QLOOYifiwOF7/a3Itcopw3MvkDDyb+kYRQtknzFAxTX+Gt7GlfyXY/KFhv3 ZFGcX+62lumdJ6hYe9WgZveTGEqHhkcpO5CoZBp+Kdtm0jQqv5jTUWL9yMv4BQ7yPq fgamEUMheszzdBjS7D09xExjkmipLOYe+w6hAkKcsDE4WdTj0FHVpM7GDRx0GfKY6b VRt2WvEL/HyvVQuY7pIjb0lSBIbOeOVQB34HbJn8oOSe6+UG+IfI13/kz8oAIAriJt mO+JOmmRTVEV73j5rHQkxliB5PArcpei31pCfE7SDh29l+XG+vGZdcN+zWT2MF04+n v7GqHonTgirIQ== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers , stable@vger.kernel.org Subject: [PATCH 04/22] dm-verity-fec: fix the size of dm_verity_fec_io::erasures Date: Thu, 5 Feb 2026 20:59:23 -0800 Message-ID: <20260206045942.52965-5-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" At most 25 entries in dm_verity_fec_io::erasures are used: the maximum number of FEC roots plus one. Therefore, set the array size accordingly. This reduces the size of dm_verity_fec_io by 912 bytes. Note: a later commit introduces a constant DM_VERITY_FEC_MAX_ROOTS, which allows the size to be more clearly expressed as DM_VERITY_FEC_MAX_ROOTS + 1. This commit just fixes the size first. Fixes: a739ff3f543a ("dm verity: add support for forward error correction") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h index 35d28d9f8a9b0..32ca2bfee1db7 100644 --- a/drivers/md/dm-verity-fec.h +++ b/drivers/md/dm-verity-fec.h @@ -45,11 +45,12 @@ struct dm_verity_fec { }; =20 /* per-bio data */ struct dm_verity_fec_io { struct rs_control *rs; /* Reed-Solomon state */ - int erasures[DM_VERITY_FEC_MAX_RSN]; /* erasures for decode_rs8 */ + /* erasures for decode_rs8 */ + int erasures[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN + 1]; u8 *output; /* buffer for corrected output */ unsigned int level; /* recursion level */ unsigned int nbufs; /* number of buffers allocated */ /* * Buffers for deinterleaving RS blocks. Each buffer has space for --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62AD233B6C2; Fri, 6 Feb 2026 05:01:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354116; cv=none; b=gKVRHXtDs3WQ24zuCUEbfaZr50Amkc1ZJGAonJlvuOab026CbGyQAu66B2rzyPlQ+WQ4G3AyxAS3DNd5uSpAKsLCADL9u7H46fWIgO8JmuFesFTnrIBYNRhZaIRw847203VKUhiBan3n9etWYUzOqZZXlsR+3aD806zBp5N6FD0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354116; c=relaxed/simple; bh=HEihQ3GqjiYSd4FKeWzWwMymUXxpIM+mdkN25ie7fqo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Iy1gYsonltUOJZganfgVzn2rkxucM3IbSlr1ZAcojmuKE7eD1rgvkL2HD+WbSDdJl/m9+e6cdboiV6H1KdASq06dHAJkBzBxTYUDG/rxiom3tXZ7TqEc+Z89BEU9mleA5xlhPEe11ztEX8GnTXOijfnykPkfKvsMi2gnkUZhtEU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NCYPOJ79; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NCYPOJ79" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C708BC19425; Fri, 6 Feb 2026 05:01:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354116; bh=HEihQ3GqjiYSd4FKeWzWwMymUXxpIM+mdkN25ie7fqo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NCYPOJ79+EvyMnCWZurdXvf0YjW+/7x6MrisLpOZnVpnWDsFsCRgMnWsJCe+z0vjL jeGGclIosizPaXofS0FtEPtEmZZIOeoLZBzHuYJo+mK5jSD9NlKkHlHU4cdCkb31xb nHzAdE0MsQ8yiT77rNkeuoj1vsDc0jb0nUbez0urmASr8hwinnpvzvR1w57ylXytAV /4V+5I75uYtfqvsenCpe6FnpjGTnZjG9xSjxUSZee/Yfh+Z99VCs/s1H9F580byQyy /bmADZ6yYdlKDFz9B0eCj5fEGzKvyV1F925e8JHqNhJqE96IL6oCsIlH7aTn5BXXUc PISVjCdExhksw== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers , stable@vger.kernel.org Subject: [PATCH 05/22] dm-verity-fec: fix reading parity bytes split across blocks (take 3) Date: Thu, 5 Feb 2026 20:59:24 -0800 Message-ID: <20260206045942.52965-6-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" fec_decode_bufs() assumes that the parity bytes of the first RS codeword it decodes are never split across parity blocks. This assumption is false. Consider v->fec->block_size =3D=3D 4096 && v->fec->roots =3D=3D 17 && fio->nbufs =3D=3D 1, for example. In that case,= each call to fec_decode_bufs() consumes v->fec->roots * (fio->nbufs << DM_VERITY_FEC_BUF_RS_BITS) =3D 272 parity bytes. Considering that the parity data for each message block starts on a block boundary, the byte alignment in the parity data will iterate through 272*i mod 4096 until the 3 parity blocks have been consumed. On the 16th call (i=3D15), the alignment will be 4080 bytes into the first block. Only 16 bytes remain in that block, but 17 parity bytes will be needed. The code reads out-of-bounds from the parity block buffer. Fortunately this doesn't normally happen, since it can occur only for certain non-default values of fec_roots *and* when the maximum number of buffers couldn't be allocated due to low memory. For example with block_size=3D4096 only the following cases are affected: fec_roots=3D17: nbufs in [1, 3, 5, 15] fec_roots=3D19: nbufs in [1, 229] fec_roots=3D21: nbufs in [1, 3, 5, 13, 15, 39, 65, 195] fec_roots=3D23: nbufs in [1, 89] Regardless, fix it by refactoring how the parity blocks are read. Fixes: 6df90c02bae4 ("dm-verity FEC: Fix RS FEC repair for roots unaligned = to block size (take 2)") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 100 ++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 56 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index d4a9367a2fee6..fcfacaec2989a 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -31,40 +31,10 @@ static inline u64 fec_interleave(struct dm_verity *v, u= 64 offset) =20 mod =3D do_div(offset, v->fec->rsn); return offset + mod * (v->fec->rounds << v->data_dev_block_bits); } =20 -/* - * Read error-correcting codes for the requested RS block. Returns a point= er - * to the data block. Caller is responsible for releasing buf. - */ -static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index, - unsigned int *offset, unsigned int par_buf_offset, - struct dm_buffer **buf, unsigned short ioprio) -{ - u64 position, block, rem; - u8 *res; - - /* We have already part of parity bytes read, skip to the next block */ - if (par_buf_offset) - index++; - - position =3D (index + rsb) * v->fec->roots; - block =3D div64_u64_rem(position, v->fec->io_size, &rem); - *offset =3D par_buf_offset ? 0 : (unsigned int)rem; - - res =3D dm_bufio_read_with_ioprio(v->fec->bufio, block, buf, ioprio); - if (IS_ERR(res)) { - DMERR("%s: FEC %llu: parity read failed (block %llu): %ld", - v->data_dev->name, (unsigned long long)rsb, - (unsigned long long)block, PTR_ERR(res)); - *buf =3D NULL; - } - - return res; -} - /* Loop over each allocated buffer. */ #define fec_for_each_buffer(io, __i) \ for (__i =3D 0; __i < (io)->nbufs; __i++) =20 /* Loop over each RS block in each allocated buffer. */ @@ -100,28 +70,66 @@ static int fec_decode_bufs(struct dm_verity *v, struct= dm_verity_io *io, struct dm_verity_fec_io *fio, u64 rsb, int byte_index, unsigned int block_offset, int neras) { int r, corrected =3D 0, res; struct dm_buffer *buf; - unsigned int n, i, j, offset, par_buf_offset =3D 0; + unsigned int n, i, j, parity_pos, to_copy; uint16_t par_buf[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN]; u8 *par, *block; + u64 parity_block; struct bio *bio =3D dm_bio_from_per_bio_data(io, v->ti->per_io_data_size); =20 - par =3D fec_read_parity(v, rsb, block_offset, &offset, - par_buf_offset, &buf, bio->bi_ioprio); - if (IS_ERR(par)) + /* + * Compute the index of the first parity block that will be needed and + * the starting position in that block. Then read that block. + * + * io_size is always a power of 2, but roots might not be. Note that + * when it's not, a codeword's parity bytes can span a block boundary. + */ + parity_block =3D (rsb + block_offset) * v->fec->roots; + parity_pos =3D parity_block & (v->fec->io_size - 1); + parity_block >>=3D v->data_dev_block_bits; + par =3D dm_bufio_read_with_ioprio(v->fec->bufio, parity_block, &buf, + bio->bi_ioprio); + if (IS_ERR(par)) { + DMERR("%s: FEC %llu: parity read failed (block %llu): %ld", + v->data_dev->name, rsb, parity_block, PTR_ERR(par)); return PTR_ERR(par); + } =20 /* * Decode the RS blocks we have in bufs. Each RS block results in * one corrected target byte and consumes fec->roots parity bytes. */ fec_for_each_buffer_rs_block(fio, n, i) { block =3D fec_buffer_rs_block(v, fio, n, i); - for (j =3D 0; j < v->fec->roots - par_buf_offset; j++) - par_buf[par_buf_offset + j] =3D par[offset + j]; + + /* + * Copy the next 'roots' parity bytes to 'par_buf', reading + * another parity block if needed. + */ + to_copy =3D min(v->fec->io_size - parity_pos, v->fec->roots); + for (j =3D 0; j < to_copy; j++) + par_buf[j] =3D par[parity_pos++]; + if (to_copy < v->fec->roots) { + parity_block++; + parity_pos =3D 0; + + dm_bufio_release(buf); + par =3D dm_bufio_read_with_ioprio(v->fec->bufio, + parity_block, &buf, + bio->bi_ioprio); + if (IS_ERR(par)) { + DMERR("%s: FEC %llu: parity read failed (block %llu): %ld", + v->data_dev->name, rsb, parity_block, + PTR_ERR(par)); + return PTR_ERR(par); + } + for (; j < v->fec->roots; j++) + par_buf[j] =3D par[parity_pos++]; + } + /* Decode an RS block using Reed-Solomon */ res =3D decode_rs8(fio->rs, block, par_buf, v->fec->rsn, NULL, neras, fio->erasures, 0, NULL); if (res < 0) { r =3D res; @@ -132,30 +140,10 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, fio->output[block_offset] =3D block[byte_index]; =20 block_offset++; if (block_offset >=3D 1 << v->data_dev_block_bits) goto done; - - /* Read the next block when we run out of parity bytes */ - offset +=3D (v->fec->roots - par_buf_offset); - /* Check if parity bytes are split between blocks */ - if (offset < v->fec->io_size && (offset + v->fec->roots) > v->fec->io_si= ze) { - par_buf_offset =3D v->fec->io_size - offset; - for (j =3D 0; j < par_buf_offset; j++) - par_buf[j] =3D par[offset + j]; - offset +=3D par_buf_offset; - } else - par_buf_offset =3D 0; - - if (offset >=3D v->fec->io_size) { - dm_bufio_release(buf); - - par =3D fec_read_parity(v, rsb, block_offset, &offset, - par_buf_offset, &buf, bio->bi_ioprio); - if (IS_ERR(par)) - return PTR_ERR(par); - } } done: r =3D corrected; error: dm_bufio_release(buf); --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 95AC233B6E1; Fri, 6 Feb 2026 05:01:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354116; cv=none; b=IkT2j0kdgj/4Lv6NVtmHQHRAAmW/u6qYVFobQWIBx2YTMve/SZ/4iY117uJDDUXTrP43VFDG7CSuYV+akPu0bq4rtXHMwxnyoyF3zZ/B+6sZhcPj99IjnmbMEvKe5TZH74zOpi3eMddLVhC2FC5vKOLHDE844VKLB9QeDkLveSE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354116; c=relaxed/simple; bh=xrKH+ehGVoyb6JwhTs96FBZNr3Fvc+0Rbe+tg2c8EGo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dWN8D2T7wV0OI9bC4TfRA5gqKNG6O7C5XphJKanwALUv0y37V4HE0iJ+ZnKQ4V5INTzoop6/5CrZNRoXAcdTZF61IgnVC3kAQu/2L3cFgEWPLqDtXRNrBqbLa6rkviDeoymTUEP4wGPNivPQa3yc8thJY9kOHit/MSG8C1PhlX4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=r8/qe32U; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="r8/qe32U" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3B587C2BC87; Fri, 6 Feb 2026 05:01:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354116; bh=xrKH+ehGVoyb6JwhTs96FBZNr3Fvc+0Rbe+tg2c8EGo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r8/qe32UJz0pIzEQLLtIuYQPtwD+94Ox8oIKFfR30MVgbz5YTvPYt93UuoAPUiPZS osjEuxqjhpyFpZwK5+R7bFLA3Y71XsvirODnjw0nnhuPujXeZNYkJ56WgNB4d/yMgF fyUxiX+68qqghEeI/AOZ1v6FFi/zqDOSWaWe7t7YW5BNLiKjHm7Gsvrh63tcXuTN8/ Fopc461BhswvpfsGHzbXffpkJd/SdAe+yk/y02EWzIgWrU6RJcaOmO+4BoZgj9+mFp YfdyUANxkCQsvabdAuUT9lvG8cPqA2HGUZbugymDdFi2Vmw2mYPML9oIR+78KmFmD1 ToxjZEmfyplkQ== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 06/22] dm-verity: rename dm_verity::hash_blocks to dm_verity::hash_end Date: Thu, 5 Feb 2026 20:59:25 -0800 Message-ID: <20260206045942.52965-7-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Rename hash_blocks to hash_end to reflect what it actually is. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 2 +- drivers/md/dm-verity-target.c | 8 ++++---- drivers/md/dm-verity.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index fcfacaec2989a..c3f2516f9c2a9 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -633,11 +633,11 @@ int verity_fec_ctr(struct dm_verity *v) * * If metadata is included, we require it to be available on the * hash device after the hash blocks. */ =20 - hash_blocks =3D v->hash_blocks - v->hash_start; + hash_blocks =3D v->hash_end - v->hash_start; =20 /* * Require matching block sizes for data and hash devices for * simplicity. */ diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index 631ccc6a2bb7e..ad9a86e8e44bb 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -730,12 +730,12 @@ static void verity_prefetch_io(struct work_struct *wo= rk) if (unlikely(cluster & (cluster - 1))) cluster =3D 1 << __fls(cluster); =20 hash_block_start &=3D ~(sector_t)(cluster - 1); hash_block_end |=3D cluster - 1; - if (unlikely(hash_block_end >=3D v->hash_blocks)) - hash_block_end =3D v->hash_blocks - 1; + if (unlikely(hash_block_end >=3D v->hash_end)) + hash_block_end =3D v->hash_end - 1; } no_prefetch_cluster: dm_bufio_prefetch_with_ioprio(v->bufio, hash_block_start, hash_block_end - hash_block_start + 1, pw->ioprio); @@ -1604,11 +1604,11 @@ static int verity_ctr(struct dm_target *ti, unsigne= d int argc, char **argv) r =3D -E2BIG; goto bad; } hash_position +=3D s; } - v->hash_blocks =3D hash_position; + v->hash_end =3D hash_position; =20 r =3D mempool_init_page_pool(&v->recheck_pool, 1, 0); if (unlikely(r)) { ti->error =3D "Cannot allocate mempool"; goto bad; @@ -1631,11 +1631,11 @@ static int verity_ctr(struct dm_target *ti, unsigne= d int argc, char **argv) r =3D PTR_ERR(v->bufio); v->bufio =3D NULL; goto bad; } =20 - if (dm_bufio_get_device_size(v->bufio) < v->hash_blocks) { + if (dm_bufio_get_device_size(v->bufio) < v->hash_end) { ti->error =3D "Hash device is too small"; r =3D -E2BIG; goto bad; } =20 diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h index d6bfabb27113b..2922263501f68 100644 --- a/drivers/md/dm-verity.h +++ b/drivers/md/dm-verity.h @@ -51,13 +51,13 @@ struct dm_verity { #ifdef CONFIG_SECURITY u8 *root_digest_sig; /* signature of the root digest */ unsigned int sig_size; /* root digest signature size */ #endif /* CONFIG_SECURITY */ unsigned int salt_size; - sector_t hash_start; /* hash start in blocks */ + sector_t hash_start; /* index of first hash block on hash_dev */ + sector_t hash_end; /* 1 + index of last hash block on hash dev */ sector_t data_blocks; /* the number of data blocks */ - sector_t hash_blocks; /* the number of hash blocks */ unsigned char data_dev_block_bits; /* log2(data blocksize) */ unsigned char hash_dev_block_bits; /* log2(hash blocksize) */ unsigned char hash_per_block_bits; /* log2(hashes in hash block) */ unsigned char levels; /* the number of tree levels */ unsigned char version; --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1BC1333C183; Fri, 6 Feb 2026 05:01:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354117; cv=none; b=KoKi3lnRl+fkZhchEv11guU8qaxBDRc9O/0gCyGuC9OZL99W1C4CObNSBd9+KmAn6iLW10FEMh4eOcqQNzKER/jpy/S8vE2U9/V6PjHS3jkukC6xkIFntH1K04L2hq1ctBw26O/UiNebWfF6Ia04W3Qb4LpmQsOavyFm2pBkwHA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354117; c=relaxed/simple; bh=EimmtiTLQrF3E7DUZrtI9fJXkoOVz3amkyBv+hDIiC4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hTOYtveRY09tOqD6Efb4idmND/LIIyyDJsWqVRPeexwcbpcHAI+QUqNggQG3NHfsfejygUdN65O6ns5jLC+pf+ES8kRnze8WUo0ci6ygksMwKaWUixyoMuQlDb+9ZcOxe1P/GD3vqqITQcht9L1ZLoo8ffKFvutCAT6uymuImy8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=R1icAi/i; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="R1icAi/i" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9CEECC16AAE; Fri, 6 Feb 2026 05:01:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354116; bh=EimmtiTLQrF3E7DUZrtI9fJXkoOVz3amkyBv+hDIiC4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=R1icAi/iVUx7AGGZ9dVB114ep+eG7MdzVCzkcXA/wCD3b5H1iq/F4farm2kSCs2YD /ItQzzF9YEOdRBkiu329TKotwRomcCH23vO/+45IWINqIAcLbsbc/xuiqYkfOBZ4qj ZWGKBWd/7juqzeT5suUFOu81LGLud3JBI20fgIXFoHkjDlJdlVwQc2/If3ia4bbdRt tQeil9DldeJc6FOtBA91dDpUufsuudJWpNj0TOQMm8ZGFgFIggbJL2WqTqXD9lOyuZ t7qK0lSV5FaamqBNE3v6PJmOtBOjXm3XyCiq3p1kOI8VeWxGlyUrxEr+dxgzNk9n8b p90hncQASXGDg== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 07/22] dm-verity-fec: improve documentation for Forward Error Correction Date: Thu, 5 Feb 2026 20:59:26 -0800 Message-ID: <20260206045942.52965-8-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Update verity.rst to add a dedicated section about FEC and improve the documentation for the FEC-related parameters. Signed-off-by: Eric Biggers --- .../admin-guide/device-mapper/verity.rst | 122 +++++++++++++++--- 1 file changed, 102 insertions(+), 20 deletions(-) diff --git a/Documentation/admin-guide/device-mapper/verity.rst b/Documenta= tion/admin-guide/device-mapper/verity.rst index 3ecab1cff9c64..eb9475d7e1965 100644 --- a/Documentation/admin-guide/device-mapper/verity.rst +++ b/Documentation/admin-guide/device-mapper/verity.rst @@ -100,33 +100,46 @@ ignore_zero_blocks Do not verify blocks that are expected to contain zeroes and always re= turn zeroes instead. This may be useful if the partition contains unused bl= ocks that are not guaranteed to contain zeroes. =20 use_fec_from_device - Use forward error correction (FEC) to recover from corruption if hash - verification fails. Use encoding data from the specified device. This - may be the same device where data and hash blocks reside, in which case - fec_start must be outside data and hash areas. + Use forward error correction (FEC) parity data from the specified devi= ce to + try to automatically recover from corruption and I/O errors. =20 - If the encoding data covers additional metadata, it must be accessible - on the hash device after the hash blocks. + If this option is given, then and must also be + given. must also be equal to . =20 - Note: block sizes for data and hash devices must match. Also, if the - verity is encrypted the should be too. + can be the same as , in which case must be + outside the data area. It can also be the same as , in whic= h case + must be outside the hash and optional additional metadata = areas. + + If the data is encrypted, the should be too. + + For more information, see `Forward error correction`_. =20 fec_roots - Number of generator roots. This equals to the number of parity bytes in - the encoding data. For example, in RS(M, N) encoding, the number of ro= ots - is M-N. + The number of parity bytes in each 255-byte Reed-Solomon codeword. The + Reed-Solomon code used will be an RS(255, k) code where k =3D 255 - fe= c_roots. + + The supported values are 2 through 24 inclusive. Higher values provide + stronger error correction. However, the minimum value of 2 already pr= ovides + strong error correction due to the use of interleaving, so 2 is the + recommended value for most users. fec_roots=3D2 corresponds to an + RS(255, 253) code, which has a space overhead of about 0.8%. =20 fec_blocks - The number of encoding data blocks on the FEC device. The block size f= or - the FEC device is . + The total number of blocks that are error-checked us= ing + FEC. This must be at least the sum of and the numbe= r of + blocks needed by the hash tree. It can include additional metadata bl= ocks, + which are assumed to be accessible on following the hash bl= ocks. + + Note that this is *not* the number of parity blocks. The number of pa= rity + blocks is inferred from , , and . =20 fec_start - This is the offset, in blocks, from the start of the - FEC device to the beginning of the encoding data. + This is the offset, in blocks, from the start of + to the beginning of the parity data. =20 check_at_most_once Verify data blocks only the first time they are read from the data dev= ice, rather than every time. This reduces the overhead of dm-verity so tha= t it can be used on systems that are memory and/or CPU constrained. Howeve= r, it @@ -178,15 +191,10 @@ tampering with any data on the device and the hash da= ta. Cryptographic hashes are used to assert the integrity of the device on a per-block basis. This allows for a lightweight hash computation on first r= ead into the page cache. Block hashes are stored linearly, aligned to the near= est block size. =20 -If forward error correction (FEC) support is enabled any recovery of -corrupted data will be verified using the cryptographic hash of the -corresponding data. This is why combining error correction with -integrity checking is essential. - Hash Tree --------- =20 Each node in the tree is a cryptographic hash. If it is a leaf node, the = hash of some data block on disk is calculated. If it is an intermediary node, @@ -210,10 +218,84 @@ The tree looks something like: / . . . \ . . . \ [entry_0_0] . . . [entry_0_127] . . . . [entry_1_127] / ... \ / . . . \ / \ blk_0 ... blk_127 blk_16256 blk_16383 blk_32640 . . . blk_327= 67 =20 +Forward error correction +------------------------ + +dm-verity's optional forward error correction (FEC) support adds strong er= ror +correction capabilities to dm-verity. It allows systems that would be ren= dered +inoperable by errors to continue operating, albeit with reduced performanc= e. + +FEC uses Reed-Solomon (RS) codes that are interleaved across the entire +device(s), allowing long bursts of corrupt or unreadable blocks to be reco= vered. + +dm-verity validates any FEC-corrected block against the wanted hash before= using +it. Therefore, FEC doesn't affect the security properties of dm-verity. + +The integration of FEC with dm-verity provides significant benefits over a +separate error correction layer: + +- dm-verity invokes FEC only when a block's hash doesn't match the wanted = hash + or the block cannot be read at all. As a result, FEC doesn't add overhe= ad to + the common case where no error occurs. + +- dm-verity hashes are also used to identify erasure locations for RS deco= ding. + This allows correcting twice as many errors. + +FEC uses an RS(255, k) code where k =3D 255 - fec_roots. fec_roots is usu= ally 2. +This means that each k (usually 253) message bytes have fec_roots (usually= 2) +bytes of parity data added to get a 255-byte codeword. (Many external sou= rces +call RS codewords "blocks". Since dm-verity already uses the term "block"= to +mean something else, we'll use the clearer term "RS codeword".) + +FEC checks fec_blocks blocks of message data in total, consisting of: + +1. The data blocks from the data device +2. The hash blocks from the hash device +3. Optional additional metadata that follows the hash blocks on the hash d= evice + +dm-verity assumes that the FEC parity data was computed as if the following +procedure were followed: + +1. Concatenate the message data from the above sources. +2. Zero-pad to the next multiple of k blocks. Let msg be the resulting by= te + array, and msglen its length in bytes. +3. For 0 <=3D i < msglen / k (for each RS codeword): + a. Select msg[i + j * msglen / k] for 0 <=3D j < k. + Consider these to be the 'k' message bytes of an RS codeword. + b. Compute the corresponding 'fec_roots' parity bytes of the RS codew= ord, + and concatenate them to the FEC parity data. + +Step 3a interleaves the RS codewords across the entire device using an +interleaving degree of data_block_size * ceil(fec_blocks / k). This is the +maximal interleaving, such that the message data consists of a region cont= aining +byte 0 of all the RS codewords, then a region containing byte 1 of all the= RS +codewords, and so on up to the region for byte 'k - 1'. Note that the num= ber of +codewords is set to a multiple of data_block_size; thus, the regions are +block-aligned, and there is an implicit zero padding of up to 'k - 1' bloc= ks. + +This interleaving allows long bursts of errors to be corrected. It provid= es +much stronger error correction than storage devices typically provide, whi= le +keeping the space overhead low. + +The cost is slow decoding: correcting a single block usually requires read= ing +254 extra blocks spread evenly across the device(s). However, that is +acceptable because dm-verity uses FEC only when there is actually an error. + +The list below contains additional details about the RS codes used by +dm-verity's FEC. Userspace programs that generate the parity data need to= use +these parameters for the parity data to match exactly: + +- Field used is GF(256) +- Bytes are mapped to/from GF(256) elements in the natural way, where bits= 0 + through 7 (low-order to high-order) map to the coefficients of x^0 throu= gh x^7 +- Field generator polynomial is x^8 + x^4 + x^3 + x^2 + 1 +- The codes used are systematic, BCH-view codes +- Primitive element alpha is 'x' +- First consecutive root of code generator polynomial is 'x^0' =20 On-disk format =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 The verity kernel code does not read the verity metadata on-disk header. --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6410E33C50D; Fri, 6 Feb 2026 05:01:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354117; cv=none; b=bX07x47IakNv/z8/IoGS+TK0X3xPztsr/q+XL/rugIYRobqqLXBeSCi2RHcypgVCxsljYB6BB2LDMX9+ILcHHoNyWqd+iCKyDtL6eOAxPOBdXuZ4kbmAOSnb0Y4HGD4isI+ocXGqXa9JwEGyyKl3AM3ipS/wPzpsrau+3JF3+BE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354117; c=relaxed/simple; bh=rf4dX9huoPWX3DYxIAsVDveY0+x+aP1dl4Xg7gjew8E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ArsRf+gSXHz48HoeO5kVHY4phE17ZGxFa1iik8Y3eA9BNVXJHMw19/GFXgM/TcDPRXIJOlEri/+jlV5ahP9z9nGkjU92N6x8/svgQAwhz80PmoLL179QROfKeE5zNU+AXsA8q8UV81UkDC9znuJWJKRB9muiewc1UCPAb/wm+6Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=W8weZUE5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="W8weZUE5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 089B7C2BCC4; Fri, 6 Feb 2026 05:01:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354117; bh=rf4dX9huoPWX3DYxIAsVDveY0+x+aP1dl4Xg7gjew8E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W8weZUE5otCaZSzYUP31ltH6Q7N7gp0altqbnpxcPM36imFuFo+uXljQ67CWttgLJ DeeKXtcwn9S/KFDBYh1lhbVGc7QtGou8jlgu5qLfFz+fmsUom9+9HVVP77fH3MB7uO lGn9zcGglxa1/Cdv2s2v0uUgkfKjSEnQMRiE6fN1SdU0BCBtEKJJM+f5tgrjIoVNG4 svt+v5u7EMKHUHsFttAiSa3LthdR35xmnCrhwyOLDjl5T05PMKiOpo/3thg0Lzx57T DzPtp8+0PAg1dxeR/x0f0otaojNrWLn42uvmhXEPbExqvZRtN33SKX6jX4+EHa2kT2 kLUzthtm38xbg== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 08/22] dm-verity-fec: replace {MAX,MIN}_RSN with {MIN,MAX}_ROOTS Date: Thu, 5 Feb 2026 20:59:27 -0800 Message-ID: <20260206045942.52965-9-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Every time DM_VERITY_FEC_{MAX,MIN}_RSN are used, they are subtracted from DM_VERITY_FEC_RSM to get the bounds on the number of roots. Therefore, replace these with {MIN,MAX}_ROOTS constants which are more directly useful. (Note the inversion, where MAX_RSN maps to MIN_ROOTS and MIN_RSN maps to MAX_ROOTS.) No functional change. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 6 +++--- drivers/md/dm-verity-fec.h | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index c3f2516f9c2a9..c5f97a49e5b79 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -71,11 +71,11 @@ static int fec_decode_bufs(struct dm_verity *v, struct = dm_verity_io *io, unsigned int block_offset, int neras) { int r, corrected =3D 0, res; struct dm_buffer *buf; unsigned int n, i, j, parity_pos, to_copy; - uint16_t par_buf[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN]; + uint16_t par_buf[DM_VERITY_FEC_MAX_ROOTS]; u8 *par, *block; u64 parity_block; struct bio *bio =3D dm_bio_from_per_bio_data(io, v->ti->per_io_data_size); =20 /* @@ -570,12 +570,12 @@ int verity_fec_parse_opt_args(struct dm_arg_set *as, = struct dm_verity *v, } v->fec->start =3D num_ll; =20 } else if (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_ROOTS)) { if (sscanf(arg_value, "%hhu%c", &num_c, &dummy) !=3D 1 || !num_c || - num_c < (DM_VERITY_FEC_RSM - DM_VERITY_FEC_MAX_RSN) || - num_c > (DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN)) { + num_c < DM_VERITY_FEC_MIN_ROOTS || + num_c > DM_VERITY_FEC_MAX_ROOTS) { ti->error =3D "Invalid " DM_VERITY_OPT_FEC_ROOTS; return -EINVAL; } v->fec->roots =3D num_c; =20 diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h index 32ca2bfee1db7..d8d0e81da2701 100644 --- a/drivers/md/dm-verity-fec.h +++ b/drivers/md/dm-verity-fec.h @@ -11,12 +11,12 @@ #include "dm-verity.h" #include =20 /* Reed-Solomon(M, N) parameters */ #define DM_VERITY_FEC_RSM 255 -#define DM_VERITY_FEC_MAX_RSN 253 -#define DM_VERITY_FEC_MIN_RSN 231 /* ~10% space overhead */ +#define DM_VERITY_FEC_MIN_ROOTS 2 /* RS(255, 253): ~0.8% space overhead */ +#define DM_VERITY_FEC_MAX_ROOTS 24 /* RS(255, 231): ~10% space overhead */ =20 /* buffers for deinterleaving and decoding */ #define DM_VERITY_FEC_BUF_RS_BITS 4 /* 1 << RS blocks per buffer */ =20 #define DM_VERITY_OPT_FEC_DEV "use_fec_from_device" @@ -45,12 +45,11 @@ struct dm_verity_fec { }; =20 /* per-bio data */ struct dm_verity_fec_io { struct rs_control *rs; /* Reed-Solomon state */ - /* erasures for decode_rs8 */ - int erasures[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN + 1]; + int erasures[DM_VERITY_FEC_MAX_ROOTS + 1]; /* erasures for decode_rs8 */ u8 *output; /* buffer for corrected output */ unsigned int level; /* recursion level */ unsigned int nbufs; /* number of buffers allocated */ /* * Buffers for deinterleaving RS blocks. Each buffer has space for --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C72B333CEAF; Fri, 6 Feb 2026 05:01:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354117; cv=none; b=pRiesBw6gTdcWT+sEd0tTwydoW9RrG+/0xRShECg3SWfTWVJLC1t72gM6tPQdy5d6tOhKoLmU4wmJ1QEFOqERXalAJco/msWgyVglrnUQGuz/8XJ2CFBgOurll5BljSjcsPwKspr+1jkYjAn4Kk2cVAooxsnqc7a/5c9YJH2IQ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354117; c=relaxed/simple; bh=UmBnnJD5gutfSn3AllzRmWoVzM59iVB0G7xY9DxeVR0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GHYr79+oWyOuI9jcj+GZLzkp2GHKJ3vzOnQD6TBIAaOHZrGbS58sJCMjHx2oIt0A7ItgetKi14sht3zaydKiq+XpqRtoBiP5ni5o/Kk4o5kFSM4NCMVdm2IZEU5PNZQGZRAVSYEJ05UZN+EPfy3vWLYrkZjPMa1FA8rCLrY6Jd4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VRQFpMcy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VRQFpMcy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6C104C19425; Fri, 6 Feb 2026 05:01:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354117; bh=UmBnnJD5gutfSn3AllzRmWoVzM59iVB0G7xY9DxeVR0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VRQFpMcyBGGEyYYa4ijosyzDSG7/WtIWHwM9AJhkQp+4UyFGEsaeAHmCMmvCMvwq1 cxKuzKyJulPY/zRmOWtyebBmJDaWjLKZ1HNFgsNI8y2kjZl2AAbqCp27gocFGX/87k S5u5d/X9vsOXT57pwyxGtren7IV3FwSkdW82TK77+cD7BzrmeKFFkawHXZ0DDzMjWR ur6IwgJeiMLN/3Zi3RpjlpHpKW50evCoeVW8nInuY8cL6+QdVSykLl+sKD6IkcBJ6T CjasXrCc6Z2WDoQ1FPTM4QicKxhWmS+cSQFUx14tvNRX03JIJrVFMtW+7ERehPXND6 mSurCE0bqJlPw== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 09/22] dm-verity-fec: use standard names for Reed-Solomon parameters Date: Thu, 5 Feb 2026 20:59:28 -0800 Message-ID: <20260206045942.52965-10-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" "RS(n, k)" is by far the most common and standard notation for describing Reed-Solomon codes. Each RS codeword consists of 'n' symbols, divided into 'k' message symbols and 'n - k' parity symbols. 'n - k' is also the number of roots of the generator polynomial. dm-verity uses "RS(M, N)" instead. I haven't been able to find any other source that uses this convention. This quirk makes the code harder to understand than necessary, especially due to dm-verity's 'N' meaning something different from the standard 'n'. Therefore, update dm-verity-fec.c and dm-verity-fec.h to use the standard parameter names. No functional changes. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 30 +++++++++++++++--------------- drivers/md/dm-verity-fec.h | 8 ++++---- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index c5f97a49e5b79..8e9482a6df4a1 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -27,11 +27,11 @@ static inline unsigned int fec_max_nbufs(struct dm_veri= ty *v) */ static inline u64 fec_interleave(struct dm_verity *v, u64 offset) { u32 mod; =20 - mod =3D do_div(offset, v->fec->rsn); + mod =3D do_div(offset, v->fec->rs_k); return offset + mod * (v->fec->rounds << v->data_dev_block_bits); } =20 /* Loop over each allocated buffer. */ #define fec_for_each_buffer(io, __i) \ @@ -48,11 +48,11 @@ static inline u64 fec_interleave(struct dm_verity *v, u= 64 offset) */ static inline u8 *fec_buffer_rs_block(struct dm_verity *v, struct dm_verity_fec_io *fio, unsigned int i, unsigned int j) { - return &fio->bufs[i][j * v->fec->rsn]; + return &fio->bufs[i][j * v->fec->rs_k]; } =20 /* * Return an index to the current RS block when called inside * fec_for_each_buffer_rs_block. @@ -127,11 +127,11 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, for (; j < v->fec->roots; j++) par_buf[j] =3D par[parity_pos++]; } =20 /* Decode an RS block using Reed-Solomon */ - res =3D decode_rs8(fio->rs, block, par_buf, v->fec->rsn, + res =3D decode_rs8(fio->rs, block, par_buf, v->fec->rs_k, NULL, neras, fio->erasures, 0, NULL); if (res < 0) { r =3D res; goto error; } @@ -195,19 +195,19 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, =20 if (WARN_ON(v->digest_size > sizeof(want_digest))) return -EINVAL; =20 /* - * read each of the rsn data blocks that are part of the RS block, and + * read each of the rs_k data blocks that are part of the RS block, and * interleave contents to available bufs */ - for (i =3D 0; i < v->fec->rsn; i++) { - ileaved =3D fec_interleave(v, rsb * v->fec->rsn + i); + for (i =3D 0; i < v->fec->rs_k; i++) { + ileaved =3D fec_interleave(v, rsb * v->fec->rs_k + i); =20 /* * target is the data block we want to correct, target_index is - * the index of this block within the rsn RS blocks + * the index of this block within the rs_k RS blocks */ if (ileaved =3D=3D target) target_index =3D i; =20 block =3D ileaved >> v->data_dev_block_bits; @@ -320,11 +320,11 @@ static struct dm_verity_fec_io *fec_alloc_and_init_io= (struct dm_verity *v) static void fec_init_bufs(struct dm_verity *v, struct dm_verity_fec_io *fi= o) { unsigned int n; =20 fec_for_each_buffer(fio, n) - memset(fio->bufs[n], 0, v->fec->rsn << DM_VERITY_FEC_BUF_RS_BITS); + memset(fio->bufs[n], 0, v->fec->rs_k << DM_VERITY_FEC_BUF_RS_BITS); =20 memset(fio->erasures, 0, sizeof(fio->erasures)); } =20 /* @@ -392,16 +392,16 @@ int verity_fec_decode(struct dm_verity *v, struct dm_= verity_io *io, =20 if (type =3D=3D DM_VERITY_BLOCK_TYPE_METADATA) block =3D block - v->hash_start + v->data_blocks; =20 /* - * For RS(M, N), the continuous FEC data is divided into blocks of N - * bytes. Since block size may not be divisible by N, the last block + * For RS(n, k), the continuous FEC data is divided into blocks of k + * bytes. Since block size may not be divisible by k, the last block * is zero padded when decoding. * - * Each byte of the block is covered by a different RS(M, N) code, - * and each code is interleaved over N blocks to make it less likely + * Each byte of the block is covered by a different RS(n, k) code, + * and each code is interleaved over k blocks to make it less likely * that bursty corruption will leave us in unrecoverable state. */ =20 offset =3D block << v->data_dev_block_bits; res =3D div64_u64(offset, v->fec->rounds << v->data_dev_block_bits); @@ -648,19 +648,19 @@ int verity_fec_ctr(struct dm_verity *v) =20 if (!f->roots) { ti->error =3D "Missing " DM_VERITY_OPT_FEC_ROOTS; return -EINVAL; } - f->rsn =3D DM_VERITY_FEC_RSM - f->roots; + f->rs_k =3D DM_VERITY_FEC_RS_N - f->roots; =20 if (!f->blocks) { ti->error =3D "Missing " DM_VERITY_OPT_FEC_BLOCKS; return -EINVAL; } =20 f->rounds =3D f->blocks; - if (sector_div(f->rounds, f->rsn)) + if (sector_div(f->rounds, f->rs_k)) f->rounds++; =20 /* * Due to optional metadata, f->blocks can be larger than * data_blocks and hash_blocks combined. @@ -728,11 +728,11 @@ int verity_fec_ctr(struct dm_verity *v) ti->error =3D "Cannot allocate RS pool"; return ret; } =20 f->cache =3D kmem_cache_create("dm_verity_fec_buffers", - f->rsn << DM_VERITY_FEC_BUF_RS_BITS, + f->rs_k << DM_VERITY_FEC_BUF_RS_BITS, 0, 0, NULL); if (!f->cache) { ti->error =3D "Cannot create FEC buffer cache"; return -ENOMEM; } diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h index d8d0e81da2701..5afa93f2f1fc7 100644 --- a/drivers/md/dm-verity-fec.h +++ b/drivers/md/dm-verity-fec.h @@ -9,12 +9,12 @@ #define DM_VERITY_FEC_H =20 #include "dm-verity.h" #include =20 -/* Reed-Solomon(M, N) parameters */ -#define DM_VERITY_FEC_RSM 255 +/* Reed-Solomon(n, k) parameters */ +#define DM_VERITY_FEC_RS_N 255 #define DM_VERITY_FEC_MIN_ROOTS 2 /* RS(255, 253): ~0.8% space overhead */ #define DM_VERITY_FEC_MAX_ROOTS 24 /* RS(255, 231): ~10% space overhead */ =20 /* buffers for deinterleaving and decoding */ #define DM_VERITY_FEC_BUF_RS_BITS 4 /* 1 << RS blocks per buffer */ @@ -32,12 +32,12 @@ struct dm_verity_fec { size_t io_size; /* IO size for roots */ sector_t start; /* parity data start in blocks */ sector_t blocks; /* number of blocks covered */ sector_t rounds; /* number of interleaving rounds */ sector_t hash_blocks; /* blocks covered after v->hash_start */ - unsigned char roots; /* number of parity bytes, M-N of RS(M, N) */ - unsigned char rsn; /* N of RS(M, N) */ + unsigned char roots; /* parity bytes per RS codeword, n-k of RS(n, k) */ + unsigned char rs_k; /* message bytes per RS codeword, k of RS(n, k) */ mempool_t fio_pool; /* mempool for dm_verity_fec_io */ mempool_t rs_pool; /* mempool for fio->rs */ mempool_t prealloc_pool; /* mempool for preallocated buffers */ mempool_t output_pool; /* mempool for output */ struct kmem_cache *cache; /* cache for buffers */ --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 33C6933D6C2; Fri, 6 Feb 2026 05:01:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354118; cv=none; b=FCZ02cfAvZIh9sR4ING4w9GGLlZAVAUdmF10mPaaKnT7xLo02h92Bl5KC4yCxG/H+FnqP2SINtD07HMV+KxfnqkvowtJ8f7oDDv7imeAP8xTfmCsaH7UeveT0qlBm6uhG8nyPk7jzKS4KK8aDUEE/d+JA3RJzPYaaAugYtCRFPw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354118; c=relaxed/simple; bh=0+BZxKuKZeUs+WBhbuBBTQwZHtqoL7AOSTxD/oy7SJw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uAZyGim41MhpayHp1wO3J6VgzxN3rwmwb2UBDJEqjZ9mM66g6ATxwVDBmD7FocyARgvYLzXxX9GrEHZkCeVzQJVHrlYxF6iezcfmS9LaYzSDHpxTUmeJmYdzdeOj+IpnHvQ8CELgFgK35waFSFgsyB6GKPm+cSiuWJq9QJ6oYNM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uGGs8Y0r; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uGGs8Y0r" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CDC7DC4AF09; Fri, 6 Feb 2026 05:01:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354118; bh=0+BZxKuKZeUs+WBhbuBBTQwZHtqoL7AOSTxD/oy7SJw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uGGs8Y0rGBxiObjAD68WKduXPfx1GyZBCJvJ4oSF98Jz+MYt54gHsXqb9WhtYN7xt Fb776b82jVyT9CE7PFYDx21FlcSgk5Yjb97lN58+JT68xziBblHE1Zt83oCRP+H23i 4P/vu0L6YTDE1Zq8S5R6O4t6+BCbVeGGgf4Ly9JajD6EMvfkACM8HlID5cQawjNJOc /AXV9K11vTfbl6pEwaFrZG3RXhq2HweJAC/iOYH+gk3Sxcc2aRo5OlsPLKXpbtqx1t lT7husKZZ5UuTfLwsGPmY/0tv6hR/RfZvIdDZuUCIR/DxQkQ3g2vpvdNGG3hBbX6z3 rilOK6VOnTZAg== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 10/22] dm-verity-fec: rename "RS block" to "RS codeword" Date: Thu, 5 Feb 2026 20:59:29 -0800 Message-ID: <20260206045942.52965-11-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The literature refers to the unit of a Reed-Solomon (RS) code as either a "block" or a "codeword". dm-verity's source code uses "RS block". Unfortunately, that's really confusing because "block" already means something else in dm-verity. Especially problematic is the fact that dm-verity sometimes uses "RS block" to mean an RS codeword and sometimes to mean some dm-verity block that's related to the RS decoding process, for example one of the blocks that shares its RS codewords with the target block. Let's use "RS codeword" instead, or "RS message" when referring to just the message part of the codeword. Update some comments, function names, macro names, and variable names accordingly. No functional change. There are still some remaining comments where "RS block" refers to a dm-verity block. Later commits will handle these cases. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 58 ++++++++++++++++++++------------------ drivers/md/dm-verity-fec.h | 10 +++---- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 8e9482a6df4a1..619645edaf509 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -9,15 +9,16 @@ #include =20 #define DM_MSG_PREFIX "verity-fec" =20 /* - * When correcting a data block, the FEC code performs optimally when it c= an - * collect all the associated RS blocks at the same time. As each byte is= part - * of a different RS block, there are '1 << data_dev_block_bits' RS blocks. - * There are '1 << DM_VERITY_FEC_BUF_RS_BITS' RS blocks per buffer, so that - * gives '1 << (data_dev_block_bits - DM_VERITY_FEC_BUF_RS_BITS)' buffers. + * When correcting a block, the FEC implementation performs optimally when= it + * can collect all the associated RS codewords at the same time. As each = byte + * is part of a different codeword, there are '1 << data_dev_block_bits' + * codewords. Each buffer has space for the message bytes for + * '1 << DM_VERITY_FEC_BUF_RS_BITS' codewords, so that gives + * '1 << (data_dev_block_bits - DM_VERITY_FEC_BUF_RS_BITS)' buffers. */ static inline unsigned int fec_max_nbufs(struct dm_verity *v) { return 1 << (v->data_dev_block_bits - DM_VERITY_FEC_BUF_RS_BITS); } @@ -35,48 +36,49 @@ static inline u64 fec_interleave(struct dm_verity *v, u= 64 offset) =20 /* Loop over each allocated buffer. */ #define fec_for_each_buffer(io, __i) \ for (__i =3D 0; __i < (io)->nbufs; __i++) =20 -/* Loop over each RS block in each allocated buffer. */ -#define fec_for_each_buffer_rs_block(io, __i, __j) \ +/* Loop over each RS message in each allocated buffer. */ +/* To stop early, use 'goto', not 'break' (since this uses nested loops). = */ +#define fec_for_each_buffer_rs_message(io, __i, __j) \ fec_for_each_buffer(io, __i) \ for (__j =3D 0; __j < 1 << DM_VERITY_FEC_BUF_RS_BITS; __j++) =20 /* - * Return a pointer to the current RS block when called inside - * fec_for_each_buffer_rs_block. + * Return a pointer to the current RS message when called inside + * fec_for_each_buffer_rs_message. */ -static inline u8 *fec_buffer_rs_block(struct dm_verity *v, - struct dm_verity_fec_io *fio, - unsigned int i, unsigned int j) +static inline u8 *fec_buffer_rs_message(struct dm_verity *v, + struct dm_verity_fec_io *fio, + unsigned int i, unsigned int j) { return &fio->bufs[i][j * v->fec->rs_k]; } =20 /* - * Return an index to the current RS block when called inside - * fec_for_each_buffer_rs_block. + * Return the index of the current RS message when called inside + * fec_for_each_buffer_rs_message. */ static inline unsigned int fec_buffer_rs_index(unsigned int i, unsigned in= t j) { return (i << DM_VERITY_FEC_BUF_RS_BITS) + j; } =20 /* - * Decode all RS blocks from buffers and copy corrected bytes into fio->ou= tput - * starting from block_offset. + * Decode all RS codewords whose message bytes were loaded into fio->bufs.= Copy + * the corrected bytes into fio->output starting from block_offset. */ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io, struct dm_verity_fec_io *fio, u64 rsb, int byte_index, unsigned int block_offset, int neras) { int r, corrected =3D 0, res; struct dm_buffer *buf; unsigned int n, i, j, parity_pos, to_copy; uint16_t par_buf[DM_VERITY_FEC_MAX_ROOTS]; - u8 *par, *block; + u8 *par, *msg_buf; u64 parity_block; struct bio *bio =3D dm_bio_from_per_bio_data(io, v->ti->per_io_data_size); =20 /* * Compute the index of the first parity block that will be needed and @@ -95,15 +97,16 @@ static int fec_decode_bufs(struct dm_verity *v, struct = dm_verity_io *io, v->data_dev->name, rsb, parity_block, PTR_ERR(par)); return PTR_ERR(par); } =20 /* - * Decode the RS blocks we have in bufs. Each RS block results in - * one corrected target byte and consumes fec->roots parity bytes. + * Decode the RS codewords whose message bytes are in bufs. Each RS + * codeword results in one corrected target byte and consumes fec->roots + * parity bytes. */ - fec_for_each_buffer_rs_block(fio, n, i) { - block =3D fec_buffer_rs_block(v, fio, n, i); + fec_for_each_buffer_rs_message(fio, n, i) { + msg_buf =3D fec_buffer_rs_message(v, fio, n, i); =20 /* * Copy the next 'roots' parity bytes to 'par_buf', reading * another parity block if needed. */ @@ -126,20 +129,20 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, } for (; j < v->fec->roots; j++) par_buf[j] =3D par[parity_pos++]; } =20 - /* Decode an RS block using Reed-Solomon */ - res =3D decode_rs8(fio->rs, block, par_buf, v->fec->rs_k, + /* Decode an RS codeword using the Reed-Solomon library. */ + res =3D decode_rs8(fio->rs, msg_buf, par_buf, v->fec->rs_k, NULL, neras, fio->erasures, 0, NULL); if (res < 0) { r =3D res; goto error; } =20 corrected +=3D res; - fio->output[block_offset] =3D block[byte_index]; + fio->output[block_offset] =3D msg_buf[byte_index]; =20 block_offset++; if (block_offset >=3D 1 << v->data_dev_block_bits) goto done; } @@ -183,11 +186,11 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, int i, j, target_index =3D -1; struct dm_buffer *buf; struct dm_bufio_client *bufio; struct dm_verity_fec_io *fio =3D io->fec_io; u64 block, ileaved; - u8 *bbuf, *rs_block; + u8 *bbuf; u8 want_digest[HASH_MAX_DIGESTSIZE]; unsigned int n, k; struct bio *bio =3D dm_bio_from_per_bio_data(io, v->ti->per_io_data_size); =20 if (neras) @@ -260,18 +263,17 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, =20 /* * deinterleave and copy the bytes that fit into bufs, * starting from block_offset */ - fec_for_each_buffer_rs_block(fio, n, j) { + fec_for_each_buffer_rs_message(fio, n, j) { k =3D fec_buffer_rs_index(n, j) + block_offset; =20 if (k >=3D 1 << v->data_dev_block_bits) goto done; =20 - rs_block =3D fec_buffer_rs_block(v, fio, n, j); - rs_block[i] =3D bbuf[k]; + fec_buffer_rs_message(v, fio, n, j)[i] =3D bbuf[k]; } done: dm_bufio_release(buf); } =20 diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h index 5afa93f2f1fc7..257a609274c7c 100644 --- a/drivers/md/dm-verity-fec.h +++ b/drivers/md/dm-verity-fec.h @@ -15,11 +15,11 @@ #define DM_VERITY_FEC_RS_N 255 #define DM_VERITY_FEC_MIN_ROOTS 2 /* RS(255, 253): ~0.8% space overhead */ #define DM_VERITY_FEC_MAX_ROOTS 24 /* RS(255, 231): ~10% space overhead */ =20 /* buffers for deinterleaving and decoding */ -#define DM_VERITY_FEC_BUF_RS_BITS 4 /* 1 << RS blocks per buffer */ +#define DM_VERITY_FEC_BUF_RS_BITS 4 /* log2(RS messages per buffer) */ =20 #define DM_VERITY_OPT_FEC_DEV "use_fec_from_device" #define DM_VERITY_OPT_FEC_BLOCKS "fec_blocks" #define DM_VERITY_OPT_FEC_START "fec_start" #define DM_VERITY_OPT_FEC_ROOTS "fec_roots" @@ -50,14 +50,14 @@ struct dm_verity_fec_io { int erasures[DM_VERITY_FEC_MAX_ROOTS + 1]; /* erasures for decode_rs8 */ u8 *output; /* buffer for corrected output */ unsigned int level; /* recursion level */ unsigned int nbufs; /* number of buffers allocated */ /* - * Buffers for deinterleaving RS blocks. Each buffer has space for - * the data bytes of (1 << DM_VERITY_FEC_BUF_RS_BITS) RS blocks. The - * array length is fec_max_nbufs(v), and we try to allocate that many - * buffers. However, in low-memory situations we may be unable to + * Buffers for deinterleaving RS codewords. Each buffer has space for + * the message bytes of (1 << DM_VERITY_FEC_BUF_RS_BITS) RS codewords. + * The array length is fec_max_nbufs(v), and we try to allocate that + * many buffers. However, in low-memory situations we may be unable to * allocate all buffers. 'nbufs' holds the number actually allocated. */ u8 *bufs[]; }; =20 --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CB5B833DEF7; Fri, 6 Feb 2026 05:01:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354118; cv=none; b=ZNMlI/QmfMQb0hZI1GnnRXaF2WvbBQnltbp9r5qulSOI5VIIKpJe64Bp9e7gC982G0dwnEodw1zcQSdY2wlDg414UpiqCGtG/4dJ28F1Y6wR2dJMxbBaAieDG0VpYkJJQ2+GX+zj7Lqu88AvmA3d/aBHBs/nE2P+PPnDcUs+Q1k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354118; c=relaxed/simple; bh=d9stYeak2OGhlQrw6Kehk1/8I5GK23UT0p/tohYxgYQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cUPL8pFvg1i+DrhjExaNpBd1F5HVIZRqqnusfDdEp0mmaawqTuL8DPzmhQ2DQZ/R98ncYEtCr48y2DFZLwZjB/3cQNYMTjAbbfjK3ZmE+3rm8LKuEmUGsxQOooBWsvu1vw/MEazjDNbvilQya751k7YYhdclBTHbfG7d3/O71kQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QCnDMRV3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QCnDMRV3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3A300C116C6; Fri, 6 Feb 2026 05:01:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354118; bh=d9stYeak2OGhlQrw6Kehk1/8I5GK23UT0p/tohYxgYQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QCnDMRV30iwnHS6MCziivbFthqyxPgUPu3nNdszFD6N4+tTMZ1Qd362E1Qtofu9CV RQRYWVPsB2G8OMGe8iuqhB/CkdQ2U5vAXoKIhbpDBWWmtEZpstWEm9WJrEk7CJwNuS t9gDy+eqc8ZR4V2mCg/e7acojUjnGEidlyiuJdU8pxLSKoO30nIuPMidMM6RxmpF7r JiFJpszQt7X9tj+FAB/0HboNW9pI3FtSDiy2nKIXBaTgTWca3EJI6iR6WIoep16wr4 jp+1IhIctwpKPUKWl3d+TN+TVFLup9g9RBJuVQeUvEPx7YPBdOSUh4MVgrFXhu+fBA yQj4yaMXg4QJQ== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 11/22] dm-verity-fec: replace io_size with block_size Date: Thu, 5 Feb 2026 20:59:30 -0800 Message-ID: <20260206045942.52965-12-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" dm-verity's FEC implementation assumes that data_block_size =3D=3D hash_block_size, and it accesses the FEC device in units of the same size. Many places in the code want that size and compute it on-demand as '1 << v->data_dev_block_bits'. However, it's actually already available in v->fec->io_size. Rename that field to block_size, initialize it a bit earlier, and use it in the appropriate places. Note that while these sizes could in principle be different, that case is not supported. So there's no need to complicate the code for it. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 30 +++++++++++++----------------- drivers/md/dm-verity-fec.h | 2 +- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 619645edaf509..6ba9a1e039be3 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -82,15 +82,15 @@ static int fec_decode_bufs(struct dm_verity *v, struct = dm_verity_io *io, =20 /* * Compute the index of the first parity block that will be needed and * the starting position in that block. Then read that block. * - * io_size is always a power of 2, but roots might not be. Note that + * block_size is always a power of 2, but roots might not be. Note that * when it's not, a codeword's parity bytes can span a block boundary. */ parity_block =3D (rsb + block_offset) * v->fec->roots; - parity_pos =3D parity_block & (v->fec->io_size - 1); + parity_pos =3D parity_block & (v->fec->block_size - 1); parity_block >>=3D v->data_dev_block_bits; par =3D dm_bufio_read_with_ioprio(v->fec->bufio, parity_block, &buf, bio->bi_ioprio); if (IS_ERR(par)) { DMERR("%s: FEC %llu: parity read failed (block %llu): %ld", @@ -108,11 +108,11 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, =20 /* * Copy the next 'roots' parity bytes to 'par_buf', reading * another parity block if needed. */ - to_copy =3D min(v->fec->io_size - parity_pos, v->fec->roots); + to_copy =3D min(v->fec->block_size - parity_pos, v->fec->roots); for (j =3D 0; j < to_copy; j++) par_buf[j] =3D par[parity_pos++]; if (to_copy < v->fec->roots) { parity_block++; parity_pos =3D 0; @@ -141,11 +141,11 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, =20 corrected +=3D res; fio->output[block_offset] =3D msg_buf[byte_index]; =20 block_offset++; - if (block_offset >=3D 1 << v->data_dev_block_bits) + if (block_offset >=3D v->fec->block_size) goto done; } done: r =3D corrected; error: @@ -165,11 +165,11 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, * Locate data block erasures using verity hashes. */ static int fec_is_erasure(struct dm_verity *v, struct dm_verity_io *io, const u8 *want_digest, const u8 *data) { - if (unlikely(verity_hash(v, io, data, 1 << v->data_dev_block_bits, + if (unlikely(verity_hash(v, io, data, v->fec->block_size, io->tmp_digest))) return 0; =20 return memcmp(io->tmp_digest, want_digest, v->digest_size) !=3D 0; } @@ -266,11 +266,11 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, * starting from block_offset */ fec_for_each_buffer_rs_message(fio, n, j) { k =3D fec_buffer_rs_index(n, j) + block_offset; =20 - if (k >=3D 1 << v->data_dev_block_bits) + if (k >=3D v->fec->block_size) goto done; =20 fec_buffer_rs_message(v, fio, n, j)[i] =3D bbuf[k]; } done: @@ -339,11 +339,11 @@ static int fec_decode_rsb(struct dm_verity *v, struct= dm_verity_io *io, const u8 *want_digest, bool use_erasures) { int r, neras =3D 0; unsigned int pos; =20 - for (pos =3D 0; pos < 1 << v->data_dev_block_bits; ) { + for (pos =3D 0; pos < v->fec->block_size;) { fec_init_bufs(v, fio); =20 r =3D fec_read_bufs(v, io, rsb, offset, pos, use_erasures ? &neras : NULL); if (unlikely(r < 0)) @@ -355,12 +355,11 @@ static int fec_decode_rsb(struct dm_verity *v, struct= dm_verity_io *io, =20 pos +=3D fio->nbufs << DM_VERITY_FEC_BUF_RS_BITS; } =20 /* Always re-validate the corrected block against the expected hash */ - r =3D verity_hash(v, io, fio->output, 1 << v->data_dev_block_bits, - io->tmp_digest); + r =3D verity_hash(v, io, fio->output, v->fec->block_size, io->tmp_digest); if (unlikely(r < 0)) return r; =20 if (memcmp(io->tmp_digest, want_digest, v->digest_size)) { DMERR_LIMIT("%s: FEC %llu: failed to correct (%d erasures)", @@ -424,11 +423,11 @@ int verity_fec_decode(struct dm_verity *v, struct dm_= verity_io *io, r =3D fec_decode_rsb(v, io, fio, rsb, offset, want_digest, true); if (r < 0) goto done; } =20 - memcpy(dest, fio->output, 1 << v->data_dev_block_bits); + memcpy(dest, fio->output, v->fec->block_size); atomic64_inc(&v->fec->corrected); =20 done: fio->level--; return r; @@ -645,10 +644,11 @@ int verity_fec_ctr(struct dm_verity *v) */ if (v->data_dev_block_bits !=3D v->hash_dev_block_bits) { ti->error =3D "Block sizes must match to use FEC"; return -EINVAL; } + f->block_size =3D 1 << v->data_dev_block_bits; =20 if (!f->roots) { ti->error =3D "Missing " DM_VERITY_OPT_FEC_ROOTS; return -EINVAL; } @@ -682,14 +682,11 @@ int verity_fec_ctr(struct dm_verity *v) ti->error =3D "Hash device is too small for " DM_VERITY_OPT_FEC_BLOCKS; return -E2BIG; } =20 - f->io_size =3D 1 << v->data_dev_block_bits; - - f->bufio =3D dm_bufio_client_create(f->dev->bdev, - f->io_size, + f->bufio =3D dm_bufio_client_create(f->dev->bdev, f->block_size, 1, 0, NULL, NULL, 0); if (IS_ERR(f->bufio)) { ti->error =3D "Cannot initialize FEC bufio client"; return PTR_ERR(f->bufio); } @@ -699,12 +696,11 @@ int verity_fec_ctr(struct dm_verity *v) if (dm_bufio_get_device_size(f->bufio) < f->rounds * f->roots) { ti->error =3D "FEC device is too small"; return -E2BIG; } =20 - f->data_bufio =3D dm_bufio_client_create(v->data_dev->bdev, - 1 << v->data_dev_block_bits, + f->data_bufio =3D dm_bufio_client_create(v->data_dev->bdev, f->block_size, 1, 0, NULL, NULL, 0); if (IS_ERR(f->data_bufio)) { ti->error =3D "Cannot initialize FEC data bufio client"; return PTR_ERR(f->data_bufio); } @@ -747,11 +743,11 @@ int verity_fec_ctr(struct dm_verity *v) return ret; } =20 /* Preallocate an output buffer for each thread */ ret =3D mempool_init_kmalloc_pool(&f->output_pool, num_online_cpus(), - 1 << v->data_dev_block_bits); + f->block_size); if (ret) { ti->error =3D "Cannot allocate FEC output pool"; return ret; } =20 diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h index 257a609274c7c..49d43894ea746 100644 --- a/drivers/md/dm-verity-fec.h +++ b/drivers/md/dm-verity-fec.h @@ -27,11 +27,11 @@ /* configuration */ struct dm_verity_fec { struct dm_dev *dev; /* parity data device */ struct dm_bufio_client *data_bufio; /* for data dev access */ struct dm_bufio_client *bufio; /* for parity data access */ - size_t io_size; /* IO size for roots */ + size_t block_size; /* size of data, hash, and parity blocks in bytes */ sector_t start; /* parity data start in blocks */ sector_t blocks; /* number of blocks covered */ sector_t rounds; /* number of interleaving rounds */ sector_t hash_blocks; /* blocks covered after v->hash_start */ unsigned char roots; /* parity bytes per RS codeword, n-k of RS(n, k) */ --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 29AC333E362; Fri, 6 Feb 2026 05:01:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354119; cv=none; b=gBZPmC/uhvSqW9zKyRuMEmPpLDjJD4NLh1Zj7mzZenAgOsgRBf3nb5HneJ/PUsNVQkGiYgU092Ag2xypplXyVtiU/4acscWQiQ5GWvy50DzXaOqEZ5G/SSWUYwTKG2R5y7jCKvyvap5nTWyeeMwfA4849HBRV1yQvNGOgjVmp+o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354119; c=relaxed/simple; bh=JrIa7qVjgco23oEdNk11fbBPh6eb3JlTnlJk1zebbOs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CBOYv0DzurLJckyF2/BYWqDqb5NgQ/w17TXQ7TBBknOonWNLdK+SLJGKq08ey31gcpw5I4Zj17OGhuG6myRlj70ZWQiMnxJQy/OUgcddue2T/ZxX8dwk7OfHSD8ZSndbnJ07G/mczl3MG7iXYJMKTs7bNSnHXdiXZsZiHIJmojE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KOFHYNJW; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KOFHYNJW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9BBC5C19422; Fri, 6 Feb 2026 05:01:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354118; bh=JrIa7qVjgco23oEdNk11fbBPh6eb3JlTnlJk1zebbOs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KOFHYNJW3bEFPhHNOyMlL7yBpDBMjQaf70zEdryOu0pGuRV88GZ2pY+LYZeo1yab9 S7CGv3Kiy4SIyqlCcxsU0VqpXPRS59msEkXAS10vgBl7TBBNyqd+NqGduB1QLbZIl3 F8LefsEQ1lhOCkdobQ8Ca+E/SrPUN+SjLKiAv/RZi086M+gdkVELpGTBc/IDYcQKtx qqbFPH5I2XaaF4I7dyEhGRRkzTzy3B6h/S5F++9oxx8wj77VBTb7VbN6k6u0zd7hlp 4BTbqkm+NEWC2RMIokcNg6Eg9QeJQtHMJVOYKaBCzFxJTSmggoFu/mWWLZcbW0QnVz qIFJtLxsYhxIw== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 12/22] dm-verity-fec: rename rounds to region_blocks Date: Thu, 5 Feb 2026 20:59:31 -0800 Message-ID: <20260206045942.52965-13-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" It's hard to reconcile the value stored in dm_verity_fec::rounds with its name and documentation. Most likely "rounds" is being used as an alias for what is more commonly called the interleaving degree or "number of ways". But the interleaving is done at the byte level, whereas the units of "rounds" are blocks. So it's not really that. In practice, the reason the code needs this value is that it expresses the number of blocks in each "region" of the message data, where each region contains the bytes from a particular index in the RS codewords. Rename it to region_blocks to make the code a bit more understandable. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 16 ++++++++-------- drivers/md/dm-verity-fec.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 6ba9a1e039be3..28b47497c3d3f 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -29,11 +29,11 @@ static inline unsigned int fec_max_nbufs(struct dm_veri= ty *v) static inline u64 fec_interleave(struct dm_verity *v, u64 offset) { u32 mod; =20 mod =3D do_div(offset, v->fec->rs_k); - return offset + mod * (v->fec->rounds << v->data_dev_block_bits); + return offset + mod * (v->fec->region_blocks << v->data_dev_block_bits); } =20 /* Loop over each allocated buffer. */ #define fec_for_each_buffer(io, __i) \ for (__i =3D 0; __i < (io)->nbufs; __i++) @@ -403,17 +403,17 @@ int verity_fec_decode(struct dm_verity *v, struct dm_= verity_io *io, * and each code is interleaved over k blocks to make it less likely * that bursty corruption will leave us in unrecoverable state. */ =20 offset =3D block << v->data_dev_block_bits; - res =3D div64_u64(offset, v->fec->rounds << v->data_dev_block_bits); + res =3D div64_u64(offset, v->fec->region_blocks << v->data_dev_block_bits= ); =20 /* * The base RS block we can feed to the interleaver to find out all * blocks required for decoding. */ - rsb =3D offset - res * (v->fec->rounds << v->data_dev_block_bits); + rsb =3D offset - res * (v->fec->region_blocks << v->data_dev_block_bits); =20 /* * Locating erasures is slow, so attempt to recover the block without * them first. Do a second attempt with erasures if the corruption is * bad enough. @@ -657,19 +657,19 @@ int verity_fec_ctr(struct dm_verity *v) if (!f->blocks) { ti->error =3D "Missing " DM_VERITY_OPT_FEC_BLOCKS; return -EINVAL; } =20 - f->rounds =3D f->blocks; - if (sector_div(f->rounds, f->rs_k)) - f->rounds++; + f->region_blocks =3D f->blocks; + if (sector_div(f->region_blocks, f->rs_k)) + f->region_blocks++; =20 /* * Due to optional metadata, f->blocks can be larger than * data_blocks and hash_blocks combined. */ - if (f->blocks < v->data_blocks + hash_blocks || !f->rounds) { + if (f->blocks < v->data_blocks + hash_blocks || !f->region_blocks) { ti->error =3D "Invalid " DM_VERITY_OPT_FEC_BLOCKS; return -EINVAL; } =20 /* @@ -691,11 +691,11 @@ int verity_fec_ctr(struct dm_verity *v) return PTR_ERR(f->bufio); } =20 dm_bufio_set_sector_offset(f->bufio, f->start << (v->data_dev_block_bits = - SECTOR_SHIFT)); =20 - if (dm_bufio_get_device_size(f->bufio) < f->rounds * f->roots) { + if (dm_bufio_get_device_size(f->bufio) < f->region_blocks * f->roots) { ti->error =3D "FEC device is too small"; return -E2BIG; } =20 f->data_bufio =3D dm_bufio_client_create(v->data_dev->bdev, f->block_size, diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h index 49d43894ea746..50b5e187d5cc1 100644 --- a/drivers/md/dm-verity-fec.h +++ b/drivers/md/dm-verity-fec.h @@ -30,11 +30,11 @@ struct dm_verity_fec { struct dm_bufio_client *data_bufio; /* for data dev access */ struct dm_bufio_client *bufio; /* for parity data access */ size_t block_size; /* size of data, hash, and parity blocks in bytes */ sector_t start; /* parity data start in blocks */ sector_t blocks; /* number of blocks covered */ - sector_t rounds; /* number of interleaving rounds */ + sector_t region_blocks; /* blocks per region: ceil(blocks / rs_k) */ sector_t hash_blocks; /* blocks covered after v->hash_start */ unsigned char roots; /* parity bytes per RS codeword, n-k of RS(n, k) */ unsigned char rs_k; /* message bytes per RS codeword, k of RS(n, k) */ mempool_t fio_pool; /* mempool for dm_verity_fec_io */ mempool_t rs_pool; /* mempool for fio->rs */ --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 621DD33EAEC; Fri, 6 Feb 2026 05:01:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354119; cv=none; b=MO23/PqAwQJvD6FLBwINVJ3JHsLlwnDsUe4Jp9nt0cw8XpGYa8iOWkWN2JgEUQewVFrFZQLhoxJrbnmaQ4T0HfjkX5v3wC6n2/QDK5pK4C/Yx1TbzZZbTdXKJUtU2nTUjyMM6SZ7lWYHbrRxnG7wQQYvJd++o9dTPXPzTHvg4LY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354119; c=relaxed/simple; bh=T8lDA28MsVDIauTKzWNfgbQTTKQ8fipu5tFuLLG1PfA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BuWp2BiyDlK6sH2IeQy/kYI96nsDPvYOEwl1g9kIktE5UcLCPuxrDy7iQ29Yj40UPaBvGXjBG0/T4xAGhtNiKLsYJeyUA4dX1VGRG7lv8aG7fU0AD1ebUW24yZvj1qS4UkrLcA0maSU5opKhe/fixCB7fPiPbK0hxzZ6u+OQNNY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HCf0+Tek; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HCf0+Tek" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 083FDC16AAE; Fri, 6 Feb 2026 05:01:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354119; bh=T8lDA28MsVDIauTKzWNfgbQTTKQ8fipu5tFuLLG1PfA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HCf0+TekljTvqknjH4W8S32Whq3PB1cgeaKjwDoF1HRvREV76MU06e48YV36jehxr 1FDBlNoqpnt4GBlsuBx5leXjZPOjZOIcL7ELPloC7oAsRlhV0m5ue4ZnLDEgjJu/oe QnHbXbQoZFJSYv/How+eLTYjWhwTJ97l8qlsKFdhIqcvXmKPO6h1wWhaRNFQugmDhx qHHm4f/B8GG3DibM9wMwmoCBE6LNemmbP7sRUz+L9e+CGg6MedmxrAMejc6prfo2nU PaXE6j1SiZdUQY8x346MA6DczNn/foyohZ5fNveFoaIjEMs+EuSxcDy19BQjE99L07 xZNzH/ERgG9SA== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 13/22] dm-verity-fec: simplify computation of rsb Date: Thu, 5 Feb 2026 20:59:32 -0800 Message-ID: <20260206045942.52965-14-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To compute 'rsb', verity_fec_decode() divides 'offset' by 'v->fec->region_blocks << v->data_dev_block_bits', then subtracts the quotient times that divisor. That's simply the long way to do a modulo operation, i.e. a - b * floor(a / b) instead of just a % b. Use div64_u64_rem() to get the remainder more concisely. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 28b47497c3d3f..63eeef26a3999 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -375,11 +375,11 @@ int verity_fec_decode(struct dm_verity *v, struct dm_= verity_io *io, enum verity_block_type type, const u8 *want_digest, sector_t block, u8 *dest) { int r; struct dm_verity_fec_io *fio; - u64 offset, res, rsb; + u64 offset, rsb; =20 if (!verity_fec_is_enabled(v)) return -EOPNOTSUPP; =20 fio =3D io->fec_io; @@ -403,17 +403,17 @@ int verity_fec_decode(struct dm_verity *v, struct dm_= verity_io *io, * and each code is interleaved over k blocks to make it less likely * that bursty corruption will leave us in unrecoverable state. */ =20 offset =3D block << v->data_dev_block_bits; - res =3D div64_u64(offset, v->fec->region_blocks << v->data_dev_block_bits= ); =20 /* * The base RS block we can feed to the interleaver to find out all * blocks required for decoding. */ - rsb =3D offset - res * (v->fec->region_blocks << v->data_dev_block_bits); + div64_u64_rem(offset, v->fec->region_blocks << v->data_dev_block_bits, + &rsb); =20 /* * Locating erasures is slow, so attempt to recover the block without * them first. Do a second attempt with erasures if the corruption is * bad enough. --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CF39433F8B7; Fri, 6 Feb 2026 05:01:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354119; cv=none; b=iVVAl5DG842pQK7ivtC5YxUc7V989jD9CKqkLHVM3/l0c4FcIuCrk2oDN8HbITuuAY20Grr08BAqa3p9EEd79mg6zSWOedFTLwdK/HTZ2JcPYJ05Ky+WwzOtQ4+a1DLzp+8lwsD0nzExyswTSOrQD7wLjTdBisrepxZCkXzvF3I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354119; c=relaxed/simple; bh=q12ukdq0V7Gw2F67fSDK+zMw1si1jmRuVzdXOJkXwZ0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BGsdWUcECcXmm6V06PQ4pol+9p0LAljP5Mo81GYsDURR0Zz1oRYVaVynz3GtHG7ujTnXxYeo3vqvU+VnVG2k3VmuGIAF/B9Zcq9gqM/zd2lhTiT3vJOz5wIVcDsleDFgGPdZFcGj87hUFJSR+vV6e1FtkHzitE4xnpj+kSFVoo0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=k6TgFLqk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="k6TgFLqk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 68EA7C19425; Fri, 6 Feb 2026 05:01:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354119; bh=q12ukdq0V7Gw2F67fSDK+zMw1si1jmRuVzdXOJkXwZ0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=k6TgFLqkFiPkoJA2yzN9EMlKE7Db5v+wM4sXrvjaAOr30h5g71I366HONEQHf0BOs GY+l7ebGIfQrvz9rwZOTtBn42t4pz9uaRmiuZgMDrIUVq8qzNQr4w4p3B+4bVhndGq kMNjcZ0igkFU5FtwCiTYjoulGQEh4vhTXHGuOKL3GTR36evQ2NTWpONlVWxVCwJDzm P5O5hUUHbhOs05piW0J3LDQXgHm05P2YgDaEpXdMJUS+WsVr0cKnjYjgdKiVGQ9QNx 0emY+LjPZcBwYEJG4K9ChoInM9mril1WjrbF2D1E9B/BNoZLC8766X/X6RMeZVYcR+ KTaKbsiyGEB2g== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 14/22] dm-verity-fec: simplify computation of ileaved Date: Thu, 5 Feb 2026 20:59:33 -0800 Message-ID: <20260206045942.52965-15-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" fec_read_bufs() just iterates over a sequence of message blocks with step size region_blocks. At each step, 'ileaved' is just the offset (in bytes) to one of these blocks. Compute it in the straightforward way, eliminating fec_interleave(). In more detail, previously the code computed 'ileaved =3D (n / k) + (n % k) * (region_blocks * block_size)' where n =3D rsb * k + i and 0 <=3D i < k. Substituting 'n' gives: ileaved =3D ((rsb * k + i) / k) + ((rsb * k + i) % k) * region_blocks *= block_size =3D rsb + (i * region_blocks * block_size) The result is more efficient and easier to understand. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 63eeef26a3999..3122017569718 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -21,21 +21,10 @@ static inline unsigned int fec_max_nbufs(struct dm_verity *v) { return 1 << (v->data_dev_block_bits - DM_VERITY_FEC_BUF_RS_BITS); } =20 -/* - * Return an interleaved offset for a byte in RS block. - */ -static inline u64 fec_interleave(struct dm_verity *v, u64 offset) -{ - u32 mod; - - mod =3D do_div(offset, v->fec->rs_k); - return offset + mod * (v->fec->region_blocks << v->data_dev_block_bits); -} - /* Loop over each allocated buffer. */ #define fec_for_each_buffer(io, __i) \ for (__i =3D 0; __i < (io)->nbufs; __i++) =20 /* Loop over each RS message in each allocated buffer. */ @@ -202,11 +191,11 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, /* * read each of the rs_k data blocks that are part of the RS block, and * interleave contents to available bufs */ for (i =3D 0; i < v->fec->rs_k; i++) { - ileaved =3D fec_interleave(v, rsb * v->fec->rs_k + i); + ileaved =3D rsb + i * (v->fec->region_blocks << v->data_dev_block_bits); =20 /* * target is the data block we want to correct, target_index is * the index of this block within the rs_k RS blocks */ --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6CD6B340A47; Fri, 6 Feb 2026 05:02:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354120; cv=none; b=oFy4fjTBNl+Hsck8NgGzxpFV6Qwb87PvYqTzbfe5teKS5NgY+LbdMfoZHJ1rxB5xuDdtDhH6hkPQ12vKIyKqJOe2uFghrSAkZPfaoEnV6mn968ZxLh107s3STWawzgg1X4ns1qCY0xA6LjywW4g7DGu8de8MG6vSKl/AFEuFG0Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354120; c=relaxed/simple; bh=Us/3A/uVIpXU4eoqytLGpmeBBcgd8JSB5lx6TRXvCoA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jkjnOQN7QiIxqZYtokIY9tqR39V3Syb/ghXdm5ExV/ViBE9eKoHrc+/No82PI+Nu52NvB2rml6bG4RZGhNZLvzm37sLOY2RRmufrRS6evgghdUjUF7u14WNVmzkiH2bGdJxOx6Nu5n5mUy8SPxr1UDpfXp3Q1/I9cgm0ZDHwgMY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EwYV3WzB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EwYV3WzB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C8F04C16AAE; Fri, 6 Feb 2026 05:01:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354120; bh=Us/3A/uVIpXU4eoqytLGpmeBBcgd8JSB5lx6TRXvCoA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EwYV3WzBq7DiPyapUyaMqDUtFMuRHMle2OXx8nzy/+q5mp4N7VshIzSGE0xGECNCx AgkTKunwRcDbMc+ngN4ixita4dH2YNUCfGQJvUAzXhBXbYso+200RdEXeTaxvgc06p TC7Iq2oOt3I6o8r2GObwncQz4rzzBPBoRpIo8VMJpnKCrh5AT8TlM7lYkYVTlbArgA agqIzlSdw/jc37st2q2N31LKVW+vtydK3FUZJj72k6xM1XbnFXAccxtJ4dds8O3PVO IZ3o6VEa+H9K6Cdv3bvTRTGYbkD3PtXH0LiBYnRTG20E4Lj8XgjaWi3oPPG/UrFFM9 lhw4NLuKabVWA== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 15/22] dm-verity-fec: simplify deinterleaving Date: Thu, 5 Feb 2026 20:59:34 -0800 Message-ID: <20260206045942.52965-16-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since fec_read_bufs() deinterleaves the bytes from 'bbuf' sequentially starting from 'block_offset', it can just do simple increments instead of the more complex fec_buffer_rs_index() computation. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 3122017569718..a49c43ca07763 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -42,19 +42,10 @@ static inline u8 *fec_buffer_rs_message(struct dm_verit= y *v, unsigned int i, unsigned int j) { return &fio->bufs[i][j * v->fec->rs_k]; } =20 -/* - * Return the index of the current RS message when called inside - * fec_for_each_buffer_rs_message. - */ -static inline unsigned int fec_buffer_rs_index(unsigned int i, unsigned in= t j) -{ - return (i << DM_VERITY_FEC_BUF_RS_BITS) + j; -} - /* * Decode all RS codewords whose message bytes were loaded into fio->bufs.= Copy * the corrected bytes into fio->output starting from block_offset. */ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io, @@ -177,11 +168,11 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, struct dm_bufio_client *bufio; struct dm_verity_fec_io *fio =3D io->fec_io; u64 block, ileaved; u8 *bbuf; u8 want_digest[HASH_MAX_DIGESTSIZE]; - unsigned int n, k; + unsigned int n, src_pos; struct bio *bio =3D dm_bio_from_per_bio_data(io, v->ti->per_io_data_size); =20 if (neras) *neras =3D 0; =20 @@ -252,17 +243,15 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, =20 /* * deinterleave and copy the bytes that fit into bufs, * starting from block_offset */ + src_pos =3D block_offset; fec_for_each_buffer_rs_message(fio, n, j) { - k =3D fec_buffer_rs_index(n, j) + block_offset; - - if (k >=3D v->fec->block_size) + if (src_pos >=3D v->fec->block_size) goto done; - - fec_buffer_rs_message(v, fio, n, j)[i] =3D bbuf[k]; + fec_buffer_rs_message(v, fio, n, j)[i] =3D bbuf[src_pos++]; } done: dm_bufio_release(buf); } =20 --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AAE11340DA3; Fri, 6 Feb 2026 05:02:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354120; cv=none; b=i8t3C6HZwweDeik2ks4tMHvxWHiEI1i0e94r04XjswYYU1krpZYTSudHEK7ZWWznSKZ3sCBJXuxfp7jLGR5/stJHhmHoO//Hz4MTNWoI6wA5nsxzfJ0JHcGi/nBKMZxieg4/Jqe5D/770d5hPUVO5zUowtO0Qe5PEqH5uW4AjCI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354120; c=relaxed/simple; bh=7YFdj7HGxucUA+eICYH6sRcb993Ixkn68/c5y+lugeU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iq1Bqv0/iPbPuaattwOS6h9wf4MoUpHLWcLtnVU/cRjgSXf/D5eTcJNjGKHW9hOnrRlCbesbnFcp8LLA0puKSSXCpfYC6y9jhJgWyXJe6E63wJ9dee3oJEo8txHDKynMvY6I7ijwqMbljkzR/yWVgxUdeq94MbrZRYNJVrt21x4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BLrWF0l7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BLrWF0l7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 511D9C19424; Fri, 6 Feb 2026 05:02:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354120; bh=7YFdj7HGxucUA+eICYH6sRcb993Ixkn68/c5y+lugeU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BLrWF0l7rLW5FQ4SQ9witABWfIwFLDN1v/tLphMawII2hy3AZ7O/iDDCcAV9SkGdn bA7pcZ/BIRwRWAPf50Nnx9mkYEyt35FRrfsJA9MmTU8f1yXzT+N81HabOmMSHh4XY6 /z/fKviVp32vUWYtP96EZFzWuXJPxyIk0mp7XWI4l4L7uAhJ3U1ubD9y2nI3JOpQ1E coVAjFLFzTMyWUml/wRcl+ghcJfZNMCYr5oh75u6HjIOvGocGM5EOYZUxxgBIifou3 RYUfBam31BstTSYuZ1dfgrj0FaIXOJxAMJmwLstqRsDt3SxczzI2Wot3ez2HDlxEus 6Ppyo8LeAdpiA== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 16/22] dm-verity-fec: rename block_offset to out_pos Date: Thu, 5 Feb 2026 20:59:35 -0800 Message-ID: <20260206045942.52965-17-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The current position in the output block buffer is called 'pos' in fec_decode_rsb(), and 'block_offset' in fec_read_bufs() and fec_decode_bufs(). These names aren't very clear, especially 'block_offset' which is easily confused with the offset of a message or parity block or the position in the current parity block. Rename it to 'out_pos'. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index a49c43ca07763..51263f2be1350 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -44,15 +44,15 @@ static inline u8 *fec_buffer_rs_message(struct dm_verit= y *v, return &fio->bufs[i][j * v->fec->rs_k]; } =20 /* * Decode all RS codewords whose message bytes were loaded into fio->bufs.= Copy - * the corrected bytes into fio->output starting from block_offset. + * the corrected bytes into fio->output starting from out_pos. */ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io, struct dm_verity_fec_io *fio, u64 rsb, int byte_index, - unsigned int block_offset, int neras) + unsigned int out_pos, int neras) { int r, corrected =3D 0, res; struct dm_buffer *buf; unsigned int n, i, j, parity_pos, to_copy; uint16_t par_buf[DM_VERITY_FEC_MAX_ROOTS]; @@ -65,11 +65,11 @@ static int fec_decode_bufs(struct dm_verity *v, struct = dm_verity_io *io, * the starting position in that block. Then read that block. * * block_size is always a power of 2, but roots might not be. Note that * when it's not, a codeword's parity bytes can span a block boundary. */ - parity_block =3D (rsb + block_offset) * v->fec->roots; + parity_block =3D (rsb + out_pos) * v->fec->roots; parity_pos =3D parity_block & (v->fec->block_size - 1); parity_block >>=3D v->data_dev_block_bits; par =3D dm_bufio_read_with_ioprio(v->fec->bufio, parity_block, &buf, bio->bi_ioprio); if (IS_ERR(par)) { @@ -118,14 +118,13 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, r =3D res; goto error; } =20 corrected +=3D res; - fio->output[block_offset] =3D msg_buf[byte_index]; + fio->output[out_pos++] =3D msg_buf[byte_index]; =20 - block_offset++; - if (block_offset >=3D v->fec->block_size) + if (out_pos >=3D v->fec->block_size) goto done; } done: r =3D corrected; error: @@ -157,12 +156,11 @@ static int fec_is_erasure(struct dm_verity *v, struct= dm_verity_io *io, /* * Read data blocks that are part of the RS block and deinterleave as much= as * fits into buffers. Check for erasure locations if @neras is non-NULL. */ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io, - u64 rsb, u64 target, unsigned int block_offset, - int *neras) + u64 rsb, u64 target, unsigned int out_pos, int *neras) { bool is_zero; int i, j, target_index =3D -1; struct dm_buffer *buf; struct dm_bufio_client *bufio; @@ -241,13 +239,13 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, fio->erasures[(*neras)++] =3D i; } =20 /* * deinterleave and copy the bytes that fit into bufs, - * starting from block_offset + * starting from out_pos */ - src_pos =3D block_offset; + src_pos =3D out_pos; fec_for_each_buffer_rs_message(fio, n, j) { if (src_pos >=3D v->fec->block_size) goto done; fec_buffer_rs_message(v, fio, n, j)[i] =3D bbuf[src_pos++]; } @@ -315,25 +313,25 @@ static void fec_init_bufs(struct dm_verity *v, struct= dm_verity_fec_io *fio) static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io, struct dm_verity_fec_io *fio, u64 rsb, u64 offset, const u8 *want_digest, bool use_erasures) { int r, neras =3D 0; - unsigned int pos; + unsigned int out_pos; =20 - for (pos =3D 0; pos < v->fec->block_size;) { + for (out_pos =3D 0; out_pos < v->fec->block_size;) { fec_init_bufs(v, fio); =20 - r =3D fec_read_bufs(v, io, rsb, offset, pos, + r =3D fec_read_bufs(v, io, rsb, offset, out_pos, use_erasures ? &neras : NULL); if (unlikely(r < 0)) return r; =20 - r =3D fec_decode_bufs(v, io, fio, rsb, r, pos, neras); + r =3D fec_decode_bufs(v, io, fio, rsb, r, out_pos, neras); if (r < 0) return r; =20 - pos +=3D fio->nbufs << DM_VERITY_FEC_BUF_RS_BITS; + out_pos +=3D fio->nbufs << DM_VERITY_FEC_BUF_RS_BITS; } =20 /* Always re-validate the corrected block against the expected hash */ r =3D verity_hash(v, io, fio->output, v->fec->block_size, io->tmp_digest); if (unlikely(r < 0)) --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 17C3034166B; Fri, 6 Feb 2026 05:02:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354121; cv=none; b=AF7XO/5uSfwkhrUhgQabTljCbZxi46qIPzfmRN5L5QgSwoUJLqW+1a+i0i4pPlHDinJP/F7ce/tRfQ0ZZpg5jkokncLFdL1fJbuKnOpo860o0P2BrstT2Resnf/Xc/m3JVgqLcgtx1Kly7kah8QHoJNPUyTw1rISt1TLDNIo13k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354121; c=relaxed/simple; bh=kQGaA79ZZ0qnBy8uSBPsiJSgf6TH8GUt3oPgCulvrtk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nae1gbzMV+CwAwtZ/z55z2v4vMZlRb1GNXbxGlU3XSDg8YdpFK5C1Cn30W+j5ssEmvh1SgEG/dH221jz7PdlqO/Yx97gkg9WrfB2FeE4xA+VlMRqAyTdrqMKXRQKc4hD9fv92t5t1sss90G/uxgMtWylDxU7g5cZWTbGNYIfPhY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EpFIws9v; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EpFIws9v" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B17ACC2BC86; Fri, 6 Feb 2026 05:02:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354121; bh=kQGaA79ZZ0qnBy8uSBPsiJSgf6TH8GUt3oPgCulvrtk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EpFIws9v8bFGgta8dpR03g5iyKk1ox0oj/EI+pCXpSdhbzxoDsRcBpvu3+mDeAe5m 1ob0a+ISfB7nlQkijBnXPAZLLKSbvl6Y4y02YfudxH68Ue8Ka0W0ErwZr0PVdwX9Yj 9UoQQfwNOlt9sWcTAIJcNsQNzeJHk2drpPH6rEwUMuVMMOvNdWcHb+oh8NLHXe4fxh mwRPGakvHX/CMQZhNwmmx6tk/tae+/mzw4pxuXkcgq4vJmzPyhhVfikE07JfwkkDxs smJdQZ/sQ1emlJPH4k0RX8YDp09FME0H0pXcYj9fB2ka7o0FpFv65MvO3LEJgzev9z Q9jC3ljiv9Vpg== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 17/22] dm-verity-fec: move computation of offset and rsb down a level Date: Thu, 5 Feb 2026 20:59:36 -0800 Message-ID: <20260206045942.52965-18-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" verity_fec_decode() computes (offset, rsb) from the target block index and calls fec_decode_rsb() with these parameters. Move this computation into fec_decode_rsb(), and rename fec_decode_rsb() to fec_decode(). This ends up being simpler and enables further refactoring, specifically making use of the quotient from the division more easily. The function renaming also eliminates a reference to the ambiguous term "rsb". This change does mean the same div64_u64_rem() can now be executed twice per block, since verity_fec_decode() calls fec_decode() up to twice per block. However, this cost is negligible compared to the rest of FEC. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 46 +++++++++++++++----------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 51263f2be1350..91670f7d0ea16 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -304,20 +304,30 @@ static void fec_init_bufs(struct dm_verity *v, struct= dm_verity_fec_io *fio) =20 memset(fio->erasures, 0, sizeof(fio->erasures)); } =20 /* - * Decode all RS blocks in a single data block and return the target block - * (indicated by @offset) in fio->output. If @use_erasures is non-zero, us= es - * hashes to locate erasures. + * Try to correct the message (data or hash) block at index @target_block. + * + * If @use_erasures is true, use verity hashes to locate erasures. This m= akes + * the error correction slower but up to twice as capable. + * + * On success, return 0 and write the corrected block to @fio->output. 0 = is + * returned only if the digest of the corrected block matches @want_digest= ; this + * is critical to ensure that FEC can't cause dm-verity to return bad data. */ -static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io, - struct dm_verity_fec_io *fio, u64 rsb, u64 offset, - const u8 *want_digest, bool use_erasures) +static int fec_decode(struct dm_verity *v, struct dm_verity_io *io, + struct dm_verity_fec_io *fio, u64 target_block, + const u8 *want_digest, bool use_erasures) { int r, neras =3D 0; unsigned int out_pos; + u64 offset =3D target_block << v->data_dev_block_bits; + u64 rsb; + + div64_u64_rem(offset, v->fec->region_blocks << v->data_dev_block_bits, + &rsb); =20 for (out_pos =3D 0; out_pos < v->fec->block_size;) { fec_init_bufs(v, fio); =20 r =3D fec_read_bufs(v, io, rsb, offset, out_pos, @@ -351,11 +361,10 @@ int verity_fec_decode(struct dm_verity *v, struct dm_= verity_io *io, enum verity_block_type type, const u8 *want_digest, sector_t block, u8 *dest) { int r; struct dm_verity_fec_io *fio; - u64 offset, rsb; =20 if (!verity_fec_is_enabled(v)) return -EOPNOTSUPP; =20 fio =3D io->fec_io; @@ -368,37 +377,18 @@ int verity_fec_decode(struct dm_verity *v, struct dm_= verity_io *io, fio->level++; =20 if (type =3D=3D DM_VERITY_BLOCK_TYPE_METADATA) block =3D block - v->hash_start + v->data_blocks; =20 - /* - * For RS(n, k), the continuous FEC data is divided into blocks of k - * bytes. Since block size may not be divisible by k, the last block - * is zero padded when decoding. - * - * Each byte of the block is covered by a different RS(n, k) code, - * and each code is interleaved over k blocks to make it less likely - * that bursty corruption will leave us in unrecoverable state. - */ - - offset =3D block << v->data_dev_block_bits; - - /* - * The base RS block we can feed to the interleaver to find out all - * blocks required for decoding. - */ - div64_u64_rem(offset, v->fec->region_blocks << v->data_dev_block_bits, - &rsb); - /* * Locating erasures is slow, so attempt to recover the block without * them first. Do a second attempt with erasures if the corruption is * bad enough. */ - r =3D fec_decode_rsb(v, io, fio, rsb, offset, want_digest, false); + r =3D fec_decode(v, io, fio, block, want_digest, false); if (r < 0) { - r =3D fec_decode_rsb(v, io, fio, rsb, offset, want_digest, true); + r =3D fec_decode(v, io, fio, block, want_digest, true); if (r < 0) goto done; } =20 memcpy(dest, fio->output, v->fec->block_size); --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 77CB8342505; Fri, 6 Feb 2026 05:02:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354121; cv=none; b=moaBn93iYJ/XA4YzKCsnD9LbiORhhImJxudxATlfMGZRDzMJqWSBp/+SwObGLooBLaOAnhfaTyRQjPKHOZnIdB5xQzGmc93+hYYq0BHwJSKerN0Q2HXkuhBJVC9J0umFOwu/0t6eqIFaJy5wOckFrRFMH8Ep+3fIchgIyc8TAUc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354121; c=relaxed/simple; bh=9lLlz3z9s/vvSc0JN+a5VnYUBnydoxuxrX8yNCkyfyU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TN9bIbg2NaxcrQz8/SVsh0bonRhSfhB52SEE9lOhiU0bloXQm+6XSti7r/f7ApYDXfxjE39N3p/pAK0Ph379mojTFlyNiPUJm7dQ4+2MW2LVLEQM7UkTPCcyHeeq+2v/LMalV6TIsRNpGeM9fFDY7LgS/K4fVyr1X+3LcONLj60= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iT95Zvqb; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iT95Zvqb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1D99AC116C6; Fri, 6 Feb 2026 05:02:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354121; bh=9lLlz3z9s/vvSc0JN+a5VnYUBnydoxuxrX8yNCkyfyU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iT95ZvqbipvmO67SazFYneVoeInYWlH4gtZo/TN+AqyQs8uSmcugRwtL7ApmKNmTT P1nVAcWyHUt7OXm2o9Gl0Wm/O/H4HqAJG6PnrsvRc6YQQuxvQ4wTiVR/g6mgeAOvRX PJg0lUcfmp8wmhPIrrMMVT/lfTRU5GX260D3HNypgaOWyEUarwoeMwObCjKB6ya/8K 20TS13YKj0HvHmok9DsDvUsFo+SrQDSRGr0AYU0jWqK8s1bxWtq8pja/XuWxiwn4eF pqeFpqXG/Fqdeu/oNGpHtxZui/CZ2gD7DFKsPe0SuaSdHNT8agcCFmHNOa4ILi+53R oUlm3P8D2gVbQ== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 18/22] dm-verity-fec: compute target region directly Date: Thu, 5 Feb 2026 20:59:37 -0800 Message-ID: <20260206045942.52965-19-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Instead of determining the target block's region by checking which block of the k blocks being iterated over in fec_read_bufs() is equal to the target block, instead just directly use the quotient of the division of target_block by region_blocks. This is the same value, just derived in a more straightforward way. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 91670f7d0ea16..1b5052ba4f5a5 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -47,12 +47,12 @@ static inline u8 *fec_buffer_rs_message(struct dm_verit= y *v, /* * Decode all RS codewords whose message bytes were loaded into fio->bufs.= Copy * the corrected bytes into fio->output starting from out_pos. */ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io, - struct dm_verity_fec_io *fio, u64 rsb, int byte_index, - unsigned int out_pos, int neras) + struct dm_verity_fec_io *fio, u64 rsb, + int target_region, unsigned int out_pos, int neras) { int r, corrected =3D 0, res; struct dm_buffer *buf; unsigned int n, i, j, parity_pos, to_copy; uint16_t par_buf[DM_VERITY_FEC_MAX_ROOTS]; @@ -118,11 +118,11 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, r =3D res; goto error; } =20 corrected +=3D res; - fio->output[out_pos++] =3D msg_buf[byte_index]; + fio->output[out_pos++] =3D msg_buf[target_region]; =20 if (out_pos >=3D v->fec->block_size) goto done; } done: @@ -156,14 +156,14 @@ static int fec_is_erasure(struct dm_verity *v, struct= dm_verity_io *io, /* * Read data blocks that are part of the RS block and deinterleave as much= as * fits into buffers. Check for erasure locations if @neras is non-NULL. */ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io, - u64 rsb, u64 target, unsigned int out_pos, int *neras) + u64 rsb, unsigned int out_pos, int *neras) { bool is_zero; - int i, j, target_index =3D -1; + int i, j; struct dm_buffer *buf; struct dm_bufio_client *bufio; struct dm_verity_fec_io *fio =3D io->fec_io; u64 block, ileaved; u8 *bbuf; @@ -181,18 +181,10 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, * read each of the rs_k data blocks that are part of the RS block, and * interleave contents to available bufs */ for (i =3D 0; i < v->fec->rs_k; i++) { ileaved =3D rsb + i * (v->fec->region_blocks << v->data_dev_block_bits); - - /* - * target is the data block we want to correct, target_index is - * the index of this block within the rs_k RS blocks - */ - if (ileaved =3D=3D target) - target_index =3D i; - block =3D ileaved >> v->data_dev_block_bits; bufio =3D v->fec->data_bufio; =20 if (block >=3D v->data_blocks) { block -=3D v->data_blocks; @@ -250,12 +242,11 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, fec_buffer_rs_message(v, fio, n, j)[i] =3D bbuf[src_pos++]; } done: dm_bufio_release(buf); } - - return target_index; + return 0; } =20 /* * Allocate and initialize a struct dm_verity_fec_io to use for FEC for a = bio. * This runs the first time a block needs to be corrected for a bio. In t= he @@ -318,26 +309,30 @@ static void fec_init_bufs(struct dm_verity *v, struct= dm_verity_fec_io *fio) static int fec_decode(struct dm_verity *v, struct dm_verity_io *io, struct dm_verity_fec_io *fio, u64 target_block, const u8 *want_digest, bool use_erasures) { int r, neras =3D 0; - unsigned int out_pos; - u64 offset =3D target_block << v->data_dev_block_bits; + unsigned int target_region, out_pos; u64 rsb; =20 - div64_u64_rem(offset, v->fec->region_blocks << v->data_dev_block_bits, - &rsb); + target_region =3D div64_u64_rem( + target_block << v->data_dev_block_bits, + v->fec->region_blocks << v->data_dev_block_bits, &rsb); + if (WARN_ON_ONCE(target_region >=3D v->fec->rs_k)) + /* target_block is out-of-bounds. Should never happen. */ + return -EIO; =20 for (out_pos =3D 0; out_pos < v->fec->block_size;) { fec_init_bufs(v, fio); =20 - r =3D fec_read_bufs(v, io, rsb, offset, out_pos, + r =3D fec_read_bufs(v, io, rsb, out_pos, use_erasures ? &neras : NULL); if (unlikely(r < 0)) return r; =20 - r =3D fec_decode_bufs(v, io, fio, rsb, r, out_pos, neras); + r =3D fec_decode_bufs(v, io, fio, rsb, target_region, + out_pos, neras); if (r < 0) return r; =20 out_pos +=3D fio->nbufs << DM_VERITY_FEC_BUF_RS_BITS; } --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D9E3C34252C; Fri, 6 Feb 2026 05:02:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354121; cv=none; b=QFpzwJV5bzs/CQ94ea56LEfPAQGa4isy58rcKYOO/0X8yzAhLY8LQ8ljYhxe068tTRIMvZygpwsEoTaJE8I+/aeEK9rv4/Bzh+/aQpUNonnDANhUIkuRLSl9AHennB5kOjl52ZWTMv1d4tolUL4f/uiZftg5/1shPn9d2SiY+vA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354121; c=relaxed/simple; bh=JaFArVCeKak5JqJx5bGIqX4e+QcFezwCPEZlB/x+PKY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K+pWYcJwg7RkBOyqATzIJ85DG4RWja78+BloBlOeOifbDiNbnrce+nP6PNL2QqyN7ZT2PPJF1og+WUN92UKXAdlCcUwNr+UzEmvg9pPGXQdapy58ZTqOw8zjgqUrZO28QMmib9LBSWz//dgS2mJhuok93qPEcEavurYud7s/uCw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oL/5vUxK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oL/5vUxK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F58FC4AF0B; Fri, 6 Feb 2026 05:02:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354121; bh=JaFArVCeKak5JqJx5bGIqX4e+QcFezwCPEZlB/x+PKY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oL/5vUxKyzfSqqFKddcNTDZT3ArfVJcsOg+xzQ5gF+WJctSlAFTb/rmajQXDKC+OT 1RLHYtpyN3xyhzESRChturCmySQDsDCmkgRqm2s4POz168DrP74PH+RxyJKLcTqYB9 vq304NUTQIeCC5MH6068dLvlyJabtKaWg7ktD2CnKl8B8kA2+/smvP4vwKd4vjcMyA IZFIVBwMRuzrQYJD8dr4dgx18iBiO7Q2DrASY/Q6Dl75GNPdoziXGQ9OQ98JazwxVx 9qUL3HWNaJPI7+cwBtrufaWCUc7LCEHdSYH/4y3ccxsnnewnNLXUH/TlpJasfwH/Ys +QVY2OMZ0Gg3w== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 19/22] dm-verity-fec: pass down index_in_region instead of rsb Date: Thu, 5 Feb 2026 20:59:38 -0800 Message-ID: <20260206045942.52965-20-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Replace 'rsb', which is a byte index, with 'index_in_region' which is a block index. The block index is slightly easier to compute, it matches what fec_read_bufs() wants, and it avoids the mismatch between the name and the units of the variable. ('rsb' stood for "Reed-Solomon block", but its units were bytes, not blocks.) fec_decode_bufs() does want it as a byte index when computing parity_block, but that's easily handled locally. As long as the parameters to the log messages are being adjusted, also eliminate the unnecessary casts to 'unsigned long long'. %llu is the correct way to print a u64 in the Linux kernel, as documented in printk-formats.rst. There's no PRIu64 macro like there is in userspace. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 47 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 1b5052ba4f5a5..37c4eb6a11dee 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -47,11 +47,11 @@ static inline u8 *fec_buffer_rs_message(struct dm_verit= y *v, /* * Decode all RS codewords whose message bytes were loaded into fio->bufs.= Copy * the corrected bytes into fio->output starting from out_pos. */ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io, - struct dm_verity_fec_io *fio, u64 rsb, + struct dm_verity_fec_io *fio, u64 index_in_region, int target_region, unsigned int out_pos, int neras) { int r, corrected =3D 0, res; struct dm_buffer *buf; unsigned int n, i, j, parity_pos, to_copy; @@ -65,18 +65,20 @@ static int fec_decode_bufs(struct dm_verity *v, struct = dm_verity_io *io, * the starting position in that block. Then read that block. * * block_size is always a power of 2, but roots might not be. Note that * when it's not, a codeword's parity bytes can span a block boundary. */ - parity_block =3D (rsb + out_pos) * v->fec->roots; + parity_block =3D ((index_in_region << v->data_dev_block_bits) + out_pos) * + v->fec->roots; parity_pos =3D parity_block & (v->fec->block_size - 1); parity_block >>=3D v->data_dev_block_bits; par =3D dm_bufio_read_with_ioprio(v->fec->bufio, parity_block, &buf, bio->bi_ioprio); if (IS_ERR(par)) { DMERR("%s: FEC %llu: parity read failed (block %llu): %ld", - v->data_dev->name, rsb, parity_block, PTR_ERR(par)); + v->data_dev->name, index_in_region, parity_block, + PTR_ERR(par)); return PTR_ERR(par); } =20 /* * Decode the RS codewords whose message bytes are in bufs. Each RS @@ -101,12 +103,12 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, par =3D dm_bufio_read_with_ioprio(v->fec->bufio, parity_block, &buf, bio->bi_ioprio); if (IS_ERR(par)) { DMERR("%s: FEC %llu: parity read failed (block %llu): %ld", - v->data_dev->name, rsb, parity_block, - PTR_ERR(par)); + v->data_dev->name, index_in_region, + parity_block, PTR_ERR(par)); return PTR_ERR(par); } for (; j < v->fec->roots; j++) par_buf[j] =3D par[parity_pos++]; } @@ -130,14 +132,14 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, error: dm_bufio_release(buf); =20 if (r < 0 && neras) DMERR_LIMIT("%s: FEC %llu: failed to correct: %d", - v->data_dev->name, (unsigned long long)rsb, r); + v->data_dev->name, index_in_region, r); else if (r > 0) DMWARN_LIMIT("%s: FEC %llu: corrected %d errors", - v->data_dev->name, (unsigned long long)rsb, r); + v->data_dev->name, index_in_region, r); =20 return r; } =20 /* @@ -156,18 +158,18 @@ static int fec_is_erasure(struct dm_verity *v, struct= dm_verity_io *io, /* * Read data blocks that are part of the RS block and deinterleave as much= as * fits into buffers. Check for erasure locations if @neras is non-NULL. */ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io, - u64 rsb, unsigned int out_pos, int *neras) + u64 index_in_region, unsigned int out_pos, int *neras) { bool is_zero; int i, j; struct dm_buffer *buf; struct dm_bufio_client *bufio; struct dm_verity_fec_io *fio =3D io->fec_io; - u64 block, ileaved; + u64 block; u8 *bbuf; u8 want_digest[HASH_MAX_DIGESTSIZE]; unsigned int n, src_pos; struct bio *bio =3D dm_bio_from_per_bio_data(io, v->ti->per_io_data_size); =20 @@ -180,12 +182,11 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, /* * read each of the rs_k data blocks that are part of the RS block, and * interleave contents to available bufs */ for (i =3D 0; i < v->fec->rs_k; i++) { - ileaved =3D rsb + i * (v->fec->region_blocks << v->data_dev_block_bits); - block =3D ileaved >> v->data_dev_block_bits; + block =3D i * v->fec->region_blocks + index_in_region; bufio =3D v->fec->data_bufio; =20 if (block >=3D v->data_blocks) { block -=3D v->data_blocks; =20 @@ -201,13 +202,12 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, } =20 bbuf =3D dm_bufio_read_with_ioprio(bufio, block, &buf, bio->bi_ioprio); if (IS_ERR(bbuf)) { DMWARN_LIMIT("%s: FEC %llu: read failed (%llu): %ld", - v->data_dev->name, - (unsigned long long)rsb, - (unsigned long long)block, PTR_ERR(bbuf)); + v->data_dev->name, index_in_region, block, + PTR_ERR(bbuf)); =20 /* assume the block is corrupted */ if (neras && *neras <=3D v->fec->roots) fio->erasures[(*neras)++] =3D i; =20 @@ -310,28 +310,33 @@ static int fec_decode(struct dm_verity *v, struct dm_= verity_io *io, struct dm_verity_fec_io *fio, u64 target_block, const u8 *want_digest, bool use_erasures) { int r, neras =3D 0; unsigned int target_region, out_pos; - u64 rsb; + u64 index_in_region; =20 - target_region =3D div64_u64_rem( - target_block << v->data_dev_block_bits, - v->fec->region_blocks << v->data_dev_block_bits, &rsb); + /* + * Compute 'target_region', the index of the region the target block is + * in; and 'index_in_region', the index of the target block within its + * region. The latter value is also the index within its region of each + * message block that shares its RS codewords with the target block. + */ + target_region =3D div64_u64_rem(target_block, v->fec->region_blocks, + &index_in_region); if (WARN_ON_ONCE(target_region >=3D v->fec->rs_k)) /* target_block is out-of-bounds. Should never happen. */ return -EIO; =20 for (out_pos =3D 0; out_pos < v->fec->block_size;) { fec_init_bufs(v, fio); =20 - r =3D fec_read_bufs(v, io, rsb, out_pos, + r =3D fec_read_bufs(v, io, index_in_region, out_pos, use_erasures ? &neras : NULL); if (unlikely(r < 0)) return r; =20 - r =3D fec_decode_bufs(v, io, fio, rsb, target_region, + r =3D fec_decode_bufs(v, io, fio, index_in_region, target_region, out_pos, neras); if (r < 0) return r; =20 out_pos +=3D fio->nbufs << DM_VERITY_FEC_BUF_RS_BITS; @@ -342,11 +347,11 @@ static int fec_decode(struct dm_verity *v, struct dm_= verity_io *io, if (unlikely(r < 0)) return r; =20 if (memcmp(io->tmp_digest, want_digest, v->digest_size)) { DMERR_LIMIT("%s: FEC %llu: failed to correct (%d erasures)", - v->data_dev->name, (unsigned long long)rsb, neras); + v->data_dev->name, index_in_region, neras); return -EILSEQ; } =20 return 0; } --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A5DB343D72; Fri, 6 Feb 2026 05:02:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354122; cv=none; b=I0MMCfeEBGiXH9A/lFOhifOehP6TbG3pvQ2YCkUmxP4v5tD77yqamdxTCkbVu6ZVeW2clMXMzdmiDdrVNMgb2Wo3Uy8lpppi71Q6g7EdKM6CLvMwqHxOR0UyI+VeUHrmbKmuLgLUrDqPPtZj27pUXU4dFmDD1IWS5MG9efYbexk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354122; c=relaxed/simple; bh=uhnDZGfNOyIrde+6rFo8e20IIuPqoNWAbX5cdfnOAzc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RDWkEl1JB235vh32KKm8GYkQ1YvkMfmF8vZvVhhzQOXe16I7DRfKW8kVn+/2u2W9IuH5UHhiHIAFOTZ1yD97xAUPOj6REh1RUen2ZsxgUr91iCTcN5kkcrm8IZwHO4vBdM47lAZ5D3D84StnEAhRZ79uGj6r9hoO6LqV8LDzdiI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PHBXOY59; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PHBXOY59" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DF560C19422; Fri, 6 Feb 2026 05:02:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354122; bh=uhnDZGfNOyIrde+6rFo8e20IIuPqoNWAbX5cdfnOAzc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PHBXOY599q/peMFFzyk7cUOqE4jmqgfUre036O50Na5OKAXW2M5SEmQgTOFRkgi5J 7k2aMRDkK0ymHB5TZWrllwdjwXJ4Z8ZzK23Quwvru9hdKgbHxtTv77Yr4IuVSrX3AD d93FeSBdkWjaZxWYwn74dwDHrhfN02tRguGZn6UnieS4dFNPcbyL/9t7JRb74G530s xbkS4xIOHKZohIfQs7GKscyuJ9yTUnJjDCibzh1V3wJeJy0ytHFneFGUV097L3GyhA GfZE3SiygL/oRoyIVB5vovzCZV4tdA8LjXXHWbaPyILenERSTXOAOKzsNQCH4AP5im KgjvhrypRrabA== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 20/22] dm-verity-fec: make fec_decode_bufs() just return 0 or error Date: Thu, 5 Feb 2026 20:59:39 -0800 Message-ID: <20260206045942.52965-21-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" fec_decode_bufs() returns the number of errors corrected or a negative errno value. However, the caller just checks for an errno value and doesn't do anything with the number of errors corrected. Simplify the code by just returning 0 instead of the number of errors corrected. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 37c4eb6a11dee..59ff3d58f49df 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -50,11 +50,11 @@ static inline u8 *fec_buffer_rs_message(struct dm_verit= y *v, */ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io, struct dm_verity_fec_io *fio, u64 index_in_region, int target_region, unsigned int out_pos, int neras) { - int r, corrected =3D 0, res; + int r =3D 0, corrected =3D 0, res; struct dm_buffer *buf; unsigned int n, i, j, parity_pos, to_copy; uint16_t par_buf[DM_VERITY_FEC_MAX_ROOTS]; u8 *par, *msg_buf; u64 parity_block; @@ -116,30 +116,27 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, /* Decode an RS codeword using the Reed-Solomon library. */ res =3D decode_rs8(fio->rs, msg_buf, par_buf, v->fec->rs_k, NULL, neras, fio->erasures, 0, NULL); if (res < 0) { r =3D res; - goto error; + goto done; } - corrected +=3D res; fio->output[out_pos++] =3D msg_buf[target_region]; =20 if (out_pos >=3D v->fec->block_size) goto done; } done: - r =3D corrected; -error: dm_bufio_release(buf); =20 if (r < 0 && neras) DMERR_LIMIT("%s: FEC %llu: failed to correct: %d", v->data_dev->name, index_in_region, r); - else if (r > 0) + else if (r =3D=3D 0 && corrected > 0) DMWARN_LIMIT("%s: FEC %llu: corrected %d errors", - v->data_dev->name, index_in_region, r); + v->data_dev->name, index_in_region, corrected); =20 return r; } =20 /* --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A694833893D; Fri, 6 Feb 2026 05:02:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354122; cv=none; b=p4SbPykY00b9DBOsK3mezzdamBtanurKtbRoTGJBdZDvkrQjautnUDTCXfziXrfkoGQULK3l4sZQbjqLrvBnBoWKyFor/vuSooEdMG8ZPu5TeT6zl/1oEATZpzJM6SOLERgecyE6P7spPvpsh9RDzbRHYBl2hU2ysbFnUD5LUeE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354122; c=relaxed/simple; bh=Jo0yT6tvQafUN2nmhO1lBz5NcR9q25+Kc6/PVRBk1es=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DfkiVlAvh53aBwp/DikdZl8Sd7xuGQq8v8XDaqfrTPcgkrmudzPPaCe/THfrlty0tNeWNO8VAtAgJ3DEmke+/f9ZAwvcrKBJlbgsS4IC1EEjQyH50Yy1HXcalmAYqTxVYXPPv7/uGB8nipn2JFFmhqfDzWOzXZyk2LncaDPNXeA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Gns522oK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Gns522oK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4DA50C19424; Fri, 6 Feb 2026 05:02:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354122; bh=Jo0yT6tvQafUN2nmhO1lBz5NcR9q25+Kc6/PVRBk1es=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Gns522oKiZmgOnPDA7XMkCaIgJj0U4H/FteGOB6Sg28PqAIGz6fOnn3bcq3Z77qsx HBXAasZmeNLo3kp/lF9/q7Ee0vxubwFJ1x7kRcsaK5FDUCVdmUrHyhpUkNdCHtRX/K SPLods299jKnhEfkrqtB3Emq5uAi7tCUkwlkheGOMCC9s4hSyugHiL2MOQ/tqp7yYk 8jl6Fv8wVBDk0EGgcjsmBlHo/ESMJKAivRJllgVToz+qK3U38NQLZsLABwpaoHvwwh mACt+EsK0aDJRuUIkl4PYi9wGSCeyQi4C0CtEIhuPwf0Mvm8+jrCmjzG46JIG5NHE0 VhtjQc6ysEsVg== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 21/22] dm-verity-fec: log target_block instead of index_in_region Date: Thu, 5 Feb 2026 20:59:40 -0800 Message-ID: <20260206045942.52965-22-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The log message for a FEC error or correction includes the data device name and index_in_region as the context. Although the result of FEC (for a particular dm-verity instance) is expected to be the same for a given index_in_region, index_in_region does not uniquely identify the actual target block that is being corrected. Since that value (target_block) is likely more useful, log it instead. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 59ff3d58f49df..fbe01f809aca3 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -47,12 +47,13 @@ static inline u8 *fec_buffer_rs_message(struct dm_verit= y *v, /* * Decode all RS codewords whose message bytes were loaded into fio->bufs.= Copy * the corrected bytes into fio->output starting from out_pos. */ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io, - struct dm_verity_fec_io *fio, u64 index_in_region, - int target_region, unsigned int out_pos, int neras) + struct dm_verity_fec_io *fio, u64 target_block, + unsigned int target_region, u64 index_in_region, + unsigned int out_pos, int neras) { int r =3D 0, corrected =3D 0, res; struct dm_buffer *buf; unsigned int n, i, j, parity_pos, to_copy; uint16_t par_buf[DM_VERITY_FEC_MAX_ROOTS]; @@ -73,11 +74,11 @@ static int fec_decode_bufs(struct dm_verity *v, struct = dm_verity_io *io, parity_block >>=3D v->data_dev_block_bits; par =3D dm_bufio_read_with_ioprio(v->fec->bufio, parity_block, &buf, bio->bi_ioprio); if (IS_ERR(par)) { DMERR("%s: FEC %llu: parity read failed (block %llu): %ld", - v->data_dev->name, index_in_region, parity_block, + v->data_dev->name, target_block, parity_block, PTR_ERR(par)); return PTR_ERR(par); } =20 /* @@ -103,11 +104,11 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, par =3D dm_bufio_read_with_ioprio(v->fec->bufio, parity_block, &buf, bio->bi_ioprio); if (IS_ERR(par)) { DMERR("%s: FEC %llu: parity read failed (block %llu): %ld", - v->data_dev->name, index_in_region, + v->data_dev->name, target_block, parity_block, PTR_ERR(par)); return PTR_ERR(par); } for (; j < v->fec->roots; j++) par_buf[j] =3D par[parity_pos++]; @@ -129,14 +130,14 @@ static int fec_decode_bufs(struct dm_verity *v, struc= t dm_verity_io *io, done: dm_bufio_release(buf); =20 if (r < 0 && neras) DMERR_LIMIT("%s: FEC %llu: failed to correct: %d", - v->data_dev->name, index_in_region, r); + v->data_dev->name, target_block, r); else if (r =3D=3D 0 && corrected > 0) DMWARN_LIMIT("%s: FEC %llu: corrected %d errors", - v->data_dev->name, index_in_region, corrected); + v->data_dev->name, target_block, corrected); =20 return r; } =20 /* @@ -155,11 +156,12 @@ static int fec_is_erasure(struct dm_verity *v, struct= dm_verity_io *io, /* * Read data blocks that are part of the RS block and deinterleave as much= as * fits into buffers. Check for erasure locations if @neras is non-NULL. */ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io, - u64 index_in_region, unsigned int out_pos, int *neras) + u64 target_block, u64 index_in_region, + unsigned int out_pos, int *neras) { bool is_zero; int i, j; struct dm_buffer *buf; struct dm_bufio_client *bufio; @@ -199,11 +201,11 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, } =20 bbuf =3D dm_bufio_read_with_ioprio(bufio, block, &buf, bio->bi_ioprio); if (IS_ERR(bbuf)) { DMWARN_LIMIT("%s: FEC %llu: read failed (%llu): %ld", - v->data_dev->name, index_in_region, block, + v->data_dev->name, target_block, block, PTR_ERR(bbuf)); =20 /* assume the block is corrupted */ if (neras && *neras <=3D v->fec->roots) fio->erasures[(*neras)++] =3D i; @@ -324,17 +326,17 @@ static int fec_decode(struct dm_verity *v, struct dm_= verity_io *io, return -EIO; =20 for (out_pos =3D 0; out_pos < v->fec->block_size;) { fec_init_bufs(v, fio); =20 - r =3D fec_read_bufs(v, io, index_in_region, out_pos, + r =3D fec_read_bufs(v, io, target_block, index_in_region, out_pos, use_erasures ? &neras : NULL); if (unlikely(r < 0)) return r; =20 - r =3D fec_decode_bufs(v, io, fio, index_in_region, target_region, - out_pos, neras); + r =3D fec_decode_bufs(v, io, fio, target_block, target_region, + index_in_region, out_pos, neras); if (r < 0) return r; =20 out_pos +=3D fio->nbufs << DM_VERITY_FEC_BUF_RS_BITS; } @@ -344,11 +346,11 @@ static int fec_decode(struct dm_verity *v, struct dm_= verity_io *io, if (unlikely(r < 0)) return r; =20 if (memcmp(io->tmp_digest, want_digest, v->digest_size)) { DMERR_LIMIT("%s: FEC %llu: failed to correct (%d erasures)", - v->data_dev->name, index_in_region, neras); + v->data_dev->name, target_block, neras); return -EILSEQ; } =20 return 0; } --=20 2.52.0 From nobody Sat Feb 7 18:16:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13211344053; Fri, 6 Feb 2026 05:02:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354123; cv=none; b=R4k2Ms/5ZXdmfRFYQ8+fQMGfiNQCtXFfKZZn+RHrK0gjqvx4e3vdgkSz1eTFcBX+TOtqplCZYMBvHp7hOAP7ZTKVlm3sirC68iKsvg9AiElZ7vf/6n57cASA47jq8zFW4KBr3IYfwye/uZAy4cOGrA/8Mf5Nt/+D4/FRhaL6WhY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770354123; c=relaxed/simple; bh=j7cUUZCXDpGOPnDD6xevilNT4R6dBIcSSIK4b1WnMi4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XRIFraHvU+z7wcUYzXgUGv+Ol6MaJoWbFiCJOJZaieuu25nPwO/LGrWW18e6MC6HWdiTe6MXJS/v05ua5rnUzske4VT97mtCle/cC09a9nvKHpLYDfAgJcB93iLk5gvp2avjcqRzXEVg6NzxR0G5wqvRgyUJF4nFlaW+9Sy27LQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MrJeie8J; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MrJeie8J" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD453C19422; Fri, 6 Feb 2026 05:02:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770354122; bh=j7cUUZCXDpGOPnDD6xevilNT4R6dBIcSSIK4b1WnMi4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MrJeie8JydDPc99h00Or1pVIqsWDekJiW71Kw9Pu+aT1sHlsB9fCLiMe66Yv/GQP1 zdWrjPX3eWh71fbTSesgcTwCzwZ/NiBpANXKhDui9uLWn7Bc+DtHJZt971GDOldn6a GNVOePhH/akFTiQmh+VNjInWMA3v3NiPxUjrxtqfxzOHMljilx8t9qYLEcg2+LNmZy tXZeaosab2srQqNLnhSZ0rbmxkbazXCGFN3sNfWJhYWLf3AqWT7cRGfx6d8SZgG6kq X+Ji56aupMdKodOrv0htb50l3il1fkDih62+QGLOSVguvMnjiYj2aw2ArSK7LEEd/5 Zf6MTYTVJm21A== From: Eric Biggers To: dm-devel@lists.linux.dev, Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: Sami Tolvanen , linux-kernel@vger.kernel.org, Eric Biggers Subject: [PATCH 22/22] dm-verity-fec: improve comments for fec_read_bufs() Date: Thu, 5 Feb 2026 20:59:41 -0800 Message-ID: <20260206045942.52965-23-ebiggers@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260206045942.52965-1-ebiggers@kernel.org> References: <20260206045942.52965-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Update the comments in and above fec_read_bufs() to more clearly describe what it does. Signed-off-by: Eric Biggers --- drivers/md/dm-verity-fec.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index fbe01f809aca3..70aa4a20891bc 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -152,12 +152,25 @@ static int fec_is_erasure(struct dm_verity *v, struct= dm_verity_io *io, =20 return memcmp(io->tmp_digest, want_digest, v->digest_size) !=3D 0; } =20 /* - * Read data blocks that are part of the RS block and deinterleave as much= as - * fits into buffers. Check for erasure locations if @neras is non-NULL. + * Read the message block at index @index_in_region within each of the + * @v->fec->rs_k regions and deinterleave their contents into @io->fec_io-= >bufs. + * + * @target_block gives the index of specific block within this sequence th= at is + * being corrected, relative to the start of all the FEC message blocks. + * + * @out_pos gives the current output position, i.e. the position in (each)= block + * from which to start the deinterleaving. Deinterleaving continues until + * either end-of-block is reached or there's no more buffer space. + * + * If @neras is non-NULL, then also use verity hashes and the presence/abs= ence + * of I/O errors to determine which of the message blocks in the sequence = are + * likely to be incorrect. Write the number of such blocks to *@neras and= the + * indices of the corresponding RS message bytes in [0, k - 1] to + * @io->fec_io->erasures, up to a limit of @v->fec->roots + 1 such blocks. */ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io, u64 target_block, u64 index_in_region, unsigned int out_pos, int *neras) { @@ -176,15 +189,15 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, *neras =3D 0; =20 if (WARN_ON(v->digest_size > sizeof(want_digest))) return -EINVAL; =20 - /* - * read each of the rs_k data blocks that are part of the RS block, and - * interleave contents to available bufs - */ for (i =3D 0; i < v->fec->rs_k; i++) { + /* + * Read the block from region i. It contains the i'th message + * byte of the target block's RS codewords. + */ block =3D i * v->fec->region_blocks + index_in_region; bufio =3D v->fec->data_bufio; =20 if (block >=3D v->data_blocks) { block -=3D v->data_blocks; @@ -229,12 +242,13 @@ static int fec_read_bufs(struct dm_verity *v, struct = dm_verity_io *io, fec_is_erasure(v, io, want_digest, bbuf)) fio->erasures[(*neras)++] =3D i; } =20 /* - * deinterleave and copy the bytes that fit into bufs, - * starting from out_pos + * Deinterleave the bytes of the block, starting from 'out_pos', + * into the i'th byte of the RS message buffers. Stop when + * end-of-block is reached or there are no more buffers. */ src_pos =3D out_pos; fec_for_each_buffer_rs_message(fio, n, j) { if (src_pos >=3D v->fec->block_size) goto done; --=20 2.52.0