summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2018-07-03 20:40:26 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2018-07-03 20:40:26 +0000
commit7172f60910c3353e8a649d297b80d3bcab9cabfe (patch)
treeda1b4649fcf0d17b6d56cff207990e21be67cd8e /sys
parent9decf10757b69d8f3d9fc71615993eb79208ce45 (diff)
Add a new so_seek member to "struct file" such that we can have seekable
files that aren't vnodes. Move the vnode-specific code into its own function. Add an implementation for the "DMA buffers" that can be used by DRI3/prime code to find out the size of the graphics buffer. This implementation is very limited and only supports offset 0 and only for SEEK_SET and SEEK_END. This doesn't really make sense; implementing stat(2) would be a more obvious choice. But this is what Linux does. ok guenther@, visa@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/drm/drm_linux.c29
-rw-r--r--sys/kern/vfs_syscalls.c47
-rw-r--r--sys/kern/vfs_vnops.c46
-rw-r--r--sys/sys/file.h3
4 files changed, 83 insertions, 42 deletions
diff --git a/sys/dev/pci/drm/drm_linux.c b/sys/dev/pci/drm/drm_linux.c
index 4205b46291a..6564fd89b2a 100644
--- a/sys/dev/pci/drm/drm_linux.c
+++ b/sys/dev/pci/drm/drm_linux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: drm_linux.c,v 1.25 2018/07/01 12:12:14 kettenis Exp $ */
+/* $OpenBSD: drm_linux.c,v 1.26 2018/07/03 20:40:25 kettenis Exp $ */
/*
* Copyright (c) 2013 Jonathan Gray <jsg@openbsd.org>
* Copyright (c) 2015, 2016 Mark Kettenis <kettenis@openbsd.org>
@@ -22,6 +22,7 @@
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/stat.h>
+#include <sys/unistd.h>
struct mutex sch_mtx = MUTEX_INITIALIZER(IPL_SCHED);
void *sch_ident;
@@ -859,6 +860,29 @@ dmabuf_close(struct file *fp, struct proc *p)
return (0);
}
+int
+dmabuf_seek(struct file *fp, off_t *offset, int whence, struct proc *p)
+{
+ struct dma_buf *dmabuf = fp->f_data;
+ off_t newoff;
+
+ if (*offset != 0)
+ return (EINVAL);
+
+ switch (whence) {
+ case SEEK_SET:
+ newoff = 0;
+ break;
+ case SEEK_END:
+ newoff = dmabuf->size;
+ break;
+ default:
+ return (EINVAL);
+ }
+ fp->f_offset = *offset = newoff;
+ return (0);
+}
+
struct fileops dmabufops = {
.fo_read = dmabuf_read,
.fo_write = dmabuf_write,
@@ -866,7 +890,8 @@ struct fileops dmabufops = {
.fo_poll = dmabuf_poll,
.fo_kqfilter = dmabuf_kqfilter,
.fo_stat = dmabuf_stat,
- .fo_close = dmabuf_close
+ .fo_close = dmabuf_close,
+ .fo_seek = dmabuf_seek,
};
struct dma_buf *
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index ffc171b6576..da74978c8da 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.291 2018/06/25 16:06:27 visa Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.292 2018/07/03 20:40:25 kettenis Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -1621,51 +1621,24 @@ sys_lseek(struct proc *p, void *v, register_t *retval)
syscallarg(off_t) offset;
syscallarg(int) whence;
} */ *uap = v;
- struct ucred *cred = p->p_ucred;
struct filedesc *fdp = p->p_fd;
struct file *fp;
- struct vattr vattr;
- struct vnode *vp;
- off_t offarg, newoff;
- int error, special;
+ off_t offset;
+ int error;
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
return (EBADF);
- vp = fp->f_data;
- if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
+ if (fp->f_ops->fo_seek == NULL) {
error = ESPIPE;
goto bad;
}
- if (vp->v_type == VCHR)
- special = 1;
- else
- special = 0;
- offarg = SCARG(uap, offset);
-
- switch (SCARG(uap, whence)) {
- case SEEK_CUR:
- newoff = fp->f_offset + offarg;
- break;
- case SEEK_END:
- error = VOP_GETATTR(vp, &vattr, cred, p);
- if (error)
- goto bad;
- newoff = offarg + (off_t)vattr.va_size;
- break;
- case SEEK_SET:
- newoff = offarg;
- break;
- default:
- error = EINVAL;
+ offset = SCARG(uap, offset);
+
+ error = (*fp->f_ops->fo_seek)(fp, &offset, SCARG(uap, whence), p);
+ if (error)
goto bad;
- }
- if (!special) {
- if (newoff < 0) {
- error = EINVAL;
- goto bad;
- }
- }
- *(off_t *)retval = fp->f_offset = newoff;
+
+ *(off_t *)retval = offset;
mtx_enter(&fp->f_mtx);
fp->f_seek++;
mtx_leave(&fp->f_mtx);
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 2dbc93adba4..c20982e0308 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_vnops.c,v 1.94 2018/07/03 12:58:18 anton Exp $ */
+/* $OpenBSD: vfs_vnops.c,v 1.95 2018/07/03 20:40:25 kettenis Exp $ */
/* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */
/*
@@ -64,6 +64,7 @@ int vn_write(struct file *, off_t *, struct uio *, struct ucred *);
int vn_poll(struct file *, int, struct proc *);
int vn_kqfilter(struct file *, struct knote *);
int vn_closefile(struct file *, struct proc *);
+int vn_seek(struct file *, off_t *, int, struct proc *);
struct fileops vnops = {
.fo_read = vn_read,
@@ -72,7 +73,8 @@ struct fileops vnops = {
.fo_poll = vn_poll,
.fo_kqfilter = vn_kqfilter,
.fo_stat = vn_statfile,
- .fo_close = vn_closefile
+ .fo_close = vn_closefile,
+ .fo_seek = vn_seek,
};
/*
@@ -561,6 +563,46 @@ vn_kqfilter(struct file *fp, struct knote *kn)
return (VOP_KQFILTER(fp->f_data, kn));
}
+int
+vn_seek(struct file *fp, off_t *offset, int whence, struct proc *p)
+{
+ struct ucred *cred = p->p_ucred;
+ struct vnode *vp = fp->f_data;
+ struct vattr vattr;
+ off_t newoff;
+ int error, special;
+
+ if (vp->v_type == VFIFO)
+ return (ESPIPE);
+ if (vp->v_type == VCHR)
+ special = 1;
+ else
+ special = 0;
+
+ switch (whence) {
+ case SEEK_CUR:
+ newoff = fp->f_offset + *offset;
+ break;
+ case SEEK_END:
+ error = VOP_GETATTR(vp, &vattr, cred, p);
+ if (error)
+ return (error);
+ newoff = *offset + (off_t)vattr.va_size;
+ break;
+ case SEEK_SET:
+ newoff = *offset;
+ break;
+ default:
+ return (EINVAL);
+ }
+ if (!special) {
+ if (newoff < 0)
+ return(EINVAL);
+ }
+ fp->f_offset = *offset = newoff;
+ return (0);
+}
+
/*
* Common code for vnode access operations.
*/
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 114c192d766..ef543367479 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.h,v 1.51 2018/07/02 14:36:33 visa Exp $ */
+/* $OpenBSD: file.h,v 1.52 2018/07/03 20:40:25 kettenis Exp $ */
/* $NetBSD: file.h,v 1.11 1995/03/26 20:24:13 jtc Exp $ */
/*
@@ -57,6 +57,7 @@ struct fileops {
int (*fo_kqfilter)(struct file *, struct knote *);
int (*fo_stat)(struct file *, struct stat *, struct proc *);
int (*fo_close)(struct file *, struct proc *);
+ int (*fo_seek)(struct file *, off_t *, int, struct proc *);
};
/*