tmpfs: check residence in data_locked

tmpfs_seek_data_locked should return the offset of the first page
either resident in memory or in swap, but may return an offset to a
nonresident page. Check for residence to fix that.

Reviewed by:	alc, kib
Differential Revision:	https://reviews.freebsd.org/D46879
This commit is contained in:
Doug Moore 2024-10-04 02:44:19 -05:00
parent 64b0f52be2
commit 75734c4360

View File

@ -2099,7 +2099,7 @@ static off_t
tmpfs_seek_data_locked(vm_object_t obj, off_t noff)
{
vm_page_t m;
vm_pindex_t p, p_m, p_swp;
vm_pindex_t p, p_swp;
p = OFF_TO_IDX(noff);
m = vm_page_find_least(obj, p);
@ -2108,15 +2108,24 @@ tmpfs_seek_data_locked(vm_object_t obj, off_t noff)
* Microoptimize the most common case for SEEK_DATA, where
* there is no hole and the page is resident.
*/
if (m != NULL && vm_page_any_valid(m) && m->pindex == p)
if (m != NULL && m->pindex == p && vm_page_any_valid(m))
return (noff);
p_swp = swap_pager_find_least(obj, p);
if (p_swp == p)
return (noff);
p_m = m == NULL ? obj->size : m->pindex;
return (IDX_TO_OFF(MIN(p_m, p_swp)));
/*
* Find the first resident page after p, before p_swp.
*/
while (m != NULL && m->pindex < p_swp) {
if (vm_page_any_valid(m))
return (IDX_TO_OFF(m->pindex));
m = TAILQ_NEXT(m, listq);
}
if (p_swp == OBJ_MAX_SIZE)
p_swp = obj->size;
return (IDX_TO_OFF(p_swp));
}
static off_t