On Thu, Jun 08, 2023 at 05:51:57PM -0700, Suren Baghdasaryan wrote: > static inline bool folio_lock_or_retry(struct folio *folio, > - struct mm_struct *mm, unsigned int flags) > + struct vm_area_struct *vma, unsigned int flags, > + bool *lock_dropped) I hate these double-return-value functions. How about this for an API: vm_fault_t folio_lock_fault(struct folio *folio, struct vm_fault *vmf) { might_sleep(); if (folio_trylock(folio)) return 0; return __folio_lock_fault(folio, vmf); } Then the users look like ... > @@ -3580,8 +3581,10 @@ static vm_fault_t remove_device_exclusive_entry(struct vm_fault *vmf) > if (!folio_try_get(folio)) > return 0; > > - if (!folio_lock_or_retry(folio, vma->vm_mm, vmf->flags)) { > + if (!folio_lock_or_retry(folio, vma, vmf->flags, &lock_dropped)) { > folio_put(folio); > + if (lock_dropped && vmf->flags & FAULT_FLAG_VMA_LOCK) > + return VM_FAULT_VMA_UNLOCKED | VM_FAULT_RETRY; > return VM_FAULT_RETRY; > } ret = folio_lock_fault(folio, vmf); if (ret) return ret; > @@ -3837,9 +3840,9 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) > goto out_release; > } > > - locked = folio_lock_or_retry(folio, vma->vm_mm, vmf->flags); > - > - if (!locked) { > + if (!folio_lock_or_retry(folio, vma, vmf->flags, &lock_dropped)) { > + if (lock_dropped && vmf->flags & FAULT_FLAG_VMA_LOCK) > + ret |= VM_FAULT_VMA_UNLOCKED; > ret |= VM_FAULT_RETRY; > goto out_release; > } ret |= folio_lock_fault(folio, vmf); if (ret & VM_FAULT_RETRY) goto out_release; ie instead of trying to reconstruct what __folio_lock_fault() did from its outputs, we just let folio_lock_fault() tell us what it did.