1*d35b86acSpooka /* $NetBSD: umserv.c,v 1.3 2016/01/25 11:45:58 pooka Exp $ */
28b5875c7Spooka
38b5875c7Spooka /*
48b5875c7Spooka * Copyright (c) 2009 Antti Kantee. All Rights Reserved.
58b5875c7Spooka *
68b5875c7Spooka * Redistribution and use in source and binary forms, with or without
78b5875c7Spooka * modification, are permitted provided that the following conditions
88b5875c7Spooka * are met:
98b5875c7Spooka * 1. Redistributions of source code must retain the above copyright
108b5875c7Spooka * notice, this list of conditions and the following disclaimer.
118b5875c7Spooka * 2. Redistributions in binary form must reproduce the above copyright
128b5875c7Spooka * notice, this list of conditions and the following disclaimer in the
138b5875c7Spooka * documentation and/or other materials provided with the distribution.
148b5875c7Spooka *
158b5875c7Spooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
168b5875c7Spooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
178b5875c7Spooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
188b5875c7Spooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
198b5875c7Spooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
208b5875c7Spooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
218b5875c7Spooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
228b5875c7Spooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
238b5875c7Spooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
248b5875c7Spooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
258b5875c7Spooka * SUCH DAMAGE.
268b5875c7Spooka */
278b5875c7Spooka
288b5875c7Spooka /*
298b5875c7Spooka * This is a [quick, simple & dirty] userspace sd@umass server.
308b5875c7Spooka * We probe USB devices using rump and attach them to the host kernel
318b5875c7Spooka * using pud(4). The resulting block devices can be e.g. read
328b5875c7Spooka * and/or mounted.
338b5875c7Spooka *
348b5875c7Spooka * Since there is no devfs support in NetBSD, we create crudo & cotto
358b5875c7Spooka * device nodes in the current directory. Operating on these in the
368b5875c7Spooka * host OS will direct operations to this userspace server, e.g.:
378b5875c7Spooka * golem> disklabel ./rumpsd0d
388b5875c7Spooka * golem> mount_msdos ./rumpsd0e /mnt
398b5875c7Spooka * will cause file system access to /mnt be backed by the umass server
408b5875c7Spooka * in userspace. Due to the relatively experimental nature of this
418b5875c7Spooka * server, rump file servers are recommended for mounting experiments.
428b5875c7Spooka */
438b5875c7Spooka
448b5875c7Spooka #include <sys/types.h>
458b5875c7Spooka #include <sys/syslimits.h>
468b5875c7Spooka
478b5875c7Spooka #include <dev/pud/pud_msgif.h>
488b5875c7Spooka
498b5875c7Spooka #include <rump/rump.h>
50*d35b86acSpooka #include <rump/rumpvnode_if.h>
518b5875c7Spooka
528b5875c7Spooka #include <assert.h>
538b5875c7Spooka #include <err.h>
548b5875c7Spooka #include <errno.h>
558b5875c7Spooka #include <fcntl.h>
568b5875c7Spooka #include <paths.h>
578b5875c7Spooka #include <stdio.h>
588b5875c7Spooka #include <stdlib.h>
598b5875c7Spooka #include <string.h>
608b5875c7Spooka #include <unistd.h>
618b5875c7Spooka
628b5875c7Spooka /*
638b5875c7Spooka * No devfs? No problem. We just hack a bit & wait for the dust to settle.
648b5875c7Spooka */
658b5875c7Spooka #define NODEBASE "rumpsd0"
668b5875c7Spooka #define MYMAJOR 411
678b5875c7Spooka static int
makenodes(void)688b5875c7Spooka makenodes(void)
698b5875c7Spooka {
708b5875c7Spooka char path[PATH_MAX];
718b5875c7Spooka struct stat sb;
728b5875c7Spooka int i, j, rv;
738b5875c7Spooka
748b5875c7Spooka for (i = 0; i < 2; i++) {
758b5875c7Spooka int minnum = 0;
768b5875c7Spooka
778b5875c7Spooka for (j = 0; j < 8; j++, minnum++) {
788b5875c7Spooka sprintf(path, "%s%s%c",
798b5875c7Spooka i == 0 ? "" : "r", NODEBASE, minnum + 'a');
808b5875c7Spooka if (stat(path, &sb) == 0)
818b5875c7Spooka continue;
828b5875c7Spooka rv = mknod(path, (i == 0 ? S_IFBLK : S_IFCHR) | 0666,
838b5875c7Spooka makedev(MYMAJOR, minnum));
848b5875c7Spooka if (rv != 0 && !(rv == -1 && errno == EEXIST))
858b5875c7Spooka return rv;
868b5875c7Spooka }
878b5875c7Spooka }
888b5875c7Spooka
898b5875c7Spooka return 0;
908b5875c7Spooka }
918b5875c7Spooka
928b5875c7Spooka int
main(int argc,char * argv[])938b5875c7Spooka main(int argc, char *argv[])
948b5875c7Spooka {
958b5875c7Spooka char path[PATH_MAX];
968b5875c7Spooka struct pud_conf_reg pcr;
978b5875c7Spooka struct pud_req *pdr;
988b5875c7Spooka struct vnode *devvps[8], *devvp;
998b5875c7Spooka kauth_cred_t rootcred;
1008b5875c7Spooka ssize_t n;
1018b5875c7Spooka int fd, rv, i;
1028b5875c7Spooka
1038b5875c7Spooka if (makenodes() == -1)
1048b5875c7Spooka err(1, "makenodes");
1058b5875c7Spooka
1068b5875c7Spooka fd = open(_PATH_PUD, O_RDWR);
1078b5875c7Spooka if (fd == -1)
1088b5875c7Spooka err(1, "open");
1098b5875c7Spooka
1108b5875c7Spooka #define PDRSIZE (64*1024+1024)
1118b5875c7Spooka pdr = malloc(PDRSIZE);
1128b5875c7Spooka if (pdr == NULL)
1138b5875c7Spooka err(1, "malloc");
1148b5875c7Spooka
1158b5875c7Spooka memset(&pcr, 0, sizeof(pcr));
1168b5875c7Spooka pcr.pm_pdr.pdr_pth.pth_framelen = sizeof(struct pud_conf_reg);
1178b5875c7Spooka pcr.pm_version = PUD_DEVELVERSION | PUD_VERSION;
1188b5875c7Spooka pcr.pm_pdr.pdr_reqclass = PUD_REQ_CONF;
1198b5875c7Spooka pcr.pm_pdr.pdr_reqtype = PUD_CONF_REG;
1208b5875c7Spooka
1218b5875c7Spooka pcr.pm_regdev = makedev(MYMAJOR, 0);
1228b5875c7Spooka pcr.pm_flags = PUD_CONFFLAG_BDEV;
1238b5875c7Spooka strlcpy(pcr.pm_devname, "youmass", sizeof(pcr.pm_devname));
1248b5875c7Spooka
1258b5875c7Spooka n = write(fd, &pcr, pcr.pm_pdr.pdr_pth.pth_framelen);
1268b5875c7Spooka if (n == -1)
1278b5875c7Spooka err(1, "configure"); /* XXX: doubles as protocol error */
1288b5875c7Spooka
1298b5875c7Spooka rump_boot_sethowto(RUMP_AB_VERBOSE);
1308b5875c7Spooka rump_init();
1318b5875c7Spooka
1328b5875c7Spooka /*
1338b5875c7Spooka * We use the raw devices. This avoids undesired block caching
1348b5875c7Spooka * in read/write. It's also simpler. It's even mostly correct.
1358b5875c7Spooka *
1368b5875c7Spooka * As is probably obvious by now, we execute ops through specfs.
1378b5875c7Spooka * Why? Can't say it wasn't because specfs-via-vnodes was
1388b5875c7Spooka * already supported by rump. But, that's mostly how the
1398b5875c7Spooka * kernel does it (cf. mounting file system etc).
1408b5875c7Spooka */
1418b5875c7Spooka for (i = 0; i < 8; i++) {
1428b5875c7Spooka sprintf(path, "/dev/rsd0%c", 'a' + i);
1438b5875c7Spooka if ((rv = rump_pub_namei(RUMP_NAMEI_LOOKUP, 0, path,
1448b5875c7Spooka NULL, &devvps[i], NULL)) != 0)
1458b5875c7Spooka errx(1, "raw device lookup failed %d", rv);
1468b5875c7Spooka }
1478b5875c7Spooka
1488b5875c7Spooka rootcred = rump_pub_cred_create(0, 0, 0, NULL);
1498b5875c7Spooka
1508b5875c7Spooka /* process requests ad infinitum */
1518b5875c7Spooka for (;;) {
1528b5875c7Spooka struct pud_creq_open *pr_open;
1538b5875c7Spooka struct pud_creq_close *pr_close;
1548b5875c7Spooka struct pud_req_readwrite *pr_rw;
1558b5875c7Spooka struct pud_req_ioctl *pr_ioctl;
1568b5875c7Spooka struct uio *uio;
1578b5875c7Spooka size_t reslen;
1588b5875c7Spooka int minordev;
1598b5875c7Spooka
1608b5875c7Spooka n = read(fd, pdr, PDRSIZE);
1618b5875c7Spooka if (n == -1)
1628b5875c7Spooka err(1, "read");
1638b5875c7Spooka
1648b5875c7Spooka minordev = minor(pdr->pdr_dev);
1658b5875c7Spooka if (minordev < 0 || minordev >= 8) {
1668b5875c7Spooka rv = ENXIO;
1678b5875c7Spooka goto sendresponse;
1688b5875c7Spooka }
1698b5875c7Spooka devvp = devvps[minordev];
1708b5875c7Spooka
1718b5875c7Spooka switch (pdr->pdr_reqtype) {
1728b5875c7Spooka case PUD_BDEV_OPEN:
1738b5875c7Spooka pr_open = (void *)pdr;
1748b5875c7Spooka RUMP_VOP_LOCK(devvp, RUMP_LK_EXCLUSIVE);
1758b5875c7Spooka rv = RUMP_VOP_OPEN(devvp, pr_open->pm_fmt, rootcred);
1761423e65bShannken RUMP_VOP_UNLOCK(devvp);
1778b5875c7Spooka break;
1788b5875c7Spooka
1798b5875c7Spooka case PUD_BDEV_CLOSE:
1808b5875c7Spooka pr_close = (void *)pdr;
1818b5875c7Spooka RUMP_VOP_LOCK(devvp, RUMP_LK_EXCLUSIVE);
1828b5875c7Spooka rv = RUMP_VOP_CLOSE(devvp, pr_close->pm_fmt, rootcred);
1831423e65bShannken RUMP_VOP_UNLOCK(devvp);
1848b5875c7Spooka break;
1858b5875c7Spooka
1868b5875c7Spooka case PUD_BDEV_IOCTL:
1878b5875c7Spooka pr_ioctl = (void *)pdr;
1888b5875c7Spooka rv = RUMP_VOP_IOCTL(devvp, pr_ioctl->pm_iocmd,
1898b5875c7Spooka pr_ioctl->pm_data, pr_ioctl->pm_flag, rootcred);
1908b5875c7Spooka break;
1918b5875c7Spooka
1928b5875c7Spooka case PUD_BDEV_STRATREAD:
1938b5875c7Spooka pr_rw = (void *)pdr;
1948b5875c7Spooka assert(pr_rw->pm_resid <= 64*1024);
1958b5875c7Spooka uio = rump_pub_uio_setup(&pr_rw->pm_data[0],
1968b5875c7Spooka pr_rw->pm_resid, pr_rw->pm_offset, RUMPUIO_READ);
1978b5875c7Spooka RUMP_VOP_LOCK(devvp, RUMP_LK_SHARED);
1988b5875c7Spooka rv = RUMP_VOP_READ(devvp, uio, 0, rootcred);
1991423e65bShannken RUMP_VOP_UNLOCK(devvp);
2008b5875c7Spooka reslen = rump_pub_uio_free(uio);
2018b5875c7Spooka pdr->pdr_pth.pth_framelen -= reslen;
2028b5875c7Spooka pr_rw->pm_resid = reslen;
2038b5875c7Spooka break;
2048b5875c7Spooka
2058b5875c7Spooka case PUD_BDEV_STRATWRITE:
2068b5875c7Spooka pr_rw = (void *)pdr;
2078b5875c7Spooka uio = rump_pub_uio_setup(&pr_rw->pm_data[0],
2088b5875c7Spooka pr_rw->pm_resid, pr_rw->pm_offset, RUMPUIO_WRITE);
2098b5875c7Spooka RUMP_VOP_LOCK(devvp, RUMP_LK_EXCLUSIVE);
2108b5875c7Spooka rv = RUMP_VOP_WRITE(devvp, uio, 0, rootcred);
2111423e65bShannken RUMP_VOP_UNLOCK(devvp);
2128b5875c7Spooka reslen = rump_pub_uio_free(uio);
2138b5875c7Spooka pr_rw->pm_resid = reslen;
2148b5875c7Spooka pdr->pdr_pth.pth_framelen=sizeof(struct pud_creq_write);
2158b5875c7Spooka rv = 0;
2168b5875c7Spooka break;
2178b5875c7Spooka
2188b5875c7Spooka }
2198b5875c7Spooka
2208b5875c7Spooka sendresponse:
2218b5875c7Spooka pdr->pdr_rv = rv;
2228b5875c7Spooka n = write(fd, pdr, pdr->pdr_pth.pth_framelen);
2238b5875c7Spooka assert(n == (ssize_t)pdr->pdr_pth.pth_framelen);
2248b5875c7Spooka }
2258b5875c7Spooka }
226