Date: Wed, 20 Nov 2013 08:45:26 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r258365 - in head/sys: kern vm Message-ID: <201311200845.rAK8jQRv012600@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Wed Nov 20 08:45:26 2013 New Revision: 258365 URL: http://svnweb.freebsd.org/changeset/base/258365 Log: 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 Modified: head/sys/kern/vfs_vnops.c head/sys/vm/vm_fault.c Modified: head/sys/kern/vfs_vnops.c ============================================================================== --- head/sys/kern/vfs_vnops.c Wed Nov 20 02:20:27 2013 (r258364) +++ head/sys/kern/vfs_vnops.c Wed Nov 20 08:45:26 2013 (r258365) @@ -933,9 +933,8 @@ vn_io_fault(struct file *fp, struct uio 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_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) { Modified: head/sys/vm/vm_fault.c ============================================================================== --- head/sys/vm/vm_fault.c Wed Nov 20 02:20:27 2013 (r258364) +++ head/sys/vm/vm_fault.c Wed Nov 20 08:45:26 2013 (r258365) @@ -1074,12 +1074,12 @@ vm_fault_quick_hold_pages(vm_map_t map, { 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, 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201311200845.rAK8jQRv012600>