mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
NFSv4/flexfiles: Use the full 64-bit stripe_unit
ff_layout_alloc_lseg() decodes stripe_unit as the 64-bit value the
protocol defines and struct nfs4_ff_layout_segment stores it as one, but
both consumers narrow it back to 32 bits: nfs4_ff_layout_calc_dss_id()
divides with do_div(), which casts the divisor, and ff_layout_pg_test()
copies it into a u32 first. A stripe_unit that does not fit is silently
truncated, so the client stripes on a unit the server did not specify --
or divides by zero, if the low 32 bits happen to be clear.
Divide by the full value, with div64_u64() and div64_u64_rem().
Fixes: 20b1d75fb8 ("NFSv4/flexfiles: Add support for striped layouts")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-fable-5
Signed-off-by: Benjamin Coddington <bcodding@hammerspace.com>
Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
This commit is contained in:
parent
a7c8e96d1b
commit
0cc1191538
|
|
@ -995,9 +995,9 @@ ff_layout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
|
|||
{
|
||||
unsigned int size;
|
||||
u64 p_stripe, r_stripe;
|
||||
u32 stripe_offset;
|
||||
u64 stripe_offset;
|
||||
u64 segment_offset = pgio->pg_lseg->pls_range.offset;
|
||||
u32 stripe_unit = FF_LAYOUT_LSEG(pgio->pg_lseg)->stripe_unit;
|
||||
u64 stripe_unit = FF_LAYOUT_LSEG(pgio->pg_lseg)->stripe_unit;
|
||||
|
||||
/* calls nfs_generic_pg_test */
|
||||
size = pnfs_generic_pg_test(pgio, prev, req);
|
||||
|
|
@ -1010,21 +1010,21 @@ ff_layout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
|
|||
if (prev) {
|
||||
p_stripe = (u64)req_offset(prev) - segment_offset;
|
||||
r_stripe = (u64)req_offset(req) - segment_offset;
|
||||
do_div(p_stripe, stripe_unit);
|
||||
do_div(r_stripe, stripe_unit);
|
||||
p_stripe = div64_u64(p_stripe, stripe_unit);
|
||||
r_stripe = div64_u64(r_stripe, stripe_unit);
|
||||
|
||||
if (p_stripe != r_stripe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calculate remaining bytes in the current stripe */
|
||||
div_u64_rem((u64)req_offset(req) - segment_offset,
|
||||
div64_u64_rem((u64)req_offset(req) - segment_offset,
|
||||
stripe_unit,
|
||||
&stripe_offset);
|
||||
WARN_ON_ONCE(stripe_offset > stripe_unit);
|
||||
if (stripe_offset >= stripe_unit)
|
||||
return 0;
|
||||
return min(stripe_unit - (unsigned int)stripe_offset, size);
|
||||
return min_t(u64, stripe_unit - stripe_offset, size);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ nfs4_ff_layout_calc_dss_id(const u64 stripe_unit, const u32 dss_count, const lof
|
|||
if (dss_count == 1 || stripe_unit == 0)
|
||||
return 0;
|
||||
|
||||
do_div(tmp, stripe_unit);
|
||||
tmp = div64_u64(tmp, stripe_unit);
|
||||
|
||||
return do_div(tmp, dss_count);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user