svn commit: r358451 - in head/sys: kern vm
Gleb Smirnoff
glebius at freebsd.org
Thu Mar 5 00:36:39 UTC 2020
Hi Jeff,
may be I'm missing something, but from a quick review this change doesn't
seem to be correct for sendfile with INVARIANTS on.
sendfile_swapin does immediate vm_page_xunbusy() for all valid pages
that are substituted to bogus one. With this change KASSERT in
vm_page_relookup() would fire:
KASSERT(m != NULL && vm_page_busied(m) &&
On Fri, Feb 28, 2020 at 09:42:48PM +0000, Jeff Roberson wrote:
J> Author: jeff
J> Date: Fri Feb 28 21:42:48 2020
J> New Revision: 358451
J> URL: https://svnweb.freebsd.org/changeset/base/358451
J>
J> Log:
J> Provide a lock free alternative to resolve bogus pages. This is not likely
J> to be much of a perf win, just a nice code simplification.
J>
J> Reviewed by: markj, kib
J> Differential Revision: https://reviews.freebsd.org/D23866
J>
J> Modified:
J> head/sys/kern/kern_sendfile.c
J> head/sys/kern/vfs_bio.c
J> head/sys/vm/vm_page.c
J> head/sys/vm/vm_page.h
J>
J> Modified: head/sys/kern/kern_sendfile.c
J> ==============================================================================
J> --- head/sys/kern/kern_sendfile.c Fri Feb 28 21:31:40 2020 (r358450)
J> +++ head/sys/kern/kern_sendfile.c Fri Feb 28 21:42:48 2020 (r358451)
J> @@ -350,7 +350,6 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> {
J> vm_page_t *pa = sfio->pa;
J> int grabbed;
J> - bool locked;
J>
J> *nios = 0;
J> flags = (flags & SF_NODISKIO) ? VM_ALLOC_NOWAIT : 0;
J> @@ -359,8 +358,6 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> * First grab all the pages and wire them. Note that we grab
J> * only required pages. Readahead pages are dealt with later.
J> */
J> - locked = false;
J> -
J> grabbed = vm_page_grab_pages_unlocked(obj, OFF_TO_IDX(off),
J> VM_ALLOC_NORMAL | VM_ALLOC_WIRED | flags, pa, npages);
J> if (grabbed < npages) {
J> @@ -381,10 +378,6 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> i++;
J> continue;
J> }
J> - if (!locked) {
J> - VM_OBJECT_WLOCK(obj);
J> - locked = true;
J> - }
J>
J> /*
J> * Next page is invalid. Check if it belongs to pager. It
J> @@ -396,8 +389,10 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> * stored in 'a', about how many pages we can pagein after
J> * this page in a single I/O.
J> */
J> + VM_OBJECT_RLOCK(obj);
J> if (!vm_pager_has_page(obj, OFF_TO_IDX(vmoff(i, off)), NULL,
J> &a)) {
J> + VM_OBJECT_RUNLOCK(obj);
J> pmap_zero_page(pa[i]);
J> vm_page_valid(pa[i]);
J> MPASS(pa[i]->dirty == 0);
J> @@ -405,6 +400,7 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> i++;
J> continue;
J> }
J> + VM_OBJECT_RUNLOCK(obj);
J>
J> /*
J> * We want to pagein as many pages as possible, limited only
J> @@ -435,11 +431,9 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> }
J>
J> refcount_acquire(&sfio->nios);
J> - VM_OBJECT_WUNLOCK(obj);
J> rv = vm_pager_get_pages_async(obj, pa + i, count, NULL,
J> i + count == npages ? &rhpages : NULL,
J> &sendfile_iodone, sfio);
J> - VM_OBJECT_WLOCK(obj);
J> if (__predict_false(rv != VM_PAGER_OK)) {
J> /*
J> * Perform full pages recovery before returning EIO.
J> @@ -451,7 +445,7 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> for (j = 0; j < npages; j++) {
J> if (j > i && j < i + count - 1 &&
J> pa[j] == bogus_page)
J> - pa[j] = vm_page_lookup(obj,
J> + pa[j] = vm_page_relookup(obj,
J> OFF_TO_IDX(vmoff(j, off)));
J> else if (j >= i)
J> vm_page_xunbusy(pa[j]);
J> @@ -460,7 +454,6 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> __func__, pa, j));
J> vm_page_unwire(pa[j], PQ_INACTIVE);
J> }
J> - VM_OBJECT_WUNLOCK(obj);
J> return (EIO);
J> }
J>
J> @@ -475,7 +468,7 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> */
J> for (j = i + 1; j < i + count - 1; j++)
J> if (pa[j] == bogus_page) {
J> - pa[j] = vm_page_lookup(obj,
J> + pa[j] = vm_page_relookup(obj,
J> OFF_TO_IDX(vmoff(j, off)));
J> KASSERT(pa[j], ("%s: page %p[%d] disappeared",
J> __func__, pa, j));
J> @@ -484,9 +477,6 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, i
J> i += count;
J> (*nios)++;
J> }
J> -
J> - if (locked)
J> - VM_OBJECT_WUNLOCK(obj);
J>
J> if (*nios == 0 && npages != 0)
J> SFSTAT_INC(sf_noiocnt);
J>
J> Modified: head/sys/kern/vfs_bio.c
J> ==============================================================================
J> --- head/sys/kern/vfs_bio.c Fri Feb 28 21:31:40 2020 (r358450)
J> +++ head/sys/kern/vfs_bio.c Fri Feb 28 21:42:48 2020 (r358451)
J> @@ -2878,11 +2878,8 @@ vfs_vmio_iodone(struct buf *bp)
J> */
J> m = bp->b_pages[i];
J> if (m == bogus_page) {
J> - if (bogus == false) {
J> - bogus = true;
J> - VM_OBJECT_RLOCK(obj);
J> - }
J> - m = vm_page_lookup(obj, OFF_TO_IDX(foff));
J> + bogus = true;
J> + m = vm_page_relookup(obj, OFF_TO_IDX(foff));
J> if (m == NULL)
J> panic("biodone: page disappeared!");
J> bp->b_pages[i] = m;
J> @@ -2905,8 +2902,6 @@ vfs_vmio_iodone(struct buf *bp)
J> foff = (foff + PAGE_SIZE) & ~(off_t)PAGE_MASK;
J> iosize -= resid;
J> }
J> - if (bogus)
J> - VM_OBJECT_RUNLOCK(obj);
J> vm_object_pip_wakeupn(obj, bp->b_npages);
J> if (bogus && buf_mapped(bp)) {
J> BUF_CHECK_MAPPED(bp);
J> @@ -4470,22 +4465,16 @@ vfs_unbusy_pages(struct buf *bp)
J> int i;
J> vm_object_t obj;
J> vm_page_t m;
J> - bool bogus;
J>
J> runningbufwakeup(bp);
J> if (!(bp->b_flags & B_VMIO))
J> return;
J>
J> obj = bp->b_bufobj->bo_object;
J> - bogus = false;
J> for (i = 0; i < bp->b_npages; i++) {
J> m = bp->b_pages[i];
J> if (m == bogus_page) {
J> - if (bogus == false) {
J> - bogus = true;
J> - VM_OBJECT_RLOCK(obj);
J> - }
J> - m = vm_page_lookup(obj, OFF_TO_IDX(bp->b_offset) + i);
J> + m = vm_page_relookup(obj, OFF_TO_IDX(bp->b_offset) + i);
J> if (!m)
J> panic("vfs_unbusy_pages: page missing\n");
J> bp->b_pages[i] = m;
J> @@ -4498,8 +4487,6 @@ vfs_unbusy_pages(struct buf *bp)
J> }
J> vm_page_sunbusy(m);
J> }
J> - if (bogus)
J> - VM_OBJECT_RUNLOCK(obj);
J> vm_object_pip_wakeupn(obj, bp->b_npages);
J> }
J>
J>
J> Modified: head/sys/vm/vm_page.c
J> ==============================================================================
J> --- head/sys/vm/vm_page.c Fri Feb 28 21:31:40 2020 (r358450)
J> +++ head/sys/vm/vm_page.c Fri Feb 28 21:42:48 2020 (r358451)
J> @@ -1671,6 +1671,24 @@ vm_page_lookup(vm_object_t object, vm_pindex_t pindex)
J> }
J>
J> /*
J> + * vm_page_relookup:
J> + *
J> + * Returns a page that must already have been busied by
J> + * the caller. Used for bogus page replacement.
J> + */
J> +vm_page_t
J> +vm_page_relookup(vm_object_t object, vm_pindex_t pindex)
J> +{
J> + vm_page_t m;
J> +
J> + m = vm_radix_lookup_unlocked(&object->rtree, pindex);
J> + KASSERT(m != NULL && vm_page_busied(m) &&
J> + m->object == object && m->pindex == pindex,
J> + ("vm_page_relookup: Invalid page %p", m));
J> + return (m);
J> +}
J> +
J> +/*
J> * This should only be used by lockless functions for releasing transient
J> * incorrect acquires. The page may have been freed after we acquired a
J> * busy lock. In this case busy_lock == VPB_FREED and we have nothing
J>
J> Modified: head/sys/vm/vm_page.h
J> ==============================================================================
J> --- head/sys/vm/vm_page.h Fri Feb 28 21:31:40 2020 (r358450)
J> +++ head/sys/vm/vm_page.h Fri Feb 28 21:42:48 2020 (r358451)
J> @@ -653,6 +653,7 @@ void vm_page_reference(vm_page_t m);
J> #define VPR_NOREUSE 0x02
J> void vm_page_release(vm_page_t m, int flags);
J> void vm_page_release_locked(vm_page_t m, int flags);
J> +vm_page_t vm_page_relookup(vm_object_t, vm_pindex_t);
J> bool vm_page_remove(vm_page_t);
J> bool vm_page_remove_xbusy(vm_page_t);
J> int vm_page_rename(vm_page_t, vm_object_t, vm_pindex_t);
J> _______________________________________________
J> svn-src-all at freebsd.org mailing list
J> https://lists.freebsd.org/mailman/listinfo/svn-src-all
J> To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
--
Gleb Smirnoff
More information about the svn-src-all
mailing list