Revert back to use int for the page counts. In vn_io_fault(), the i/o
is chunked to pieces limited by integer io_hold_cnt tunable, while vm_fault_quick_hold_pages() takes integer max_count as the upper bound. Rearrange the checks to correctly handle overflowing address arithmetic. Submitted by: bde Tested by: pho Discussed with: alc MFC after: 1 week
This commit is contained in:
parent
a2c0f474c4
commit
7e14088d93
@ -933,9 +933,8 @@ vn_io_fault(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
void *rl_cookie;
|
||||
struct mount *mp;
|
||||
vm_page_t *prev_td_ma;
|
||||
int error, save, saveheld, prev_td_ma_cnt;
|
||||
int error, cnt, save, saveheld, prev_td_ma_cnt;
|
||||
vm_offset_t addr, end;
|
||||
vm_size_t cnt;
|
||||
vm_prot_t prot;
|
||||
size_t len, resid;
|
||||
ssize_t adv;
|
||||
@ -1008,21 +1007,20 @@ vn_io_fault(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
uio_clone->uio_iovcnt--;
|
||||
continue;
|
||||
}
|
||||
|
||||
addr = (vm_offset_t)uio_clone->uio_iov->iov_base;
|
||||
if (len > io_hold_cnt * PAGE_SIZE)
|
||||
len = io_hold_cnt * PAGE_SIZE;
|
||||
addr = (uintptr_t)uio_clone->uio_iov->iov_base;
|
||||
end = round_page(addr + len);
|
||||
cnt = howmany(end - trunc_page(addr), PAGE_SIZE);
|
||||
if (end < addr) {
|
||||
error = EFAULT;
|
||||
break;
|
||||
}
|
||||
cnt = atop(end - trunc_page(addr));
|
||||
/*
|
||||
* A perfectly misaligned address and length could cause
|
||||
* both the start and the end of the chunk to use partial
|
||||
* page. +2 accounts for such a situation.
|
||||
*/
|
||||
if (cnt > io_hold_cnt + 2) {
|
||||
len = io_hold_cnt * PAGE_SIZE;
|
||||
KASSERT(howmany(round_page(addr + len) -
|
||||
trunc_page(addr), PAGE_SIZE) <= io_hold_cnt + 2,
|
||||
("cnt overflow"));
|
||||
}
|
||||
cnt = vm_fault_quick_hold_pages(&td->td_proc->p_vmspace->vm_map,
|
||||
addr, len, prot, ma, io_hold_cnt + 2);
|
||||
if (cnt == -1) {
|
||||
|
@ -1074,12 +1074,12 @@ vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len,
|
||||
{
|
||||
vm_offset_t end, va;
|
||||
vm_page_t *mp;
|
||||
vm_size_t count;
|
||||
int count;
|
||||
boolean_t pmap_failed;
|
||||
|
||||
if (len == 0)
|
||||
return (0);
|
||||
end = round_page(addr + len);
|
||||
end = round_page(addr + len);
|
||||
addr = trunc_page(addr);
|
||||
|
||||
/*
|
||||
@ -1088,9 +1088,9 @@ vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len,
|
||||
if (addr < vm_map_min(map) || addr > end || end > vm_map_max(map))
|
||||
return (-1);
|
||||
|
||||
count = howmany(end - addr, PAGE_SIZE);
|
||||
if (count > max_count)
|
||||
if (atop(end - addr) > max_count)
|
||||
panic("vm_fault_quick_hold_pages: count > max_count");
|
||||
count = atop(end - addr);
|
||||
|
||||
/*
|
||||
* Most likely, the physical pages are resident in the pmap, so it is
|
||||
|
Loading…
x
Reference in New Issue
Block a user