diff options
Diffstat (limited to 'fs/xfs/xfs_aops.c')
| -rw-r--r-- | fs/xfs/xfs_aops.c | 42 | 
1 files changed, 28 insertions, 14 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index c8c15c3c3147..9d6a67c7d227 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -136,7 +136,20 @@ done:  	memalloc_nofs_restore(nofs_flag);  } -/* Finish all pending io completions. */ +/* + * Finish all pending IO completions that require transactional modifications. + * + * We try to merge physical and logically contiguous ioends before completion to + * minimise the number of transactions we need to perform during IO completion. + * Both unwritten extent conversion and COW remapping need to iterate and modify + * one physical extent at a time, so we gain nothing by merging physically + * discontiguous extents here. + * + * The ioend chain length that we can be processing here is largely unbound in + * length and we may have to perform significant amounts of work on each ioend + * to complete it. Hence we have to be careful about holding the CPU for too + * long in this loop. + */  void  xfs_end_io(  	struct work_struct	*work) @@ -157,6 +170,7 @@ xfs_end_io(  		list_del_init(&ioend->io_list);  		iomap_ioend_try_merge(ioend, &tmp);  		xfs_end_ioend(ioend); +		cond_resched();  	}  } @@ -359,7 +373,7 @@ retry:  	    isnullstartblock(imap.br_startblock))  		goto allocate_blocks; -	xfs_bmbt_to_iomap(ip, &wpc->iomap, &imap, 0); +	xfs_bmbt_to_iomap(ip, &wpc->iomap, &imap, 0, 0);  	trace_xfs_map_blocks_found(ip, offset, count, whichfork, &imap);  	return 0;  allocate_blocks: @@ -437,37 +451,37 @@ xfs_prepare_ioend(   * see a ENOSPC in writeback).   */  static void -xfs_discard_page( -	struct page		*page, -	loff_t			fileoff) +xfs_discard_folio( +	struct folio		*folio, +	loff_t			pos)  { -	struct inode		*inode = page->mapping->host; +	struct inode		*inode = folio->mapping->host;  	struct xfs_inode	*ip = XFS_I(inode);  	struct xfs_mount	*mp = ip->i_mount; -	unsigned int		pageoff = offset_in_page(fileoff); -	xfs_fileoff_t		start_fsb = XFS_B_TO_FSBT(mp, fileoff); -	xfs_fileoff_t		pageoff_fsb = XFS_B_TO_FSBT(mp, pageoff); +	size_t			offset = offset_in_folio(folio, pos); +	xfs_fileoff_t		start_fsb = XFS_B_TO_FSBT(mp, pos); +	xfs_fileoff_t		pageoff_fsb = XFS_B_TO_FSBT(mp, offset);  	int			error;  	if (xfs_is_shutdown(mp))  		goto out_invalidate;  	xfs_alert_ratelimited(mp, -		"page discard on page "PTR_FMT", inode 0x%llx, offset %llu.", -			page, ip->i_ino, fileoff); +		"page discard on page "PTR_FMT", inode 0x%llx, pos %llu.", +			folio, ip->i_ino, pos);  	error = xfs_bmap_punch_delalloc_range(ip, start_fsb, -			i_blocks_per_page(inode, page) - pageoff_fsb); +			i_blocks_per_folio(inode, folio) - pageoff_fsb);  	if (error && !xfs_is_shutdown(mp))  		xfs_alert(mp, "page discard unable to remove delalloc mapping.");  out_invalidate: -	iomap_invalidatepage(page, pageoff, PAGE_SIZE - pageoff); +	iomap_invalidate_folio(folio, offset, folio_size(folio) - offset);  }  static const struct iomap_writeback_ops xfs_writeback_ops = {  	.map_blocks		= xfs_map_blocks,  	.prepare_ioend		= xfs_prepare_ioend, -	.discard_page		= xfs_discard_page, +	.discard_folio		= xfs_discard_folio,  };  STATIC int  |