diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-07-03 20:40:26 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-07-03 20:40:26 +0000 |
commit | 7172f60910c3353e8a649d297b80d3bcab9cabfe (patch) | |
tree | da1b4649fcf0d17b6d56cff207990e21be67cd8e /sys | |
parent | 9decf10757b69d8f3d9fc71615993eb79208ce45 (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.c | 29 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 47 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 46 | ||||
-rw-r--r-- | sys/sys/file.h | 3 |
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 *); }; /* |