[05/31] mm/filemap: allow pte_offset_map_lock() to fail

Message ID 3e6d4f8-9f4d-fa7e-304e-1494dddd45b@google.com
State New
Headers
Series mm: allow pte_offset_map[_lock]() to fail |

Commit Message

Hugh Dickins May 22, 2023, 4:54 a.m. UTC
  filemap_map_pages() allow pte_offset_map_lock() to fail; and remove the
pmd_devmap_trans_unstable() check from filemap_map_pmd(), which can safely
return to filemap_map_pages() and let pte_offset_map_lock() discover that.

Signed-off-by: Hugh Dickins <hughd@google.com>
---
 mm/filemap.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)
  

Comments

Qi Zheng May 22, 2023, 11:23 a.m. UTC | #1
On 2023/5/22 12:54, Hugh Dickins wrote:
> filemap_map_pages() allow pte_offset_map_lock() to fail; and remove the
> pmd_devmap_trans_unstable() check from filemap_map_pmd(), which can safely
> return to filemap_map_pages() and let pte_offset_map_lock() discover that.
> 
> Signed-off-by: Hugh Dickins <hughd@google.com>
> ---
>   mm/filemap.c | 12 +++++-------
>   1 file changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 28b42ee848a4..9e129ad43e0d 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -3408,13 +3408,6 @@ static bool filemap_map_pmd(struct vm_fault *vmf, struct folio *folio,
>   	if (pmd_none(*vmf->pmd))
>   		pmd_install(mm, vmf->pmd, &vmf->prealloc_pte);
>   
> -	/* See comment in handle_pte_fault() */
> -	if (pmd_devmap_trans_unstable(vmf->pmd)) {
> -		folio_unlock(folio);
> -		folio_put(folio);
> -		return true;
> -	}
> -
>   	return false;
>   }
>   
> @@ -3501,6 +3494,11 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
>   
>   	addr = vma->vm_start + ((start_pgoff - vma->vm_pgoff) << PAGE_SHIFT);
>   	vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, addr, &vmf->ptl);
> +	if (!vmf->pte) {
> +		folio_unlock(folio);
> +		folio_put(folio);

Missing:
		ret = VM_FAULT_NOPAGE;
?

> +		goto out;
> +	}
>   	do {
>   again:
>   		page = folio_file_page(folio, xas.xa_index);
  
Hugh Dickins May 24, 2023, 2:35 a.m. UTC | #2
On Mon, 22 May 2023, Qi Zheng wrote:
> On 2023/5/22 12:54, Hugh Dickins wrote:
> > filemap_map_pages() allow pte_offset_map_lock() to fail; and remove the
> > pmd_devmap_trans_unstable() check from filemap_map_pmd(), which can safely
> > return to filemap_map_pages() and let pte_offset_map_lock() discover that.
> > 
> > Signed-off-by: Hugh Dickins <hughd@google.com>
> > ---
> >   mm/filemap.c | 12 +++++-------
> >   1 file changed, 5 insertions(+), 7 deletions(-)
> > 
> > diff --git a/mm/filemap.c b/mm/filemap.c
> > index 28b42ee848a4..9e129ad43e0d 100644
> > --- a/mm/filemap.c
> > +++ b/mm/filemap.c
> > @@ -3408,13 +3408,6 @@ static bool filemap_map_pmd(struct vm_fault *vmf,
> > struct folio *folio,
> >    if (pmd_none(*vmf->pmd))
> >     pmd_install(mm, vmf->pmd, &vmf->prealloc_pte);
> >   -	/* See comment in handle_pte_fault() */
> > -	if (pmd_devmap_trans_unstable(vmf->pmd)) {
> > -		folio_unlock(folio);
> > -		folio_put(folio);
> > -		return true;
> > -	}
> > -
> >   	return false;
> >   }
> >   
> > @@ -3501,6 +3494,11 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
> >   
> >    addr = vma->vm_start + ((start_pgoff - vma->vm_pgoff) << PAGE_SHIFT);
> >    vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, addr, &vmf->ptl);
> > +	if (!vmf->pte) {
> > +		folio_unlock(folio);
> > +		folio_put(folio);
> 
> Missing:
> 		ret = VM_FAULT_NOPAGE;
> ?

No, not missed.  Here ret is 0, which leads do_read_fault() to try
__do_fault() afterwards.  Whereas VM_FAULT_NOPAGE would send it back
to userspace to retry the whole fault.  Either will work, but I think
the intention of VM_FAULT_NOPAGE here in filemap_map_pages() is to say
"the page you want is now inserted", which is probably not the case.

Hugh
  
Qi Zheng May 24, 2023, 3:14 a.m. UTC | #3
On 2023/5/24 10:35, Hugh Dickins wrote:
> On Mon, 22 May 2023, Qi Zheng wrote:
>> On 2023/5/22 12:54, Hugh Dickins wrote:
>>> filemap_map_pages() allow pte_offset_map_lock() to fail; and remove the
>>> pmd_devmap_trans_unstable() check from filemap_map_pmd(), which can safely
>>> return to filemap_map_pages() and let pte_offset_map_lock() discover that.
>>>
>>> Signed-off-by: Hugh Dickins <hughd@google.com>
>>> ---
>>>    mm/filemap.c | 12 +++++-------
>>>    1 file changed, 5 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/mm/filemap.c b/mm/filemap.c
>>> index 28b42ee848a4..9e129ad43e0d 100644
>>> --- a/mm/filemap.c
>>> +++ b/mm/filemap.c
>>> @@ -3408,13 +3408,6 @@ static bool filemap_map_pmd(struct vm_fault *vmf,
>>> struct folio *folio,
>>>     if (pmd_none(*vmf->pmd))
>>>      pmd_install(mm, vmf->pmd, &vmf->prealloc_pte);
>>>    -	/* See comment in handle_pte_fault() */
>>> -	if (pmd_devmap_trans_unstable(vmf->pmd)) {
>>> -		folio_unlock(folio);
>>> -		folio_put(folio);
>>> -		return true;
>>> -	}
>>> -
>>>    	return false;
>>>    }
>>>    
>>> @@ -3501,6 +3494,11 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
>>>    
>>>     addr = vma->vm_start + ((start_pgoff - vma->vm_pgoff) << PAGE_SHIFT);
>>>     vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, addr, &vmf->ptl);
>>> +	if (!vmf->pte) {
>>> +		folio_unlock(folio);
>>> +		folio_put(folio);
>>
>> Missing:
>> 		ret = VM_FAULT_NOPAGE;
>> ?
> 
> No, not missed.  Here ret is 0, which leads do_read_fault() to try
> __do_fault() afterwards.  Whereas VM_FAULT_NOPAGE would send it back
> to userspace to retry the whole fault.  Either will work, but I think
> the intention of VM_FAULT_NOPAGE here in filemap_map_pages() is to say
> "the page you want is now inserted", which is probably not the case.

Got it. Thanks for the explanation.

> 
> Hugh
  

Patch

diff --git a/mm/filemap.c b/mm/filemap.c
index 28b42ee848a4..9e129ad43e0d 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -3408,13 +3408,6 @@  static bool filemap_map_pmd(struct vm_fault *vmf, struct folio *folio,
 	if (pmd_none(*vmf->pmd))
 		pmd_install(mm, vmf->pmd, &vmf->prealloc_pte);
 
-	/* See comment in handle_pte_fault() */
-	if (pmd_devmap_trans_unstable(vmf->pmd)) {
-		folio_unlock(folio);
-		folio_put(folio);
-		return true;
-	}
-
 	return false;
 }
 
@@ -3501,6 +3494,11 @@  vm_fault_t filemap_map_pages(struct vm_fault *vmf,
 
 	addr = vma->vm_start + ((start_pgoff - vma->vm_pgoff) << PAGE_SHIFT);
 	vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, addr, &vmf->ptl);
+	if (!vmf->pte) {
+		folio_unlock(folio);
+		folio_put(folio);
+		goto out;
+	}
 	do {
 again:
 		page = folio_file_page(folio, xas.xa_index);