Skip to content

Commit c862722

Browse files
mjkravetzakpm00
authored andcommitted
hugetlb: create remove_inode_single_folio to remove single file folio
Create the new routine remove_inode_single_folio that will remove a single folio from a file. This is refactored code from remove_inode_hugepages. It checks for the uncommon case in which the folio is still mapped and unmaps. No functional change. This refactoring will be put to use and expanded upon in a subsequent patches. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Mike Kravetz <[email protected]> Reviewed-by: Miaohe Lin <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: "Aneesh Kumar K.V" <[email protected]> Cc: Axel Rasmussen <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Davidlohr Bueso <[email protected]> Cc: James Houghton <[email protected]> Cc: "Kirill A. Shutemov" <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Mina Almasry <[email protected]> Cc: Muchun Song <[email protected]> Cc: Naoya Horiguchi <[email protected]> Cc: Pasha Tatashin <[email protected]> Cc: Peter Xu <[email protected]> Cc: Prakash Sangappa <[email protected]> Cc: Sven Schnelle <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 7e1813d commit c862722

File tree

1 file changed

+63
-42
lines changed

1 file changed

+63
-42
lines changed

fs/hugetlbfs/inode.c

Lines changed: 63 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -411,18 +411,71 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end,
411411
}
412412
}
413413

414+
/*
415+
* Called with hugetlb fault mutex held.
416+
* Returns true if page was actually removed, false otherwise.
417+
*/
418+
static bool remove_inode_single_folio(struct hstate *h, struct inode *inode,
419+
struct address_space *mapping,
420+
struct folio *folio, pgoff_t index,
421+
bool truncate_op)
422+
{
423+
bool ret = false;
424+
425+
/*
426+
* If folio is mapped, it was faulted in after being
427+
* unmapped in caller. Unmap (again) while holding
428+
* the fault mutex. The mutex will prevent faults
429+
* until we finish removing the folio.
430+
*/
431+
if (unlikely(folio_mapped(folio))) {
432+
i_mmap_lock_write(mapping);
433+
hugetlb_vmdelete_list(&mapping->i_mmap,
434+
index * pages_per_huge_page(h),
435+
(index + 1) * pages_per_huge_page(h),
436+
ZAP_FLAG_DROP_MARKER);
437+
i_mmap_unlock_write(mapping);
438+
}
439+
440+
folio_lock(folio);
441+
/*
442+
* After locking page, make sure mapping is the same.
443+
* We could have raced with page fault populate and
444+
* backout code.
445+
*/
446+
if (folio_mapping(folio) == mapping) {
447+
/*
448+
* We must remove the folio from page cache before removing
449+
* the region/ reserve map (hugetlb_unreserve_pages). In
450+
* rare out of memory conditions, removal of the region/reserve
451+
* map could fail. Correspondingly, the subpool and global
452+
* reserve usage count can need to be adjusted.
453+
*/
454+
VM_BUG_ON(HPageRestoreReserve(&folio->page));
455+
hugetlb_delete_from_page_cache(&folio->page);
456+
ret = true;
457+
if (!truncate_op) {
458+
if (unlikely(hugetlb_unreserve_pages(inode, index,
459+
index + 1, 1)))
460+
hugetlb_fix_reserve_counts(inode);
461+
}
462+
}
463+
464+
folio_unlock(folio);
465+
return ret;
466+
}
467+
414468
/*
415469
* remove_inode_hugepages handles two distinct cases: truncation and hole
416470
* punch. There are subtle differences in operation for each case.
417471
*
418472
* truncation is indicated by end of range being LLONG_MAX
419473
* In this case, we first scan the range and release found pages.
420474
* After releasing pages, hugetlb_unreserve_pages cleans up region/reserve
421-
* maps and global counts. Page faults can not race with truncation
422-
* in this routine. hugetlb_no_page() prevents page faults in the
423-
* truncated range. It checks i_size before allocation, and again after
424-
* with the page table lock for the page held. The same lock must be
425-
* acquired to unmap a page.
475+
* maps and global counts. Page faults can race with truncation.
476+
* During faults, hugetlb_no_page() checks i_size before page allocation,
477+
* and again after obtaining page table lock. It will 'back out'
478+
* allocations in the truncated range.
426479
* hole punch is indicated if end is not LLONG_MAX
427480
* In the hole punch case we scan the range and release found pages.
428481
* Only when releasing a page is the associated region/reserve map
@@ -456,44 +509,12 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
456509
mutex_lock(&hugetlb_fault_mutex_table[hash]);
457510

458511
/*
459-
* If folio is mapped, it was faulted in after being
460-
* unmapped in caller. Unmap (again) now after taking
461-
* the fault mutex. The mutex will prevent faults
462-
* until we finish removing the folio.
463-
*
464-
* This race can only happen in the hole punch case.
465-
* Getting here in a truncate operation is a bug.
512+
* Remove folio that was part of folio_batch.
466513
*/
467-
if (unlikely(folio_mapped(folio))) {
468-
BUG_ON(truncate_op);
469-
470-
i_mmap_lock_write(mapping);
471-
hugetlb_vmdelete_list(&mapping->i_mmap,
472-
index * pages_per_huge_page(h),
473-
(index + 1) * pages_per_huge_page(h),
474-
ZAP_FLAG_DROP_MARKER);
475-
i_mmap_unlock_write(mapping);
476-
}
477-
478-
folio_lock(folio);
479-
/*
480-
* We must free the huge page and remove from page
481-
* cache BEFORE removing the region/reserve map
482-
* (hugetlb_unreserve_pages). In rare out of memory
483-
* conditions, removal of the region/reserve map could
484-
* fail. Correspondingly, the subpool and global
485-
* reserve usage count can need to be adjusted.
486-
*/
487-
VM_BUG_ON(HPageRestoreReserve(&folio->page));
488-
hugetlb_delete_from_page_cache(&folio->page);
489-
freed++;
490-
if (!truncate_op) {
491-
if (unlikely(hugetlb_unreserve_pages(inode,
492-
index, index + 1, 1)))
493-
hugetlb_fix_reserve_counts(inode);
494-
}
495-
496-
folio_unlock(folio);
514+
if (remove_inode_single_folio(h, inode, mapping, folio,
515+
index, truncate_op))
516+
freed++;
517+
497518
mutex_unlock(&hugetlb_fault_mutex_table[hash]);
498519
}
499520
folio_batch_release(&fbatch);

0 commit comments

Comments
 (0)