xref: /openbsd-src/sys/dev/diskmap.c (revision c90a81c56dcebd6a1b73fe4aff9b03385b8e63b3)
1 /*	$OpenBSD: diskmap.c,v 1.24 2018/08/20 14:59:02 visa Exp $	*/
2 
3 /*
4  * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Disk mapper.
21  */
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/device.h>
26 #include <sys/errno.h>
27 #include <sys/conf.h>
28 #include <sys/dkio.h>
29 #include <sys/disk.h>
30 #include <sys/disklabel.h>
31 #include <sys/fcntl.h>
32 #include <sys/file.h>
33 #include <sys/filedesc.h>
34 #include <sys/lock.h>
35 #include <sys/malloc.h>
36 #include <sys/namei.h>
37 #include <sys/proc.h>
38 #include <sys/vnode.h>
39 #include <sys/pledge.h>
40 #include <sys/namei.h>
41 
42 int
43 diskmapopen(dev_t dev, int flag, int fmt, struct proc *p)
44 {
45 	return 0;
46 }
47 
48 int
49 diskmapclose(dev_t dev, int flag, int fmt, struct proc *p)
50 {
51 	return 0;
52 }
53 
54 int
55 diskmapioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
56 {
57 	struct dk_diskmap *dm;
58 	struct nameidata ndp;
59 	struct filedesc *fdp = p->p_fd;
60 	struct file *fp0 = NULL, *fp = NULL;
61 	struct vnode *vp = NULL;
62 	char *devname, flags;
63 	int fd, error = EINVAL;
64 
65 	if (cmd != DIOCMAP)
66 		return EINVAL;
67 
68 	/*
69 	 * Map a request for a disk to the correct device. We should be
70 	 * supplied with either a diskname or a disklabel UID.
71 	 */
72 
73 	dm = (struct dk_diskmap *)addr;
74 	fd = dm->fd;
75 	devname = malloc(PATH_MAX, M_DEVBUF, M_WAITOK);
76 	if (copyinstr(dm->device, devname, PATH_MAX, NULL))
77 		goto invalid;
78 	if (disk_map(devname, devname, PATH_MAX, dm->flags) == 0)
79 		if (copyoutstr(devname, dm->device, PATH_MAX, NULL))
80 			goto invalid;
81 
82 	/* Attempt to open actual device. */
83 	if ((error = getvnode(p, fd, &fp0)) != 0)
84 		goto invalid;
85 
86 	NDINIT(&ndp, 0, 0, UIO_SYSSPACE, devname, p);
87 	ndp.ni_pledge = PLEDGE_RPATH;
88 	ndp.ni_unveil = UNVEIL_READ;
89 	if ((error = vn_open(&ndp, fp0->f_flag, 0)) != 0)
90 		goto invalid;
91 
92 	vp = ndp.ni_vp;
93 	VOP_UNLOCK(vp);
94 
95 	fdplock(fdp);
96 	/*
97 	 * Stop here if the 'struct file *' has been replaced,
98 	 * for example by another thread calling dup2(2), while
99 	 * this thread was sleeping in vn_open().
100 	 *
101 	 * Note that this would not happen for correct usages of
102 	 * "/dev/diskmap".
103 	 */
104 	if (fdp->fd_ofiles[fd] != fp0) {
105 		error = EAGAIN;
106 		goto bad;
107 	}
108 
109 	fp = fnew(p);
110 	if (fp == NULL) {
111 		error = ENFILE;
112 		goto bad;
113 	}
114 
115 	/* Zap old file. */
116 	mtx_enter(&fdp->fd_fplock);
117 	KASSERT(fdp->fd_ofiles[fd] == fp0);
118 	flags = fdp->fd_ofileflags[fd];
119 	fdp->fd_ofiles[fd] = NULL;
120 	fdp->fd_ofileflags[fd] = 0;
121 	mtx_leave(&fdp->fd_fplock);
122 
123 	/* Insert new file. */
124 	fp->f_flag = fp0->f_flag;
125 	fp->f_type = DTYPE_VNODE;
126 	fp->f_ops = &vnops;
127 	fp->f_data = (caddr_t)vp;
128 	fdinsert(fdp, fd, flags, fp);
129 	fdpunlock(fdp);
130 
131 	closef(fp0, p);
132 	free(devname, M_DEVBUF, PATH_MAX);
133 
134 	return 0;
135 
136 bad:
137 	fdpunlock(fdp);
138 
139 	if (vp)
140 		vrele(vp);
141 invalid:
142 	if (fp0)
143 		FRELE(fp0, p);
144 
145 	free(devname, M_DEVBUF, PATH_MAX);
146 
147 	return (error);
148 }
149 
150 int
151 diskmapread(dev_t dev, struct uio *uio, int flag)
152 {
153 	return ENXIO;
154 }
155 
156 int
157 diskmapwrite(dev_t dev, struct uio *uio, int flag)
158 {
159 	return ENXIO;
160 }
161