forked from mirrors/linux
		
	fsdax,xfs: port unshare to fsdax
Implement unshare in fsdax mode: copy data from srcmap to iomap. Link: https://lkml.kernel.org/r/1669908753-169-1-git-send-email-ruansy.fnst@fujitsu.com Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Cc: Alistair Popple <apopple@nvidia.com> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Dave Chinner <david@fromorbit.com> Cc: Jason Gunthorpe <jgg@nvidia.com> Cc: John Hubbard <jhubbard@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									64e6edc185
								
							
						
					
					
						commit
						d984648e42
					
				
					 3 changed files with 60 additions and 2 deletions
				
			
		
							
								
								
									
										52
									
								
								fs/dax.c
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								fs/dax.c
									
									
									
									
									
								
							| 
						 | 
					@ -1245,6 +1245,58 @@ static vm_fault_t dax_pmd_load_hole(struct xa_state *xas, struct vm_fault *vmf,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_FS_DAX_PMD */
 | 
					#endif /* CONFIG_FS_DAX_PMD */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static s64 dax_unshare_iter(struct iomap_iter *iter)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct iomap *iomap = &iter->iomap;
 | 
				
			||||||
 | 
						const struct iomap *srcmap = iomap_iter_srcmap(iter);
 | 
				
			||||||
 | 
						loff_t pos = iter->pos;
 | 
				
			||||||
 | 
						loff_t length = iomap_length(iter);
 | 
				
			||||||
 | 
						int id = 0;
 | 
				
			||||||
 | 
						s64 ret = 0;
 | 
				
			||||||
 | 
						void *daddr = NULL, *saddr = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* don't bother with blocks that are not shared to start with */
 | 
				
			||||||
 | 
						if (!(iomap->flags & IOMAP_F_SHARED))
 | 
				
			||||||
 | 
							return length;
 | 
				
			||||||
 | 
						/* don't bother with holes or unwritten extents */
 | 
				
			||||||
 | 
						if (srcmap->type == IOMAP_HOLE || srcmap->type == IOMAP_UNWRITTEN)
 | 
				
			||||||
 | 
							return length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						id = dax_read_lock();
 | 
				
			||||||
 | 
						ret = dax_iomap_direct_access(iomap, pos, length, &daddr, NULL);
 | 
				
			||||||
 | 
						if (ret < 0)
 | 
				
			||||||
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = dax_iomap_direct_access(srcmap, pos, length, &saddr, NULL);
 | 
				
			||||||
 | 
						if (ret < 0)
 | 
				
			||||||
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = copy_mc_to_kernel(daddr, saddr, length);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							ret = -EIO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out_unlock:
 | 
				
			||||||
 | 
						dax_read_unlock(id);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int dax_file_unshare(struct inode *inode, loff_t pos, loff_t len,
 | 
				
			||||||
 | 
							const struct iomap_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct iomap_iter iter = {
 | 
				
			||||||
 | 
							.inode		= inode,
 | 
				
			||||||
 | 
							.pos		= pos,
 | 
				
			||||||
 | 
							.len		= len,
 | 
				
			||||||
 | 
							.flags		= IOMAP_WRITE | IOMAP_UNSHARE | IOMAP_DAX,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((ret = iomap_iter(&iter, ops)) > 0)
 | 
				
			||||||
 | 
							iter.processed = dax_unshare_iter(&iter);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(dax_file_unshare);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dax_memzero(struct iomap_iter *iter, loff_t pos, size_t size)
 | 
					static int dax_memzero(struct iomap_iter *iter, loff_t pos, size_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct iomap *iomap = &iter->iomap;
 | 
						const struct iomap *iomap = &iter->iomap;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1693,6 +1693,10 @@ xfs_reflink_unshare(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inode_dio_wait(inode);
 | 
						inode_dio_wait(inode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (IS_DAX(inode))
 | 
				
			||||||
 | 
							error = dax_file_unshare(inode, offset, len,
 | 
				
			||||||
 | 
									&xfs_dax_write_iomap_ops);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
		error = iomap_file_unshare(inode, offset, len,
 | 
							error = iomap_file_unshare(inode, offset, len,
 | 
				
			||||||
				&xfs_buffered_write_iomap_ops);
 | 
									&xfs_buffered_write_iomap_ops);
 | 
				
			||||||
	if (error)
 | 
						if (error)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,6 +205,8 @@ static inline void dax_unlock_mapping_entry(struct address_space *mapping,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int dax_file_unshare(struct inode *inode, loff_t pos, loff_t len,
 | 
				
			||||||
 | 
							const struct iomap_ops *ops);
 | 
				
			||||||
int dax_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
 | 
					int dax_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
 | 
				
			||||||
		const struct iomap_ops *ops);
 | 
							const struct iomap_ops *ops);
 | 
				
			||||||
int dax_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
 | 
					int dax_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue