Re: uvm_fault: entering swap code
On Sat, Dec 12, 2020 at 10:54:57PM +1000, Jonathan Matthew wrote: > On Thu, Dec 10, 2020 at 10:46:58AM -0300, Martin Pieuchot wrote: > > On 08/12/20(Tue) 22:55, Jonathan Matthew wrote: > > > On Mon, Dec 07, 2020 at 03:15:50PM -0300, Martin Pieuchot wrote: > > > > Getting a page from the fault handler might require poking at some > > > > swap-related states. > > > > > > > > These are not in the hot-path of the fault handler so for the moment > > > > just assert that the KERNEL_LOCK() is held or grab it if the function > > > > might be called from an future unlocked path. > > > > > > > > ok? > > > > > > Could you add 'K' to the list of locks in the comment above struct uvmexp > > > too? > > > > Updated diff below. > > > > > I went looking for other uses of swpgonly and saw that it's used under > > > uvm_map_teardown -> uvm_unmap_kill_entry -> uvm_km_pgremove, > > > and uvm_map_teardown ensures that the kernel lock is not held. > > > Not related to this diff exactly, but is this something we need to fix? > > > > I suppose that the problem can only occur if a kernel thread is exiting > > since this code is only executed for the kernel pmap. Anyway I added an > > assertion. > > Right, and as I understand it, kernel threads all share the proc0 vm space, > so its reference count won't ever reach 0, so the kernel map portions of > uvm_unmap_kill_entry() can't be reached from the reaper. Looks like this is > all safe, it just requires a bit more reading than I did the first time. > I'll see if I can find a way to make it more clear. And now that I've tested this out and checked that it doesn't blow up when you drive the machine into swap, ok jmatthew@ > > > > > Index: uvm/uvm_km.c > > === > > RCS file: /cvs/src/sys/uvm/uvm_km.c,v > > retrieving revision 1.137 > > diff -u -p -r1.137 uvm_km.c > > --- uvm/uvm_km.c23 May 2020 06:15:09 - 1.137 > > +++ uvm/uvm_km.c10 Dec 2020 13:33:49 - > > @@ -243,6 +243,7 @@ uvm_km_pgremove(struct uvm_object *uobj, > > voff_t curoff; > > int slot; > > > > + KERNEL_ASSERT_LOCKED(); > > KASSERT(uobj->pgops == _pager); > > > > for (curoff = start ; curoff < end ; curoff += PAGE_SIZE) { > > Index: uvm/uvm_swap.c > > === > > RCS file: /cvs/src/sys/uvm/uvm_swap.c,v > > retrieving revision 1.147 > > diff -u -p -r1.147 uvm_swap.c > > --- uvm/uvm_swap.c 29 Sep 2020 11:47:41 - 1.147 > > +++ uvm/uvm_swap.c 10 Dec 2020 13:30:30 - > > @@ -1403,7 +1403,7 @@ uvm_swap_alloc(int *nslots, boolean_t le > > /* > > * lock data lock, convert slots into blocks, and enter loop > > */ > > - > > + KERNEL_ASSERT_LOCKED(); > > ReTry: /* XXXMRG */ > > LIST_FOREACH(spp, _priority, spi_swappri) { > > TAILQ_FOREACH(sdp, >spi_swapdev, swd_next) { > > @@ -1449,8 +1449,10 @@ uvm_swapisfull(void) > > { > > int result; > > > > + KERNEL_LOCK(); > > KASSERT(uvmexp.swpgonly <= uvmexp.swpages); > > result = (uvmexp.swpgonly == uvmexp.swpages); > > + KERNEL_UNLOCK(); > > > > return result; > > } > > @@ -1465,6 +1467,7 @@ uvm_swap_markbad(int startslot, int nslo > > { > > struct swapdev *sdp; > > > > + KERNEL_LOCK(); > > sdp = swapdrum_getsdp(startslot); > > if (sdp != NULL) { > > /* > > @@ -1475,6 +1478,7 @@ uvm_swap_markbad(int startslot, int nslo > > */ > > sdp->swd_npgbad += nslots; > > } > > + KERNEL_UNLOCK(); > > } > > > > /* > > @@ -1501,7 +1505,7 @@ uvm_swap_free(int startslot, int nslots) > > * in the extent, and return. must hold pri lock to do > > * lookup and access the extent. > > */ > > - > > + KERNEL_LOCK(); > > sdp = swapdrum_getsdp(startslot); > > KASSERT(uvmexp.nswapdev >= 1); > > KASSERT(sdp != NULL); > > @@ -1533,6 +1537,7 @@ uvm_swap_free(int startslot, int nslots) > > } > > } > > #endif /* UVM_SWAP_ENCRYPT */ > > + KERNEL_UNLOCK(); > > } > > > > /* > > @@ -1567,6 +1572,7 @@ uvm_swap_get(struct vm_page *page, int s > > return VM_PAGER_ERROR; > > } > > > > + KERNEL_LOCK(); > > /* this page is (about to be) no longer only in swap. */ > > uvmexp.swpgonly--; > > > > @@ -1577,7 +1583,7 @@ uvm_swap_get(struct vm_page *page, int s > > /* oops, the read failed so it really is still only in swap. */ > > uvmexp.swpgonly++; > > } > > - > > + KERNEL_UNLOCK(); > > return (result); > > } > > > > @@ -1599,6 +1605,8 @@ uvm_swap_io(struct vm_page **pps, int st > > struct swapdev *sdp; > > int encrypt = 0; > > #endif > > + > > + KERNEL_ASSERT_LOCKED(); > > > > write = (flags & B_READ) == 0; > > async = (flags & B_ASYNC) != 0; > > Index: uvm/uvmexp.h > > === > > RCS file:
Re: uvm_fault: entering swap code
On Thu, Dec 10, 2020 at 10:46:58AM -0300, Martin Pieuchot wrote: > On 08/12/20(Tue) 22:55, Jonathan Matthew wrote: > > On Mon, Dec 07, 2020 at 03:15:50PM -0300, Martin Pieuchot wrote: > > > Getting a page from the fault handler might require poking at some > > > swap-related states. > > > > > > These are not in the hot-path of the fault handler so for the moment > > > just assert that the KERNEL_LOCK() is held or grab it if the function > > > might be called from an future unlocked path. > > > > > > ok? > > > > Could you add 'K' to the list of locks in the comment above struct uvmexp > > too? > > Updated diff below. > > > I went looking for other uses of swpgonly and saw that it's used under > > uvm_map_teardown -> uvm_unmap_kill_entry -> uvm_km_pgremove, > > and uvm_map_teardown ensures that the kernel lock is not held. > > Not related to this diff exactly, but is this something we need to fix? > > I suppose that the problem can only occur if a kernel thread is exiting > since this code is only executed for the kernel pmap. Anyway I added an > assertion. Right, and as I understand it, kernel threads all share the proc0 vm space, so its reference count won't ever reach 0, so the kernel map portions of uvm_unmap_kill_entry() can't be reached from the reaper. Looks like this is all safe, it just requires a bit more reading than I did the first time. I'll see if I can find a way to make it more clear. > > Index: uvm/uvm_km.c > === > RCS file: /cvs/src/sys/uvm/uvm_km.c,v > retrieving revision 1.137 > diff -u -p -r1.137 uvm_km.c > --- uvm/uvm_km.c 23 May 2020 06:15:09 - 1.137 > +++ uvm/uvm_km.c 10 Dec 2020 13:33:49 - > @@ -243,6 +243,7 @@ uvm_km_pgremove(struct uvm_object *uobj, > voff_t curoff; > int slot; > > + KERNEL_ASSERT_LOCKED(); > KASSERT(uobj->pgops == _pager); > > for (curoff = start ; curoff < end ; curoff += PAGE_SIZE) { > Index: uvm/uvm_swap.c > === > RCS file: /cvs/src/sys/uvm/uvm_swap.c,v > retrieving revision 1.147 > diff -u -p -r1.147 uvm_swap.c > --- uvm/uvm_swap.c29 Sep 2020 11:47:41 - 1.147 > +++ uvm/uvm_swap.c10 Dec 2020 13:30:30 - > @@ -1403,7 +1403,7 @@ uvm_swap_alloc(int *nslots, boolean_t le > /* >* lock data lock, convert slots into blocks, and enter loop >*/ > - > + KERNEL_ASSERT_LOCKED(); > ReTry: /* XXXMRG */ > LIST_FOREACH(spp, _priority, spi_swappri) { > TAILQ_FOREACH(sdp, >spi_swapdev, swd_next) { > @@ -1449,8 +1449,10 @@ uvm_swapisfull(void) > { > int result; > > + KERNEL_LOCK(); > KASSERT(uvmexp.swpgonly <= uvmexp.swpages); > result = (uvmexp.swpgonly == uvmexp.swpages); > + KERNEL_UNLOCK(); > > return result; > } > @@ -1465,6 +1467,7 @@ uvm_swap_markbad(int startslot, int nslo > { > struct swapdev *sdp; > > + KERNEL_LOCK(); > sdp = swapdrum_getsdp(startslot); > if (sdp != NULL) { > /* > @@ -1475,6 +1478,7 @@ uvm_swap_markbad(int startslot, int nslo >*/ > sdp->swd_npgbad += nslots; > } > + KERNEL_UNLOCK(); > } > > /* > @@ -1501,7 +1505,7 @@ uvm_swap_free(int startslot, int nslots) >* in the extent, and return. must hold pri lock to do >* lookup and access the extent. >*/ > - > + KERNEL_LOCK(); > sdp = swapdrum_getsdp(startslot); > KASSERT(uvmexp.nswapdev >= 1); > KASSERT(sdp != NULL); > @@ -1533,6 +1537,7 @@ uvm_swap_free(int startslot, int nslots) > } > } > #endif /* UVM_SWAP_ENCRYPT */ > + KERNEL_UNLOCK(); > } > > /* > @@ -1567,6 +1572,7 @@ uvm_swap_get(struct vm_page *page, int s > return VM_PAGER_ERROR; > } > > + KERNEL_LOCK(); > /* this page is (about to be) no longer only in swap. */ > uvmexp.swpgonly--; > > @@ -1577,7 +1583,7 @@ uvm_swap_get(struct vm_page *page, int s > /* oops, the read failed so it really is still only in swap. */ > uvmexp.swpgonly++; > } > - > + KERNEL_UNLOCK(); > return (result); > } > > @@ -1599,6 +1605,8 @@ uvm_swap_io(struct vm_page **pps, int st > struct swapdev *sdp; > int encrypt = 0; > #endif > + > + KERNEL_ASSERT_LOCKED(); > > write = (flags & B_READ) == 0; > async = (flags & B_ASYNC) != 0; > Index: uvm/uvmexp.h > === > RCS file: /cvs/src/sys/uvm/uvmexp.h,v > retrieving revision 1.6 > diff -u -p -r1.6 uvmexp.h > --- uvm/uvmexp.h 1 Dec 2020 13:56:22 - 1.6 > +++ uvm/uvmexp.h 10 Dec 2020 13:31:01 - > @@ -42,6 +42,7 @@ > * > * Locks used to protect struct members in this file: > * I immutable after creation > + * K kernel lock > * F uvm_lock_fpageq
Re: uvm_fault: entering swap code
On 08/12/20(Tue) 22:55, Jonathan Matthew wrote: > On Mon, Dec 07, 2020 at 03:15:50PM -0300, Martin Pieuchot wrote: > > Getting a page from the fault handler might require poking at some > > swap-related states. > > > > These are not in the hot-path of the fault handler so for the moment > > just assert that the KERNEL_LOCK() is held or grab it if the function > > might be called from an future unlocked path. > > > > ok? > > Could you add 'K' to the list of locks in the comment above struct uvmexp too? Updated diff below. > I went looking for other uses of swpgonly and saw that it's used under > uvm_map_teardown -> uvm_unmap_kill_entry -> uvm_km_pgremove, > and uvm_map_teardown ensures that the kernel lock is not held. > Not related to this diff exactly, but is this something we need to fix? I suppose that the problem can only occur if a kernel thread is exiting since this code is only executed for the kernel pmap. Anyway I added an assertion. Index: uvm/uvm_km.c === RCS file: /cvs/src/sys/uvm/uvm_km.c,v retrieving revision 1.137 diff -u -p -r1.137 uvm_km.c --- uvm/uvm_km.c23 May 2020 06:15:09 - 1.137 +++ uvm/uvm_km.c10 Dec 2020 13:33:49 - @@ -243,6 +243,7 @@ uvm_km_pgremove(struct uvm_object *uobj, voff_t curoff; int slot; + KERNEL_ASSERT_LOCKED(); KASSERT(uobj->pgops == _pager); for (curoff = start ; curoff < end ; curoff += PAGE_SIZE) { Index: uvm/uvm_swap.c === RCS file: /cvs/src/sys/uvm/uvm_swap.c,v retrieving revision 1.147 diff -u -p -r1.147 uvm_swap.c --- uvm/uvm_swap.c 29 Sep 2020 11:47:41 - 1.147 +++ uvm/uvm_swap.c 10 Dec 2020 13:30:30 - @@ -1403,7 +1403,7 @@ uvm_swap_alloc(int *nslots, boolean_t le /* * lock data lock, convert slots into blocks, and enter loop */ - + KERNEL_ASSERT_LOCKED(); ReTry: /* XXXMRG */ LIST_FOREACH(spp, _priority, spi_swappri) { TAILQ_FOREACH(sdp, >spi_swapdev, swd_next) { @@ -1449,8 +1449,10 @@ uvm_swapisfull(void) { int result; + KERNEL_LOCK(); KASSERT(uvmexp.swpgonly <= uvmexp.swpages); result = (uvmexp.swpgonly == uvmexp.swpages); + KERNEL_UNLOCK(); return result; } @@ -1465,6 +1467,7 @@ uvm_swap_markbad(int startslot, int nslo { struct swapdev *sdp; + KERNEL_LOCK(); sdp = swapdrum_getsdp(startslot); if (sdp != NULL) { /* @@ -1475,6 +1478,7 @@ uvm_swap_markbad(int startslot, int nslo */ sdp->swd_npgbad += nslots; } + KERNEL_UNLOCK(); } /* @@ -1501,7 +1505,7 @@ uvm_swap_free(int startslot, int nslots) * in the extent, and return. must hold pri lock to do * lookup and access the extent. */ - + KERNEL_LOCK(); sdp = swapdrum_getsdp(startslot); KASSERT(uvmexp.nswapdev >= 1); KASSERT(sdp != NULL); @@ -1533,6 +1537,7 @@ uvm_swap_free(int startslot, int nslots) } } #endif /* UVM_SWAP_ENCRYPT */ + KERNEL_UNLOCK(); } /* @@ -1567,6 +1572,7 @@ uvm_swap_get(struct vm_page *page, int s return VM_PAGER_ERROR; } + KERNEL_LOCK(); /* this page is (about to be) no longer only in swap. */ uvmexp.swpgonly--; @@ -1577,7 +1583,7 @@ uvm_swap_get(struct vm_page *page, int s /* oops, the read failed so it really is still only in swap. */ uvmexp.swpgonly++; } - + KERNEL_UNLOCK(); return (result); } @@ -1599,6 +1605,8 @@ uvm_swap_io(struct vm_page **pps, int st struct swapdev *sdp; int encrypt = 0; #endif + + KERNEL_ASSERT_LOCKED(); write = (flags & B_READ) == 0; async = (flags & B_ASYNC) != 0; Index: uvm/uvmexp.h === RCS file: /cvs/src/sys/uvm/uvmexp.h,v retrieving revision 1.6 diff -u -p -r1.6 uvmexp.h --- uvm/uvmexp.h1 Dec 2020 13:56:22 - 1.6 +++ uvm/uvmexp.h10 Dec 2020 13:31:01 - @@ -42,6 +42,7 @@ * * Locks used to protect struct members in this file: * I immutable after creation + * K kernel lock * F uvm_lock_fpageq */ struct uvmexp { @@ -79,9 +80,9 @@ struct uvmexp { /* swap */ int nswapdev; /* number of configured swap devices in system */ - int swpages;/* number of PAGE_SIZE'ed swap pages */ + int swpages;/* [K] number of PAGE_SIZE'ed swap pages */ int swpginuse; /* number of swap pages in use */ - int swpgonly; /* number of swap pages in use, not also in RAM */ + int swpgonly; /* [K] number of swap pages in use, not also in RAM */ int nswget; /* number of swap pages moved from disk to RAM */ int
Re: uvm_fault: entering swap code
On 08/12/20(Tue) 22:55, Jonathan Matthew wrote: > On Mon, Dec 07, 2020 at 03:15:50PM -0300, Martin Pieuchot wrote: > > Getting a page from the fault handler might require poking at some > > swap-related states. > > > > These are not in the hot-path of the fault handler so for the moment > > just assert that the KERNEL_LOCK() is held or grab it if the function > > might be called from an future unlocked path. > > > > ok? > > Could you add 'K' to the list of locks in the comment above struct uvmexp too? > > I went looking for other uses of swpgonly and saw that it's used under > uvm_map_teardown -> uvm_unmap_kill_entry -> uvm_km_pgremove, > and uvm_map_teardown ensures that the kernel lock is not held. > Not related to this diff exactly, but is this something we need to fix? Good catch! uvm_km_pgremove() is indeed not safe to be called w/o KERNEL_LOCK() but `swpgonly' is the minor of the problems :o) - uvm_pagelookup() iterates over `uvm_objtree' which as previously explained is sometimes protected by the "page queue lock" sometimes the KERNEL_LOCK(), here none is taken. Note that for the moment the KERNEL_LOCK prevails. - calling tsleep_nsec() after checking PG_BUSY without being executed under a lock is racy as the flag could be removed and a wakeup event lost between the two conditions. - uao_dropswap() is certainly not ready to be called w/o KERNEL_LOCK(). > > Index: uvm/uvm_swap.c > > === > > RCS file: /cvs/src/sys/uvm/uvm_swap.c,v > > retrieving revision 1.147 > > diff -u -p -r1.147 uvm_swap.c > > --- uvm/uvm_swap.c 29 Sep 2020 11:47:41 - 1.147 > > +++ uvm/uvm_swap.c 7 Dec 2020 18:07:03 - > > @@ -1403,7 +1403,7 @@ uvm_swap_alloc(int *nslots, boolean_t le > > /* > > * lock data lock, convert slots into blocks, and enter loop > > */ > > - > > + KERNEL_ASSERT_LOCKED(); > > ReTry: /* XXXMRG */ > > LIST_FOREACH(spp, _priority, spi_swappri) { > > TAILQ_FOREACH(sdp, >spi_swapdev, swd_next) { > > @@ -1449,8 +1449,10 @@ uvm_swapisfull(void) > > { > > int result; > > > > + KERNEL_LOCK(); > > KASSERT(uvmexp.swpgonly <= uvmexp.swpages); > > result = (uvmexp.swpgonly == uvmexp.swpages); > > + KERNEL_UNLOCK(); > > > > return result; > > } > > @@ -1465,6 +1467,7 @@ uvm_swap_markbad(int startslot, int nslo > > { > > struct swapdev *sdp; > > > > + KERNEL_LOCK(); > > sdp = swapdrum_getsdp(startslot); > > if (sdp != NULL) { > > /* > > @@ -1475,6 +1478,7 @@ uvm_swap_markbad(int startslot, int nslo > > */ > > sdp->swd_npgbad += nslots; > > } > > + KERNEL_UNLOCK(); > > } > > > > /* > > @@ -1501,7 +1505,7 @@ uvm_swap_free(int startslot, int nslots) > > * in the extent, and return. must hold pri lock to do > > * lookup and access the extent. > > */ > > - > > + KERNEL_LOCK(); > > sdp = swapdrum_getsdp(startslot); > > KASSERT(uvmexp.nswapdev >= 1); > > KASSERT(sdp != NULL); > > @@ -1533,6 +1537,7 @@ uvm_swap_free(int startslot, int nslots) > > } > > } > > #endif /* UVM_SWAP_ENCRYPT */ > > + KERNEL_UNLOCK(); > > } > > > > /* > > @@ -1567,6 +1572,7 @@ uvm_swap_get(struct vm_page *page, int s > > return VM_PAGER_ERROR; > > } > > > > + KERNEL_LOCK(); > > /* this page is (about to be) no longer only in swap. */ > > uvmexp.swpgonly--; > > > > @@ -1577,7 +1583,7 @@ uvm_swap_get(struct vm_page *page, int s > > /* oops, the read failed so it really is still only in swap. */ > > uvmexp.swpgonly++; > > } > > - > > + KERNEL_UNLOCK(); > > return (result); > > } > > > > @@ -1599,6 +1605,8 @@ uvm_swap_io(struct vm_page **pps, int st > > struct swapdev *sdp; > > int encrypt = 0; > > #endif > > + > > + KERNEL_ASSERT_LOCKED(); > > > > write = (flags & B_READ) == 0; > > async = (flags & B_ASYNC) != 0; > > Index: uvm/uvmexp.h > > === > > RCS file: /cvs/src/sys/uvm/uvmexp.h,v > > retrieving revision 1.6 > > diff -u -p -r1.6 uvmexp.h > > --- uvm/uvmexp.h1 Dec 2020 13:56:22 - 1.6 > > +++ uvm/uvmexp.h7 Dec 2020 18:09:06 - > > @@ -79,9 +79,9 @@ struct uvmexp { > > > > /* swap */ > > int nswapdev; /* number of configured swap devices in system */ > > - int swpages;/* number of PAGE_SIZE'ed swap pages */ > > + int swpages;/* [K] number of PAGE_SIZE'ed swap pages */ > > int swpginuse; /* number of swap pages in use */ > > - int swpgonly; /* number of swap pages in use, not also in RAM */ > > + int swpgonly; /* [K] number of swap pages in use, not also in RAM */ > > int nswget; /* number of swap pages moved from disk to RAM */ > > int nanon; /* XXX number total of anon's in system */ > > int unused05; /* formerly nanonneeded */ >
Re: uvm_fault: entering swap code
On Mon, Dec 07, 2020 at 03:15:50PM -0300, Martin Pieuchot wrote: > Getting a page from the fault handler might require poking at some > swap-related states. > > These are not in the hot-path of the fault handler so for the moment > just assert that the KERNEL_LOCK() is held or grab it if the function > might be called from an future unlocked path. > > ok? Could you add 'K' to the list of locks in the comment above struct uvmexp too? I went looking for other uses of swpgonly and saw that it's used under uvm_map_teardown -> uvm_unmap_kill_entry -> uvm_km_pgremove, and uvm_map_teardown ensures that the kernel lock is not held. Not related to this diff exactly, but is this something we need to fix? > > Index: uvm/uvm_swap.c > === > RCS file: /cvs/src/sys/uvm/uvm_swap.c,v > retrieving revision 1.147 > diff -u -p -r1.147 uvm_swap.c > --- uvm/uvm_swap.c29 Sep 2020 11:47:41 - 1.147 > +++ uvm/uvm_swap.c7 Dec 2020 18:07:03 - > @@ -1403,7 +1403,7 @@ uvm_swap_alloc(int *nslots, boolean_t le > /* >* lock data lock, convert slots into blocks, and enter loop >*/ > - > + KERNEL_ASSERT_LOCKED(); > ReTry: /* XXXMRG */ > LIST_FOREACH(spp, _priority, spi_swappri) { > TAILQ_FOREACH(sdp, >spi_swapdev, swd_next) { > @@ -1449,8 +1449,10 @@ uvm_swapisfull(void) > { > int result; > > + KERNEL_LOCK(); > KASSERT(uvmexp.swpgonly <= uvmexp.swpages); > result = (uvmexp.swpgonly == uvmexp.swpages); > + KERNEL_UNLOCK(); > > return result; > } > @@ -1465,6 +1467,7 @@ uvm_swap_markbad(int startslot, int nslo > { > struct swapdev *sdp; > > + KERNEL_LOCK(); > sdp = swapdrum_getsdp(startslot); > if (sdp != NULL) { > /* > @@ -1475,6 +1478,7 @@ uvm_swap_markbad(int startslot, int nslo >*/ > sdp->swd_npgbad += nslots; > } > + KERNEL_UNLOCK(); > } > > /* > @@ -1501,7 +1505,7 @@ uvm_swap_free(int startslot, int nslots) >* in the extent, and return. must hold pri lock to do >* lookup and access the extent. >*/ > - > + KERNEL_LOCK(); > sdp = swapdrum_getsdp(startslot); > KASSERT(uvmexp.nswapdev >= 1); > KASSERT(sdp != NULL); > @@ -1533,6 +1537,7 @@ uvm_swap_free(int startslot, int nslots) > } > } > #endif /* UVM_SWAP_ENCRYPT */ > + KERNEL_UNLOCK(); > } > > /* > @@ -1567,6 +1572,7 @@ uvm_swap_get(struct vm_page *page, int s > return VM_PAGER_ERROR; > } > > + KERNEL_LOCK(); > /* this page is (about to be) no longer only in swap. */ > uvmexp.swpgonly--; > > @@ -1577,7 +1583,7 @@ uvm_swap_get(struct vm_page *page, int s > /* oops, the read failed so it really is still only in swap. */ > uvmexp.swpgonly++; > } > - > + KERNEL_UNLOCK(); > return (result); > } > > @@ -1599,6 +1605,8 @@ uvm_swap_io(struct vm_page **pps, int st > struct swapdev *sdp; > int encrypt = 0; > #endif > + > + KERNEL_ASSERT_LOCKED(); > > write = (flags & B_READ) == 0; > async = (flags & B_ASYNC) != 0; > Index: uvm/uvmexp.h > === > RCS file: /cvs/src/sys/uvm/uvmexp.h,v > retrieving revision 1.6 > diff -u -p -r1.6 uvmexp.h > --- uvm/uvmexp.h 1 Dec 2020 13:56:22 - 1.6 > +++ uvm/uvmexp.h 7 Dec 2020 18:09:06 - > @@ -79,9 +79,9 @@ struct uvmexp { > > /* swap */ > int nswapdev; /* number of configured swap devices in system */ > - int swpages;/* number of PAGE_SIZE'ed swap pages */ > + int swpages;/* [K] number of PAGE_SIZE'ed swap pages */ > int swpginuse; /* number of swap pages in use */ > - int swpgonly; /* number of swap pages in use, not also in RAM */ > + int swpgonly; /* [K] number of swap pages in use, not also in RAM */ > int nswget; /* number of swap pages moved from disk to RAM */ > int nanon; /* XXX number total of anon's in system */ > int unused05; /* formerly nanonneeded */ >
uvm_fault: entering swap code
Getting a page from the fault handler might require poking at some swap-related states. These are not in the hot-path of the fault handler so for the moment just assert that the KERNEL_LOCK() is held or grab it if the function might be called from an future unlocked path. ok? Index: uvm/uvm_swap.c === RCS file: /cvs/src/sys/uvm/uvm_swap.c,v retrieving revision 1.147 diff -u -p -r1.147 uvm_swap.c --- uvm/uvm_swap.c 29 Sep 2020 11:47:41 - 1.147 +++ uvm/uvm_swap.c 7 Dec 2020 18:07:03 - @@ -1403,7 +1403,7 @@ uvm_swap_alloc(int *nslots, boolean_t le /* * lock data lock, convert slots into blocks, and enter loop */ - + KERNEL_ASSERT_LOCKED(); ReTry: /* XXXMRG */ LIST_FOREACH(spp, _priority, spi_swappri) { TAILQ_FOREACH(sdp, >spi_swapdev, swd_next) { @@ -1449,8 +1449,10 @@ uvm_swapisfull(void) { int result; + KERNEL_LOCK(); KASSERT(uvmexp.swpgonly <= uvmexp.swpages); result = (uvmexp.swpgonly == uvmexp.swpages); + KERNEL_UNLOCK(); return result; } @@ -1465,6 +1467,7 @@ uvm_swap_markbad(int startslot, int nslo { struct swapdev *sdp; + KERNEL_LOCK(); sdp = swapdrum_getsdp(startslot); if (sdp != NULL) { /* @@ -1475,6 +1478,7 @@ uvm_swap_markbad(int startslot, int nslo */ sdp->swd_npgbad += nslots; } + KERNEL_UNLOCK(); } /* @@ -1501,7 +1505,7 @@ uvm_swap_free(int startslot, int nslots) * in the extent, and return. must hold pri lock to do * lookup and access the extent. */ - + KERNEL_LOCK(); sdp = swapdrum_getsdp(startslot); KASSERT(uvmexp.nswapdev >= 1); KASSERT(sdp != NULL); @@ -1533,6 +1537,7 @@ uvm_swap_free(int startslot, int nslots) } } #endif /* UVM_SWAP_ENCRYPT */ + KERNEL_UNLOCK(); } /* @@ -1567,6 +1572,7 @@ uvm_swap_get(struct vm_page *page, int s return VM_PAGER_ERROR; } + KERNEL_LOCK(); /* this page is (about to be) no longer only in swap. */ uvmexp.swpgonly--; @@ -1577,7 +1583,7 @@ uvm_swap_get(struct vm_page *page, int s /* oops, the read failed so it really is still only in swap. */ uvmexp.swpgonly++; } - + KERNEL_UNLOCK(); return (result); } @@ -1599,6 +1605,8 @@ uvm_swap_io(struct vm_page **pps, int st struct swapdev *sdp; int encrypt = 0; #endif + + KERNEL_ASSERT_LOCKED(); write = (flags & B_READ) == 0; async = (flags & B_ASYNC) != 0; Index: uvm/uvmexp.h === RCS file: /cvs/src/sys/uvm/uvmexp.h,v retrieving revision 1.6 diff -u -p -r1.6 uvmexp.h --- uvm/uvmexp.h1 Dec 2020 13:56:22 - 1.6 +++ uvm/uvmexp.h7 Dec 2020 18:09:06 - @@ -79,9 +79,9 @@ struct uvmexp { /* swap */ int nswapdev; /* number of configured swap devices in system */ - int swpages;/* number of PAGE_SIZE'ed swap pages */ + int swpages;/* [K] number of PAGE_SIZE'ed swap pages */ int swpginuse; /* number of swap pages in use */ - int swpgonly; /* number of swap pages in use, not also in RAM */ + int swpgonly; /* [K] number of swap pages in use, not also in RAM */ int nswget; /* number of swap pages moved from disk to RAM */ int nanon; /* XXX number total of anon's in system */ int unused05; /* formerly nanonneeded */