Message ID | 20200824145511.10500-3-willy@infradead.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | THP iomap patches for 5.10 | expand |
On Mon, Aug 24, 2020 at 03:55:03PM +0100, Matthew Wilcox (Oracle) wrote: > This helper is useful for both THPs and for supporting block size larger > than page size. Convert all users that I could find (we have a few > different ways of writing this idiom, and I may have missed some). There probably is - ISTR having a lot more of these changes for the block_size > page_size patches as it needed the same {page, inode} abstraction for calculating the range to iterate. But they can be dealt with on a case by case basis, I think. > Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> > Reviewed-by: Christoph Hellwig <hch@lst.de> > --- > fs/iomap/buffered-io.c | 8 ++++---- > fs/jfs/jfs_metapage.c | 2 +- > fs/xfs/xfs_aops.c | 2 +- > include/linux/pagemap.h | 16 ++++++++++++++++ > 4 files changed, 22 insertions(+), 6 deletions(-) Otherwise looks good. Reviewed-by: Dave Chinner <dchinner@redhat.com>
On Mon, Aug 24, 2020 at 03:55:03PM +0100, Matthew Wilcox (Oracle) wrote: > This helper is useful for both THPs and for supporting block size larger > than page size. Convert all users that I could find (we have a few > different ways of writing this idiom, and I may have missed some). > > Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> > Reviewed-by: Christoph Hellwig <hch@lst.de> /me wonders what will happen when someone tries to make blocksz > pagesize work, but as the most likely someone already rvb'd this I guess it's fine: Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> --D > --- > fs/iomap/buffered-io.c | 8 ++++---- > fs/jfs/jfs_metapage.c | 2 +- > fs/xfs/xfs_aops.c | 2 +- > include/linux/pagemap.h | 16 ++++++++++++++++ > 4 files changed, 22 insertions(+), 6 deletions(-) > > diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c > index cffd575e57b6..13d5cdab8dcd 100644 > --- a/fs/iomap/buffered-io.c > +++ b/fs/iomap/buffered-io.c > @@ -46,7 +46,7 @@ iomap_page_create(struct inode *inode, struct page *page) > { > struct iomap_page *iop = to_iomap_page(page); > > - if (iop || i_blocksize(inode) == PAGE_SIZE) > + if (iop || i_blocks_per_page(inode, page) <= 1) > return iop; > > iop = kmalloc(sizeof(*iop), GFP_NOFS | __GFP_NOFAIL); > @@ -147,7 +147,7 @@ iomap_iop_set_range_uptodate(struct page *page, unsigned off, unsigned len) > unsigned int i; > > spin_lock_irqsave(&iop->uptodate_lock, flags); > - for (i = 0; i < PAGE_SIZE / i_blocksize(inode); i++) { > + for (i = 0; i < i_blocks_per_page(inode, page); i++) { > if (i >= first && i <= last) > set_bit(i, iop->uptodate); > else if (!test_bit(i, iop->uptodate)) > @@ -1078,7 +1078,7 @@ iomap_finish_page_writeback(struct inode *inode, struct page *page, > mapping_set_error(inode->i_mapping, -EIO); > } > > - WARN_ON_ONCE(i_blocksize(inode) < PAGE_SIZE && !iop); > + WARN_ON_ONCE(i_blocks_per_page(inode, page) > 1 && !iop); > WARN_ON_ONCE(iop && atomic_read(&iop->write_count) <= 0); > > if (!iop || atomic_dec_and_test(&iop->write_count)) > @@ -1374,7 +1374,7 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc, > int error = 0, count = 0, i; > LIST_HEAD(submit_list); > > - WARN_ON_ONCE(i_blocksize(inode) < PAGE_SIZE && !iop); > + WARN_ON_ONCE(i_blocks_per_page(inode, page) > 1 && !iop); > WARN_ON_ONCE(iop && atomic_read(&iop->write_count) != 0); > > /* > diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c > index a2f5338a5ea1..176580f54af9 100644 > --- a/fs/jfs/jfs_metapage.c > +++ b/fs/jfs/jfs_metapage.c > @@ -473,7 +473,7 @@ static int metapage_readpage(struct file *fp, struct page *page) > struct inode *inode = page->mapping->host; > struct bio *bio = NULL; > int block_offset; > - int blocks_per_page = PAGE_SIZE >> inode->i_blkbits; > + int blocks_per_page = i_blocks_per_page(inode, page); > sector_t page_start; /* address of page in fs blocks */ > sector_t pblock; > int xlen; > diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c > index b35611882ff9..55d126d4e096 100644 > --- a/fs/xfs/xfs_aops.c > +++ b/fs/xfs/xfs_aops.c > @@ -544,7 +544,7 @@ xfs_discard_page( > page, ip->i_ino, offset); > > error = xfs_bmap_punch_delalloc_range(ip, start_fsb, > - PAGE_SIZE / i_blocksize(inode)); > + i_blocks_per_page(inode, page)); > if (error && !XFS_FORCED_SHUTDOWN(mp)) > xfs_alert(mp, "page discard unable to remove delalloc mapping."); > out_invalidate: > diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h > index 7de11dcd534d..853733286138 100644 > --- a/include/linux/pagemap.h > +++ b/include/linux/pagemap.h > @@ -899,4 +899,20 @@ static inline int page_mkwrite_check_truncate(struct page *page, > return offset; > } > > +/** > + * i_blocks_per_page - How many blocks fit in this page. > + * @inode: The inode which contains the blocks. > + * @page: The page (head page if the page is a THP). > + * > + * If the block size is larger than the size of this page, return zero. > + * > + * Context: The caller should hold a refcount on the page to prevent it > + * from being split. > + * Return: The number of filesystem blocks covered by this page. > + */ > +static inline > +unsigned int i_blocks_per_page(struct inode *inode, struct page *page) > +{ > + return thp_size(page) >> inode->i_blkbits; > +} > #endif /* _LINUX_PAGEMAP_H */ > -- > 2.28.0 >
On Tue, Aug 25, 2020 at 01:49:22PM -0700, Darrick J. Wong wrote: > On Mon, Aug 24, 2020 at 03:55:03PM +0100, Matthew Wilcox (Oracle) wrote: > > This helper is useful for both THPs and for supporting block size larger > > than page size. Convert all users that I could find (we have a few > > different ways of writing this idiom, and I may have missed some). > > > > Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> > > Reviewed-by: Christoph Hellwig <hch@lst.de> > > /me wonders what will happen when someone tries to make blocksz > > pagesize work, I abstract the page/block size stuff into "chunks". i.e. we work on the smallest contiguous chunk of data the current combination of page and inode define. In the context of this patch, it is simply just: s/i_blocks_per_page/iomap_chunks_per_page/g i.e. The helper functions end up looking like this: static inline unsigned iomap_chunk_size(struct inode *inode, struct page *page) { return min_t(unsigned, page_size(page), i_blocksize(inode)); } static inline unsigned iomap_chunk_bits(struct inode *inode, struct page *page) { return min_t(unsigned, page_shift(page), inode->i_blkbits); } static inline unsigned iomap_chunks_per_page(struct inode *inode, struct page *page) { return page_size(page) >> inode->i_blkbits; } and the latter is actually the same as what i_block_per_page() is currently implemented as.... Cheers, Dave.
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index cffd575e57b6..13d5cdab8dcd 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -46,7 +46,7 @@ iomap_page_create(struct inode *inode, struct page *page) { struct iomap_page *iop = to_iomap_page(page); - if (iop || i_blocksize(inode) == PAGE_SIZE) + if (iop || i_blocks_per_page(inode, page) <= 1) return iop; iop = kmalloc(sizeof(*iop), GFP_NOFS | __GFP_NOFAIL); @@ -147,7 +147,7 @@ iomap_iop_set_range_uptodate(struct page *page, unsigned off, unsigned len) unsigned int i; spin_lock_irqsave(&iop->uptodate_lock, flags); - for (i = 0; i < PAGE_SIZE / i_blocksize(inode); i++) { + for (i = 0; i < i_blocks_per_page(inode, page); i++) { if (i >= first && i <= last) set_bit(i, iop->uptodate); else if (!test_bit(i, iop->uptodate)) @@ -1078,7 +1078,7 @@ iomap_finish_page_writeback(struct inode *inode, struct page *page, mapping_set_error(inode->i_mapping, -EIO); } - WARN_ON_ONCE(i_blocksize(inode) < PAGE_SIZE && !iop); + WARN_ON_ONCE(i_blocks_per_page(inode, page) > 1 && !iop); WARN_ON_ONCE(iop && atomic_read(&iop->write_count) <= 0); if (!iop || atomic_dec_and_test(&iop->write_count)) @@ -1374,7 +1374,7 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc, int error = 0, count = 0, i; LIST_HEAD(submit_list); - WARN_ON_ONCE(i_blocksize(inode) < PAGE_SIZE && !iop); + WARN_ON_ONCE(i_blocks_per_page(inode, page) > 1 && !iop); WARN_ON_ONCE(iop && atomic_read(&iop->write_count) != 0); /* diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index a2f5338a5ea1..176580f54af9 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -473,7 +473,7 @@ static int metapage_readpage(struct file *fp, struct page *page) struct inode *inode = page->mapping->host; struct bio *bio = NULL; int block_offset; - int blocks_per_page = PAGE_SIZE >> inode->i_blkbits; + int blocks_per_page = i_blocks_per_page(inode, page); sector_t page_start; /* address of page in fs blocks */ sector_t pblock; int xlen; diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index b35611882ff9..55d126d4e096 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -544,7 +544,7 @@ xfs_discard_page( page, ip->i_ino, offset); error = xfs_bmap_punch_delalloc_range(ip, start_fsb, - PAGE_SIZE / i_blocksize(inode)); + i_blocks_per_page(inode, page)); if (error && !XFS_FORCED_SHUTDOWN(mp)) xfs_alert(mp, "page discard unable to remove delalloc mapping."); out_invalidate: diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 7de11dcd534d..853733286138 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -899,4 +899,20 @@ static inline int page_mkwrite_check_truncate(struct page *page, return offset; } +/** + * i_blocks_per_page - How many blocks fit in this page. + * @inode: The inode which contains the blocks. + * @page: The page (head page if the page is a THP). + * + * If the block size is larger than the size of this page, return zero. + * + * Context: The caller should hold a refcount on the page to prevent it + * from being split. + * Return: The number of filesystem blocks covered by this page. + */ +static inline +unsigned int i_blocks_per_page(struct inode *inode, struct page *page) +{ + return thp_size(page) >> inode->i_blkbits; +} #endif /* _LINUX_PAGEMAP_H */