1 /* 2 * Copyright (c) 2020 iXsystems, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/dmu.h> 29 #include <sys/dmu_impl.h> 30 #include <sys/dmu_recv.h> 31 #include <sys/dmu_tx.h> 32 #include <sys/dbuf.h> 33 #include <sys/dnode.h> 34 #include <sys/zfs_context.h> 35 #include <sys/dmu_objset.h> 36 #include <sys/dmu_traverse.h> 37 #include <sys/dsl_dataset.h> 38 #include <sys/dsl_dir.h> 39 #include <sys/dsl_pool.h> 40 #include <sys/dsl_synctask.h> 41 #include <sys/zfs_ioctl.h> 42 #include <sys/zap.h> 43 #include <sys/zio_checksum.h> 44 #include <sys/zfs_znode.h> 45 #include <sys/zfs_file.h> 46 #include <sys/buf.h> 47 #include <sys/stat.h> 48 49 int 50 zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp) 51 { 52 struct thread *td; 53 struct vnode *vp; 54 struct file *fp; 55 struct nameidata nd; 56 int error; 57 58 td = curthread; 59 pwd_ensure_dirs(); 60 61 KASSERT((flags & (O_EXEC | O_PATH)) == 0, 62 ("invalid flags: 0x%x", flags)); 63 KASSERT((flags & O_ACCMODE) != O_ACCMODE, 64 ("invalid flags: 0x%x", flags)); 65 flags = FFLAGS(flags); 66 67 error = falloc_noinstall(td, &fp); 68 if (error != 0) { 69 return (error); 70 } 71 fp->f_flag = flags & FMASK; 72 73 #if __FreeBSD_version >= 1400043 74 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path); 75 #else 76 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); 77 #endif 78 error = vn_open(&nd, &flags, mode, fp); 79 if (error != 0) { 80 falloc_abort(td, fp); 81 return (SET_ERROR(error)); 82 } 83 NDFREE_PNBUF(&nd); 84 vp = nd.ni_vp; 85 fp->f_vnode = vp; 86 if (fp->f_ops == &badfileops) { 87 finit_vnode(fp, flags, NULL, &vnops); 88 } 89 VOP_UNLOCK(vp); 90 if (vp->v_type != VREG) { 91 zfs_file_close(fp); 92 return (SET_ERROR(EACCES)); 93 } 94 95 if (flags & O_TRUNC) { 96 error = fo_truncate(fp, 0, td->td_ucred, td); 97 if (error != 0) { 98 zfs_file_close(fp); 99 return (SET_ERROR(error)); 100 } 101 } 102 103 *fpp = fp; 104 105 return (0); 106 } 107 108 void 109 zfs_file_close(zfs_file_t *fp) 110 { 111 fdrop(fp, curthread); 112 } 113 114 static int 115 zfs_file_write_impl(zfs_file_t *fp, const void *buf, size_t count, loff_t *offp, 116 ssize_t *resid) 117 { 118 ssize_t rc; 119 struct uio auio; 120 struct thread *td; 121 struct iovec aiov; 122 123 td = curthread; 124 aiov.iov_base = (void *)(uintptr_t)buf; 125 aiov.iov_len = count; 126 auio.uio_iov = &aiov; 127 auio.uio_iovcnt = 1; 128 auio.uio_segflg = UIO_SYSSPACE; 129 auio.uio_resid = count; 130 auio.uio_rw = UIO_WRITE; 131 auio.uio_td = td; 132 auio.uio_offset = *offp; 133 134 if ((fp->f_flag & FWRITE) == 0) 135 return (SET_ERROR(EBADF)); 136 137 if (fp->f_type == DTYPE_VNODE) 138 bwillwrite(); 139 140 rc = fo_write(fp, &auio, td->td_ucred, FOF_OFFSET, td); 141 if (rc) 142 return (SET_ERROR(rc)); 143 if (resid) 144 *resid = auio.uio_resid; 145 else if (auio.uio_resid) 146 return (SET_ERROR(EIO)); 147 *offp += count - auio.uio_resid; 148 return (rc); 149 } 150 151 int 152 zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid) 153 { 154 loff_t off = fp->f_offset; 155 ssize_t rc; 156 157 rc = zfs_file_write_impl(fp, buf, count, &off, resid); 158 if (rc == 0) 159 fp->f_offset = off; 160 161 return (SET_ERROR(rc)); 162 } 163 164 int 165 zfs_file_pwrite(zfs_file_t *fp, const void *buf, size_t count, loff_t off, 166 ssize_t *resid) 167 { 168 return (zfs_file_write_impl(fp, buf, count, &off, resid)); 169 } 170 171 static int 172 zfs_file_read_impl(zfs_file_t *fp, void *buf, size_t count, loff_t *offp, 173 ssize_t *resid) 174 { 175 ssize_t rc; 176 struct uio auio; 177 struct thread *td; 178 struct iovec aiov; 179 180 td = curthread; 181 aiov.iov_base = (void *)(uintptr_t)buf; 182 aiov.iov_len = count; 183 auio.uio_iov = &aiov; 184 auio.uio_iovcnt = 1; 185 auio.uio_segflg = UIO_SYSSPACE; 186 auio.uio_resid = count; 187 auio.uio_rw = UIO_READ; 188 auio.uio_td = td; 189 auio.uio_offset = *offp; 190 191 if ((fp->f_flag & FREAD) == 0) 192 return (SET_ERROR(EBADF)); 193 194 rc = fo_read(fp, &auio, td->td_ucred, FOF_OFFSET, td); 195 if (rc) 196 return (SET_ERROR(rc)); 197 if (resid) 198 *resid = auio.uio_resid; 199 *offp += count - auio.uio_resid; 200 return (SET_ERROR(0)); 201 } 202 203 int 204 zfs_file_read(zfs_file_t *fp, void *buf, size_t count, ssize_t *resid) 205 { 206 loff_t off = fp->f_offset; 207 ssize_t rc; 208 209 rc = zfs_file_read_impl(fp, buf, count, &off, resid); 210 if (rc == 0) 211 fp->f_offset = off; 212 return (rc); 213 } 214 215 int 216 zfs_file_pread(zfs_file_t *fp, void *buf, size_t count, loff_t off, 217 ssize_t *resid) 218 { 219 return (zfs_file_read_impl(fp, buf, count, &off, resid)); 220 } 221 222 int 223 zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence) 224 { 225 int rc; 226 struct thread *td; 227 228 td = curthread; 229 if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0) 230 return (SET_ERROR(ESPIPE)); 231 rc = fo_seek(fp, *offp, whence, td); 232 if (rc == 0) 233 *offp = td->td_uretoff.tdu_off; 234 return (SET_ERROR(rc)); 235 } 236 237 int 238 zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr) 239 { 240 struct thread *td; 241 struct stat sb; 242 int rc; 243 244 td = curthread; 245 246 #if __FreeBSD_version < 1400037 247 rc = fo_stat(fp, &sb, td->td_ucred, td); 248 #else 249 rc = fo_stat(fp, &sb, td->td_ucred); 250 #endif 251 if (rc) 252 return (SET_ERROR(rc)); 253 zfattr->zfa_size = sb.st_size; 254 zfattr->zfa_mode = sb.st_mode; 255 256 return (0); 257 } 258 259 static __inline int 260 zfs_vop_fsync(vnode_t *vp) 261 { 262 struct mount *mp; 263 int error; 264 265 #if __FreeBSD_version < 1400068 266 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 267 #else 268 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 269 #endif 270 goto drop; 271 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 272 error = VOP_FSYNC(vp, MNT_WAIT, curthread); 273 VOP_UNLOCK(vp); 274 vn_finished_write(mp); 275 drop: 276 return (SET_ERROR(error)); 277 } 278 279 int 280 zfs_file_fsync(zfs_file_t *fp, int flags) 281 { 282 if (fp->f_type != DTYPE_VNODE) 283 return (EINVAL); 284 285 return (zfs_vop_fsync(fp->f_vnode)); 286 } 287 288 /* 289 * deallocate - zero and/or deallocate file storage 290 * 291 * fp - file pointer 292 * offset - offset to start zeroing or deallocating 293 * len - length to zero or deallocate 294 */ 295 int 296 zfs_file_deallocate(zfs_file_t *fp, loff_t offset, loff_t len) 297 { 298 int rc; 299 #if __FreeBSD_version >= 1400029 300 struct thread *td; 301 302 td = curthread; 303 rc = fo_fspacectl(fp, SPACECTL_DEALLOC, &offset, &len, 0, 304 td->td_ucred, td); 305 #else 306 (void) fp, (void) offset, (void) len; 307 rc = EOPNOTSUPP; 308 #endif 309 if (rc) 310 return (SET_ERROR(rc)); 311 return (0); 312 } 313 314 zfs_file_t * 315 zfs_file_get(int fd) 316 { 317 struct file *fp; 318 319 if (fget(curthread, fd, &cap_no_rights, &fp)) 320 return (NULL); 321 322 return (fp); 323 } 324 325 void 326 zfs_file_put(zfs_file_t *fp) 327 { 328 zfs_file_close(fp); 329 } 330 331 loff_t 332 zfs_file_off(zfs_file_t *fp) 333 { 334 return (fp->f_offset); 335 } 336 337 void * 338 zfs_file_private(zfs_file_t *fp) 339 { 340 file_t *tmpfp; 341 void *data; 342 int error; 343 344 tmpfp = curthread->td_fpop; 345 curthread->td_fpop = fp; 346 error = devfs_get_cdevpriv(&data); 347 curthread->td_fpop = tmpfp; 348 if (error != 0) 349 return (NULL); 350 return (data); 351 } 352 353 int 354 zfs_file_unlink(const char *fnamep) 355 { 356 zfs_uio_seg_t seg = UIO_SYSSPACE; 357 int rc; 358 359 rc = kern_funlinkat(curthread, AT_FDCWD, fnamep, FD_NONE, seg, 0, 0); 360 return (SET_ERROR(rc)); 361 } 362