aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2020-01-08 19:05:32 +0000
committerKyle Evans <kevans@FreeBSD.org>2020-01-08 19:05:32 +0000
commit2856d85ecbe2e402e55913c31d77823f83316a5a (patch)
tree4fff4fdea8b74e3436b02ce7fbcf31319ed0d65b /sys/kern
parentf57d4d4641a329fad1d373d2d098560da48d53ee (diff)
downloadsrc-2856d85ecbe2e402e55913c31d77823f83316a5a.tar.gz
src-2856d85ecbe2e402e55913c31d77823f83316a5a.zip
posix_fallocate: push vnop implementation into the fileop layer
This opens the door for other descriptor types to implement posix_fallocate(2) as needed. Reviewed by: kib, bcr (manpages) Differential Revision: https://reviews.freebsd.org/D23042
Notes
Notes: svn path=/head/; revision=356510
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/sys_generic.c41
-rw-r--r--sys/kern/vfs_syscalls.c93
-rw-r--r--sys/kern/vfs_vnops.c59
3 files changed, 100 insertions, 93 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index cd78cfbfbba2..8e614a0accc6 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -819,6 +819,47 @@ out:
}
int
+sys_posix_fallocate(struct thread *td, struct posix_fallocate_args *uap)
+{
+ int error;
+
+ error = kern_posix_fallocate(td, uap->fd, uap->offset, uap->len);
+ return (kern_posix_error(td, error));
+}
+
+int
+kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len)
+{
+ struct file *fp;
+ int error;
+
+ AUDIT_ARG_FD(fd);
+ if (offset < 0 || len <= 0)
+ return (EINVAL);
+ /* Check for wrap. */
+ if (offset > OFF_MAX - len)
+ return (EFBIG);
+ AUDIT_ARG_FD(fd);
+ error = fget(td, fd, &cap_pwrite_rights, &fp);
+ if (error != 0)
+ return (error);
+ AUDIT_ARG_FILE(td->td_proc, fp);
+ if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0) {
+ error = ESPIPE;
+ goto out;
+ }
+ if ((fp->f_flag & FWRITE) == 0) {
+ error = EBADF;
+ goto out;
+ }
+
+ error = fo_fallocate(fp, offset, len, td);
+ out:
+ fdrop(fp, td);
+ return (error);
+}
+
+int
poll_no_poll(int events)
{
/*
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index b954e3a6dd45..a3b66f0bcf47 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -4565,99 +4565,6 @@ out:
return (error);
}
-int
-kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len)
-{
- struct file *fp;
- struct mount *mp;
- struct vnode *vp;
- off_t olen, ooffset;
- int error;
-#ifdef AUDIT
- int audited_vnode1 = 0;
-#endif
-
- AUDIT_ARG_FD(fd);
- if (offset < 0 || len <= 0)
- return (EINVAL);
- /* Check for wrap. */
- if (offset > OFF_MAX - len)
- return (EFBIG);
- AUDIT_ARG_FD(fd);
- error = fget(td, fd, &cap_pwrite_rights, &fp);
- if (error != 0)
- return (error);
- AUDIT_ARG_FILE(td->td_proc, fp);
- if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0) {
- error = ESPIPE;
- goto out;
- }
- if ((fp->f_flag & FWRITE) == 0) {
- error = EBADF;
- goto out;
- }
- if (fp->f_type != DTYPE_VNODE) {
- error = ENODEV;
- goto out;
- }
- vp = fp->f_vnode;
- if (vp->v_type != VREG) {
- error = ENODEV;
- goto out;
- }
-
- /* Allocating blocks may take a long time, so iterate. */
- for (;;) {
- olen = len;
- ooffset = offset;
-
- bwillwrite();
- mp = NULL;
- error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
- if (error != 0)
- break;
- error = vn_lock(vp, LK_EXCLUSIVE);
- if (error != 0) {
- vn_finished_write(mp);
- break;
- }
-#ifdef AUDIT
- if (!audited_vnode1) {
- AUDIT_ARG_VNODE1(vp);
- audited_vnode1 = 1;
- }
-#endif
-#ifdef MAC
- error = mac_vnode_check_write(td->td_ucred, fp->f_cred, vp);
- if (error == 0)
-#endif
- error = VOP_ALLOCATE(vp, &offset, &len);
- VOP_UNLOCK(vp);
- vn_finished_write(mp);
-
- if (olen + ooffset != offset + len) {
- panic("offset + len changed from %jx/%jx to %jx/%jx",
- ooffset, olen, offset, len);
- }
- if (error != 0 || len == 0)
- break;
- KASSERT(olen > len, ("Iteration did not make progress?"));
- maybe_yield();
- }
- out:
- fdrop(fp, td);
- return (error);
-}
-
-int
-sys_posix_fallocate(struct thread *td, struct posix_fallocate_args *uap)
-{
- int error;
-
- error = kern_posix_fallocate(td, uap->fd, uap->offset, uap->len);
- return (kern_posix_error(td, error));
-}
-
/*
* Unlike madvise(2), we do not make a best effort to remember every
* possible caching hint. Instead, we remember the last setting with
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index f15ea0969b7e..61edb3165e01 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -103,6 +103,7 @@ static fo_kqfilter_t vn_kqfilter;
static fo_stat_t vn_statfile;
static fo_close_t vn_closefile;
static fo_mmap_t vn_mmap;
+static fo_fallocate_t vn_fallocate;
struct fileops vnops = {
.fo_read = vn_io_fault,
@@ -119,6 +120,7 @@ struct fileops vnops = {
.fo_seek = vn_seek,
.fo_fill_kinfo = vn_fill_kinfo,
.fo_mmap = vn_mmap,
+ .fo_fallocate = vn_fallocate,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
@@ -3150,3 +3152,60 @@ out:
free(dat, M_TEMP);
return (error);
}
+
+static int
+vn_fallocate(struct file *fp, off_t offset, off_t len, struct thread *td)
+{
+ struct mount *mp;
+ struct vnode *vp;
+ off_t olen, ooffset;
+ int error;
+#ifdef AUDIT
+ int audited_vnode1 = 0;
+#endif
+
+ vp = fp->f_vnode;
+ if (vp->v_type != VREG)
+ return (ENODEV);
+
+ /* Allocating blocks may take a long time, so iterate. */
+ for (;;) {
+ olen = len;
+ ooffset = offset;
+
+ bwillwrite();
+ mp = NULL;
+ error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
+ if (error != 0)
+ break;
+ error = vn_lock(vp, LK_EXCLUSIVE);
+ if (error != 0) {
+ vn_finished_write(mp);
+ break;
+ }
+#ifdef AUDIT
+ if (!audited_vnode1) {
+ AUDIT_ARG_VNODE1(vp);
+ audited_vnode1 = 1;
+ }
+#endif
+#ifdef MAC
+ error = mac_vnode_check_write(td->td_ucred, fp->f_cred, vp);
+ if (error == 0)
+#endif
+ error = VOP_ALLOCATE(vp, &offset, &len);
+ VOP_UNLOCK(vp);
+ vn_finished_write(mp);
+
+ if (olen + ooffset != offset + len) {
+ panic("offset + len changed from %jx/%jx to %jx/%jx",
+ ooffset, olen, offset, len);
+ }
+ if (error != 0 || len == 0)
+ break;
+ KASSERT(olen > len, ("Iteration did not make progress?"));
+ maybe_yield();
+ }
+
+ return (error);
+}