summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2010-06-08 12:46:50 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2010-06-08 12:46:50 +0000
commitfc2d3c3e9914001f51aa755467171dbebcaec775 (patch)
tree0895ad9ca2baaef2a4e1f9af7016af3cff44f53f /sys
parent718c49577dc5cf6a35fb74f67f73bd311101d708 (diff)
Introduce a diskmap pseudo device which allows userland to open a disk
specified via its disklabel UID. The mapping from the disklabel UID to the real disk and the opening of the resulting device is performed atomically using a single ioctl. ok krw@ deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files3
-rw-r--r--sys/dev/diskmap.c152
-rw-r--r--sys/sys/conf.h4
-rw-r--r--sys/sys/dkio.h10
4 files changed, 166 insertions, 3 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 4c9c5d674fb..463a1ee17a7 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.491 2010/05/26 16:16:23 thib Exp $
+# $OpenBSD: files,v 1.492 2010/06/08 12:46:49 jsing Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -591,6 +591,7 @@ file dev/auconv.c auconv
file dev/audio.c audio needs-flag
file dev/ccd.c ccd needs-flag
file dev/cons.c
+file dev/diskmap.c
file dev/firmload.c firmload
file dev/flash.c flash needs-flag
file dev/ic/ncr5380sbc.c ncr5380sbc
diff --git a/sys/dev/diskmap.c b/sys/dev/diskmap.c
new file mode 100644
index 00000000000..cf5951a6e1d
--- /dev/null
+++ b/sys/dev/diskmap.c
@@ -0,0 +1,152 @@
+/* $OpenBSD: diskmap.c,v 1.1 2010/06/08 12:46:49 jsing Exp $ */
+
+/*
+ * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Disk mapper.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/dkio.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/malloc.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+
+int
+diskmapopen(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ return 0;
+}
+
+int
+diskmapclose(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ return 0;
+}
+
+int
+diskmapioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
+{
+ struct dk_diskmap *dm;
+ struct nameidata ndp;
+ struct filedesc *fdp;
+ struct file *fp;
+ struct vnode *vp = NULL, *ovp;
+ char *devname;
+ int fd, error = EINVAL;
+
+ if (cmd != DIOCMAP)
+ return EINVAL;
+
+ /*
+ * Map a request for a disk to the correct device. We should be
+ * supplied with either a diskname or a disklabel UID.
+ */
+
+ dm = (struct dk_diskmap *)addr;
+ fd = dm->fd;
+ devname = malloc(PATH_MAX, M_DEVBUF, M_WAITOK);
+ if (copyinstr(dm->device, devname, PATH_MAX, NULL))
+ goto invalid;
+ if (disk_map(devname, devname, PATH_MAX, dm->flags) == 0)
+ if (copyoutstr(devname, dm->device, PATH_MAX, NULL))
+ goto invalid;
+
+ /* Attempt to open actual device. */
+ fdp = p->p_fd;
+ fdplock(fdp);
+
+ if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) {
+ error = EINVAL;
+ goto bad;
+ }
+
+ if (FILE_IS_USABLE(fp) == NULL) {
+ error = EINVAL;
+ goto bad;
+ }
+
+ NDINIT(&ndp, LOOKUP, NOFOLLOW | LOCKLEAF | SAVENAME, UIO_SYSSPACE,
+ devname, p);
+
+ if ((error = vn_open(&ndp, fp->f_flag, 0)) != 0)
+ goto bad;
+
+ vp = ndp.ni_vp;
+
+ /* Close the original vnode. */
+ ovp = (struct vnode *)fp->f_data;
+ if (fp->f_flag & FWRITE)
+ ovp->v_writecount--;
+
+ if (ovp->v_writecount == 0) {
+ vn_lock(ovp, LK_EXCLUSIVE | LK_RETRY, p);
+ VOP_CLOSE(ovp, fp->f_flag, p->p_ucred, p);
+ vput(ovp);
+ }
+
+ fp->f_type = DTYPE_VNODE;
+ fp->f_ops = &vnops;
+ fp->f_data = (caddr_t)vp;
+ fp->f_offset = 0;
+ fp->f_rxfer = 0;
+ fp->f_wxfer = 0;
+ fp->f_seek = 0;
+ fp->f_rbytes = 0;
+ fp->f_wbytes = 0;
+
+ VOP_UNLOCK(vp, 0, p);
+
+ fdpunlock(fdp);
+
+ return 0;
+
+bad:
+ if (vp)
+ vput(vp);
+
+ fdpunlock(fdp);
+
+invalid:
+ if (devname)
+ free(devname, M_DEVBUF);
+
+ return (error);
+}
+
+int
+diskmapread(dev_t dev, struct uio *uio, int flag)
+{
+ return ENXIO;
+}
+
+int
+diskmapwrite(dev_t dev, struct uio *uio, int flag)
+{
+ return ENXIO;
+}
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index 096b04cfe7f..5e7f3f0f62f 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.96 2010/04/12 12:57:52 tedu Exp $ */
+/* $OpenBSD: conf.h,v 1.97 2010/06/08 12:46:49 jsing Exp $ */
/* $NetBSD: conf.h,v 1.33 1996/05/03 20:03:32 christos Exp $ */
/*-
@@ -639,6 +639,8 @@ cdev_decl(rd);
bdev_decl(uk);
cdev_decl(uk);
+cdev_decl(diskmap);
+
cdev_decl(bpf);
cdev_decl(pf);
diff --git a/sys/sys/dkio.h b/sys/sys/dkio.h
index d46d518cbc8..791d790ce26 100644
--- a/sys/sys/dkio.h
+++ b/sys/sys/dkio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dkio.h,v 1.7 2010/05/19 05:29:14 dlg Exp $ */
+/* $OpenBSD: dkio.h,v 1.8 2010/06/08 12:46:49 jsing Exp $ */
/* $NetBSD: dkio.h,v 1.1 1996/01/30 18:21:48 thorpej Exp $ */
/*
@@ -76,4 +76,12 @@ struct dk_cache {
#define DIOCGCACHE _IOR('d', 117, struct dk_cache) /* get cache enabled */
#define DIOCSCACHE _IOW('d', 118, struct dk_cache) /* set cache enabled */
+struct dk_diskmap {
+ char *device;
+ int fd;
+ int flags;
+};
+
+#define DIOCMAP _IOWR('d', 119, struct dk_diskmap)
+
#endif /* _SYS_DKIO_H_ */