2 * Copyright (c) 2020 iXsystems, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
32 #include <sys/dmu_impl.h>
33 #include <sys/dmu_recv.h>
34 #include <sys/dmu_tx.h>
36 #include <sys/dnode.h>
37 #include <sys/zfs_context.h>
38 #include <sys/dmu_objset.h>
39 #include <sys/dmu_traverse.h>
40 #include <sys/dsl_dataset.h>
41 #include <sys/dsl_dir.h>
42 #include <sys/dsl_pool.h>
43 #include <sys/dsl_synctask.h>
44 #include <sys/zfs_ioctl.h>
46 #include <sys/zio_checksum.h>
47 #include <sys/zfs_znode.h>
48 #include <sys/zfs_file.h>
53 zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp)
60 /* 12.x doesn't take a const char * */
61 rc = kern_openat(td, AT_FDCWD, __DECONST(char *, path),
62 UIO_SYSSPACE, flags, mode);
64 return (SET_ERROR(rc));
65 fd = td->td_retval[0];
67 if (fget(curthread, fd, &cap_no_rights, fpp))
73 zfs_file_close(zfs_file_t *fp)
75 fo_close(fp, curthread);
79 zfs_file_write_impl(zfs_file_t *fp, const void *buf, size_t count, loff_t *offp,
88 aiov.iov_base = (void *)(uintptr_t)buf;
92 auio.uio_segflg = UIO_SYSSPACE;
93 auio.uio_resid = count;
94 auio.uio_rw = UIO_WRITE;
96 auio.uio_offset = *offp;
98 if ((fp->f_flag & FWRITE) == 0)
99 return (SET_ERROR(EBADF));
101 if (fp->f_type == DTYPE_VNODE)
104 rc = fo_write(fp, &auio, td->td_ucred, FOF_OFFSET, td);
106 return (SET_ERROR(rc));
108 *resid = auio.uio_resid;
109 else if (auio.uio_resid)
110 return (SET_ERROR(EIO));
111 *offp += count - auio.uio_resid;
116 zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid)
118 loff_t off = fp->f_offset;
121 rc = zfs_file_write_impl(fp, buf, count, &off, resid);
125 return (SET_ERROR(rc));
129 zfs_file_pwrite(zfs_file_t *fp, const void *buf, size_t count, loff_t off,
132 return (zfs_file_write_impl(fp, buf, count, &off, resid));
136 zfs_file_read_impl(zfs_file_t *fp, void *buf, size_t count, loff_t *offp,
145 aiov.iov_base = (void *)(uintptr_t)buf;
146 aiov.iov_len = count;
147 auio.uio_iov = &aiov;
149 auio.uio_segflg = UIO_SYSSPACE;
150 auio.uio_resid = count;
151 auio.uio_rw = UIO_READ;
153 auio.uio_offset = *offp;
155 if ((fp->f_flag & FREAD) == 0)
156 return (SET_ERROR(EBADF));
158 rc = fo_read(fp, &auio, td->td_ucred, FOF_OFFSET, td);
160 return (SET_ERROR(rc));
161 *resid = auio.uio_resid;
162 *offp += count - auio.uio_resid;
163 return (SET_ERROR(0));
167 zfs_file_read(zfs_file_t *fp, void *buf, size_t count, ssize_t *resid)
169 loff_t off = fp->f_offset;
172 rc = zfs_file_read_impl(fp, buf, count, &off, resid);
179 zfs_file_pread(zfs_file_t *fp, void *buf, size_t count, loff_t off,
182 return (zfs_file_read_impl(fp, buf, count, &off, resid));
186 zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence)
192 if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0)
193 return (SET_ERROR(ESPIPE));
194 rc = fo_seek(fp, *offp, whence, td);
196 *offp = td->td_uretoff.tdu_off;
197 return (SET_ERROR(rc));
201 zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr)
209 rc = fo_stat(fp, &sb, td->td_ucred, td);
211 return (SET_ERROR(rc));
212 zfattr->zfa_size = sb.st_size;
213 zfattr->zfa_mode = sb.st_mode;
219 zfs_vop_fsync(vnode_t *vp)
224 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
226 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
227 error = VOP_FSYNC(vp, MNT_WAIT, curthread);
229 vn_finished_write(mp);
231 return (SET_ERROR(error));
235 zfs_file_fsync(zfs_file_t *fp, int flags)
237 if (fp->f_type != DTYPE_VNODE)
240 return (zfs_vop_fsync(fp->f_vnode));
244 zfs_file_get(int fd, zfs_file_t **fpp)
248 if (fget(curthread, fd, &cap_no_rights, &fp))
249 return (SET_ERROR(EBADF));
260 /* No CAP_ rights required, as we're only releasing. */
261 if (fget(curthread, fd, &cap_no_rights, &fp) == 0) {
262 fdrop(fp, curthread);
263 fdrop(fp, curthread);
268 zfs_file_off(zfs_file_t *fp)
270 return (fp->f_offset);
274 zfs_file_private(zfs_file_t *fp)
280 tmpfp = curthread->td_fpop;
281 curthread->td_fpop = fp;
282 error = devfs_get_cdevpriv(&data);
283 curthread->td_fpop = tmpfp;
290 zfs_file_unlink(const char *fnamep)
292 enum uio_seg seg = UIO_SYSSPACE;
295 #if __FreeBSD_version >= 1300018
296 rc = kern_funlinkat(curthread, AT_FDCWD, fnamep, FD_NONE, seg, 0, 0);
299 rc = kern_unlinkat(curthread, AT_FDCWD, fnamep, seg, 0, 0);
301 rc = kern_unlinkat(curthread, AT_FDCWD, __DECONST(char *, fnamep),
305 return (SET_ERROR(rc));