xref: /openbsd-src/sys/dev/diskmap.c (revision 68cc39830aa48a2182a4a2976238be1f40888669)
1*68cc3983Sjsg /*	$OpenBSD: diskmap.c,v 1.27 2023/04/13 02:19:05 jsg Exp $	*/
230992ed1Sjsing 
330992ed1Sjsing /*
430992ed1Sjsing  * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org>
530992ed1Sjsing  *
630992ed1Sjsing  * Permission to use, copy, modify, and distribute this software for any
730992ed1Sjsing  * purpose with or without fee is hereby granted, provided that the above
830992ed1Sjsing  * copyright notice and this permission notice appear in all copies.
930992ed1Sjsing  *
1030992ed1Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1130992ed1Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1230992ed1Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1330992ed1Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1430992ed1Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1530992ed1Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1630992ed1Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1730992ed1Sjsing  */
1830992ed1Sjsing 
1930992ed1Sjsing /*
2030992ed1Sjsing  * Disk mapper.
2130992ed1Sjsing  */
2230992ed1Sjsing 
2330992ed1Sjsing #include <sys/param.h>
2430992ed1Sjsing #include <sys/systm.h>
2530992ed1Sjsing #include <sys/device.h>
2630992ed1Sjsing #include <sys/errno.h>
2730992ed1Sjsing #include <sys/conf.h>
2830992ed1Sjsing #include <sys/dkio.h>
2930992ed1Sjsing #include <sys/disk.h>
3030992ed1Sjsing #include <sys/disklabel.h>
314b1f64dcSguenther #include <sys/fcntl.h>
3230992ed1Sjsing #include <sys/file.h>
3330992ed1Sjsing #include <sys/filedesc.h>
34fde894e5Stedu #include <sys/lock.h>
3530992ed1Sjsing #include <sys/malloc.h>
3630992ed1Sjsing #include <sys/namei.h>
3730992ed1Sjsing #include <sys/proc.h>
3830992ed1Sjsing #include <sys/vnode.h>
392579b71cSderaadt #include <sys/pledge.h>
4030992ed1Sjsing 
4130992ed1Sjsing int
diskmapopen(dev_t dev,int flag,int fmt,struct proc * p)4230992ed1Sjsing diskmapopen(dev_t dev, int flag, int fmt, struct proc *p)
4330992ed1Sjsing {
4430992ed1Sjsing 	return 0;
4530992ed1Sjsing }
4630992ed1Sjsing 
4730992ed1Sjsing int
diskmapclose(dev_t dev,int flag,int fmt,struct proc * p)4830992ed1Sjsing diskmapclose(dev_t dev, int flag, int fmt, struct proc *p)
4930992ed1Sjsing {
5030992ed1Sjsing 	return 0;
5130992ed1Sjsing }
5230992ed1Sjsing 
5330992ed1Sjsing int
diskmapioctl(dev_t dev,u_long cmd,caddr_t addr,int flag,struct proc * p)5430992ed1Sjsing diskmapioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
5530992ed1Sjsing {
5630992ed1Sjsing 	struct dk_diskmap *dm;
5730992ed1Sjsing 	struct nameidata ndp;
589e621937Smpi 	struct filedesc *fdp = p->p_fd;
594e13440dSmpi 	struct file *fp0 = NULL, *fp = NULL;
604e13440dSmpi 	struct vnode *vp = NULL;
614e13440dSmpi 	char *devname, flags;
622759e442Santon 	int error, fd;
6330992ed1Sjsing 
6430992ed1Sjsing 	if (cmd != DIOCMAP)
652759e442Santon 		return ENOTTY;
6630992ed1Sjsing 
6730992ed1Sjsing 	/*
6830992ed1Sjsing 	 * Map a request for a disk to the correct device. We should be
6930992ed1Sjsing 	 * supplied with either a diskname or a disklabel UID.
7030992ed1Sjsing 	 */
7130992ed1Sjsing 
7230992ed1Sjsing 	dm = (struct dk_diskmap *)addr;
7330992ed1Sjsing 	fd = dm->fd;
7430992ed1Sjsing 	devname = malloc(PATH_MAX, M_DEVBUF, M_WAITOK);
752759e442Santon 	if ((error = copyinstr(dm->device, devname, PATH_MAX, NULL)) != 0)
7630992ed1Sjsing 		goto invalid;
772759e442Santon 	if (disk_map(devname, devname, PATH_MAX, dm->flags) == 0) {
782759e442Santon 		error = copyoutstr(devname, dm->device, PATH_MAX, NULL);
792759e442Santon 		if (error != 0)
8030992ed1Sjsing 			goto invalid;
812759e442Santon 	}
8230992ed1Sjsing 
8330992ed1Sjsing 	/* Attempt to open actual device. */
844e13440dSmpi 	if ((error = getvnode(p, fd, &fp0)) != 0)
85f4ce75d2Smpi 		goto invalid;
86f4ce75d2Smpi 
879b247b22Sbeck 	NDINIT(&ndp, 0, 0, UIO_SYSSPACE, devname, p);
882579b71cSderaadt 	ndp.ni_pledge = PLEDGE_RPATH;
89e1a6e226Sbeck 	ndp.ni_unveil = UNVEIL_READ;
904e13440dSmpi 	if ((error = vn_open(&ndp, fp0->f_flag, 0)) != 0)
9164c74df7Smpi 		goto invalid;
9230992ed1Sjsing 
9330992ed1Sjsing 	vp = ndp.ni_vp;
9436bb23f1Svisa 	VOP_UNLOCK(vp);
9530992ed1Sjsing 
964e13440dSmpi 	fdplock(fdp);
974e13440dSmpi 	/*
984e13440dSmpi 	 * Stop here if the 'struct file *' has been replaced,
994e13440dSmpi 	 * for example by another thread calling dup2(2), while
1004e13440dSmpi 	 * this thread was sleeping in vn_open().
1014e13440dSmpi 	 *
1024e13440dSmpi 	 * Note that this would not happen for correct usages of
1034e13440dSmpi 	 * "/dev/diskmap".
1044e13440dSmpi 	 */
1054e13440dSmpi 	if (fdp->fd_ofiles[fd] != fp0) {
1064e13440dSmpi 		error = EAGAIN;
1074e13440dSmpi 		goto bad;
1084e13440dSmpi 	}
1094e13440dSmpi 
1104e13440dSmpi 	fp = fnew(p);
1114e13440dSmpi 	if (fp == NULL) {
1124e13440dSmpi 		error = ENFILE;
1134e13440dSmpi 		goto bad;
1144e13440dSmpi 	}
1154e13440dSmpi 
1164e13440dSmpi 	/* Zap old file. */
1174e13440dSmpi 	mtx_enter(&fdp->fd_fplock);
1184e13440dSmpi 	KASSERT(fdp->fd_ofiles[fd] == fp0);
1194e13440dSmpi 	flags = fdp->fd_ofileflags[fd];
1204e13440dSmpi 	fdp->fd_ofiles[fd] = NULL;
1214e13440dSmpi 	fdp->fd_ofileflags[fd] = 0;
1224e13440dSmpi 	mtx_leave(&fdp->fd_fplock);
1234e13440dSmpi 
1244e13440dSmpi 	/* Insert new file. */
1254e13440dSmpi 	fp->f_flag = fp0->f_flag;
1264e13440dSmpi 	fp->f_type = DTYPE_VNODE;
1274e13440dSmpi 	fp->f_ops = &vnops;
1284e13440dSmpi 	fp->f_data = (caddr_t)vp;
1294e13440dSmpi 	fdinsert(fdp, fd, flags, fp);
13030992ed1Sjsing 	fdpunlock(fdp);
1314e13440dSmpi 
1324e13440dSmpi 	closef(fp0, p);
133d21cd5d0Sderaadt 	free(devname, M_DEVBUF, PATH_MAX);
13430992ed1Sjsing 
13530992ed1Sjsing 	return 0;
13630992ed1Sjsing 
13730992ed1Sjsing bad:
13830992ed1Sjsing 	fdpunlock(fdp);
1393e253b47Santon 	(void)vn_close(vp, fp0->f_flag, p->p_ucred, p);
14064c74df7Smpi invalid:
1414e13440dSmpi 	if (fp0)
1424e13440dSmpi 		FRELE(fp0, p);
1434e13440dSmpi 
144d21cd5d0Sderaadt 	free(devname, M_DEVBUF, PATH_MAX);
14530992ed1Sjsing 
1462759e442Santon 	return error;
14730992ed1Sjsing }
14830992ed1Sjsing 
14930992ed1Sjsing int
diskmapread(dev_t dev,struct uio * uio,int flag)15030992ed1Sjsing diskmapread(dev_t dev, struct uio *uio, int flag)
15130992ed1Sjsing {
15230992ed1Sjsing 	return ENXIO;
15330992ed1Sjsing }
15430992ed1Sjsing 
15530992ed1Sjsing int
diskmapwrite(dev_t dev,struct uio * uio,int flag)15630992ed1Sjsing diskmapwrite(dev_t dev, struct uio *uio, int flag)
15730992ed1Sjsing {
15830992ed1Sjsing 	return ENXIO;
15930992ed1Sjsing }
160