If the src is inlined, then just bail out. Have it attempt to uninline the dst file however. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/ceph/file.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 252aac44b8ce..774f51b0b63d 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1934,6 +1934,10 @@ static ssize_t ceph_copy_file_range(struct file *src_file, loff_t src_off, if (len < src_ci->i_layout.object_size) return -EOPNOTSUPP; /* no remote copy will be done */ + /* Fall back if src file is inlined */ + if (READ_ONCE(src_ci->i_inline_version) != CEPH_INLINE_NONE) + return -EOPNOTSUPP; + prealloc_cf = ceph_alloc_cap_flush(); if (!prealloc_cf) return -ENOMEM; @@ -1967,6 +1971,13 @@ static ssize_t ceph_copy_file_range(struct file *src_file, loff_t src_off, if (ret < 0) goto out_caps; + /* uninline the dst inode */ + dirty = ceph_uninline_data(dst_inode, NULL); + if (dirty < 0) { + ret = dirty; + goto out_caps; + } + size = i_size_read(dst_inode); endoff = dst_off + len; @@ -2080,7 +2091,7 @@ static ssize_t ceph_copy_file_range(struct file *src_file, loff_t src_off, /* Mark Fw dirty */ spin_lock(&dst_ci->i_ceph_lock); dst_ci->i_inline_version = CEPH_INLINE_NONE; - dirty = __ceph_mark_dirty_caps(dst_ci, CEPH_CAP_FILE_WR, &prealloc_cf); + dirty |= __ceph_mark_dirty_caps(dst_ci, CEPH_CAP_FILE_WR, &prealloc_cf); spin_unlock(&dst_ci->i_ceph_lock); if (dirty) __mark_inode_dirty(dst_inode, dirty); -- 2.21.0