| From: Mark Tinguely <mark.tinguely@oracle.com> |
| Subject: ocfs2: use an array of folios instead of an array of pages |
| Date: Thu, 5 Dec 2024 17:16:44 +0000 |
| |
| The ocfs2_zero_cluster_folios() / ocfs2_grab_folios() / |
| ocfs2_grab_eof_folios() family of functions pass around an array of pages. |
| Convert them to pass around an array of folios. This removes the last |
| caller of ocfs2_unlock_and_free_pages(), so delete it. |
| |
| Link: https://lkml.kernel.org/r/20241205171653.3179945-17-willy@infradead.org |
| Signed-off-by: Mark Tinguely <mark.tinguely@oracle.com> |
| Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> |
| Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com> |
| Cc: Changwei Ge <gechangwei@live.cn> |
| Cc: Joel Becker <jlbec@evilplan.org> |
| Cc: Jun Piao <piaojun@huawei.com> |
| Cc: Junxiao Bi <junxiao.bi@oracle.com> |
| Cc: Mark Fasheh <mark@fasheh.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| fs/ocfs2/alloc.c | 98 ++++++++++++++++++++++----------------------- |
| fs/ocfs2/alloc.h | 2 |
| fs/ocfs2/aops.c | 13 ----- |
| fs/ocfs2/aops.h | 1 |
| 4 files changed, 49 insertions(+), 65 deletions(-) |
| |
| --- a/fs/ocfs2/alloc.c~ocfs2-use-an-array-of-folios-instead-of-an-array-of-pages |
| +++ a/fs/ocfs2/alloc.c |
| @@ -6847,87 +6847,87 @@ void ocfs2_map_and_dirty_page(struct ino |
| flush_dcache_folio(folio); |
| } |
| |
| -static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start, |
| - loff_t end, struct page **pages, |
| - int numpages, u64 phys, handle_t *handle) |
| +static void ocfs2_zero_cluster_folios(struct inode *inode, loff_t start, |
| + loff_t end, struct folio **folios, int numfolios, |
| + u64 phys, handle_t *handle) |
| { |
| int i; |
| - struct page *page; |
| unsigned int from, to = PAGE_SIZE; |
| struct super_block *sb = inode->i_sb; |
| |
| BUG_ON(!ocfs2_sparse_alloc(OCFS2_SB(sb))); |
| |
| - if (numpages == 0) |
| + if (numfolios == 0) |
| goto out; |
| |
| to = PAGE_SIZE; |
| - for(i = 0; i < numpages; i++) { |
| - page = pages[i]; |
| + for (i = 0; i < numfolios; i++) { |
| + struct folio *folio = folios[i]; |
| |
| from = start & (PAGE_SIZE - 1); |
| - if ((end >> PAGE_SHIFT) == page->index) |
| + if ((end >> PAGE_SHIFT) == folio->index) |
| to = end & (PAGE_SIZE - 1); |
| |
| BUG_ON(from > PAGE_SIZE); |
| BUG_ON(to > PAGE_SIZE); |
| |
| - ocfs2_map_and_dirty_page(inode, handle, from, to, page, 1, |
| + ocfs2_map_and_dirty_page(inode, handle, from, to, &folio->page, 1, |
| &phys); |
| |
| - start = (page->index + 1) << PAGE_SHIFT; |
| + start = (folio->index + 1) << PAGE_SHIFT; |
| } |
| out: |
| - if (pages) |
| - ocfs2_unlock_and_free_pages(pages, numpages); |
| + if (folios) |
| + ocfs2_unlock_and_free_folios(folios, numfolios); |
| } |
| |
| -int ocfs2_grab_pages(struct inode *inode, loff_t start, loff_t end, |
| - struct page **pages, int *num) |
| +static int ocfs2_grab_folios(struct inode *inode, loff_t start, loff_t end, |
| + struct folio **folios, int *num) |
| { |
| - int numpages, ret = 0; |
| + int numfolios, ret = 0; |
| struct address_space *mapping = inode->i_mapping; |
| unsigned long index; |
| loff_t last_page_bytes; |
| |
| BUG_ON(start > end); |
| |
| - numpages = 0; |
| + numfolios = 0; |
| last_page_bytes = PAGE_ALIGN(end); |
| index = start >> PAGE_SHIFT; |
| do { |
| - pages[numpages] = find_or_create_page(mapping, index, GFP_NOFS); |
| - if (!pages[numpages]) { |
| - ret = -ENOMEM; |
| + folios[numfolios] = __filemap_get_folio(mapping, index, |
| + FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_NOFS); |
| + if (IS_ERR(folios[numfolios])) { |
| + ret = PTR_ERR(folios[numfolios]); |
| mlog_errno(ret); |
| goto out; |
| } |
| |
| - numpages++; |
| - index++; |
| + index = folio_next_index(folios[numfolios]); |
| + numfolios++; |
| } while (index < (last_page_bytes >> PAGE_SHIFT)); |
| |
| out: |
| if (ret != 0) { |
| - if (pages) |
| - ocfs2_unlock_and_free_pages(pages, numpages); |
| - numpages = 0; |
| + if (folios) |
| + ocfs2_unlock_and_free_folios(folios, numfolios); |
| + numfolios = 0; |
| } |
| |
| - *num = numpages; |
| + *num = numfolios; |
| |
| return ret; |
| } |
| |
| -static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end, |
| - struct page **pages, int *num) |
| +static int ocfs2_grab_eof_folios(struct inode *inode, loff_t start, loff_t end, |
| + struct folio **folios, int *num) |
| { |
| struct super_block *sb = inode->i_sb; |
| |
| BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits != |
| (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits); |
| |
| - return ocfs2_grab_pages(inode, start, end, pages, num); |
| + return ocfs2_grab_folios(inode, start, end, folios, num); |
| } |
| |
| /* |
| @@ -6941,8 +6941,8 @@ static int ocfs2_grab_eof_pages(struct i |
| int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle, |
| u64 range_start, u64 range_end) |
| { |
| - int ret = 0, numpages; |
| - struct page **pages = NULL; |
| + int ret = 0, numfolios; |
| + struct folio **folios = NULL; |
| u64 phys; |
| unsigned int ext_flags; |
| struct super_block *sb = inode->i_sb; |
| @@ -6955,17 +6955,17 @@ int ocfs2_zero_range_for_truncate(struct |
| return 0; |
| |
| /* |
| - * Avoid zeroing pages fully beyond current i_size. It is pointless as |
| - * underlying blocks of those pages should be already zeroed out and |
| + * Avoid zeroing folios fully beyond current i_size. It is pointless as |
| + * underlying blocks of those folios should be already zeroed out and |
| * page writeback will skip them anyway. |
| */ |
| range_end = min_t(u64, range_end, i_size_read(inode)); |
| if (range_start >= range_end) |
| return 0; |
| |
| - pages = kcalloc(ocfs2_pages_per_cluster(sb), |
| - sizeof(struct page *), GFP_NOFS); |
| - if (pages == NULL) { |
| + folios = kcalloc(ocfs2_pages_per_cluster(sb), |
| + sizeof(struct folio *), GFP_NOFS); |
| + if (folios == NULL) { |
| ret = -ENOMEM; |
| mlog_errno(ret); |
| goto out; |
| @@ -6986,18 +6986,18 @@ int ocfs2_zero_range_for_truncate(struct |
| if (phys == 0 || ext_flags & OCFS2_EXT_UNWRITTEN) |
| goto out; |
| |
| - ret = ocfs2_grab_eof_pages(inode, range_start, range_end, pages, |
| - &numpages); |
| + ret = ocfs2_grab_eof_folios(inode, range_start, range_end, folios, |
| + &numfolios); |
| if (ret) { |
| mlog_errno(ret); |
| goto out; |
| } |
| |
| - ocfs2_zero_cluster_pages(inode, range_start, range_end, pages, |
| - numpages, phys, handle); |
| + ocfs2_zero_cluster_folios(inode, range_start, range_end, folios, |
| + numfolios, phys, handle); |
| |
| /* |
| - * Initiate writeout of the pages we zero'd here. We don't |
| + * Initiate writeout of the folios we zero'd here. We don't |
| * wait on them - the truncate_inode_pages() call later will |
| * do that for us. |
| */ |
| @@ -7007,7 +7007,7 @@ int ocfs2_zero_range_for_truncate(struct |
| mlog_errno(ret); |
| |
| out: |
| - kfree(pages); |
| + kfree(folios); |
| |
| return ret; |
| } |
| @@ -7060,7 +7060,7 @@ void ocfs2_set_inode_data_inline(struct |
| int ocfs2_convert_inline_data_to_extents(struct inode *inode, |
| struct buffer_head *di_bh) |
| { |
| - int ret, has_data, num_pages = 0; |
| + int ret, has_data, num_folios = 0; |
| int need_free = 0; |
| u32 bit_off, num; |
| handle_t *handle; |
| @@ -7069,7 +7069,7 @@ int ocfs2_convert_inline_data_to_extents |
| struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
| struct ocfs2_alloc_context *data_ac = NULL; |
| - struct page *page = NULL; |
| + struct folio *folio = NULL; |
| struct ocfs2_extent_tree et; |
| int did_quota = 0; |
| |
| @@ -7124,8 +7124,8 @@ int ocfs2_convert_inline_data_to_extents |
| */ |
| block = phys = ocfs2_clusters_to_blocks(inode->i_sb, bit_off); |
| |
| - ret = ocfs2_grab_eof_pages(inode, 0, page_end, &page, |
| - &num_pages); |
| + ret = ocfs2_grab_eof_folios(inode, 0, page_end, &folio, |
| + &num_folios); |
| if (ret) { |
| mlog_errno(ret); |
| need_free = 1; |
| @@ -7136,14 +7136,14 @@ int ocfs2_convert_inline_data_to_extents |
| * This should populate the 1st page for us and mark |
| * it up to date. |
| */ |
| - ret = ocfs2_read_inline_data(inode, page, di_bh); |
| + ret = ocfs2_read_inline_data(inode, &folio->page, di_bh); |
| if (ret) { |
| mlog_errno(ret); |
| need_free = 1; |
| goto out_unlock; |
| } |
| |
| - ocfs2_map_and_dirty_page(inode, handle, 0, page_end, page, 0, |
| + ocfs2_map_and_dirty_page(inode, handle, 0, page_end, &folio->page, 0, |
| &phys); |
| } |
| |
| @@ -7175,8 +7175,8 @@ int ocfs2_convert_inline_data_to_extents |
| } |
| |
| out_unlock: |
| - if (page) |
| - ocfs2_unlock_and_free_pages(&page, num_pages); |
| + if (folio) |
| + ocfs2_unlock_and_free_folios(&folio, num_folios); |
| |
| out_commit: |
| if (ret < 0 && did_quota) |
| --- a/fs/ocfs2/alloc.h~ocfs2-use-an-array-of-folios-instead-of-an-array-of-pages |
| +++ a/fs/ocfs2/alloc.h |
| @@ -254,8 +254,6 @@ static inline int ocfs2_is_empty_extent( |
| return !rec->e_leaf_clusters; |
| } |
| |
| -int ocfs2_grab_pages(struct inode *inode, loff_t start, loff_t end, |
| - struct page **pages, int *num); |
| void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle, |
| unsigned int from, unsigned int to, |
| struct page *page, int zero, u64 *phys); |
| --- a/fs/ocfs2/aops.c~ocfs2-use-an-array-of-folios-instead-of-an-array-of-pages |
| +++ a/fs/ocfs2/aops.c |
| @@ -783,19 +783,6 @@ void ocfs2_unlock_and_free_folios(struct |
| } |
| } |
| |
| -void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages) |
| -{ |
| - int i; |
| - |
| - for(i = 0; i < num_pages; i++) { |
| - if (pages[i]) { |
| - unlock_page(pages[i]); |
| - mark_page_accessed(pages[i]); |
| - put_page(pages[i]); |
| - } |
| - } |
| -} |
| - |
| static void ocfs2_unlock_folios(struct ocfs2_write_ctxt *wc) |
| { |
| int i; |
| --- a/fs/ocfs2/aops.h~ocfs2-use-an-array-of-folios-instead-of-an-array-of-pages |
| +++ a/fs/ocfs2/aops.h |
| @@ -18,7 +18,6 @@ int ocfs2_map_folio_blocks(struct folio |
| unsigned int to, int new); |
| |
| void ocfs2_unlock_and_free_folios(struct folio **folios, int num_folios); |
| -void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages); |
| |
| int walk_page_buffers( handle_t *handle, |
| struct buffer_head *head, |
| _ |