diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2010-06-08 12:46:50 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2010-06-08 12:46:50 +0000 |
commit | fc2d3c3e9914001f51aa755467171dbebcaec775 (patch) | |
tree | 0895ad9ca2baaef2a4e1f9af7016af3cff44f53f | |
parent | 718c49577dc5cf6a35fb74f67f73bd311101d708 (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@
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/dev/diskmap.c | 152 | ||||
-rw-r--r-- | sys/sys/conf.h | 4 | ||||
-rw-r--r-- | sys/sys/dkio.h | 10 |
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_ */ |