4 * Copyright (c) 2009 Antti Kantee. All Rights Reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * This is a [quick, simple & dirty] userspace sd@umass server.
30 * We probe USB devices using rump and attach them to the host kernel
31 * using pud(4). The resulting block devices can be e.g. read
34 * Since there is no devfs support in NetBSD, we create crudo & cotto
35 * device nodes in the current directory. Operating on these in the
36 * host OS will direct operations to this userspace server, e.g.:
37 * golem> disklabel ./rumpsd0d
38 * golem> mount_msdos ./rumpsd0e /mnt
39 * will cause file system access to /mnt be backed by the umass server
40 * in userspace. Due to the relatively experimental nature of this
41 * server, rump file servers are recommended for mounting experiments.
44 #include <sys/types.h>
45 #include <sys/syslimits.h>
47 #include <dev/pud/pud_msgif.h>
49 #include <rump/rump.h>
62 * No devfs? No problem. We just hack a bit & wait for the dust to settle.
64 #define NODEBASE "rumpsd0"
73 for (i
= 0; i
< 2; i
++) {
76 for (j
= 0; j
< 8; j
++, minnum
++) {
77 sprintf(path
, "%s%s%c",
78 i
== 0 ? "" : "r", NODEBASE
, minnum
+ 'a');
79 if (stat(path
, &sb
) == 0)
81 rv
= mknod(path
, (i
== 0 ? S_IFBLK
: S_IFCHR
) | 0666,
82 makedev(MYMAJOR
, minnum
));
83 if (rv
!= 0 && !(rv
== -1 && errno
== EEXIST
))
92 main(int argc
, char *argv
[])
95 struct pud_conf_reg pcr
;
97 struct vnode
*devvps
[8], *devvp
;
98 kauth_cred_t rootcred
;
102 if (makenodes() == -1)
105 fd
= open(_PATH_PUD
, O_RDWR
);
109 #define PDRSIZE (64*1024+1024)
110 pdr
= malloc(PDRSIZE
);
114 memset(&pcr
, 0, sizeof(pcr
));
115 pcr
.pm_pdr
.pdr_pth
.pth_framelen
= sizeof(struct pud_conf_reg
);
116 pcr
.pm_version
= PUD_DEVELVERSION
| PUD_VERSION
;
117 pcr
.pm_pdr
.pdr_reqclass
= PUD_REQ_CONF
;
118 pcr
.pm_pdr
.pdr_reqtype
= PUD_CONF_REG
;
120 pcr
.pm_regdev
= makedev(MYMAJOR
, 0);
121 pcr
.pm_flags
= PUD_CONFFLAG_BDEV
;
122 strlcpy(pcr
.pm_devname
, "youmass", sizeof(pcr
.pm_devname
));
124 n
= write(fd
, &pcr
, pcr
.pm_pdr
.pdr_pth
.pth_framelen
);
126 err(1, "configure"); /* XXX: doubles as protocol error */
128 rump_boot_sethowto(RUMP_AB_VERBOSE
);
132 * We use the raw devices. This avoids undesired block caching
133 * in read/write. It's also simpler. It's even mostly correct.
135 * As is probably obvious by now, we execute ops through specfs.
136 * Why? Can't say it wasn't because specfs-via-vnodes was
137 * already supported by rump. But, that's mostly how the
138 * kernel does it (cf. mounting file system etc).
140 for (i
= 0; i
< 8; i
++) {
141 sprintf(path
, "/dev/rsd0%c", 'a' + i
);
142 if ((rv
= rump_pub_namei(RUMP_NAMEI_LOOKUP
, 0, path
,
143 NULL
, &devvps
[i
], NULL
)) != 0)
144 errx(1, "raw device lookup failed %d", rv
);
147 rootcred
= rump_pub_cred_create(0, 0, 0, NULL
);
149 /* process requests ad infinitum */
151 struct pud_creq_open
*pr_open
;
152 struct pud_creq_close
*pr_close
;
153 struct pud_req_readwrite
*pr_rw
;
154 struct pud_req_ioctl
*pr_ioctl
;
159 n
= read(fd
, pdr
, PDRSIZE
);
163 minordev
= minor(pdr
->pdr_dev
);
164 if (minordev
< 0 || minordev
>= 8) {
168 devvp
= devvps
[minordev
];
170 switch (pdr
->pdr_reqtype
) {
172 pr_open
= (void *)pdr
;
173 RUMP_VOP_LOCK(devvp
, RUMP_LK_EXCLUSIVE
);
174 rv
= RUMP_VOP_OPEN(devvp
, pr_open
->pm_fmt
, rootcred
);
175 RUMP_VOP_UNLOCK(devvp
, 0);
179 pr_close
= (void *)pdr
;
180 RUMP_VOP_LOCK(devvp
, RUMP_LK_EXCLUSIVE
);
181 rv
= RUMP_VOP_CLOSE(devvp
, pr_close
->pm_fmt
, rootcred
);
182 RUMP_VOP_UNLOCK(devvp
, 0);
186 pr_ioctl
= (void *)pdr
;
187 rv
= RUMP_VOP_IOCTL(devvp
, pr_ioctl
->pm_iocmd
,
188 pr_ioctl
->pm_data
, pr_ioctl
->pm_flag
, rootcred
);
191 case PUD_BDEV_STRATREAD
:
193 assert(pr_rw
->pm_resid
<= 64*1024);
194 uio
= rump_pub_uio_setup(&pr_rw
->pm_data
[0],
195 pr_rw
->pm_resid
, pr_rw
->pm_offset
, RUMPUIO_READ
);
196 RUMP_VOP_LOCK(devvp
, RUMP_LK_SHARED
);
197 rv
= RUMP_VOP_READ(devvp
, uio
, 0, rootcred
);
198 RUMP_VOP_UNLOCK(devvp
, 0);
199 reslen
= rump_pub_uio_free(uio
);
200 pdr
->pdr_pth
.pth_framelen
-= reslen
;
201 pr_rw
->pm_resid
= reslen
;
204 case PUD_BDEV_STRATWRITE
:
206 uio
= rump_pub_uio_setup(&pr_rw
->pm_data
[0],
207 pr_rw
->pm_resid
, pr_rw
->pm_offset
, RUMPUIO_WRITE
);
208 RUMP_VOP_LOCK(devvp
, RUMP_LK_EXCLUSIVE
);
209 rv
= RUMP_VOP_WRITE(devvp
, uio
, 0, rootcred
);
210 RUMP_VOP_UNLOCK(devvp
, 0);
211 reslen
= rump_pub_uio_free(uio
);
212 pr_rw
->pm_resid
= reslen
;
213 pdr
->pdr_pth
.pth_framelen
=sizeof(struct pud_creq_write
);
221 n
= write(fd
, pdr
, pdr
->pdr_pth
.pth_framelen
);
222 assert(n
== (ssize_t
)pdr
->pdr_pth
.pth_framelen
);