On Wed, 2019-11-06 at 10:14 -0500, Josef Bacik wrote: > On Wed, Nov 06, 2019 at 04:05:24PM +0100, Jan Kara wrote: > > On Wed 06-11-19 09:56:09, Josef Bacik wrote: > > I don't think this will work. AFAICS faultin_page() just checks > > whether > > 'nonblocking' is != NULL but doesn't ever look at its value... > > Honestly the > > whole interface is rather weird like lots of things around gup(). > > > > Oh what the hell, yeah this is super bonkers. The whole fault path > probably > should be cleaned up to handle retry better. This will do the trick > I think? I tried the patch, and it seems to fix the `mlockall(MCL_CURRENT)` issue for "my test.c". However, shutdown & reboot are still broken - i.e. the console says "Reached target reboot" and "hangs forever". Shutdown & reboot work with __get_user_pages_locked(). No clue what the difference there is. Anyway, I've captured three smaps outputs: from 5.0.21, from 5.3.9+"nonblocking patch", from 5.3.9+"__get_user_pages_locked". All three look okay to me - although I don't completely understand why some areas are not locked (-> "Locked: 0kB") - but "Locked" is always equal to "Pss", so I assume that's fine? > > Josef > > diff --git a/mm/gup.c b/mm/gup.c > index 8f236a335ae9..2468789298e6 100644 > --- a/mm/gup.c > +++ b/mm/gup.c > @@ -628,7 +628,7 @@ static int faultin_page(struct task_struct *tsk, > struct vm_area_struct *vma, > fault_flags |= FAULT_FLAG_WRITE; > if (*flags & FOLL_REMOTE) > fault_flags |= FAULT_FLAG_REMOTE; > - if (nonblocking) > + if (nonblocking && *nonblocking != 0) > fault_flags |= FAULT_FLAG_ALLOW_RETRY; > if (*flags & FOLL_NOWAIT) > fault_flags |= FAULT_FLAG_ALLOW_RETRY | > FAULT_FLAG_RETRY_NOWAIT; > @@ -1237,6 +1237,7 @@ int __mm_populate(unsigned long start, unsigned > long len, int ignore_errors) > unsigned long end, nstart, nend; > struct vm_area_struct *vma = NULL; > int locked = 0; > + int nonblocking = 1; > long ret = 0; > > end = start + len; > @@ -1268,7 +1269,7 @@ int __mm_populate(unsigned long start, unsigned > long len, int ignore_errors) > * double checks the vma flags, so that it won't mlock > pages > * if the vma was already munlocked. > */ > - ret = populate_vma_page_range(vma, nstart, nend, > &locked); > + ret = populate_vma_page_range(vma, nstart, nend, > &nonblocking); > if (ret < 0) { > if (ignore_errors) { > ret = 0; > @@ -1276,6 +1277,14 @@ int __mm_populate(unsigned long start, > unsigned long len, int ignore_errors) > } > break; > } > + > + /* > + * We dropped the mmap_sem, so we need to re-lock, and > the next > + * loop around we won't drop because nonblocking is now > 0. > + */ > + if (!nonblocking) > + locked = 0; > + > nend = nstart + ret * PAGE_SIZE; > ret = 0; > }
Attachment:
smaps-5.0.21.txt.gz
Description: application/gzip
Attachment:
smaps-add-nonblocking.txt.gz
Description: application/gzip
Attachment:
smaps-get_user_pages_locked.txt.gz
Description: application/gzip