[PATCH] NFS: filelayout: calculate dense stripe width in 64 bits

From: Jérémy Jean

Date: Mon Sep 14 2026 - 16:49:05 EST


filelayout_get_dense_offset() calculates the stripe width from the
stripe unit and count, where both values are provided by the server.
Their product is stored on 32 bits, and can wrap to zero despite
passing individual checks. For example, a 1 GiB stripe unit (0x40000000)
and four stripes (4) cause the following div_u64() to raise a divide
error during the first read through the dense layout.

Update u32 to u64 and use div64_u64() instead of div_u64().
stripe_unit is a u32 and stripe_count is limited to 4096, so the
product cannot overflow a u64.

Fixes: cfe7f4120f8b ("NFSv4.1: filelayout i/o helpers")
Assisted-by: Codex:gpt-5
Signed-off-by: Jérémy Jean <Jeremy.Jean@xxxxxxxxxxxxxxxxx>
---
fs/nfs/filelayout/filelayout.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c
index 72e20b56fbc7..a15fca123069 100644
--- a/fs/nfs/filelayout/filelayout.c
+++ b/fs/nfs/filelayout/filelayout.c
@@ -55,12 +55,13 @@ static loff_t
filelayout_get_dense_offset(struct nfs4_filelayout_segment *flseg,
loff_t offset)
{
- u32 stripe_width = flseg->stripe_unit * flseg->dsaddr->stripe_count;
+ u64 stripe_width = (u64)flseg->stripe_unit *
+ flseg->dsaddr->stripe_count;
u64 stripe_no;
u32 rem;

offset -= flseg->pattern_offset;
- stripe_no = div_u64(offset, stripe_width);
+ stripe_no = div64_u64(offset, stripe_width);
div_u64_rem(offset, flseg->stripe_unit, &rem);

return stripe_no * flseg->stripe_unit + rem;
--
2.47.3