On Mon, Aug 30, 2021 at 10:45:47AM +0200, Martin Pieuchot wrote:
> On 06/08/21(Fri) 08:08, Theo Buehler wrote:
> > > The diff below fixes this by setting the "source" amap lock to the newly
> > > allocated one.  This is not strictly necessary on OpenBSD since the amap
> > > is only inserted on the global list at the end of amap copy, but this
> > > satisfies the locking requirement of amap_wipeout() and is IMHO the
> > > simplest solution.  This has also the advantage of reducing the
> > > differences with NetBSD.
> > 
> > This diff causes a reproducible hang with mount_mfs(8) on my laptop. I
> > use an mfs noperm partition as described in
> > https://www.openbsd.org/faq/faq5.html#Release
> > 
> > $ tail -1 /etc/fstab
> > swap /dest mfs rw,nosuid,noperm,-P/var/dest,-s1.5G,noauto 0 0
> > 
> > If I run 'top -S -s.1' on an otherwise idle system and do 'mount /dest',
> > I see two mount_mfs(8) processes spin in fltamap and the pagedaemon is
> > spinning in pgdaemon before the system locks up completely (this takes
> > something between 1 and 20 seconds to happen).
> 
> I couldn't reproduce this hang here.  Do you also see it with the
> smaller fix below?

This appears to work fine. I can't reproduce the problem with this diff
across a few reboots.

The issue remains perfectly reproducible with the first version of the
diff, so if you want to poke at it, we can...

> 
> Index: uvm/uvm_amap.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_amap.c,v
> retrieving revision 1.89
> diff -u -p -r1.89 uvm_amap.c
> --- uvm/uvm_amap.c    26 Mar 2021 13:40:05 -0000      1.89
> +++ uvm/uvm_amap.c    30 Aug 2021 08:31:21 -0000
> @@ -618,6 +618,13 @@ amap_copy(struct vm_map *map, struct vm_
>               return;
>       srcamap = entry->aref.ar_amap;
>  
> +     /*
> +      * Make the new amap share the source amap's lock, and then lock
> +      * both.
> +      */
> +     amap->am_lock = srcamap->am_lock;
> +     rw_obj_hold(amap->am_lock);
> +
>       amap_lock(srcamap);
>  
>       /*
> @@ -655,7 +662,7 @@ amap_copy(struct vm_map *map, struct vm_
>  
>               chunk = amap_chunk_get(amap, lcv, 1, PR_NOWAIT);
>               if (chunk == NULL) {
> -                     amap_unlock(srcamap);
> +                     /* amap_wipeout() releases the lock. */
>                       amap->am_ref = 0;
>                       amap_wipeout(amap);
>                       return;
> @@ -695,10 +702,10 @@ amap_copy(struct vm_map *map, struct vm_
>        * If we referenced any anons, then share the source amap's lock.
>        * Otherwise, we have nothing in common, so allocate a new one.
>        */
> -     KASSERT(amap->am_lock == NULL);
> -     if (amap->am_nused != 0) {
> -             amap->am_lock = srcamap->am_lock;
> -             rw_obj_hold(amap->am_lock);
> +     KASSERT(amap->am_lock == srcamap->am_lock);
> +     if (amap->am_nused == 0) {
> +             rw_obj_free(amap->am_lock);
> +             amap->am_lock = NULL;
>       }
>       amap_unlock(srcamap);
>  

Reply via email to