vop_stdadvise(): restore correct handling of length == 0

Switch to unsigned arithmetic to handle overflow not relying on -fwrap,
and specially treat the case of length == 0 from posix_fadvise() which
passes OFF_MAX as the end to VOP.  There, roundup() overflows and -fwrap
causes bend and endn become negative.  Using uintmax_t gives the place
for roundup() to not wrap.

Also remove locals with single use, and move calculations out from under
bo lock.

Reported by:	tmunro
Reviewed by:	markj, tmunro
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D46518
This commit is contained in:
Konstantin Belousov 2024-09-03 07:20:40 +03:00
parent dc450b388b
commit 79eba754be

View file

@ -1063,8 +1063,8 @@ vop_stdadvise(struct vop_advise_args *ap)
{
struct vnode *vp;
struct bufobj *bo;
uintmax_t bstart, bend;
daddr_t startn, endn;
off_t bstart, bend, start, end;
int bsize, error;
vp = ap->a_vp;
@ -1096,7 +1096,8 @@ vop_stdadvise(struct vop_advise_args *ap)
*/
bsize = vp->v_bufobj.bo_bsize;
bstart = rounddown(ap->a_start, bsize);
bend = roundup(ap->a_end, bsize);
bend = ap->a_end;
bend = roundup(bend, bsize);
/*
* Deactivate pages in the specified range from the backing VM
@ -1105,18 +1106,17 @@ vop_stdadvise(struct vop_advise_args *ap)
* below.
*/
if (vp->v_object != NULL) {
start = trunc_page(bstart);
end = round_page(bend);
VM_OBJECT_RLOCK(vp->v_object);
vm_object_page_noreuse(vp->v_object, OFF_TO_IDX(start),
OFF_TO_IDX(end));
vm_object_page_noreuse(vp->v_object,
OFF_TO_IDX(trunc_page(bstart)),
OFF_TO_IDX(round_page(bend)));
VM_OBJECT_RUNLOCK(vp->v_object);
}
bo = &vp->v_bufobj;
BO_RLOCK(bo);
startn = bstart / bsize;
endn = bend / bsize;
BO_RLOCK(bo);
error = bnoreuselist(&bo->bo_clean, bo, startn, endn);
if (error == 0)
error = bnoreuselist(&bo->bo_dirty, bo, startn, endn);