1315ee00fSMartin Matuska /* 2315ee00fSMartin Matuska * CDDL HEADER START 3315ee00fSMartin Matuska * 4315ee00fSMartin Matuska * The contents of this file are subject to the terms of the 5315ee00fSMartin Matuska * Common Development and Distribution License (the "License"). 6315ee00fSMartin Matuska * You may not use this file except in compliance with the License. 7315ee00fSMartin Matuska * 8315ee00fSMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9315ee00fSMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10315ee00fSMartin Matuska * See the License for the specific language governing permissions 11315ee00fSMartin Matuska * and limitations under the License. 12315ee00fSMartin Matuska * 13315ee00fSMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 14315ee00fSMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15315ee00fSMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 16315ee00fSMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 17315ee00fSMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 18315ee00fSMartin Matuska * 19315ee00fSMartin Matuska * CDDL HEADER END 20315ee00fSMartin Matuska */ 21315ee00fSMartin Matuska /* 22315ee00fSMartin Matuska * Copyright (c) 2023, Klara Inc. 23315ee00fSMartin Matuska */ 24315ee00fSMartin Matuska 25315ee00fSMartin Matuska #ifdef CONFIG_COMPAT 26315ee00fSMartin Matuska #include <linux/compat.h> 27315ee00fSMartin Matuska #endif 28315ee00fSMartin Matuska #include <linux/fs.h> 29783d3ff6SMartin Matuska #ifdef HAVE_VFS_SPLICE_COPY_FILE_RANGE 30783d3ff6SMartin Matuska #include <linux/splice.h> 31783d3ff6SMartin Matuska #endif 32315ee00fSMartin Matuska #include <sys/file.h> 33315ee00fSMartin Matuska #include <sys/zfs_znode.h> 34315ee00fSMartin Matuska #include <sys/zfs_vnops.h> 35315ee00fSMartin Matuska #include <sys/zfeature.h> 36315ee00fSMartin Matuska 37315ee00fSMartin Matuska /* 38315ee00fSMartin Matuska * Clone part of a file via block cloning. 39315ee00fSMartin Matuska * 40315ee00fSMartin Matuska * Note that we are not required to update file offsets; the kernel will take 41315ee00fSMartin Matuska * care of that depending on how it was called. 42315ee00fSMartin Matuska */ 43315ee00fSMartin Matuska static ssize_t 44a4e5e010SMartin Matuska zpl_clone_file_range_impl(struct file *src_file, loff_t src_off, 45315ee00fSMartin Matuska struct file *dst_file, loff_t dst_off, size_t len) 46315ee00fSMartin Matuska { 47315ee00fSMartin Matuska struct inode *src_i = file_inode(src_file); 48315ee00fSMartin Matuska struct inode *dst_i = file_inode(dst_file); 49315ee00fSMartin Matuska uint64_t src_off_o = (uint64_t)src_off; 50315ee00fSMartin Matuska uint64_t dst_off_o = (uint64_t)dst_off; 51315ee00fSMartin Matuska uint64_t len_o = (uint64_t)len; 52315ee00fSMartin Matuska cred_t *cr = CRED(); 53315ee00fSMartin Matuska fstrans_cookie_t cookie; 54315ee00fSMartin Matuska int err; 55315ee00fSMartin Matuska 5647bb16f8SMartin Matuska if (!zfs_bclone_enabled) 5747bb16f8SMartin Matuska return (-EOPNOTSUPP); 5847bb16f8SMartin Matuska 59315ee00fSMartin Matuska if (!spa_feature_is_enabled( 60315ee00fSMartin Matuska dmu_objset_spa(ITOZSB(dst_i)->z_os), SPA_FEATURE_BLOCK_CLONING)) 61315ee00fSMartin Matuska return (-EOPNOTSUPP); 62315ee00fSMartin Matuska 63315ee00fSMartin Matuska if (src_i != dst_i) 64315ee00fSMartin Matuska spl_inode_lock_shared(src_i); 65315ee00fSMartin Matuska spl_inode_lock(dst_i); 66315ee00fSMartin Matuska 67315ee00fSMartin Matuska crhold(cr); 68315ee00fSMartin Matuska cookie = spl_fstrans_mark(); 69315ee00fSMartin Matuska 70315ee00fSMartin Matuska err = -zfs_clone_range(ITOZ(src_i), &src_off_o, ITOZ(dst_i), 71315ee00fSMartin Matuska &dst_off_o, &len_o, cr); 72315ee00fSMartin Matuska 73315ee00fSMartin Matuska spl_fstrans_unmark(cookie); 74315ee00fSMartin Matuska crfree(cr); 75315ee00fSMartin Matuska 76315ee00fSMartin Matuska spl_inode_unlock(dst_i); 77315ee00fSMartin Matuska if (src_i != dst_i) 78315ee00fSMartin Matuska spl_inode_unlock_shared(src_i); 79315ee00fSMartin Matuska 80315ee00fSMartin Matuska if (err < 0) 81315ee00fSMartin Matuska return (err); 82315ee00fSMartin Matuska 83315ee00fSMartin Matuska return ((ssize_t)len_o); 84315ee00fSMartin Matuska } 85315ee00fSMartin Matuska 86315ee00fSMartin Matuska /* 87315ee00fSMartin Matuska * Entry point for copy_file_range(). Copy len bytes from src_off in src_file 88315ee00fSMartin Matuska * to dst_off in dst_file. We are permitted to do this however we like, so we 89315ee00fSMartin Matuska * try to just clone the blocks, and if we can't support it, fall back to the 90315ee00fSMartin Matuska * kernel's generic byte copy function. 91315ee00fSMartin Matuska */ 92315ee00fSMartin Matuska ssize_t 93315ee00fSMartin Matuska zpl_copy_file_range(struct file *src_file, loff_t src_off, 94315ee00fSMartin Matuska struct file *dst_file, loff_t dst_off, size_t len, unsigned int flags) 95315ee00fSMartin Matuska { 96315ee00fSMartin Matuska ssize_t ret; 97315ee00fSMartin Matuska 98a4e5e010SMartin Matuska /* Flags is reserved for future extensions and must be zero. */ 99315ee00fSMartin Matuska if (flags != 0) 100315ee00fSMartin Matuska return (-EINVAL); 101315ee00fSMartin Matuska 102a4e5e010SMartin Matuska /* Try to do it via zfs_clone_range() and allow shortening. */ 103a4e5e010SMartin Matuska ret = zpl_clone_file_range_impl(src_file, src_off, 104315ee00fSMartin Matuska dst_file, dst_off, len); 105315ee00fSMartin Matuska 106783d3ff6SMartin Matuska #if defined(HAVE_VFS_GENERIC_COPY_FILE_RANGE) 107315ee00fSMartin Matuska /* 108315ee00fSMartin Matuska * Since Linux 5.3 the filesystem driver is responsible for executing 109315ee00fSMartin Matuska * an appropriate fallback, and a generic fallback function is provided. 110315ee00fSMartin Matuska */ 111315ee00fSMartin Matuska if (ret == -EOPNOTSUPP || ret == -EINVAL || ret == -EXDEV || 112315ee00fSMartin Matuska ret == -EAGAIN) 113315ee00fSMartin Matuska ret = generic_copy_file_range(src_file, src_off, dst_file, 114315ee00fSMartin Matuska dst_off, len, flags); 115783d3ff6SMartin Matuska #elif defined(HAVE_VFS_SPLICE_COPY_FILE_RANGE) 116783d3ff6SMartin Matuska /* 117783d3ff6SMartin Matuska * Since 6.8 the fallback function is called splice_copy_file_range 118783d3ff6SMartin Matuska * and has a slightly different signature. 119783d3ff6SMartin Matuska */ 120783d3ff6SMartin Matuska if (ret == -EOPNOTSUPP || ret == -EINVAL || ret == -EXDEV || 121783d3ff6SMartin Matuska ret == -EAGAIN) 122783d3ff6SMartin Matuska ret = splice_copy_file_range(src_file, src_off, dst_file, 123783d3ff6SMartin Matuska dst_off, len); 124315ee00fSMartin Matuska #else 125315ee00fSMartin Matuska /* 126315ee00fSMartin Matuska * Before Linux 5.3 the filesystem has to return -EOPNOTSUPP to signal 127315ee00fSMartin Matuska * to the kernel that it should fallback to a content copy. 128315ee00fSMartin Matuska */ 129315ee00fSMartin Matuska if (ret == -EINVAL || ret == -EXDEV || ret == -EAGAIN) 130315ee00fSMartin Matuska ret = -EOPNOTSUPP; 131783d3ff6SMartin Matuska #endif /* HAVE_VFS_GENERIC_COPY_FILE_RANGE || HAVE_VFS_SPLICE_COPY_FILE_RANGE */ 132315ee00fSMartin Matuska 133315ee00fSMartin Matuska return (ret); 134315ee00fSMartin Matuska } 135315ee00fSMartin Matuska 136315ee00fSMartin Matuska #ifdef HAVE_VFS_REMAP_FILE_RANGE 137315ee00fSMartin Matuska /* 138315ee00fSMartin Matuska * Entry point for FICLONE/FICLONERANGE/FIDEDUPERANGE. 139315ee00fSMartin Matuska * 140315ee00fSMartin Matuska * FICLONE and FICLONERANGE are basically the same as copy_file_range(), except 141315ee00fSMartin Matuska * that they must clone - they cannot fall back to copying. FICLONE is exactly 142315ee00fSMartin Matuska * FICLONERANGE, for the entire file. We don't need to try to tell them apart; 143315ee00fSMartin Matuska * the kernel will sort that out for us. 144315ee00fSMartin Matuska * 145315ee00fSMartin Matuska * FIDEDUPERANGE is for turning a non-clone into a clone, that is, compare the 146315ee00fSMartin Matuska * range in both files and if they're the same, arrange for them to be backed 147315ee00fSMartin Matuska * by the same storage. 148a4e5e010SMartin Matuska * 149a4e5e010SMartin Matuska * REMAP_FILE_CAN_SHORTEN lets us know we can clone less than the given range 150a4e5e010SMartin Matuska * if we want. It's designed for filesystems that may need to shorten the 151a4e5e010SMartin Matuska * length for alignment, EOF, or any other requirement. ZFS may shorten the 152a4e5e010SMartin Matuska * request when there is outstanding dirty data which hasn't been written. 153315ee00fSMartin Matuska */ 154315ee00fSMartin Matuska loff_t 155315ee00fSMartin Matuska zpl_remap_file_range(struct file *src_file, loff_t src_off, 156315ee00fSMartin Matuska struct file *dst_file, loff_t dst_off, loff_t len, unsigned int flags) 157315ee00fSMartin Matuska { 158315ee00fSMartin Matuska if (flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_CAN_SHORTEN)) 159315ee00fSMartin Matuska return (-EINVAL); 160315ee00fSMartin Matuska 161315ee00fSMartin Matuska /* No support for dedup yet */ 162a4e5e010SMartin Matuska if (flags & REMAP_FILE_DEDUP) 163315ee00fSMartin Matuska return (-EOPNOTSUPP); 164315ee00fSMartin Matuska 165315ee00fSMartin Matuska /* Zero length means to clone everything to the end of the file */ 166315ee00fSMartin Matuska if (len == 0) 167315ee00fSMartin Matuska len = i_size_read(file_inode(src_file)) - src_off; 168315ee00fSMartin Matuska 169a4e5e010SMartin Matuska ssize_t ret = zpl_clone_file_range_impl(src_file, src_off, 170a4e5e010SMartin Matuska dst_file, dst_off, len); 171a4e5e010SMartin Matuska 172a4e5e010SMartin Matuska if (!(flags & REMAP_FILE_CAN_SHORTEN) && ret >= 0 && ret != len) 173a4e5e010SMartin Matuska ret = -EINVAL; 174a4e5e010SMartin Matuska 175a4e5e010SMartin Matuska return (ret); 176315ee00fSMartin Matuska } 177315ee00fSMartin Matuska #endif /* HAVE_VFS_REMAP_FILE_RANGE */ 178315ee00fSMartin Matuska 179*7a7741afSMartin Matuska #if defined(HAVE_VFS_CLONE_FILE_RANGE) 180315ee00fSMartin Matuska /* 181315ee00fSMartin Matuska * Entry point for FICLONE and FICLONERANGE, before Linux 4.20. 182315ee00fSMartin Matuska */ 183315ee00fSMartin Matuska int 184315ee00fSMartin Matuska zpl_clone_file_range(struct file *src_file, loff_t src_off, 185315ee00fSMartin Matuska struct file *dst_file, loff_t dst_off, uint64_t len) 186315ee00fSMartin Matuska { 187315ee00fSMartin Matuska /* Zero length means to clone everything to the end of the file */ 188315ee00fSMartin Matuska if (len == 0) 189315ee00fSMartin Matuska len = i_size_read(file_inode(src_file)) - src_off; 190315ee00fSMartin Matuska 191a4e5e010SMartin Matuska /* The entire length must be cloned or this is an error. */ 192a4e5e010SMartin Matuska ssize_t ret = zpl_clone_file_range_impl(src_file, src_off, 193a4e5e010SMartin Matuska dst_file, dst_off, len); 194a4e5e010SMartin Matuska 195a4e5e010SMartin Matuska if (ret >= 0 && ret != len) 196a4e5e010SMartin Matuska ret = -EINVAL; 197a4e5e010SMartin Matuska 198a4e5e010SMartin Matuska return (ret); 199315ee00fSMartin Matuska } 200*7a7741afSMartin Matuska #endif /* HAVE_VFS_CLONE_FILE_RANGE */ 201315ee00fSMartin Matuska 202315ee00fSMartin Matuska #ifdef HAVE_VFS_DEDUPE_FILE_RANGE 203315ee00fSMartin Matuska /* 204315ee00fSMartin Matuska * Entry point for FIDEDUPERANGE, before Linux 4.20. 205315ee00fSMartin Matuska */ 206315ee00fSMartin Matuska int 207315ee00fSMartin Matuska zpl_dedupe_file_range(struct file *src_file, loff_t src_off, 208315ee00fSMartin Matuska struct file *dst_file, loff_t dst_off, uint64_t len) 209315ee00fSMartin Matuska { 210315ee00fSMartin Matuska /* No support for dedup yet */ 211315ee00fSMartin Matuska return (-EOPNOTSUPP); 212315ee00fSMartin Matuska } 213315ee00fSMartin Matuska #endif /* HAVE_VFS_DEDUPE_FILE_RANGE */ 214315ee00fSMartin Matuska 215315ee00fSMartin Matuska /* Entry point for FICLONE, before Linux 4.5. */ 216315ee00fSMartin Matuska long 217315ee00fSMartin Matuska zpl_ioctl_ficlone(struct file *dst_file, void *arg) 218315ee00fSMartin Matuska { 219315ee00fSMartin Matuska unsigned long sfd = (unsigned long)arg; 220315ee00fSMartin Matuska 221315ee00fSMartin Matuska struct file *src_file = fget(sfd); 222315ee00fSMartin Matuska if (src_file == NULL) 223315ee00fSMartin Matuska return (-EBADF); 224315ee00fSMartin Matuska 22523cf27dbSMartin Matuska if (dst_file->f_op != src_file->f_op) { 22623cf27dbSMartin Matuska fput(src_file); 227315ee00fSMartin Matuska return (-EXDEV); 22823cf27dbSMartin Matuska } 229315ee00fSMartin Matuska 230315ee00fSMartin Matuska size_t len = i_size_read(file_inode(src_file)); 231315ee00fSMartin Matuska 232a4e5e010SMartin Matuska ssize_t ret = zpl_clone_file_range_impl(src_file, 0, dst_file, 0, len); 233315ee00fSMartin Matuska 234315ee00fSMartin Matuska fput(src_file); 235315ee00fSMartin Matuska 236315ee00fSMartin Matuska if (ret < 0) { 237315ee00fSMartin Matuska if (ret == -EOPNOTSUPP) 238315ee00fSMartin Matuska return (-ENOTTY); 239315ee00fSMartin Matuska return (ret); 240315ee00fSMartin Matuska } 241315ee00fSMartin Matuska 242315ee00fSMartin Matuska if (ret != len) 243315ee00fSMartin Matuska return (-EINVAL); 244315ee00fSMartin Matuska 245315ee00fSMartin Matuska return (0); 246315ee00fSMartin Matuska } 247315ee00fSMartin Matuska 248315ee00fSMartin Matuska /* Entry point for FICLONERANGE, before Linux 4.5. */ 249315ee00fSMartin Matuska long 250315ee00fSMartin Matuska zpl_ioctl_ficlonerange(struct file *dst_file, void __user *arg) 251315ee00fSMartin Matuska { 252315ee00fSMartin Matuska zfs_ioc_compat_file_clone_range_t fcr; 253315ee00fSMartin Matuska 254315ee00fSMartin Matuska if (copy_from_user(&fcr, arg, sizeof (fcr))) 255315ee00fSMartin Matuska return (-EFAULT); 256315ee00fSMartin Matuska 257315ee00fSMartin Matuska struct file *src_file = fget(fcr.fcr_src_fd); 258315ee00fSMartin Matuska if (src_file == NULL) 259315ee00fSMartin Matuska return (-EBADF); 260315ee00fSMartin Matuska 26123cf27dbSMartin Matuska if (dst_file->f_op != src_file->f_op) { 26223cf27dbSMartin Matuska fput(src_file); 263315ee00fSMartin Matuska return (-EXDEV); 26423cf27dbSMartin Matuska } 265315ee00fSMartin Matuska 266315ee00fSMartin Matuska size_t len = fcr.fcr_src_length; 267315ee00fSMartin Matuska if (len == 0) 268315ee00fSMartin Matuska len = i_size_read(file_inode(src_file)) - fcr.fcr_src_offset; 269315ee00fSMartin Matuska 270a4e5e010SMartin Matuska ssize_t ret = zpl_clone_file_range_impl(src_file, fcr.fcr_src_offset, 271315ee00fSMartin Matuska dst_file, fcr.fcr_dest_offset, len); 272315ee00fSMartin Matuska 273315ee00fSMartin Matuska fput(src_file); 274315ee00fSMartin Matuska 275315ee00fSMartin Matuska if (ret < 0) { 276315ee00fSMartin Matuska if (ret == -EOPNOTSUPP) 277315ee00fSMartin Matuska return (-ENOTTY); 278315ee00fSMartin Matuska return (ret); 279315ee00fSMartin Matuska } 280315ee00fSMartin Matuska 281315ee00fSMartin Matuska if (ret != len) 282315ee00fSMartin Matuska return (-EINVAL); 283315ee00fSMartin Matuska 284315ee00fSMartin Matuska return (0); 285315ee00fSMartin Matuska } 286315ee00fSMartin Matuska 287315ee00fSMartin Matuska /* Entry point for FIDEDUPERANGE, before Linux 4.5. */ 288315ee00fSMartin Matuska long 289315ee00fSMartin Matuska zpl_ioctl_fideduperange(struct file *filp, void *arg) 290315ee00fSMartin Matuska { 291315ee00fSMartin Matuska (void) arg; 292315ee00fSMartin Matuska 293315ee00fSMartin Matuska /* No support for dedup yet */ 294315ee00fSMartin Matuska return (-ENOTTY); 295315ee00fSMartin Matuska } 296