The functionality and implementation of adjust_range_hwpoison() is generic, so factor it out and make it ready for generic use. [1] https://lore.kernel.org/linux-mm/aeZwAz6PcdlqSnJ2@casper.infradead.org/ Suggested-by: Matthew Wilcox Signed-off-by: Jane Chu --- fs/hugetlbfs/inode.c | 25 ------------------------- include/linux/fs.h | 2 ++ include/linux/hugetlb.h | 5 ----- mm/filemap.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 30 deletions(-) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 66520f7c53c6..f1f8c3f7388f 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -187,31 +187,6 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, return mm_get_unmapped_area_vmflags(file, addr0, len, pgoff, flags, 0); } -/* - * Someone wants to read @bytes from a HWPOISON hugetlb @folio from @offset. - * Returns the maximum number of bytes one can read without touching the 1st raw - * HWPOISON page. - */ -static size_t adjust_range_hwpoison(struct folio *folio, size_t offset, - size_t bytes) -{ - struct page *page = folio_page(folio, offset / PAGE_SIZE); - size_t safe_bytes; - - if (is_raw_hwpoison_page_in_folio(page)) - return 0; - /* Safe to read the remaining bytes in this page. */ - safe_bytes = PAGE_SIZE - (offset % PAGE_SIZE); - page++; - - /* Check each remaining page as long as we are not done yet. */ - for (; safe_bytes < bytes; safe_bytes += PAGE_SIZE, page++) - if (is_raw_hwpoison_page_in_folio(page)) - break; - - return min(safe_bytes, bytes); -} - /* * Support for read() - Find the page attached to f_mapping and copy out the * data. This provides functionality similar to filemap_read(). diff --git a/include/linux/fs.h b/include/linux/fs.h index 11559c513dfb..3876d5beda58 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3052,6 +3052,8 @@ int generic_write_checks_count(struct kiocb *iocb, loff_t *count); extern int generic_write_check_limits(struct file *file, loff_t pos, loff_t *count); extern int generic_file_rw_checks(struct file *file_in, struct file *file_out); +bool is_raw_hwpoison_page_in_folio(struct page *page); +size_t adjust_range_hwpoison(struct folio *folio, size_t offset, size_t bytes); ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *to, ssize_t already_read); extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index a9846f043712..218284e80451 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -1078,11 +1078,6 @@ void hugetlb_register_node(struct node *node); void hugetlb_unregister_node(struct node *node); #endif -/* - * Check if a given raw @page is HWPOISON in a folio of any kind - */ -bool is_raw_hwpoison_page_in_folio(struct page *page); - static inline unsigned long huge_page_mask_align(struct file *file) { return PAGE_MASK & ~huge_page_mask(hstate_file(file)); diff --git a/mm/filemap.c b/mm/filemap.c index 4e636647100c..a27ce4ad6247 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2753,6 +2753,37 @@ static void filemap_end_dropbehind_read(struct folio *folio) } } +/** + * adjust_range_hwpoison - adjust clean readable range to avoid hwpoison. + * @folio: folio that contains hwpoison(s). + * @offset: bytes into the folio where subsequent read starts. + * @bytes: number of bytes wish to read. + * + * Return: adjusted total number of bytes starting off @offset that can be + * safely read from the @folio. + */ +size_t adjust_range_hwpoison(struct folio *folio, size_t offset, + size_t bytes) +{ + struct page *page = folio_page(folio, offset / PAGE_SIZE); + size_t safe_bytes; + + if (is_raw_hwpoison_page_in_folio(page)) + return 0; + + /* Safe to read the remaining bytes in this page. */ + safe_bytes = PAGE_SIZE - (offset % PAGE_SIZE); + page++; + + /* Check each remaining page as long as we are not done yet. */ + for (; safe_bytes < bytes; safe_bytes += PAGE_SIZE, page++) + if (is_raw_hwpoison_page_in_folio(page)) + break; + + return min(safe_bytes, bytes); +} +EXPORT_SYMBOL_GPL(adjust_range_hwpoison); + /** * filemap_read - Read data from the page cache. * @iocb: The iocb to read. -- 2.43.5