Sat Aug 19 05:19:28 2017 UTC ()
Pull up following revision(s) (requested by mrg in ticket #1476):
	sys/dev/vnd.c: revision 1.260, 1.262 via patch
Put in a litany of judicious bounds checks around vnd headers.
Thought I was done with this crap after I rewrote vndcompress(1)!
From Ilja Van Sprundel.
--
Appease toxic bullshit warning from gcc.
If you have a better way to write a useful bounds check that happens
to always pass on LP64 but doesn't always on LP32, without making it
fail to compile on LP64 or making it an #ifdef conditional on LP32,
please put it in here instead.


(snj)
diff -r1.232.2.3.2.1 -r1.232.2.3.2.2 src/sys/dev/vnd.c

cvs diff -r1.232.2.3.2.1 -r1.232.2.3.2.2 src/sys/dev/vnd.c (switch to unified diff)

--- src/sys/dev/vnd.c 2016/01/02 14:38:45 1.232.2.3.2.1
+++ src/sys/dev/vnd.c 2017/08/19 05:19:28 1.232.2.3.2.2
@@ -1,2112 +1,2139 @@ @@ -1,2112 +1,2139 @@
1/* $NetBSD: vnd.c,v 1.232.2.3.2.1 2016/01/02 14:38:45 riz Exp $ */ 1/* $NetBSD: vnd.c,v 1.232.2.3.2.2 2017/08/19 05:19:28 snj Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe. 8 * by Jason R. Thorpe.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Copyright (c) 1988 University of Utah. 33 * Copyright (c) 1988 University of Utah.
34 * Copyright (c) 1990, 1993 34 * Copyright (c) 1990, 1993
35 * The Regents of the University of California. All rights reserved. 35 * The Regents of the University of California. All rights reserved.
36 * 36 *
37 * This code is derived from software contributed to Berkeley by 37 * This code is derived from software contributed to Berkeley by
38 * the Systems Programming Group of the University of Utah Computer 38 * the Systems Programming Group of the University of Utah Computer
39 * Science Department. 39 * Science Department.
40 * 40 *
41 * Redistribution and use in source and binary forms, with or without 41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions 42 * modification, are permitted provided that the following conditions
43 * are met: 43 * are met:
44 * 1. Redistributions of source code must retain the above copyright 44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer. 45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright 46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the 47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution. 48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors 49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software 50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission. 51 * without specific prior written permission.
52 * 52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE. 63 * SUCH DAMAGE.
64 * 64 *
65 * from: Utah $Hdr: vn.c 1.13 94/04/02$ 65 * from: Utah $Hdr: vn.c 1.13 94/04/02$
66 * 66 *
67 * @(#)vn.c 8.9 (Berkeley) 5/14/95 67 * @(#)vn.c 8.9 (Berkeley) 5/14/95
68 */ 68 */
69 69
70/* 70/*
71 * Vnode disk driver. 71 * Vnode disk driver.
72 * 72 *
73 * Block/character interface to a vnode. Allows one to treat a file 73 * Block/character interface to a vnode. Allows one to treat a file
74 * as a disk (e.g. build a filesystem in it, mount it, etc.). 74 * as a disk (e.g. build a filesystem in it, mount it, etc.).
75 * 75 *
76 * NOTE 1: If the vnode supports the VOP_BMAP and VOP_STRATEGY operations, 76 * NOTE 1: If the vnode supports the VOP_BMAP and VOP_STRATEGY operations,
77 * this uses them to avoid distorting the local buffer cache. If those 77 * this uses them to avoid distorting the local buffer cache. If those
78 * block-level operations are not available, this falls back to the regular 78 * block-level operations are not available, this falls back to the regular
79 * read and write calls. Using these may distort the cache in some cases 79 * read and write calls. Using these may distort the cache in some cases
80 * but better have the driver working than preventing it to work on file 80 * but better have the driver working than preventing it to work on file
81 * systems where the block-level operations are not implemented for 81 * systems where the block-level operations are not implemented for
82 * whatever reason. 82 * whatever reason.
83 * 83 *
84 * NOTE 2: There is a security issue involved with this driver. 84 * NOTE 2: There is a security issue involved with this driver.
85 * Once mounted all access to the contents of the "mapped" file via 85 * Once mounted all access to the contents of the "mapped" file via
86 * the special file is controlled by the permissions on the special 86 * the special file is controlled by the permissions on the special
87 * file, the protection of the mapped file is ignored (effectively, 87 * file, the protection of the mapped file is ignored (effectively,
88 * by using root credentials in all transactions). 88 * by using root credentials in all transactions).
89 * 89 *
90 * NOTE 3: Doesn't interact with leases, should it? 90 * NOTE 3: Doesn't interact with leases, should it?
91 */ 91 */
92 92
93#include <sys/cdefs.h> 93#include <sys/cdefs.h>
94__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.232.2.3.2.1 2016/01/02 14:38:45 riz Exp $"); 94__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.232.2.3.2.2 2017/08/19 05:19:28 snj Exp $");
95 95
96#if defined(_KERNEL_OPT) 96#if defined(_KERNEL_OPT)
97#include "opt_vnd.h" 97#include "opt_vnd.h"
98#include "opt_compat_netbsd.h" 98#include "opt_compat_netbsd.h"
99#endif 99#endif
100 100
101#include <sys/param.h> 101#include <sys/param.h>
102#include <sys/systm.h> 102#include <sys/systm.h>
103#include <sys/namei.h> 103#include <sys/namei.h>
104#include <sys/proc.h> 104#include <sys/proc.h>
105#include <sys/kthread.h> 105#include <sys/kthread.h>
106#include <sys/errno.h> 106#include <sys/errno.h>
107#include <sys/buf.h> 107#include <sys/buf.h>
108#include <sys/bufq.h> 108#include <sys/bufq.h>
109#include <sys/malloc.h> 109#include <sys/malloc.h>
110#include <sys/ioctl.h> 110#include <sys/ioctl.h>
111#include <sys/disklabel.h> 111#include <sys/disklabel.h>
112#include <sys/device.h> 112#include <sys/device.h>
113#include <sys/disk.h> 113#include <sys/disk.h>
114#include <sys/stat.h> 114#include <sys/stat.h>
115#include <sys/mount.h> 115#include <sys/mount.h>
116#include <sys/vnode.h> 116#include <sys/vnode.h>
117#include <sys/file.h> 117#include <sys/file.h>
118#include <sys/uio.h> 118#include <sys/uio.h>
119#include <sys/conf.h> 119#include <sys/conf.h>
120#include <sys/kauth.h> 120#include <sys/kauth.h>
121 121
122#include <net/zlib.h> 122#include <net/zlib.h>
123 123
124#include <miscfs/genfs/genfs.h> 124#include <miscfs/genfs/genfs.h>
125#include <miscfs/specfs/specdev.h> 125#include <miscfs/specfs/specdev.h>
126 126
127#include <dev/dkvar.h> 127#include <dev/dkvar.h>
128#include <dev/vndvar.h> 128#include <dev/vndvar.h>
129 129
130#if defined(VNDDEBUG) && !defined(DEBUG) 130#if defined(VNDDEBUG) && !defined(DEBUG)
131#define DEBUG 131#define DEBUG
132#endif 132#endif
133 133
134#ifdef DEBUG 134#ifdef DEBUG
135int dovndcluster = 1; 135int dovndcluster = 1;
136#define VDB_FOLLOW 0x01 136#define VDB_FOLLOW 0x01
137#define VDB_INIT 0x02 137#define VDB_INIT 0x02
138#define VDB_IO 0x04 138#define VDB_IO 0x04
139#define VDB_LABEL 0x08 139#define VDB_LABEL 0x08
140int vnddebug = 0; 140int vnddebug = 0;
141#endif 141#endif
142 142
143#define vndunit(x) DISKUNIT(x) 143#define vndunit(x) DISKUNIT(x)
144 144
145struct vndxfer { 145struct vndxfer {
146 struct buf vx_buf; 146 struct buf vx_buf;
147 struct vnd_softc *vx_vnd; 147 struct vnd_softc *vx_vnd;
148}; 148};
149#define VND_BUFTOXFER(bp) ((struct vndxfer *)(void *)bp) 149#define VND_BUFTOXFER(bp) ((struct vndxfer *)(void *)bp)
150 150
151#define VND_GETXFER(vnd) pool_get(&(vnd)->sc_vxpool, PR_WAITOK) 151#define VND_GETXFER(vnd) pool_get(&(vnd)->sc_vxpool, PR_WAITOK)
152#define VND_PUTXFER(vnd, vx) pool_put(&(vnd)->sc_vxpool, (vx)) 152#define VND_PUTXFER(vnd, vx) pool_put(&(vnd)->sc_vxpool, (vx))
153 153
154#define VNDLABELDEV(dev) \ 154#define VNDLABELDEV(dev) \
155 (MAKEDISKDEV(major((dev)), vndunit((dev)), RAW_PART)) 155 (MAKEDISKDEV(major((dev)), vndunit((dev)), RAW_PART))
156 156
157#define VND_MAXPENDING(vnd) ((vnd)->sc_maxactive * 4) 157#define VND_MAXPENDING(vnd) ((vnd)->sc_maxactive * 4)
158 158
159/* called by main() at boot time */ 159/* called by main() at boot time */
160void vndattach(int); 160void vndattach(int);
161 161
162static void vndclear(struct vnd_softc *, int); 162static void vndclear(struct vnd_softc *, int);
163static int vnddoclear(struct vnd_softc *, int, int, bool); 163static int vnddoclear(struct vnd_softc *, int, int, bool);
164static int vndsetcred(struct vnd_softc *, kauth_cred_t); 164static int vndsetcred(struct vnd_softc *, kauth_cred_t);
165static void vndthrottle(struct vnd_softc *, struct vnode *); 165static void vndthrottle(struct vnd_softc *, struct vnode *);
166static void vndiodone(struct buf *); 166static void vndiodone(struct buf *);
167#if 0 167#if 0
168static void vndshutdown(void); 168static void vndshutdown(void);
169#endif 169#endif
170 170
171static void vndgetdefaultlabel(struct vnd_softc *, struct disklabel *); 171static void vndgetdefaultlabel(struct vnd_softc *, struct disklabel *);
172static void vndgetdisklabel(dev_t, struct vnd_softc *); 172static void vndgetdisklabel(dev_t, struct vnd_softc *);
173 173
174static int vndlock(struct vnd_softc *); 174static int vndlock(struct vnd_softc *);
175static void vndunlock(struct vnd_softc *); 175static void vndunlock(struct vnd_softc *);
176#ifdef VND_COMPRESSION 176#ifdef VND_COMPRESSION
177static void compstrategy(struct buf *, off_t); 177static void compstrategy(struct buf *, off_t);
178static void *vnd_alloc(void *, u_int, u_int); 178static void *vnd_alloc(void *, u_int, u_int);
179static void vnd_free(void *, void *); 179static void vnd_free(void *, void *);
180#endif /* VND_COMPRESSION */ 180#endif /* VND_COMPRESSION */
181 181
182static void vndthread(void *); 182static void vndthread(void *);
183static bool vnode_has_op(const struct vnode *, int); 183static bool vnode_has_op(const struct vnode *, int);
184static void handle_with_rdwr(struct vnd_softc *, const struct buf *, 184static void handle_with_rdwr(struct vnd_softc *, const struct buf *,
185 struct buf *); 185 struct buf *);
186static void handle_with_strategy(struct vnd_softc *, const struct buf *, 186static void handle_with_strategy(struct vnd_softc *, const struct buf *,
187 struct buf *); 187 struct buf *);
188static void vnd_set_geometry(struct vnd_softc *); 188static void vnd_set_geometry(struct vnd_softc *);
189 189
190static dev_type_open(vndopen); 190static dev_type_open(vndopen);
191static dev_type_close(vndclose); 191static dev_type_close(vndclose);
192static dev_type_read(vndread); 192static dev_type_read(vndread);
193static dev_type_write(vndwrite); 193static dev_type_write(vndwrite);
194static dev_type_ioctl(vndioctl); 194static dev_type_ioctl(vndioctl);
195static dev_type_strategy(vndstrategy); 195static dev_type_strategy(vndstrategy);
196static dev_type_dump(vnddump); 196static dev_type_dump(vnddump);
197static dev_type_size(vndsize); 197static dev_type_size(vndsize);
198 198
199const struct bdevsw vnd_bdevsw = { 199const struct bdevsw vnd_bdevsw = {
200 .d_open = vndopen, 200 .d_open = vndopen,
201 .d_close = vndclose, 201 .d_close = vndclose,
202 .d_strategy = vndstrategy, 202 .d_strategy = vndstrategy,
203 .d_ioctl = vndioctl, 203 .d_ioctl = vndioctl,
204 .d_dump = vnddump, 204 .d_dump = vnddump,
205 .d_psize = vndsize, 205 .d_psize = vndsize,
206 .d_discard = nodiscard, 206 .d_discard = nodiscard,
207 .d_flag = D_DISK 207 .d_flag = D_DISK
208}; 208};
209 209
210const struct cdevsw vnd_cdevsw = { 210const struct cdevsw vnd_cdevsw = {
211 .d_open = vndopen, 211 .d_open = vndopen,
212 .d_close = vndclose, 212 .d_close = vndclose,
213 .d_read = vndread, 213 .d_read = vndread,
214 .d_write = vndwrite, 214 .d_write = vndwrite,
215 .d_ioctl = vndioctl, 215 .d_ioctl = vndioctl,
216 .d_stop = nostop, 216 .d_stop = nostop,
217 .d_tty = notty, 217 .d_tty = notty,
218 .d_poll = nopoll, 218 .d_poll = nopoll,
219 .d_mmap = nommap, 219 .d_mmap = nommap,
220 .d_kqfilter = nokqfilter, 220 .d_kqfilter = nokqfilter,
221 .d_discard = nodiscard, 221 .d_discard = nodiscard,
222 .d_flag = D_DISK 222 .d_flag = D_DISK
223}; 223};
224 224
225static int vnd_match(device_t, cfdata_t, void *); 225static int vnd_match(device_t, cfdata_t, void *);
226static void vnd_attach(device_t, device_t, void *); 226static void vnd_attach(device_t, device_t, void *);
227static int vnd_detach(device_t, int); 227static int vnd_detach(device_t, int);
228 228
229CFATTACH_DECL3_NEW(vnd, sizeof(struct vnd_softc), 229CFATTACH_DECL3_NEW(vnd, sizeof(struct vnd_softc),
230 vnd_match, vnd_attach, vnd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); 230 vnd_match, vnd_attach, vnd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
231extern struct cfdriver vnd_cd; 231extern struct cfdriver vnd_cd;
232 232
233static struct vnd_softc *vnd_spawn(int); 233static struct vnd_softc *vnd_spawn(int);
234int vnd_destroy(device_t); 234int vnd_destroy(device_t);
235 235
236static struct dkdriver vnddkdriver = { vndstrategy, minphys }; 236static struct dkdriver vnddkdriver = { vndstrategy, minphys };
237 237
238void 238void
239vndattach(int num) 239vndattach(int num)
240{ 240{
241 int error; 241 int error;
242 242
243 error = config_cfattach_attach(vnd_cd.cd_name, &vnd_ca); 243 error = config_cfattach_attach(vnd_cd.cd_name, &vnd_ca);
244 if (error) 244 if (error)
245 aprint_error("%s: unable to register cfattach\n", 245 aprint_error("%s: unable to register cfattach\n",
246 vnd_cd.cd_name); 246 vnd_cd.cd_name);
247} 247}
248 248
249static int 249static int
250vnd_match(device_t self, cfdata_t cfdata, void *aux) 250vnd_match(device_t self, cfdata_t cfdata, void *aux)
251{ 251{
252 252
253 return 1; 253 return 1;
254} 254}
255 255
256static void 256static void
257vnd_attach(device_t parent, device_t self, void *aux) 257vnd_attach(device_t parent, device_t self, void *aux)
258{ 258{
259 struct vnd_softc *sc = device_private(self); 259 struct vnd_softc *sc = device_private(self);
260 260
261 sc->sc_dev = self; 261 sc->sc_dev = self;
262 sc->sc_comp_offsets = NULL; 262 sc->sc_comp_offsets = NULL;
263 sc->sc_comp_buff = NULL; 263 sc->sc_comp_buff = NULL;
264 sc->sc_comp_decombuf = NULL; 264 sc->sc_comp_decombuf = NULL;
265 bufq_alloc(&sc->sc_tab, "disksort", BUFQ_SORT_RAWBLOCK); 265 bufq_alloc(&sc->sc_tab, "disksort", BUFQ_SORT_RAWBLOCK);
266 disk_init(&sc->sc_dkdev, device_xname(self), &vnddkdriver); 266 disk_init(&sc->sc_dkdev, device_xname(self), &vnddkdriver);
267 if (!pmf_device_register(self, NULL, NULL)) 267 if (!pmf_device_register(self, NULL, NULL))
268 aprint_error_dev(self, "couldn't establish power handler\n"); 268 aprint_error_dev(self, "couldn't establish power handler\n");
269} 269}
270 270
271static int 271static int
272vnd_detach(device_t self, int flags) 272vnd_detach(device_t self, int flags)
273{ 273{
274 int error; 274 int error;
275 struct vnd_softc *sc = device_private(self); 275 struct vnd_softc *sc = device_private(self);
276 276
277 if (sc->sc_flags & VNF_INITED) { 277 if (sc->sc_flags & VNF_INITED) {
278 error = vnddoclear(sc, 0, -1, (flags & DETACH_FORCE) != 0); 278 error = vnddoclear(sc, 0, -1, (flags & DETACH_FORCE) != 0);
279 if (error != 0) 279 if (error != 0)
280 return error; 280 return error;
281 } 281 }
282 282
283 pmf_device_deregister(self); 283 pmf_device_deregister(self);
284 bufq_free(sc->sc_tab); 284 bufq_free(sc->sc_tab);
285 disk_destroy(&sc->sc_dkdev); 285 disk_destroy(&sc->sc_dkdev);
286 286
287 return 0; 287 return 0;
288} 288}
289 289
290static struct vnd_softc * 290static struct vnd_softc *
291vnd_spawn(int unit) 291vnd_spawn(int unit)
292{ 292{
293 cfdata_t cf; 293 cfdata_t cf;
294 294
295 cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK); 295 cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
296 cf->cf_name = vnd_cd.cd_name; 296 cf->cf_name = vnd_cd.cd_name;
297 cf->cf_atname = vnd_cd.cd_name; 297 cf->cf_atname = vnd_cd.cd_name;
298 cf->cf_unit = unit; 298 cf->cf_unit = unit;
299 cf->cf_fstate = FSTATE_STAR; 299 cf->cf_fstate = FSTATE_STAR;
300 300
301 return device_private(config_attach_pseudo(cf)); 301 return device_private(config_attach_pseudo(cf));
302} 302}
303 303
304int 304int
305vnd_destroy(device_t dev) 305vnd_destroy(device_t dev)
306{ 306{
307 int error; 307 int error;
308 cfdata_t cf; 308 cfdata_t cf;
309 309
310 cf = device_cfdata(dev); 310 cf = device_cfdata(dev);
311 error = config_detach(dev, DETACH_QUIET); 311 error = config_detach(dev, DETACH_QUIET);
312 if (error) 312 if (error)
313 return error; 313 return error;
314 free(cf, M_DEVBUF); 314 free(cf, M_DEVBUF);
315 return 0; 315 return 0;
316} 316}
317 317
318static int 318static int
319vndopen(dev_t dev, int flags, int mode, struct lwp *l) 319vndopen(dev_t dev, int flags, int mode, struct lwp *l)
320{ 320{
321 int unit = vndunit(dev); 321 int unit = vndunit(dev);
322 struct vnd_softc *sc; 322 struct vnd_softc *sc;
323 int error = 0, part, pmask; 323 int error = 0, part, pmask;
324 struct disklabel *lp; 324 struct disklabel *lp;
325 325
326#ifdef DEBUG 326#ifdef DEBUG
327 if (vnddebug & VDB_FOLLOW) 327 if (vnddebug & VDB_FOLLOW)
328 printf("vndopen(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l); 328 printf("vndopen(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l);
329#endif 329#endif
330 sc = device_lookup_private(&vnd_cd, unit); 330 sc = device_lookup_private(&vnd_cd, unit);
331 if (sc == NULL) { 331 if (sc == NULL) {
332 sc = vnd_spawn(unit); 332 sc = vnd_spawn(unit);
333 if (sc == NULL) 333 if (sc == NULL)
334 return ENOMEM; 334 return ENOMEM;
335 } 335 }
336 336
337 if ((error = vndlock(sc)) != 0) 337 if ((error = vndlock(sc)) != 0)
338 return error; 338 return error;
339 339
340 if ((sc->sc_flags & VNF_CLEARING) != 0) { 340 if ((sc->sc_flags & VNF_CLEARING) != 0) {
341 error = ENXIO; 341 error = ENXIO;
342 goto done; 342 goto done;
343 } 343 }
344 344
345 lp = sc->sc_dkdev.dk_label; 345 lp = sc->sc_dkdev.dk_label;
346 346
347 part = DISKPART(dev); 347 part = DISKPART(dev);
348 pmask = (1 << part); 348 pmask = (1 << part);
349 349
350 if (sc->sc_dkdev.dk_nwedges != 0 && part != RAW_PART) { 350 if (sc->sc_dkdev.dk_nwedges != 0 && part != RAW_PART) {
351 error = EBUSY; 351 error = EBUSY;
352 goto done; 352 goto done;
353 } 353 }
354 354
355 if (sc->sc_flags & VNF_INITED) { 355 if (sc->sc_flags & VNF_INITED) {
356 if ((sc->sc_dkdev.dk_openmask & ~(1<<RAW_PART)) != 0) { 356 if ((sc->sc_dkdev.dk_openmask & ~(1<<RAW_PART)) != 0) {
357 /* 357 /*
358 * If any non-raw partition is open, but the disk 358 * If any non-raw partition is open, but the disk
359 * has been invalidated, disallow further opens. 359 * has been invalidated, disallow further opens.
360 */ 360 */
361 if ((sc->sc_flags & VNF_VLABEL) == 0) { 361 if ((sc->sc_flags & VNF_VLABEL) == 0) {
362 error = EIO; 362 error = EIO;
363 goto done; 363 goto done;
364 } 364 }
365 } else { 365 } else {
366 /* 366 /*
367 * Load the partition info if not already loaded. 367 * Load the partition info if not already loaded.
368 */ 368 */
369 if ((sc->sc_flags & VNF_VLABEL) == 0) { 369 if ((sc->sc_flags & VNF_VLABEL) == 0) {
370 sc->sc_flags |= VNF_VLABEL; 370 sc->sc_flags |= VNF_VLABEL;
371 vndgetdisklabel(dev, sc); 371 vndgetdisklabel(dev, sc);
372 } 372 }
373 } 373 }
374 } 374 }
375 375
376 /* Check that the partitions exists. */ 376 /* Check that the partitions exists. */
377 if (part != RAW_PART) { 377 if (part != RAW_PART) {
378 if (((sc->sc_flags & VNF_INITED) == 0) || 378 if (((sc->sc_flags & VNF_INITED) == 0) ||
379 ((part >= lp->d_npartitions) || 379 ((part >= lp->d_npartitions) ||
380 (lp->d_partitions[part].p_fstype == FS_UNUSED))) { 380 (lp->d_partitions[part].p_fstype == FS_UNUSED))) {
381 error = ENXIO; 381 error = ENXIO;
382 goto done; 382 goto done;
383 } 383 }
384 } 384 }
385 385
386 /* Prevent our unit from being unconfigured while open. */ 386 /* Prevent our unit from being unconfigured while open. */
387 switch (mode) { 387 switch (mode) {
388 case S_IFCHR: 388 case S_IFCHR:
389 sc->sc_dkdev.dk_copenmask |= pmask; 389 sc->sc_dkdev.dk_copenmask |= pmask;
390 break; 390 break;
391 391
392 case S_IFBLK: 392 case S_IFBLK:
393 sc->sc_dkdev.dk_bopenmask |= pmask; 393 sc->sc_dkdev.dk_bopenmask |= pmask;
394 break; 394 break;
395 } 395 }
396 sc->sc_dkdev.dk_openmask = 396 sc->sc_dkdev.dk_openmask =
397 sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask; 397 sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask;
398 398
399 done: 399 done:
400 vndunlock(sc); 400 vndunlock(sc);
401 return error; 401 return error;
402} 402}
403 403
404static int 404static int
405vndclose(dev_t dev, int flags, int mode, struct lwp *l) 405vndclose(dev_t dev, int flags, int mode, struct lwp *l)
406{ 406{
407 int unit = vndunit(dev); 407 int unit = vndunit(dev);
408 struct vnd_softc *sc; 408 struct vnd_softc *sc;
409 int error = 0, part; 409 int error = 0, part;
410 410
411#ifdef DEBUG 411#ifdef DEBUG
412 if (vnddebug & VDB_FOLLOW) 412 if (vnddebug & VDB_FOLLOW)
413 printf("vndclose(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l); 413 printf("vndclose(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l);
414#endif 414#endif
415 sc = device_lookup_private(&vnd_cd, unit); 415 sc = device_lookup_private(&vnd_cd, unit);
416 if (sc == NULL) 416 if (sc == NULL)
417 return ENXIO; 417 return ENXIO;
418 418
419 if ((error = vndlock(sc)) != 0) 419 if ((error = vndlock(sc)) != 0)
420 return error; 420 return error;
421 421
422 part = DISKPART(dev); 422 part = DISKPART(dev);
423 423
424 /* ...that much closer to allowing unconfiguration... */ 424 /* ...that much closer to allowing unconfiguration... */
425 switch (mode) { 425 switch (mode) {
426 case S_IFCHR: 426 case S_IFCHR:
427 sc->sc_dkdev.dk_copenmask &= ~(1 << part); 427 sc->sc_dkdev.dk_copenmask &= ~(1 << part);
428 break; 428 break;
429 429
430 case S_IFBLK: 430 case S_IFBLK:
431 sc->sc_dkdev.dk_bopenmask &= ~(1 << part); 431 sc->sc_dkdev.dk_bopenmask &= ~(1 << part);
432 break; 432 break;
433 } 433 }
434 sc->sc_dkdev.dk_openmask = 434 sc->sc_dkdev.dk_openmask =
435 sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask; 435 sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask;
436 436
437 vndunlock(sc); 437 vndunlock(sc);
438 438
439 if ((sc->sc_flags & VNF_INITED) == 0) { 439 if ((sc->sc_flags & VNF_INITED) == 0) {
440 if ((error = vnd_destroy(sc->sc_dev)) != 0) { 440 if ((error = vnd_destroy(sc->sc_dev)) != 0) {
441 aprint_error_dev(sc->sc_dev, 441 aprint_error_dev(sc->sc_dev,
442 "unable to detach instance\n"); 442 "unable to detach instance\n");
443 return error; 443 return error;
444 } 444 }
445 } 445 }
446 446
447 return 0; 447 return 0;
448} 448}
449 449
450/* 450/*
451 * Queue the request, and wakeup the kernel thread to handle it. 451 * Queue the request, and wakeup the kernel thread to handle it.
452 */ 452 */
453static void 453static void
454vndstrategy(struct buf *bp) 454vndstrategy(struct buf *bp)
455{ 455{
456 int unit = vndunit(bp->b_dev); 456 int unit = vndunit(bp->b_dev);
457 struct vnd_softc *vnd = 457 struct vnd_softc *vnd =
458 device_lookup_private(&vnd_cd, unit); 458 device_lookup_private(&vnd_cd, unit);
459 struct disklabel *lp; 459 struct disklabel *lp;
460 daddr_t blkno; 460 daddr_t blkno;
461 int s = splbio(); 461 int s = splbio();
462 462
463 if (vnd == NULL) { 463 if (vnd == NULL) {
464 bp->b_error = ENXIO; 464 bp->b_error = ENXIO;
465 goto done; 465 goto done;
466 } 466 }
467 lp = vnd->sc_dkdev.dk_label; 467 lp = vnd->sc_dkdev.dk_label;
468 468
469 if ((vnd->sc_flags & VNF_INITED) == 0) { 469 if ((vnd->sc_flags & VNF_INITED) == 0) {
470 bp->b_error = ENXIO; 470 bp->b_error = ENXIO;
471 goto done; 471 goto done;
472 } 472 }
473 473
474 /* 474 /*
475 * The transfer must be a whole number of blocks. 475 * The transfer must be a whole number of blocks.
476 */ 476 */
477 if ((bp->b_bcount % lp->d_secsize) != 0) { 477 if ((bp->b_bcount % lp->d_secsize) != 0) {
478 bp->b_error = EINVAL; 478 bp->b_error = EINVAL;
479 goto done; 479 goto done;
480 } 480 }
481 481
482 /* 482 /*
483 * check if we're read-only. 483 * check if we're read-only.
484 */ 484 */
485 if ((vnd->sc_flags & VNF_READONLY) && !(bp->b_flags & B_READ)) { 485 if ((vnd->sc_flags & VNF_READONLY) && !(bp->b_flags & B_READ)) {
486 bp->b_error = EACCES; 486 bp->b_error = EACCES;
487 goto done; 487 goto done;
488 } 488 }
489 489
490 /* If it's a nil transfer, wake up the top half now. */ 490 /* If it's a nil transfer, wake up the top half now. */
491 if (bp->b_bcount == 0) { 491 if (bp->b_bcount == 0) {
492 goto done; 492 goto done;
493 } 493 }
494 494
495 /* 495 /*
496 * Do bounds checking and adjust transfer. If there's an error, 496 * Do bounds checking and adjust transfer. If there's an error,
497 * the bounds check will flag that for us. 497 * the bounds check will flag that for us.
498 */ 498 */
499 if (DISKPART(bp->b_dev) == RAW_PART) { 499 if (DISKPART(bp->b_dev) == RAW_PART) {
500 if (bounds_check_with_mediasize(bp, DEV_BSIZE, 500 if (bounds_check_with_mediasize(bp, DEV_BSIZE,
501 vnd->sc_size) <= 0) 501 vnd->sc_size) <= 0)
502 goto done; 502 goto done;
503 } else { 503 } else {
504 if (bounds_check_with_label(&vnd->sc_dkdev, 504 if (bounds_check_with_label(&vnd->sc_dkdev,
505 bp, vnd->sc_flags & (VNF_WLABEL|VNF_LABELLING)) <= 0) 505 bp, vnd->sc_flags & (VNF_WLABEL|VNF_LABELLING)) <= 0)
506 goto done; 506 goto done;
507 } 507 }
508 508
509 /* 509 /*
510 * Put the block number in terms of the logical blocksize 510 * Put the block number in terms of the logical blocksize
511 * of the "device". 511 * of the "device".
512 */ 512 */
513 513
514 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); 514 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
515 515
516 /* 516 /*
517 * Translate the partition-relative block number to an absolute. 517 * Translate the partition-relative block number to an absolute.
518 */ 518 */
519 if (DISKPART(bp->b_dev) != RAW_PART) { 519 if (DISKPART(bp->b_dev) != RAW_PART) {
520 struct partition *pp; 520 struct partition *pp;
521 521
522 pp = &vnd->sc_dkdev.dk_label->d_partitions[ 522 pp = &vnd->sc_dkdev.dk_label->d_partitions[
523 DISKPART(bp->b_dev)]; 523 DISKPART(bp->b_dev)];
524 blkno += pp->p_offset; 524 blkno += pp->p_offset;
525 } 525 }
526 bp->b_rawblkno = blkno; 526 bp->b_rawblkno = blkno;
527 527
528#ifdef DEBUG 528#ifdef DEBUG
529 if (vnddebug & VDB_FOLLOW) 529 if (vnddebug & VDB_FOLLOW)
530 printf("vndstrategy(%p): unit %d\n", bp, unit); 530 printf("vndstrategy(%p): unit %d\n", bp, unit);
531#endif 531#endif
532 if ((vnd->sc_flags & VNF_USE_VN_RDWR)) { 532 if ((vnd->sc_flags & VNF_USE_VN_RDWR)) {
533 KASSERT(vnd->sc_pending >= 0 && 533 KASSERT(vnd->sc_pending >= 0 &&
534 vnd->sc_pending <= VND_MAXPENDING(vnd)); 534 vnd->sc_pending <= VND_MAXPENDING(vnd));
535 while (vnd->sc_pending == VND_MAXPENDING(vnd)) 535 while (vnd->sc_pending == VND_MAXPENDING(vnd))
536 tsleep(&vnd->sc_pending, PRIBIO, "vndpc", 0); 536 tsleep(&vnd->sc_pending, PRIBIO, "vndpc", 0);
537 vnd->sc_pending++; 537 vnd->sc_pending++;
538 } 538 }
539 bufq_put(vnd->sc_tab, bp); 539 bufq_put(vnd->sc_tab, bp);
540 wakeup(&vnd->sc_tab); 540 wakeup(&vnd->sc_tab);
541 splx(s); 541 splx(s);
542 return; 542 return;
543 543
544done: 544done:
545 bp->b_resid = bp->b_bcount; 545 bp->b_resid = bp->b_bcount;
546 biodone(bp); 546 biodone(bp);
547 splx(s); 547 splx(s);
548} 548}
549 549
550static bool 550static bool
551vnode_has_strategy(struct vnd_softc *vnd) 551vnode_has_strategy(struct vnd_softc *vnd)
552{ 552{
553 return vnode_has_op(vnd->sc_vp, VOFFSET(vop_bmap)) && 553 return vnode_has_op(vnd->sc_vp, VOFFSET(vop_bmap)) &&
554 vnode_has_op(vnd->sc_vp, VOFFSET(vop_strategy)); 554 vnode_has_op(vnd->sc_vp, VOFFSET(vop_strategy));
555} 555}
556 556
557/* XXX this function needs a reliable check to detect 557/* XXX this function needs a reliable check to detect
558 * sparse files. Otherwise, bmap/strategy may be used 558 * sparse files. Otherwise, bmap/strategy may be used
559 * and fail on non-allocated blocks. VOP_READ/VOP_WRITE 559 * and fail on non-allocated blocks. VOP_READ/VOP_WRITE
560 * works on sparse files. 560 * works on sparse files.
561 */ 561 */
562#if notyet 562#if notyet
563static bool 563static bool
564vnode_strategy_probe(struct vnd_softc *vnd) 564vnode_strategy_probe(struct vnd_softc *vnd)
565{ 565{
566 int error; 566 int error;
567 daddr_t nbn; 567 daddr_t nbn;
568 568
569 if (!vnode_has_strategy(vnd)) 569 if (!vnode_has_strategy(vnd))
570 return false; 570 return false;
571 571
572 /* Convert the first logical block number to its 572 /* Convert the first logical block number to its
573 * physical block number. 573 * physical block number.
574 */ 574 */
575 error = 0; 575 error = 0;
576 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 576 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY);
577 error = VOP_BMAP(vnd->sc_vp, 0, NULL, &nbn, NULL); 577 error = VOP_BMAP(vnd->sc_vp, 0, NULL, &nbn, NULL);
578 VOP_UNLOCK(vnd->sc_vp); 578 VOP_UNLOCK(vnd->sc_vp);
579 579
580 /* Test if that worked. */ 580 /* Test if that worked. */
581 if (error == 0 && (long)nbn == -1) 581 if (error == 0 && (long)nbn == -1)
582 return false; 582 return false;
583 583
584 return true; 584 return true;
585} 585}
586#endif 586#endif
587 587
588static void 588static void
589vndthread(void *arg) 589vndthread(void *arg)
590{ 590{
591 struct vnd_softc *vnd = arg; 591 struct vnd_softc *vnd = arg;
592 int s; 592 int s;
593 593
594 /* Determine whether we can *use* VOP_BMAP and VOP_STRATEGY to 594 /* Determine whether we can *use* VOP_BMAP and VOP_STRATEGY to
595 * directly access the backing vnode. If we can, use these two 595 * directly access the backing vnode. If we can, use these two
596 * operations to avoid messing with the local buffer cache. 596 * operations to avoid messing with the local buffer cache.
597 * Otherwise fall back to regular VOP_READ/VOP_WRITE operations 597 * Otherwise fall back to regular VOP_READ/VOP_WRITE operations
598 * which are guaranteed to work with any file system. */ 598 * which are guaranteed to work with any file system. */
599 if ((vnd->sc_flags & VNF_USE_VN_RDWR) == 0 && 599 if ((vnd->sc_flags & VNF_USE_VN_RDWR) == 0 &&
600 ! vnode_has_strategy(vnd)) 600 ! vnode_has_strategy(vnd))
601 vnd->sc_flags |= VNF_USE_VN_RDWR; 601 vnd->sc_flags |= VNF_USE_VN_RDWR;
602 602
603#ifdef DEBUG 603#ifdef DEBUG
604 if (vnddebug & VDB_INIT) 604 if (vnddebug & VDB_INIT)
605 printf("vndthread: vp %p, %s\n", vnd->sc_vp, 605 printf("vndthread: vp %p, %s\n", vnd->sc_vp,
606 (vnd->sc_flags & VNF_USE_VN_RDWR) == 0 ? 606 (vnd->sc_flags & VNF_USE_VN_RDWR) == 0 ?
607 "using bmap/strategy operations" : 607 "using bmap/strategy operations" :
608 "using read/write operations"); 608 "using read/write operations");
609#endif 609#endif
610 610
611 s = splbio(); 611 s = splbio();
612 vnd->sc_flags |= VNF_KTHREAD; 612 vnd->sc_flags |= VNF_KTHREAD;
613 wakeup(&vnd->sc_kthread); 613 wakeup(&vnd->sc_kthread);
614 614
615 /* 615 /*
616 * Dequeue requests and serve them depending on the available 616 * Dequeue requests and serve them depending on the available
617 * vnode operations. 617 * vnode operations.
618 */ 618 */
619 while ((vnd->sc_flags & VNF_VUNCONF) == 0) { 619 while ((vnd->sc_flags & VNF_VUNCONF) == 0) {
620 struct vndxfer *vnx; 620 struct vndxfer *vnx;
621 struct buf *obp; 621 struct buf *obp;
622 struct buf *bp; 622 struct buf *bp;
623 623
624 obp = bufq_get(vnd->sc_tab); 624 obp = bufq_get(vnd->sc_tab);
625 if (obp == NULL) { 625 if (obp == NULL) {
626 tsleep(&vnd->sc_tab, PRIBIO, "vndbp", 0); 626 tsleep(&vnd->sc_tab, PRIBIO, "vndbp", 0);
627 continue; 627 continue;
628 }; 628 };
629 if ((vnd->sc_flags & VNF_USE_VN_RDWR)) { 629 if ((vnd->sc_flags & VNF_USE_VN_RDWR)) {
630 KASSERT(vnd->sc_pending > 0 && 630 KASSERT(vnd->sc_pending > 0 &&
631 vnd->sc_pending <= VND_MAXPENDING(vnd)); 631 vnd->sc_pending <= VND_MAXPENDING(vnd));
632 if (vnd->sc_pending-- == VND_MAXPENDING(vnd)) 632 if (vnd->sc_pending-- == VND_MAXPENDING(vnd))
633 wakeup(&vnd->sc_pending); 633 wakeup(&vnd->sc_pending);
634 } 634 }
635 splx(s); 635 splx(s);
636#ifdef DEBUG 636#ifdef DEBUG
637 if (vnddebug & VDB_FOLLOW) 637 if (vnddebug & VDB_FOLLOW)
638 printf("vndthread(%p)\n", obp); 638 printf("vndthread(%p)\n", obp);
639#endif 639#endif
640 640
641 if (vnd->sc_vp->v_mount == NULL) { 641 if (vnd->sc_vp->v_mount == NULL) {
642 obp->b_error = ENXIO; 642 obp->b_error = ENXIO;
643 goto done; 643 goto done;
644 } 644 }
645#ifdef VND_COMPRESSION 645#ifdef VND_COMPRESSION
646 /* handle a compressed read */ 646 /* handle a compressed read */
647 if ((obp->b_flags & B_READ) != 0 && (vnd->sc_flags & VNF_COMP)) { 647 if ((obp->b_flags & B_READ) != 0 && (vnd->sc_flags & VNF_COMP)) {
648 off_t bn; 648 off_t bn;
649  649
650 /* Convert to a byte offset within the file. */ 650 /* Convert to a byte offset within the file. */
651 bn = obp->b_rawblkno * 651 bn = obp->b_rawblkno *
652 vnd->sc_dkdev.dk_label->d_secsize; 652 vnd->sc_dkdev.dk_label->d_secsize;
653 653
654 compstrategy(obp, bn); 654 compstrategy(obp, bn);
655 goto done; 655 goto done;
656 } 656 }
657#endif /* VND_COMPRESSION */ 657#endif /* VND_COMPRESSION */
658  658
659 /* 659 /*
660 * Allocate a header for this transfer and link it to the 660 * Allocate a header for this transfer and link it to the
661 * buffer 661 * buffer
662 */ 662 */
663 s = splbio(); 663 s = splbio();
664 vnx = VND_GETXFER(vnd); 664 vnx = VND_GETXFER(vnd);
665 splx(s); 665 splx(s);
666 vnx->vx_vnd = vnd; 666 vnx->vx_vnd = vnd;
667 667
668 s = splbio(); 668 s = splbio();
669 while (vnd->sc_active >= vnd->sc_maxactive) { 669 while (vnd->sc_active >= vnd->sc_maxactive) {
670 tsleep(&vnd->sc_tab, PRIBIO, "vndac", 0); 670 tsleep(&vnd->sc_tab, PRIBIO, "vndac", 0);
671 } 671 }
672 vnd->sc_active++; 672 vnd->sc_active++;
673 splx(s); 673 splx(s);
674 674
675 /* Instrumentation. */ 675 /* Instrumentation. */
676 disk_busy(&vnd->sc_dkdev); 676 disk_busy(&vnd->sc_dkdev);
677 677
678 bp = &vnx->vx_buf; 678 bp = &vnx->vx_buf;
679 buf_init(bp); 679 buf_init(bp);
680 bp->b_flags = (obp->b_flags & B_READ); 680 bp->b_flags = (obp->b_flags & B_READ);
681 bp->b_oflags = obp->b_oflags; 681 bp->b_oflags = obp->b_oflags;
682 bp->b_cflags = obp->b_cflags; 682 bp->b_cflags = obp->b_cflags;
683 bp->b_iodone = vndiodone; 683 bp->b_iodone = vndiodone;
684 bp->b_private = obp; 684 bp->b_private = obp;
685 bp->b_vp = vnd->sc_vp; 685 bp->b_vp = vnd->sc_vp;
686 bp->b_objlock = bp->b_vp->v_interlock; 686 bp->b_objlock = bp->b_vp->v_interlock;
687 bp->b_data = obp->b_data; 687 bp->b_data = obp->b_data;
688 bp->b_bcount = obp->b_bcount; 688 bp->b_bcount = obp->b_bcount;
689 BIO_COPYPRIO(bp, obp); 689 BIO_COPYPRIO(bp, obp);
690 690
691 /* Handle the request using the appropriate operations. */ 691 /* Handle the request using the appropriate operations. */
692 if ((vnd->sc_flags & VNF_USE_VN_RDWR) == 0) 692 if ((vnd->sc_flags & VNF_USE_VN_RDWR) == 0)
693 handle_with_strategy(vnd, obp, bp); 693 handle_with_strategy(vnd, obp, bp);
694 else 694 else
695 handle_with_rdwr(vnd, obp, bp); 695 handle_with_rdwr(vnd, obp, bp);
696 696
697 s = splbio(); 697 s = splbio();
698 continue; 698 continue;
699 699
700done: 700done:
701 biodone(obp); 701 biodone(obp);
702 s = splbio(); 702 s = splbio();
703 } 703 }
704 704
705 vnd->sc_flags &= (~VNF_KTHREAD | VNF_VUNCONF); 705 vnd->sc_flags &= (~VNF_KTHREAD | VNF_VUNCONF);
706 wakeup(&vnd->sc_kthread); 706 wakeup(&vnd->sc_kthread);
707 splx(s); 707 splx(s);
708 kthread_exit(0); 708 kthread_exit(0);
709} 709}
710 710
711/* 711/*
712 * Checks if the given vnode supports the requested operation. 712 * Checks if the given vnode supports the requested operation.
713 * The operation is specified the offset returned by VOFFSET. 713 * The operation is specified the offset returned by VOFFSET.
714 * 714 *
715 * XXX The test below used to determine this is quite fragile 715 * XXX The test below used to determine this is quite fragile
716 * because it relies on the file system to use genfs to specify 716 * because it relies on the file system to use genfs to specify
717 * unimplemented operations. There might be another way to do 717 * unimplemented operations. There might be another way to do
718 * it more cleanly. 718 * it more cleanly.
719 */ 719 */
720static bool 720static bool
721vnode_has_op(const struct vnode *vp, int opoffset) 721vnode_has_op(const struct vnode *vp, int opoffset)
722{ 722{
723 int (*defaultp)(void *); 723 int (*defaultp)(void *);
724 int (*opp)(void *); 724 int (*opp)(void *);
725 725
726 defaultp = vp->v_op[VOFFSET(vop_default)]; 726 defaultp = vp->v_op[VOFFSET(vop_default)];
727 opp = vp->v_op[opoffset]; 727 opp = vp->v_op[opoffset];
728 728
729 return opp != defaultp && opp != genfs_eopnotsupp && 729 return opp != defaultp && opp != genfs_eopnotsupp &&
730 opp != genfs_badop && opp != genfs_nullop; 730 opp != genfs_badop && opp != genfs_nullop;
731} 731}
732 732
733/* 733/*
734 * Handes the read/write request given in 'bp' using the vnode's VOP_READ 734 * Handes the read/write request given in 'bp' using the vnode's VOP_READ
735 * and VOP_WRITE operations. 735 * and VOP_WRITE operations.
736 * 736 *
737 * 'obp' is a pointer to the original request fed to the vnd device. 737 * 'obp' is a pointer to the original request fed to the vnd device.
738 */ 738 */
739static void 739static void
740handle_with_rdwr(struct vnd_softc *vnd, const struct buf *obp, struct buf *bp) 740handle_with_rdwr(struct vnd_softc *vnd, const struct buf *obp, struct buf *bp)
741{ 741{
742 bool doread; 742 bool doread;
743 off_t offset; 743 off_t offset;
744 size_t len, resid; 744 size_t len, resid;
745 struct vnode *vp; 745 struct vnode *vp;
746 746
747 doread = bp->b_flags & B_READ; 747 doread = bp->b_flags & B_READ;
748 offset = obp->b_rawblkno * vnd->sc_dkdev.dk_label->d_secsize; 748 offset = obp->b_rawblkno * vnd->sc_dkdev.dk_label->d_secsize;
749 len = bp->b_bcount; 749 len = bp->b_bcount;
750 vp = vnd->sc_vp; 750 vp = vnd->sc_vp;
751 751
752#if defined(DEBUG) 752#if defined(DEBUG)
753 if (vnddebug & VDB_IO) 753 if (vnddebug & VDB_IO)
754 printf("vnd (rdwr): vp %p, %s, rawblkno 0x%" PRIx64 754 printf("vnd (rdwr): vp %p, %s, rawblkno 0x%" PRIx64
755 ", secsize %d, offset %" PRIu64 755 ", secsize %d, offset %" PRIu64
756 ", bcount %d\n", 756 ", bcount %d\n",
757 vp, doread ? "read" : "write", obp->b_rawblkno, 757 vp, doread ? "read" : "write", obp->b_rawblkno,
758 vnd->sc_dkdev.dk_label->d_secsize, offset, 758 vnd->sc_dkdev.dk_label->d_secsize, offset,
759 bp->b_bcount); 759 bp->b_bcount);
760#endif 760#endif
761 761
762 /* Issue the read or write operation. */ 762 /* Issue the read or write operation. */
763 bp->b_error = 763 bp->b_error =
764 vn_rdwr(doread ? UIO_READ : UIO_WRITE, 764 vn_rdwr(doread ? UIO_READ : UIO_WRITE,
765 vp, bp->b_data, len, offset, UIO_SYSSPACE, 765 vp, bp->b_data, len, offset, UIO_SYSSPACE,
766 IO_ADV_ENCODE(POSIX_FADV_NOREUSE), vnd->sc_cred, &resid, NULL); 766 IO_ADV_ENCODE(POSIX_FADV_NOREUSE), vnd->sc_cred, &resid, NULL);
767 bp->b_resid = resid; 767 bp->b_resid = resid;
768 768
769 mutex_enter(vp->v_interlock); 769 mutex_enter(vp->v_interlock);
770 (void) VOP_PUTPAGES(vp, 0, 0, 770 (void) VOP_PUTPAGES(vp, 0, 0,
771 PGO_ALLPAGES | PGO_CLEANIT | PGO_FREE | PGO_SYNCIO); 771 PGO_ALLPAGES | PGO_CLEANIT | PGO_FREE | PGO_SYNCIO);
772 772
773 /* We need to increase the number of outputs on the vnode if 773 /* We need to increase the number of outputs on the vnode if
774 * there was any write to it. */ 774 * there was any write to it. */
775 if (!doread) { 775 if (!doread) {
776 mutex_enter(vp->v_interlock); 776 mutex_enter(vp->v_interlock);
777 vp->v_numoutput++; 777 vp->v_numoutput++;
778 mutex_exit(vp->v_interlock); 778 mutex_exit(vp->v_interlock);
779 } 779 }
780 780
781 biodone(bp); 781 biodone(bp);
782} 782}
783 783
784/* 784/*
785 * Handes the read/write request given in 'bp' using the vnode's VOP_BMAP 785 * Handes the read/write request given in 'bp' using the vnode's VOP_BMAP
786 * and VOP_STRATEGY operations. 786 * and VOP_STRATEGY operations.
787 * 787 *
788 * 'obp' is a pointer to the original request fed to the vnd device. 788 * 'obp' is a pointer to the original request fed to the vnd device.
789 */ 789 */
790static void 790static void
791handle_with_strategy(struct vnd_softc *vnd, const struct buf *obp, 791handle_with_strategy(struct vnd_softc *vnd, const struct buf *obp,
792 struct buf *bp) 792 struct buf *bp)
793{ 793{
794 int bsize, error, flags, skipped; 794 int bsize, error, flags, skipped;
795 size_t resid, sz; 795 size_t resid, sz;
796 off_t bn, offset; 796 off_t bn, offset;
797 struct vnode *vp; 797 struct vnode *vp;
798 struct buf *nbp = NULL; 798 struct buf *nbp = NULL;
799 799
800 flags = obp->b_flags; 800 flags = obp->b_flags;
801 801
802 802
803 /* convert to a byte offset within the file. */ 803 /* convert to a byte offset within the file. */
804 bn = obp->b_rawblkno * vnd->sc_dkdev.dk_label->d_secsize; 804 bn = obp->b_rawblkno * vnd->sc_dkdev.dk_label->d_secsize;
805 805
806 bsize = vnd->sc_vp->v_mount->mnt_stat.f_iosize; 806 bsize = vnd->sc_vp->v_mount->mnt_stat.f_iosize;
807 skipped = 0; 807 skipped = 0;
808 808
809 /* 809 /*
810 * Break the request into bsize pieces and feed them 810 * Break the request into bsize pieces and feed them
811 * sequentially using VOP_BMAP/VOP_STRATEGY. 811 * sequentially using VOP_BMAP/VOP_STRATEGY.
812 * We do it this way to keep from flooding NFS servers if we 812 * We do it this way to keep from flooding NFS servers if we
813 * are connected to an NFS file. This places the burden on 813 * are connected to an NFS file. This places the burden on
814 * the client rather than the server. 814 * the client rather than the server.
815 */ 815 */
816 error = 0; 816 error = 0;
817 bp->b_resid = bp->b_bcount; 817 bp->b_resid = bp->b_bcount;
818 for (offset = 0, resid = bp->b_resid; /* true */; 818 for (offset = 0, resid = bp->b_resid; /* true */;
819 resid -= sz, offset += sz) { 819 resid -= sz, offset += sz) {
820 daddr_t nbn; 820 daddr_t nbn;
821 int off, nra; 821 int off, nra;
822 822
823 nra = 0; 823 nra = 0;
824 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 824 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY);
825 error = VOP_BMAP(vnd->sc_vp, bn / bsize, &vp, &nbn, &nra); 825 error = VOP_BMAP(vnd->sc_vp, bn / bsize, &vp, &nbn, &nra);
826 VOP_UNLOCK(vnd->sc_vp); 826 VOP_UNLOCK(vnd->sc_vp);
827 827
828 if (error == 0 && (long)nbn == -1) 828 if (error == 0 && (long)nbn == -1)
829 error = EIO; 829 error = EIO;
830 830
831 /* 831 /*
832 * If there was an error or a hole in the file...punt. 832 * If there was an error or a hole in the file...punt.
833 * Note that we may have to wait for any operations 833 * Note that we may have to wait for any operations
834 * that we have already fired off before releasing 834 * that we have already fired off before releasing
835 * the buffer. 835 * the buffer.
836 * 836 *
837 * XXX we could deal with holes here but it would be 837 * XXX we could deal with holes here but it would be
838 * a hassle (in the write case). 838 * a hassle (in the write case).
839 */ 839 */
840 if (error) { 840 if (error) {
841 skipped += resid; 841 skipped += resid;
842 break; 842 break;
843 } 843 }
844 844
845#ifdef DEBUG 845#ifdef DEBUG
846 if (!dovndcluster) 846 if (!dovndcluster)
847 nra = 0; 847 nra = 0;
848#endif 848#endif
849 849
850 off = bn % bsize; 850 off = bn % bsize;
851 sz = MIN(((off_t)1 + nra) * bsize - off, resid); 851 sz = MIN(((off_t)1 + nra) * bsize - off, resid);
852#ifdef DEBUG 852#ifdef DEBUG
853 if (vnddebug & VDB_IO) 853 if (vnddebug & VDB_IO)
854 printf("vndstrategy: vp %p/%p bn 0x%qx/0x%" PRIx64 854 printf("vndstrategy: vp %p/%p bn 0x%qx/0x%" PRIx64
855 " sz 0x%zx\n", vnd->sc_vp, vp, (long long)bn, 855 " sz 0x%zx\n", vnd->sc_vp, vp, (long long)bn,
856 nbn, sz); 856 nbn, sz);
857#endif 857#endif
858 858
859 nbp = getiobuf(vp, true); 859 nbp = getiobuf(vp, true);
860 nestiobuf_setup(bp, nbp, offset, sz); 860 nestiobuf_setup(bp, nbp, offset, sz);
861 nbp->b_blkno = nbn + btodb(off); 861 nbp->b_blkno = nbn + btodb(off);
862 862
863#if 0 /* XXX #ifdef DEBUG */ 863#if 0 /* XXX #ifdef DEBUG */
864 if (vnddebug & VDB_IO) 864 if (vnddebug & VDB_IO)
865 printf("vndstart(%ld): bp %p vp %p blkno " 865 printf("vndstart(%ld): bp %p vp %p blkno "
866 "0x%" PRIx64 " flags %x addr %p cnt 0x%x\n", 866 "0x%" PRIx64 " flags %x addr %p cnt 0x%x\n",
867 (long) (vnd-vnd_softc), &nbp->vb_buf, 867 (long) (vnd-vnd_softc), &nbp->vb_buf,
868 nbp->vb_buf.b_vp, nbp->vb_buf.b_blkno, 868 nbp->vb_buf.b_vp, nbp->vb_buf.b_blkno,
869 nbp->vb_buf.b_flags, nbp->vb_buf.b_data, 869 nbp->vb_buf.b_flags, nbp->vb_buf.b_data,
870 nbp->vb_buf.b_bcount); 870 nbp->vb_buf.b_bcount);
871#endif 871#endif
872 if (resid == sz) { 872 if (resid == sz) {
873 break; 873 break;
874 } 874 }
875 VOP_STRATEGY(vp, nbp); 875 VOP_STRATEGY(vp, nbp);
876 bn += sz; 876 bn += sz;
877 } 877 }
878 if (!(flags & B_READ)) { 878 if (!(flags & B_READ)) {
879 struct vnode *w_vp; 879 struct vnode *w_vp;
880 /* 880 /*
881 * this is the last nested buf, account for 881 * this is the last nested buf, account for
882 * the parent buf write too. 882 * the parent buf write too.
883 * This has to be done last, so that 883 * This has to be done last, so that
884 * fsync won't wait for this write which 884 * fsync won't wait for this write which
885 * has no chance to complete before all nested bufs 885 * has no chance to complete before all nested bufs
886 * have been queued. But it has to be done 886 * have been queued. But it has to be done
887 * before the last VOP_STRATEGY()  887 * before the last VOP_STRATEGY()
888 * or the call to nestiobuf_done(). 888 * or the call to nestiobuf_done().
889 */ 889 */
890 w_vp = bp->b_vp; 890 w_vp = bp->b_vp;
891 mutex_enter(w_vp->v_interlock); 891 mutex_enter(w_vp->v_interlock);
892 w_vp->v_numoutput++; 892 w_vp->v_numoutput++;
893 mutex_exit(w_vp->v_interlock); 893 mutex_exit(w_vp->v_interlock);
894 } 894 }
895 KASSERT(skipped != 0 || nbp != NULL); 895 KASSERT(skipped != 0 || nbp != NULL);
896 if (skipped)  896 if (skipped)
897 nestiobuf_done(bp, skipped, error); 897 nestiobuf_done(bp, skipped, error);
898 else  898 else
899 VOP_STRATEGY(vp, nbp); 899 VOP_STRATEGY(vp, nbp);
900} 900}
901 901
902static void 902static void
903vndiodone(struct buf *bp) 903vndiodone(struct buf *bp)
904{ 904{
905 struct vndxfer *vnx = VND_BUFTOXFER(bp); 905 struct vndxfer *vnx = VND_BUFTOXFER(bp);
906 struct vnd_softc *vnd = vnx->vx_vnd; 906 struct vnd_softc *vnd = vnx->vx_vnd;
907 struct buf *obp = bp->b_private; 907 struct buf *obp = bp->b_private;
908 int s = splbio(); 908 int s = splbio();
909 909
910 KASSERT(&vnx->vx_buf == bp); 910 KASSERT(&vnx->vx_buf == bp);
911 KASSERT(vnd->sc_active > 0); 911 KASSERT(vnd->sc_active > 0);
912#ifdef DEBUG 912#ifdef DEBUG
913 if (vnddebug & VDB_IO) { 913 if (vnddebug & VDB_IO) {
914 printf("vndiodone1: bp %p iodone: error %d\n", 914 printf("vndiodone1: bp %p iodone: error %d\n",
915 bp, bp->b_error); 915 bp, bp->b_error);
916 } 916 }
917#endif 917#endif
918 disk_unbusy(&vnd->sc_dkdev, bp->b_bcount - bp->b_resid, 918 disk_unbusy(&vnd->sc_dkdev, bp->b_bcount - bp->b_resid,
919 (bp->b_flags & B_READ)); 919 (bp->b_flags & B_READ));
920 vnd->sc_active--; 920 vnd->sc_active--;
921 if (vnd->sc_active == 0) { 921 if (vnd->sc_active == 0) {
922 wakeup(&vnd->sc_tab); 922 wakeup(&vnd->sc_tab);
923 } 923 }
924 splx(s); 924 splx(s);
925 obp->b_error = bp->b_error; 925 obp->b_error = bp->b_error;
926 obp->b_resid = bp->b_resid; 926 obp->b_resid = bp->b_resid;
927 buf_destroy(bp); 927 buf_destroy(bp);
928 VND_PUTXFER(vnd, vnx); 928 VND_PUTXFER(vnd, vnx);
929 biodone(obp); 929 biodone(obp);
930} 930}
931 931
932/* ARGSUSED */ 932/* ARGSUSED */
933static int 933static int
934vndread(dev_t dev, struct uio *uio, int flags) 934vndread(dev_t dev, struct uio *uio, int flags)
935{ 935{
936 int unit = vndunit(dev); 936 int unit = vndunit(dev);
937 struct vnd_softc *sc; 937 struct vnd_softc *sc;
938 938
939#ifdef DEBUG 939#ifdef DEBUG
940 if (vnddebug & VDB_FOLLOW) 940 if (vnddebug & VDB_FOLLOW)
941 printf("vndread(0x%"PRIx64", %p)\n", dev, uio); 941 printf("vndread(0x%"PRIx64", %p)\n", dev, uio);
942#endif 942#endif
943 943
944 sc = device_lookup_private(&vnd_cd, unit); 944 sc = device_lookup_private(&vnd_cd, unit);
945 if (sc == NULL) 945 if (sc == NULL)
946 return ENXIO; 946 return ENXIO;
947 947
948 if ((sc->sc_flags & VNF_INITED) == 0) 948 if ((sc->sc_flags & VNF_INITED) == 0)
949 return ENXIO; 949 return ENXIO;
950 950
951 return physio(vndstrategy, NULL, dev, B_READ, minphys, uio); 951 return physio(vndstrategy, NULL, dev, B_READ, minphys, uio);
952} 952}
953 953
954/* ARGSUSED */ 954/* ARGSUSED */
955static int 955static int
956vndwrite(dev_t dev, struct uio *uio, int flags) 956vndwrite(dev_t dev, struct uio *uio, int flags)
957{ 957{
958 int unit = vndunit(dev); 958 int unit = vndunit(dev);
959 struct vnd_softc *sc; 959 struct vnd_softc *sc;
960 960
961#ifdef DEBUG 961#ifdef DEBUG
962 if (vnddebug & VDB_FOLLOW) 962 if (vnddebug & VDB_FOLLOW)
963 printf("vndwrite(0x%"PRIx64", %p)\n", dev, uio); 963 printf("vndwrite(0x%"PRIx64", %p)\n", dev, uio);
964#endif 964#endif
965 965
966 sc = device_lookup_private(&vnd_cd, unit); 966 sc = device_lookup_private(&vnd_cd, unit);
967 if (sc == NULL) 967 if (sc == NULL)
968 return ENXIO; 968 return ENXIO;
969 969
970 if ((sc->sc_flags & VNF_INITED) == 0) 970 if ((sc->sc_flags & VNF_INITED) == 0)
971 return ENXIO; 971 return ENXIO;
972 972
973 return physio(vndstrategy, NULL, dev, B_WRITE, minphys, uio); 973 return physio(vndstrategy, NULL, dev, B_WRITE, minphys, uio);
974} 974}
975 975
976static int 976static int
977vnd_cget(struct lwp *l, int unit, int *un, struct vattr *va) 977vnd_cget(struct lwp *l, int unit, int *un, struct vattr *va)
978{ 978{
979 int error; 979 int error;
980 struct vnd_softc *vnd; 980 struct vnd_softc *vnd;
981 981
982 if (*un == -1) 982 if (*un == -1)
983 *un = unit; 983 *un = unit;
984 if (*un < 0) 984 if (*un < 0)
985 return EINVAL; 985 return EINVAL;
986 986
987 vnd = device_lookup_private(&vnd_cd, *un); 987 vnd = device_lookup_private(&vnd_cd, *un);
988 if (vnd == NULL) 988 if (vnd == NULL)
989 return -1; 989 return -1;
990 990
991 if ((vnd->sc_flags & VNF_INITED) == 0) 991 if ((vnd->sc_flags & VNF_INITED) == 0)
992 return -1; 992 return -1;
993 993
994 vn_lock(vnd->sc_vp, LK_SHARED | LK_RETRY); 994 vn_lock(vnd->sc_vp, LK_SHARED | LK_RETRY);
995 error = VOP_GETATTR(vnd->sc_vp, va, l->l_cred); 995 error = VOP_GETATTR(vnd->sc_vp, va, l->l_cred);
996 VOP_UNLOCK(vnd->sc_vp); 996 VOP_UNLOCK(vnd->sc_vp);
997 return error; 997 return error;
998} 998}
999 999
1000static int 1000static int
1001vnddoclear(struct vnd_softc *vnd, int pmask, int minor, bool force) 1001vnddoclear(struct vnd_softc *vnd, int pmask, int minor, bool force)
1002{ 1002{
1003 int error; 1003 int error;
1004 1004
1005 if ((error = vndlock(vnd)) != 0) 1005 if ((error = vndlock(vnd)) != 0)
1006 return error; 1006 return error;
1007 1007
1008 /* 1008 /*
1009 * Don't unconfigure if any other partitions are open 1009 * Don't unconfigure if any other partitions are open
1010 * or if both the character and block flavors of this 1010 * or if both the character and block flavors of this
1011 * partition are open. 1011 * partition are open.
1012 */ 1012 */
1013 if (DK_BUSY(vnd, pmask) && !force) { 1013 if (DK_BUSY(vnd, pmask) && !force) {
1014 vndunlock(vnd); 1014 vndunlock(vnd);
1015 return EBUSY; 1015 return EBUSY;
1016 } 1016 }
1017 1017
1018 /* Delete all of our wedges */ 1018 /* Delete all of our wedges */
1019 dkwedge_delall(&vnd->sc_dkdev); 1019 dkwedge_delall(&vnd->sc_dkdev);
1020 1020
1021 /* 1021 /*
1022 * XXX vndclear() might call vndclose() implicitly; 1022 * XXX vndclear() might call vndclose() implicitly;
1023 * release lock to avoid recursion 1023 * release lock to avoid recursion
1024 * 1024 *
1025 * Set VNF_CLEARING to prevent vndopen() from 1025 * Set VNF_CLEARING to prevent vndopen() from
1026 * sneaking in after we vndunlock(). 1026 * sneaking in after we vndunlock().
1027 */ 1027 */
1028 vnd->sc_flags |= VNF_CLEARING; 1028 vnd->sc_flags |= VNF_CLEARING;
1029 vndunlock(vnd); 1029 vndunlock(vnd);
1030 vndclear(vnd, minor); 1030 vndclear(vnd, minor);
1031#ifdef DEBUG 1031#ifdef DEBUG
1032 if (vnddebug & VDB_INIT) 1032 if (vnddebug & VDB_INIT)
1033 printf("%s: CLRed\n", __func__); 1033 printf("%s: CLRed\n", __func__);
1034#endif 1034#endif
1035 1035
1036 /* Destroy the xfer and buffer pools. */ 1036 /* Destroy the xfer and buffer pools. */
1037 pool_destroy(&vnd->sc_vxpool); 1037 pool_destroy(&vnd->sc_vxpool);
1038 1038
1039 /* Detach the disk. */ 1039 /* Detach the disk. */
1040 disk_detach(&vnd->sc_dkdev); 1040 disk_detach(&vnd->sc_dkdev);
1041 1041
1042 return 0; 1042 return 0;
1043} 1043}
1044 1044
1045static int 1045static int
1046vndioctl_get(struct lwp *l, void *data, int unit, struct vattr *va) 1046vndioctl_get(struct lwp *l, void *data, int unit, struct vattr *va)
1047{ 1047{
1048 int error; 1048 int error;
1049 1049
1050 KASSERT(l); 1050 KASSERT(l);
1051 1051
1052 /* the first member is always int vnd_unit in all the versions */ 1052 /* the first member is always int vnd_unit in all the versions */
1053 if (*(int *)data >= vnd_cd.cd_ndevs) 1053 if (*(int *)data >= vnd_cd.cd_ndevs)
1054 return ENXIO; 1054 return ENXIO;
1055 1055
1056 switch (error = vnd_cget(l, unit, (int *)data, va)) { 1056 switch (error = vnd_cget(l, unit, (int *)data, va)) {
1057 case -1: 1057 case -1:
1058 /* unused is not an error */ 1058 /* unused is not an error */
1059 memset(va, 0, sizeof(*va)); 1059 memset(va, 0, sizeof(*va));
1060 /*FALLTHROUGH*/ 1060 /*FALLTHROUGH*/
1061 case 0: 1061 case 0:
1062 return 0; 1062 return 0;
1063 default: 1063 default:
1064 return error; 1064 return error;
1065 } 1065 }
1066} 1066}
1067 1067
1068/* ARGSUSED */ 1068/* ARGSUSED */
1069static int 1069static int
1070vndioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1070vndioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1071{ 1071{
1072 bool force; 1072 bool force;
1073 int unit = vndunit(dev); 1073 int unit = vndunit(dev);
1074 struct vnd_softc *vnd; 1074 struct vnd_softc *vnd;
1075 struct vnd_ioctl *vio; 1075 struct vnd_ioctl *vio;
1076 struct vattr vattr; 1076 struct vattr vattr;
1077 struct pathbuf *pb; 1077 struct pathbuf *pb;
1078 struct nameidata nd; 1078 struct nameidata nd;
1079 int error, part, pmask; 1079 int error, part, pmask;
1080 uint64_t geomsize; 1080 uint64_t geomsize;
1081 int fflags; 1081 int fflags;
1082#ifdef __HAVE_OLD_DISKLABEL 1082#ifdef __HAVE_OLD_DISKLABEL
1083 struct disklabel newlabel; 1083 struct disklabel newlabel;
1084#endif 1084#endif
1085 struct dkwedge_info *dkw; 1085 struct dkwedge_info *dkw;
1086 struct dkwedge_list *dkwl; 1086 struct dkwedge_list *dkwl;
1087 1087
1088#ifdef DEBUG 1088#ifdef DEBUG
1089 if (vnddebug & VDB_FOLLOW) 1089 if (vnddebug & VDB_FOLLOW)
1090 printf("vndioctl(0x%"PRIx64", 0x%lx, %p, 0x%x, %p): unit %d\n", 1090 printf("vndioctl(0x%"PRIx64", 0x%lx, %p, 0x%x, %p): unit %d\n",
1091 dev, cmd, data, flag, l->l_proc, unit); 1091 dev, cmd, data, flag, l->l_proc, unit);
1092#endif 1092#endif
1093 /* Do the get's first; they don't need initialization or verification */ 1093 /* Do the get's first; they don't need initialization or verification */
1094 switch (cmd) { 1094 switch (cmd) {
1095#ifdef COMPAT_30 1095#ifdef COMPAT_30
1096 case VNDIOCGET30: { 1096 case VNDIOCGET30: {
1097 if ((error = vndioctl_get(l, data, unit, &vattr)) != 0) 1097 if ((error = vndioctl_get(l, data, unit, &vattr)) != 0)
1098 return error; 1098 return error;
1099 1099
1100 struct vnd_user30 *vnu = data; 1100 struct vnd_user30 *vnu = data;
1101 vnu->vnu_dev = vattr.va_fsid; 1101 vnu->vnu_dev = vattr.va_fsid;
1102 vnu->vnu_ino = vattr.va_fileid; 1102 vnu->vnu_ino = vattr.va_fileid;
1103 return 0; 1103 return 0;
1104 } 1104 }
1105#endif 1105#endif
1106#ifdef COMPAT_50 1106#ifdef COMPAT_50
1107 case VNDIOCGET50: { 1107 case VNDIOCGET50: {
1108 if ((error = vndioctl_get(l, data, unit, &vattr)) != 0) 1108 if ((error = vndioctl_get(l, data, unit, &vattr)) != 0)
1109 return error; 1109 return error;
1110 1110
1111 struct vnd_user50 *vnu = data; 1111 struct vnd_user50 *vnu = data;
1112 vnu->vnu_dev = vattr.va_fsid; 1112 vnu->vnu_dev = vattr.va_fsid;
1113 vnu->vnu_ino = vattr.va_fileid; 1113 vnu->vnu_ino = vattr.va_fileid;
1114 return 0; 1114 return 0;
1115 } 1115 }
1116#endif 1116#endif
1117 1117
1118 case VNDIOCGET: { 1118 case VNDIOCGET: {
1119 if ((error = vndioctl_get(l, data, unit, &vattr)) != 0) 1119 if ((error = vndioctl_get(l, data, unit, &vattr)) != 0)
1120 return error; 1120 return error;
1121 1121
1122 struct vnd_user *vnu = data; 1122 struct vnd_user *vnu = data;
1123 vnu->vnu_dev = vattr.va_fsid; 1123 vnu->vnu_dev = vattr.va_fsid;
1124 vnu->vnu_ino = vattr.va_fileid; 1124 vnu->vnu_ino = vattr.va_fileid;
1125 return 0; 1125 return 0;
1126 } 1126 }
1127 default: 1127 default:
1128 break; 1128 break;
1129 } 1129 }
1130 1130
1131 vnd = device_lookup_private(&vnd_cd, unit); 1131 vnd = device_lookup_private(&vnd_cd, unit);
1132 if (vnd == NULL) 1132 if (vnd == NULL)
1133 return ENXIO; 1133 return ENXIO;
1134 vio = (struct vnd_ioctl *)data; 1134 vio = (struct vnd_ioctl *)data;
1135 1135
1136 error = disk_ioctl(&vnd->sc_dkdev, cmd, data, flag, l); 1136 error = disk_ioctl(&vnd->sc_dkdev, cmd, data, flag, l);
1137 if (error != EPASSTHROUGH) 1137 if (error != EPASSTHROUGH)
1138 return (error); 1138 return (error);
1139 1139
1140 /* Must be open for writes for these commands... */ 1140 /* Must be open for writes for these commands... */
1141 switch (cmd) { 1141 switch (cmd) {
1142 case VNDIOCSET: 1142 case VNDIOCSET:
1143 case VNDIOCCLR: 1143 case VNDIOCCLR:
1144#ifdef COMPAT_50 1144#ifdef COMPAT_50
1145 case VNDIOCSET50: 1145 case VNDIOCSET50:
1146 case VNDIOCCLR50: 1146 case VNDIOCCLR50:
1147#endif 1147#endif
1148 case DIOCSDINFO: 1148 case DIOCSDINFO:
1149 case DIOCWDINFO: 1149 case DIOCWDINFO:
1150#ifdef __HAVE_OLD_DISKLABEL 1150#ifdef __HAVE_OLD_DISKLABEL
1151 case ODIOCSDINFO: 1151 case ODIOCSDINFO:
1152 case ODIOCWDINFO: 1152 case ODIOCWDINFO:
1153#endif 1153#endif
1154 case DIOCKLABEL: 1154 case DIOCKLABEL:
1155 case DIOCWLABEL: 1155 case DIOCWLABEL:
1156 if ((flag & FWRITE) == 0) 1156 if ((flag & FWRITE) == 0)
1157 return EBADF; 1157 return EBADF;
1158 } 1158 }
1159 1159
1160 /* Must be initialized for these... */ 1160 /* Must be initialized for these... */
1161 switch (cmd) { 1161 switch (cmd) {
1162 case VNDIOCCLR: 1162 case VNDIOCCLR:
1163#ifdef VNDIOCCLR50 1163#ifdef VNDIOCCLR50
1164 case VNDIOCCLR50: 1164 case VNDIOCCLR50:
1165#endif 1165#endif
1166 case DIOCGDINFO: 1166 case DIOCGDINFO:
1167 case DIOCSDINFO: 1167 case DIOCSDINFO:
1168 case DIOCWDINFO: 1168 case DIOCWDINFO:
1169 case DIOCGPART: 1169 case DIOCGPART:
1170 case DIOCKLABEL: 1170 case DIOCKLABEL:
1171 case DIOCWLABEL: 1171 case DIOCWLABEL:
1172 case DIOCGDEFLABEL: 1172 case DIOCGDEFLABEL:
1173 case DIOCCACHESYNC: 1173 case DIOCCACHESYNC:
1174#ifdef __HAVE_OLD_DISKLABEL 1174#ifdef __HAVE_OLD_DISKLABEL
1175 case ODIOCGDINFO: 1175 case ODIOCGDINFO:
1176 case ODIOCSDINFO: 1176 case ODIOCSDINFO:
1177 case ODIOCWDINFO: 1177 case ODIOCWDINFO:
1178 case ODIOCGDEFLABEL: 1178 case ODIOCGDEFLABEL:
1179#endif 1179#endif
1180 if ((vnd->sc_flags & VNF_INITED) == 0) 1180 if ((vnd->sc_flags & VNF_INITED) == 0)
1181 return ENXIO; 1181 return ENXIO;
1182 } 1182 }
1183 1183
1184 switch (cmd) { 1184 switch (cmd) {
1185#ifdef VNDIOCSET50 1185#ifdef VNDIOCSET50
1186 case VNDIOCSET50: 1186 case VNDIOCSET50:
1187#endif 1187#endif
1188 case VNDIOCSET: 1188 case VNDIOCSET:
1189 if (vnd->sc_flags & VNF_INITED) 1189 if (vnd->sc_flags & VNF_INITED)
1190 return EBUSY; 1190 return EBUSY;
1191 1191
1192 if ((error = vndlock(vnd)) != 0) 1192 if ((error = vndlock(vnd)) != 0)
1193 return error; 1193 return error;
1194 1194
1195 fflags = FREAD; 1195 fflags = FREAD;
1196 if ((vio->vnd_flags & VNDIOF_READONLY) == 0) 1196 if ((vio->vnd_flags & VNDIOF_READONLY) == 0)
1197 fflags |= FWRITE; 1197 fflags |= FWRITE;
1198 error = pathbuf_copyin(vio->vnd_file, &pb); 1198 error = pathbuf_copyin(vio->vnd_file, &pb);
1199 if (error) { 1199 if (error) {
1200 goto unlock_and_exit; 1200 goto unlock_and_exit;
1201 } 1201 }
1202 NDINIT(&nd, LOOKUP, FOLLOW, pb); 1202 NDINIT(&nd, LOOKUP, FOLLOW, pb);
1203 if ((error = vn_open(&nd, fflags, 0)) != 0) { 1203 if ((error = vn_open(&nd, fflags, 0)) != 0) {
1204 pathbuf_destroy(pb); 1204 pathbuf_destroy(pb);
1205 goto unlock_and_exit; 1205 goto unlock_and_exit;
1206 } 1206 }
1207 KASSERT(l); 1207 KASSERT(l);
1208 error = VOP_GETATTR(nd.ni_vp, &vattr, l->l_cred); 1208 error = VOP_GETATTR(nd.ni_vp, &vattr, l->l_cred);
1209 if (!error && nd.ni_vp->v_type != VREG) 1209 if (!error && nd.ni_vp->v_type != VREG)
1210 error = EOPNOTSUPP; 1210 error = EOPNOTSUPP;
1211 if (!error && vattr.va_bytes < vattr.va_size) 1211 if (!error && vattr.va_bytes < vattr.va_size)
1212 /* File is definitely sparse, use vn_rdwr() */ 1212 /* File is definitely sparse, use vn_rdwr() */
1213 vnd->sc_flags |= VNF_USE_VN_RDWR; 1213 vnd->sc_flags |= VNF_USE_VN_RDWR;
1214 if (error) { 1214 if (error) {
1215 VOP_UNLOCK(nd.ni_vp); 1215 VOP_UNLOCK(nd.ni_vp);
1216 goto close_and_exit; 1216 goto close_and_exit;
1217 } 1217 }
1218 1218
1219 /* If using a compressed file, initialize its info */ 1219 /* If using a compressed file, initialize its info */
1220 /* (or abort with an error if kernel has no compression) */ 1220 /* (or abort with an error if kernel has no compression) */
1221 if (vio->vnd_flags & VNF_COMP) { 1221 if (vio->vnd_flags & VNF_COMP) {
1222#ifdef VND_COMPRESSION 1222#ifdef VND_COMPRESSION
1223 struct vnd_comp_header *ch; 1223 struct vnd_comp_header *ch;
1224 int i; 1224 int i;
1225 u_int32_t comp_size; 1225 u_int32_t comp_size;
1226 u_int32_t comp_maxsize; 1226 u_int32_t comp_maxsize;
1227  1227
1228 /* allocate space for compresed file header */ 1228 /* allocate space for compresed file header */
1229 ch = malloc(sizeof(struct vnd_comp_header), 1229 ch = malloc(sizeof(struct vnd_comp_header),
1230 M_TEMP, M_WAITOK); 1230 M_TEMP, M_WAITOK);
1231  1231
1232 /* read compressed file header */ 1232 /* read compressed file header */
1233 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ch, 1233 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ch,
1234 sizeof(struct vnd_comp_header), 0, UIO_SYSSPACE, 1234 sizeof(struct vnd_comp_header), 0, UIO_SYSSPACE,
1235 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL); 1235 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL);
1236 if (error) { 1236 if (error) {
1237 free(ch, M_TEMP); 1237 free(ch, M_TEMP);
1238 VOP_UNLOCK(nd.ni_vp); 1238 VOP_UNLOCK(nd.ni_vp);
1239 goto close_and_exit; 1239 goto close_and_exit;
1240 } 1240 }
 1241
 1242 if (ntohl(ch->block_size) == 0 ||
 1243 ntohl(ch->num_blocks) > UINT32_MAX - 1) {
 1244 free(ch, M_TEMP);
 1245 VOP_UNLOCK(nd.ni_vp);
 1246 goto close_and_exit;
 1247 }
1241  1248
1242 /* save some header info */ 1249 /* save some header info */
1243 vnd->sc_comp_blksz = ntohl(ch->block_size); 1250 vnd->sc_comp_blksz = ntohl(ch->block_size);
1244 /* note last offset is the file byte size */ 1251 /* note last offset is the file byte size */
1245 vnd->sc_comp_numoffs = ntohl(ch->num_blocks)+1; 1252 vnd->sc_comp_numoffs = ntohl(ch->num_blocks)+1;
1246 free(ch, M_TEMP); 1253 free(ch, M_TEMP);
1247 if (!DK_DEV_BSIZE_OK(vnd->sc_comp_blksz)) { 1254 if (!DK_DEV_BSIZE_OK(vnd->sc_comp_blksz)) {
1248 VOP_UNLOCK(nd.ni_vp); 1255 VOP_UNLOCK(nd.ni_vp);
1249 error = EINVAL; 1256 error = EINVAL;
1250 goto close_and_exit; 1257 goto close_and_exit;
1251 } 1258 }
1252 if (sizeof(struct vnd_comp_header) + 1259 KASSERT(0 < vnd->sc_comp_blksz);
1253 sizeof(u_int64_t) * vnd->sc_comp_numoffs > 1260 KASSERT(0 < vnd->sc_comp_numoffs);
1254 vattr.va_size) { 1261 /*
 1262 * @#^@!$& gcc -Wtype-limits refuses to let me
 1263 * write SIZE_MAX/sizeof(uint64_t) < numoffs,
 1264 * because the range of the type on amd64 makes
 1265 * the comparisons always false.
 1266 */
 1267#if SIZE_MAX <= UINT32_MAX*(64/CHAR_BIT)
 1268 if (SIZE_MAX/sizeof(uint64_t) < vnd->sc_comp_numoffs) {
 1269 VOP_UNLOCK(nd.ni_vp);
 1270 error = EINVAL;
 1271 goto close_and_exit;
 1272 }
 1273#endif
 1274 if ((vattr.va_size < sizeof(struct vnd_comp_header)) ||
 1275 (vattr.va_size - sizeof(struct vnd_comp_header) <
 1276 sizeof(uint64_t)*vnd->sc_comp_numoffs) ||
 1277 (UQUAD_MAX/vnd->sc_comp_blksz <
 1278 vnd->sc_comp_numoffs - 1)) {
1255 VOP_UNLOCK(nd.ni_vp); 1279 VOP_UNLOCK(nd.ni_vp);
1256 error = EINVAL; 1280 error = EINVAL;
1257 goto close_and_exit; 1281 goto close_and_exit;
1258 } 1282 }
1259  1283
1260 /* set decompressed file size */ 1284 /* set decompressed file size */
 1285 KASSERT(vnd->sc_comp_numoffs - 1 <=
 1286 UQUAD_MAX/vnd->sc_comp_blksz);
1261 vattr.va_size = 1287 vattr.va_size =
1262 ((u_quad_t)vnd->sc_comp_numoffs - 1) * 1288 ((u_quad_t)vnd->sc_comp_numoffs - 1) *
1263 (u_quad_t)vnd->sc_comp_blksz; 1289 (u_quad_t)vnd->sc_comp_blksz;
1264  1290
1265 /* allocate space for all the compressed offsets */ 1291 /* allocate space for all the compressed offsets */
 1292 __CTASSERT(UINT32_MAX <= UQUAD_MAX/sizeof(uint64_t));
1266 vnd->sc_comp_offsets = 1293 vnd->sc_comp_offsets =
1267 malloc(sizeof(u_int64_t) * vnd->sc_comp_numoffs, 1294 malloc(sizeof(u_int64_t) * vnd->sc_comp_numoffs,
1268 M_DEVBUF, M_WAITOK); 1295 M_DEVBUF, M_WAITOK);
1269  1296
1270 /* read in the offsets */ 1297 /* read in the offsets */
1271 error = vn_rdwr(UIO_READ, nd.ni_vp, 1298 error = vn_rdwr(UIO_READ, nd.ni_vp,
1272 (void *)vnd->sc_comp_offsets, 1299 (void *)vnd->sc_comp_offsets,
1273 sizeof(u_int64_t) * vnd->sc_comp_numoffs, 1300 sizeof(u_int64_t) * vnd->sc_comp_numoffs,
1274 sizeof(struct vnd_comp_header), UIO_SYSSPACE, 1301 sizeof(struct vnd_comp_header), UIO_SYSSPACE,
1275 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL); 1302 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL);
1276 if (error) { 1303 if (error) {
1277 VOP_UNLOCK(nd.ni_vp); 1304 VOP_UNLOCK(nd.ni_vp);
1278 goto close_and_exit; 1305 goto close_and_exit;
1279 } 1306 }
1280 /* 1307 /*
1281 * find largest block size (used for allocation limit). 1308 * find largest block size (used for allocation limit).
1282 * Also convert offset to native byte order. 1309 * Also convert offset to native byte order.
1283 */ 1310 */
1284 comp_maxsize = 0; 1311 comp_maxsize = 0;
1285 for (i = 0; i < vnd->sc_comp_numoffs - 1; i++) { 1312 for (i = 0; i < vnd->sc_comp_numoffs - 1; i++) {
1286 vnd->sc_comp_offsets[i] = 1313 vnd->sc_comp_offsets[i] =
1287 be64toh(vnd->sc_comp_offsets[i]); 1314 be64toh(vnd->sc_comp_offsets[i]);
1288 comp_size = be64toh(vnd->sc_comp_offsets[i + 1]) 1315 comp_size = be64toh(vnd->sc_comp_offsets[i + 1])
1289 - vnd->sc_comp_offsets[i]; 1316 - vnd->sc_comp_offsets[i];
1290 if (comp_size > comp_maxsize) 1317 if (comp_size > comp_maxsize)
1291 comp_maxsize = comp_size; 1318 comp_maxsize = comp_size;
1292 } 1319 }
1293 vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1] = 1320 vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1] =
1294 be64toh(vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1]); 1321 be64toh(vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1]);
1295  1322
1296 /* create compressed data buffer */ 1323 /* create compressed data buffer */
1297 vnd->sc_comp_buff = malloc(comp_maxsize, 1324 vnd->sc_comp_buff = malloc(comp_maxsize,
1298 M_DEVBUF, M_WAITOK); 1325 M_DEVBUF, M_WAITOK);
1299  1326
1300 /* create decompressed buffer */ 1327 /* create decompressed buffer */
1301 vnd->sc_comp_decombuf = malloc(vnd->sc_comp_blksz, 1328 vnd->sc_comp_decombuf = malloc(vnd->sc_comp_blksz,
1302 M_DEVBUF, M_WAITOK); 1329 M_DEVBUF, M_WAITOK);
1303 vnd->sc_comp_buffblk = -1; 1330 vnd->sc_comp_buffblk = -1;
1304  1331
1305 /* Initialize decompress stream */ 1332 /* Initialize decompress stream */
1306 memset(&vnd->sc_comp_stream, 0, sizeof(z_stream)); 1333 memset(&vnd->sc_comp_stream, 0, sizeof(z_stream));
1307 vnd->sc_comp_stream.zalloc = vnd_alloc; 1334 vnd->sc_comp_stream.zalloc = vnd_alloc;
1308 vnd->sc_comp_stream.zfree = vnd_free; 1335 vnd->sc_comp_stream.zfree = vnd_free;
1309 error = inflateInit2(&vnd->sc_comp_stream, MAX_WBITS); 1336 error = inflateInit2(&vnd->sc_comp_stream, MAX_WBITS);
1310 if (error) { 1337 if (error) {
1311 if (vnd->sc_comp_stream.msg) 1338 if (vnd->sc_comp_stream.msg)
1312 printf("vnd%d: compressed file, %s\n", 1339 printf("vnd%d: compressed file, %s\n",
1313 unit, vnd->sc_comp_stream.msg); 1340 unit, vnd->sc_comp_stream.msg);
1314 VOP_UNLOCK(nd.ni_vp); 1341 VOP_UNLOCK(nd.ni_vp);
1315 error = EINVAL; 1342 error = EINVAL;
1316 goto close_and_exit; 1343 goto close_and_exit;
1317 } 1344 }
1318  1345
1319 vnd->sc_flags |= VNF_COMP | VNF_READONLY; 1346 vnd->sc_flags |= VNF_COMP | VNF_READONLY;
1320#else /* !VND_COMPRESSION */ 1347#else /* !VND_COMPRESSION */
1321 VOP_UNLOCK(nd.ni_vp); 1348 VOP_UNLOCK(nd.ni_vp);
1322 error = EOPNOTSUPP; 1349 error = EOPNOTSUPP;
1323 goto close_and_exit; 1350 goto close_and_exit;
1324#endif /* VND_COMPRESSION */ 1351#endif /* VND_COMPRESSION */
1325 } 1352 }
1326  1353
1327 VOP_UNLOCK(nd.ni_vp); 1354 VOP_UNLOCK(nd.ni_vp);
1328 vnd->sc_vp = nd.ni_vp; 1355 vnd->sc_vp = nd.ni_vp;
1329 vnd->sc_size = btodb(vattr.va_size); /* note truncation */ 1356 vnd->sc_size = btodb(vattr.va_size); /* note truncation */
1330 1357
1331 /* 1358 /*
1332 * Use pseudo-geometry specified. If none was provided, 1359 * Use pseudo-geometry specified. If none was provided,
1333 * use "standard" Adaptec fictitious geometry. 1360 * use "standard" Adaptec fictitious geometry.
1334 */ 1361 */
1335 if (vio->vnd_flags & VNDIOF_HASGEOM) { 1362 if (vio->vnd_flags & VNDIOF_HASGEOM) {
1336 1363
1337 memcpy(&vnd->sc_geom, &vio->vnd_geom, 1364 memcpy(&vnd->sc_geom, &vio->vnd_geom,
1338 sizeof(vio->vnd_geom)); 1365 sizeof(vio->vnd_geom));
1339 1366
1340 /* 1367 /*
1341 * Sanity-check the sector size. 1368 * Sanity-check the sector size.
1342 */ 1369 */
1343 if (!DK_DEV_BSIZE_OK(vnd->sc_geom.vng_secsize) || 1370 if (!DK_DEV_BSIZE_OK(vnd->sc_geom.vng_secsize) ||
1344 vnd->sc_geom.vng_ncylinders == 0 || 1371 vnd->sc_geom.vng_ncylinders == 0 ||
1345 vnd->sc_geom.vng_ntracks == 0 || 1372 vnd->sc_geom.vng_ntracks == 0 ||
1346 vnd->sc_geom.vng_nsectors == 0) { 1373 vnd->sc_geom.vng_nsectors == 0) {
1347 error = EINVAL; 1374 error = EINVAL;
1348 goto close_and_exit; 1375 goto close_and_exit;
1349 } 1376 }
1350 1377
1351 /* 1378 /*
1352 * Compute the size (in DEV_BSIZE blocks) specified 1379 * Compute the size (in DEV_BSIZE blocks) specified
1353 * by the geometry. 1380 * by the geometry.
1354 */ 1381 */
1355 geomsize = (vnd->sc_geom.vng_nsectors * 1382 geomsize = (vnd->sc_geom.vng_nsectors *
1356 vnd->sc_geom.vng_ntracks * 1383 vnd->sc_geom.vng_ntracks *
1357 vnd->sc_geom.vng_ncylinders) * 1384 vnd->sc_geom.vng_ncylinders) *
1358 (vnd->sc_geom.vng_secsize / DEV_BSIZE); 1385 (vnd->sc_geom.vng_secsize / DEV_BSIZE);
1359 1386
1360 /* 1387 /*
1361 * Sanity-check the size against the specified 1388 * Sanity-check the size against the specified
1362 * geometry. 1389 * geometry.
1363 */ 1390 */
1364 if (vnd->sc_size < geomsize) { 1391 if (vnd->sc_size < geomsize) {
1365 error = EINVAL; 1392 error = EINVAL;
1366 goto close_and_exit; 1393 goto close_and_exit;
1367 } 1394 }
1368 } else if (vnd->sc_size >= (32 * 64)) { 1395 } else if (vnd->sc_size >= (32 * 64)) {
1369 /* 1396 /*
1370 * Size must be at least 2048 DEV_BSIZE blocks 1397 * Size must be at least 2048 DEV_BSIZE blocks
1371 * (1M) in order to use this geometry. 1398 * (1M) in order to use this geometry.
1372 */ 1399 */
1373 vnd->sc_geom.vng_secsize = DEV_BSIZE; 1400 vnd->sc_geom.vng_secsize = DEV_BSIZE;
1374 vnd->sc_geom.vng_nsectors = 32; 1401 vnd->sc_geom.vng_nsectors = 32;
1375 vnd->sc_geom.vng_ntracks = 64; 1402 vnd->sc_geom.vng_ntracks = 64;
1376 vnd->sc_geom.vng_ncylinders = vnd->sc_size / (64 * 32); 1403 vnd->sc_geom.vng_ncylinders = vnd->sc_size / (64 * 32);
1377 } else { 1404 } else {
1378 vnd->sc_geom.vng_secsize = DEV_BSIZE; 1405 vnd->sc_geom.vng_secsize = DEV_BSIZE;
1379 vnd->sc_geom.vng_nsectors = 1; 1406 vnd->sc_geom.vng_nsectors = 1;
1380 vnd->sc_geom.vng_ntracks = 1; 1407 vnd->sc_geom.vng_ntracks = 1;
1381 vnd->sc_geom.vng_ncylinders = vnd->sc_size; 1408 vnd->sc_geom.vng_ncylinders = vnd->sc_size;
1382 } 1409 }
1383 1410
1384 vnd_set_geometry(vnd); 1411 vnd_set_geometry(vnd);
1385 1412
1386 if (vio->vnd_flags & VNDIOF_READONLY) { 1413 if (vio->vnd_flags & VNDIOF_READONLY) {
1387 vnd->sc_flags |= VNF_READONLY; 1414 vnd->sc_flags |= VNF_READONLY;
1388 } 1415 }
1389 1416
1390 if ((error = vndsetcred(vnd, l->l_cred)) != 0) 1417 if ((error = vndsetcred(vnd, l->l_cred)) != 0)
1391 goto close_and_exit; 1418 goto close_and_exit;
1392 1419
1393 vndthrottle(vnd, vnd->sc_vp); 1420 vndthrottle(vnd, vnd->sc_vp);
1394 vio->vnd_osize = dbtob(vnd->sc_size); 1421 vio->vnd_osize = dbtob(vnd->sc_size);
1395#ifdef VNDIOCSET50 1422#ifdef VNDIOCSET50
1396 if (cmd != VNDIOCSET50) 1423 if (cmd != VNDIOCSET50)
1397#endif 1424#endif
1398 vio->vnd_size = dbtob(vnd->sc_size); 1425 vio->vnd_size = dbtob(vnd->sc_size);
1399 vnd->sc_flags |= VNF_INITED; 1426 vnd->sc_flags |= VNF_INITED;
1400 1427
1401 /* create the kernel thread, wait for it to be up */ 1428 /* create the kernel thread, wait for it to be up */
1402 error = kthread_create(PRI_NONE, 0, NULL, vndthread, vnd, 1429 error = kthread_create(PRI_NONE, 0, NULL, vndthread, vnd,
1403 &vnd->sc_kthread, "%s", device_xname(vnd->sc_dev)); 1430 &vnd->sc_kthread, "%s", device_xname(vnd->sc_dev));
1404 if (error) 1431 if (error)
1405 goto close_and_exit; 1432 goto close_and_exit;
1406 while ((vnd->sc_flags & VNF_KTHREAD) == 0) { 1433 while ((vnd->sc_flags & VNF_KTHREAD) == 0) {
1407 tsleep(&vnd->sc_kthread, PRIBIO, "vndthr", 0); 1434 tsleep(&vnd->sc_kthread, PRIBIO, "vndthr", 0);
1408 } 1435 }
1409#ifdef DEBUG 1436#ifdef DEBUG
1410 if (vnddebug & VDB_INIT) 1437 if (vnddebug & VDB_INIT)
1411 printf("vndioctl: SET vp %p size 0x%lx %d/%d/%d/%d\n", 1438 printf("vndioctl: SET vp %p size 0x%lx %d/%d/%d/%d\n",
1412 vnd->sc_vp, (unsigned long) vnd->sc_size, 1439 vnd->sc_vp, (unsigned long) vnd->sc_size,
1413 vnd->sc_geom.vng_secsize, 1440 vnd->sc_geom.vng_secsize,
1414 vnd->sc_geom.vng_nsectors, 1441 vnd->sc_geom.vng_nsectors,
1415 vnd->sc_geom.vng_ntracks, 1442 vnd->sc_geom.vng_ntracks,
1416 vnd->sc_geom.vng_ncylinders); 1443 vnd->sc_geom.vng_ncylinders);
1417#endif 1444#endif
1418 1445
1419 /* Attach the disk. */ 1446 /* Attach the disk. */
1420 disk_attach(&vnd->sc_dkdev); 1447 disk_attach(&vnd->sc_dkdev);
1421 disk_blocksize(&vnd->sc_dkdev, vnd->sc_geom.vng_secsize); 1448 disk_blocksize(&vnd->sc_dkdev, vnd->sc_geom.vng_secsize);
1422 1449
1423 /* Initialize the xfer and buffer pools. */ 1450 /* Initialize the xfer and buffer pools. */
1424 pool_init(&vnd->sc_vxpool, sizeof(struct vndxfer), 0, 1451 pool_init(&vnd->sc_vxpool, sizeof(struct vndxfer), 0,
1425 0, 0, "vndxpl", NULL, IPL_BIO); 1452 0, 0, "vndxpl", NULL, IPL_BIO);
1426 1453
1427 vndunlock(vnd); 1454 vndunlock(vnd);
1428 1455
1429 pathbuf_destroy(pb); 1456 pathbuf_destroy(pb);
1430 1457
1431 /* Discover wedges on this disk */ 1458 /* Discover wedges on this disk */
1432 dkwedge_discover(&vnd->sc_dkdev); 1459 dkwedge_discover(&vnd->sc_dkdev);
1433 1460
1434 break; 1461 break;
1435 1462
1436close_and_exit: 1463close_and_exit:
1437 (void) vn_close(nd.ni_vp, fflags, l->l_cred); 1464 (void) vn_close(nd.ni_vp, fflags, l->l_cred);
1438 pathbuf_destroy(pb); 1465 pathbuf_destroy(pb);
1439unlock_and_exit: 1466unlock_and_exit:
1440#ifdef VND_COMPRESSION 1467#ifdef VND_COMPRESSION
1441 /* free any allocated memory (for compressed file) */ 1468 /* free any allocated memory (for compressed file) */
1442 if (vnd->sc_comp_offsets) { 1469 if (vnd->sc_comp_offsets) {
1443 free(vnd->sc_comp_offsets, M_DEVBUF); 1470 free(vnd->sc_comp_offsets, M_DEVBUF);
1444 vnd->sc_comp_offsets = NULL; 1471 vnd->sc_comp_offsets = NULL;
1445 } 1472 }
1446 if (vnd->sc_comp_buff) { 1473 if (vnd->sc_comp_buff) {
1447 free(vnd->sc_comp_buff, M_DEVBUF); 1474 free(vnd->sc_comp_buff, M_DEVBUF);
1448 vnd->sc_comp_buff = NULL; 1475 vnd->sc_comp_buff = NULL;
1449 } 1476 }
1450 if (vnd->sc_comp_decombuf) { 1477 if (vnd->sc_comp_decombuf) {
1451 free(vnd->sc_comp_decombuf, M_DEVBUF); 1478 free(vnd->sc_comp_decombuf, M_DEVBUF);
1452 vnd->sc_comp_decombuf = NULL; 1479 vnd->sc_comp_decombuf = NULL;
1453 } 1480 }
1454#endif /* VND_COMPRESSION */ 1481#endif /* VND_COMPRESSION */
1455 vndunlock(vnd); 1482 vndunlock(vnd);
1456 return error; 1483 return error;
1457 1484
1458#ifdef VNDIOCCLR50 1485#ifdef VNDIOCCLR50
1459 case VNDIOCCLR50: 1486 case VNDIOCCLR50:
1460#endif 1487#endif
1461 case VNDIOCCLR: 1488 case VNDIOCCLR:
1462 part = DISKPART(dev); 1489 part = DISKPART(dev);
1463 pmask = (1 << part); 1490 pmask = (1 << part);
1464 force = (vio->vnd_flags & VNDIOF_FORCE) != 0; 1491 force = (vio->vnd_flags & VNDIOF_FORCE) != 0;
1465 1492
1466 if ((error = vnddoclear(vnd, pmask, minor(dev), force)) != 0) 1493 if ((error = vnddoclear(vnd, pmask, minor(dev), force)) != 0)
1467 return error; 1494 return error;
1468 1495
1469 break; 1496 break;
1470 1497
1471 1498
1472 case DIOCGDINFO: 1499 case DIOCGDINFO:
1473 *(struct disklabel *)data = *(vnd->sc_dkdev.dk_label); 1500 *(struct disklabel *)data = *(vnd->sc_dkdev.dk_label);
1474 break; 1501 break;
1475 1502
1476#ifdef __HAVE_OLD_DISKLABEL 1503#ifdef __HAVE_OLD_DISKLABEL
1477 case ODIOCGDINFO: 1504 case ODIOCGDINFO:
1478 newlabel = *(vnd->sc_dkdev.dk_label); 1505 newlabel = *(vnd->sc_dkdev.dk_label);
1479 if (newlabel.d_npartitions > OLDMAXPARTITIONS) 1506 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
1480 return ENOTTY; 1507 return ENOTTY;
1481 memcpy(data, &newlabel, sizeof (struct olddisklabel)); 1508 memcpy(data, &newlabel, sizeof (struct olddisklabel));
1482 break; 1509 break;
1483#endif 1510#endif
1484 1511
1485 case DIOCGPART: 1512 case DIOCGPART:
1486 ((struct partinfo *)data)->disklab = vnd->sc_dkdev.dk_label; 1513 ((struct partinfo *)data)->disklab = vnd->sc_dkdev.dk_label;
1487 ((struct partinfo *)data)->part = 1514 ((struct partinfo *)data)->part =
1488 &vnd->sc_dkdev.dk_label->d_partitions[DISKPART(dev)]; 1515 &vnd->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
1489 break; 1516 break;
1490 1517
1491 case DIOCWDINFO: 1518 case DIOCWDINFO:
1492 case DIOCSDINFO: 1519 case DIOCSDINFO:
1493#ifdef __HAVE_OLD_DISKLABEL 1520#ifdef __HAVE_OLD_DISKLABEL
1494 case ODIOCWDINFO: 1521 case ODIOCWDINFO:
1495 case ODIOCSDINFO: 1522 case ODIOCSDINFO:
1496#endif 1523#endif
1497 { 1524 {
1498 struct disklabel *lp; 1525 struct disklabel *lp;
1499 1526
1500 if ((error = vndlock(vnd)) != 0) 1527 if ((error = vndlock(vnd)) != 0)
1501 return error; 1528 return error;
1502 1529
1503 vnd->sc_flags |= VNF_LABELLING; 1530 vnd->sc_flags |= VNF_LABELLING;
1504 1531
1505#ifdef __HAVE_OLD_DISKLABEL 1532#ifdef __HAVE_OLD_DISKLABEL
1506 if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) { 1533 if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
1507 memset(&newlabel, 0, sizeof newlabel); 1534 memset(&newlabel, 0, sizeof newlabel);
1508 memcpy(&newlabel, data, sizeof (struct olddisklabel)); 1535 memcpy(&newlabel, data, sizeof (struct olddisklabel));
1509 lp = &newlabel; 1536 lp = &newlabel;
1510 } else 1537 } else
1511#endif 1538#endif
1512 lp = (struct disklabel *)data; 1539 lp = (struct disklabel *)data;
1513 1540
1514 error = setdisklabel(vnd->sc_dkdev.dk_label, 1541 error = setdisklabel(vnd->sc_dkdev.dk_label,
1515 lp, 0, vnd->sc_dkdev.dk_cpulabel); 1542 lp, 0, vnd->sc_dkdev.dk_cpulabel);
1516 if (error == 0) { 1543 if (error == 0) {
1517 if (cmd == DIOCWDINFO 1544 if (cmd == DIOCWDINFO
1518#ifdef __HAVE_OLD_DISKLABEL 1545#ifdef __HAVE_OLD_DISKLABEL
1519 || cmd == ODIOCWDINFO 1546 || cmd == ODIOCWDINFO
1520#endif 1547#endif
1521 ) 1548 )
1522 error = writedisklabel(VNDLABELDEV(dev), 1549 error = writedisklabel(VNDLABELDEV(dev),
1523 vndstrategy, vnd->sc_dkdev.dk_label, 1550 vndstrategy, vnd->sc_dkdev.dk_label,
1524 vnd->sc_dkdev.dk_cpulabel); 1551 vnd->sc_dkdev.dk_cpulabel);
1525 } 1552 }
1526 1553
1527 vnd->sc_flags &= ~VNF_LABELLING; 1554 vnd->sc_flags &= ~VNF_LABELLING;
1528 1555
1529 vndunlock(vnd); 1556 vndunlock(vnd);
1530 1557
1531 if (error) 1558 if (error)
1532 return error; 1559 return error;
1533 break; 1560 break;
1534 } 1561 }
1535 1562
1536 case DIOCKLABEL: 1563 case DIOCKLABEL:
1537 if (*(int *)data != 0) 1564 if (*(int *)data != 0)
1538 vnd->sc_flags |= VNF_KLABEL; 1565 vnd->sc_flags |= VNF_KLABEL;
1539 else 1566 else
1540 vnd->sc_flags &= ~VNF_KLABEL; 1567 vnd->sc_flags &= ~VNF_KLABEL;
1541 break; 1568 break;
1542 1569
1543 case DIOCWLABEL: 1570 case DIOCWLABEL:
1544 if (*(int *)data != 0) 1571 if (*(int *)data != 0)
1545 vnd->sc_flags |= VNF_WLABEL; 1572 vnd->sc_flags |= VNF_WLABEL;
1546 else 1573 else
1547 vnd->sc_flags &= ~VNF_WLABEL; 1574 vnd->sc_flags &= ~VNF_WLABEL;
1548 break; 1575 break;
1549 1576
1550 case DIOCGDEFLABEL: 1577 case DIOCGDEFLABEL:
1551 vndgetdefaultlabel(vnd, (struct disklabel *)data); 1578 vndgetdefaultlabel(vnd, (struct disklabel *)data);
1552 break; 1579 break;
1553 1580
1554#ifdef __HAVE_OLD_DISKLABEL 1581#ifdef __HAVE_OLD_DISKLABEL
1555 case ODIOCGDEFLABEL: 1582 case ODIOCGDEFLABEL:
1556 vndgetdefaultlabel(vnd, &newlabel); 1583 vndgetdefaultlabel(vnd, &newlabel);
1557 if (newlabel.d_npartitions > OLDMAXPARTITIONS) 1584 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
1558 return ENOTTY; 1585 return ENOTTY;
1559 memcpy(data, &newlabel, sizeof (struct olddisklabel)); 1586 memcpy(data, &newlabel, sizeof (struct olddisklabel));
1560 break; 1587 break;
1561#endif 1588#endif
1562 1589
1563 case DIOCCACHESYNC: 1590 case DIOCCACHESYNC:
1564 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 1591 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY);
1565 error = VOP_FSYNC(vnd->sc_vp, vnd->sc_cred, 1592 error = VOP_FSYNC(vnd->sc_vp, vnd->sc_cred,
1566 FSYNC_WAIT | FSYNC_DATAONLY | FSYNC_CACHE, 0, 0); 1593 FSYNC_WAIT | FSYNC_DATAONLY | FSYNC_CACHE, 0, 0);
1567 VOP_UNLOCK(vnd->sc_vp); 1594 VOP_UNLOCK(vnd->sc_vp);
1568 return error; 1595 return error;
1569 1596
1570 case DIOCAWEDGE: 1597 case DIOCAWEDGE:
1571 dkw = (void *) data; 1598 dkw = (void *) data;
1572 1599
1573 if ((flag & FWRITE) == 0) 1600 if ((flag & FWRITE) == 0)
1574 return EBADF; 1601 return EBADF;
1575 1602
1576 /* If the ioctl happens here, the parent is us. */ 1603 /* If the ioctl happens here, the parent is us. */
1577 strlcpy(dkw->dkw_parent, device_xname(vnd->sc_dev), 1604 strlcpy(dkw->dkw_parent, device_xname(vnd->sc_dev),
1578 sizeof(dkw->dkw_parent)); 1605 sizeof(dkw->dkw_parent));
1579 return dkwedge_add(dkw); 1606 return dkwedge_add(dkw);
1580 1607
1581 case DIOCDWEDGE: 1608 case DIOCDWEDGE:
1582 dkw = (void *) data; 1609 dkw = (void *) data;
1583 1610
1584 if ((flag & FWRITE) == 0) 1611 if ((flag & FWRITE) == 0)
1585 return EBADF; 1612 return EBADF;
1586 1613
1587 /* If the ioctl happens here, the parent is us. */ 1614 /* If the ioctl happens here, the parent is us. */
1588 strlcpy(dkw->dkw_parent, device_xname(vnd->sc_dev), 1615 strlcpy(dkw->dkw_parent, device_xname(vnd->sc_dev),
1589 sizeof(dkw->dkw_parent)); 1616 sizeof(dkw->dkw_parent));
1590 return dkwedge_del(dkw); 1617 return dkwedge_del(dkw);
1591 1618
1592 case DIOCLWEDGES: 1619 case DIOCLWEDGES:
1593 dkwl = (void *) data; 1620 dkwl = (void *) data;
1594 1621
1595 return dkwedge_list(&vnd->sc_dkdev, dkwl, l); 1622 return dkwedge_list(&vnd->sc_dkdev, dkwl, l);
1596 1623
1597 case DIOCMWEDGES: 1624 case DIOCMWEDGES:
1598 if ((flag & FWRITE) == 0) 1625 if ((flag & FWRITE) == 0)
1599 return EBADF; 1626 return EBADF;
1600 1627
1601 dkwedge_discover(&vnd->sc_dkdev); 1628 dkwedge_discover(&vnd->sc_dkdev);
1602 return 0; 1629 return 0;
1603 1630
1604 default: 1631 default:
1605 return ENOTTY; 1632 return ENOTTY;
1606 } 1633 }
1607 1634
1608 return 0; 1635 return 0;
1609} 1636}
1610 1637
1611/* 1638/*
1612 * Duplicate the current processes' credentials. Since we are called only 1639 * Duplicate the current processes' credentials. Since we are called only
1613 * as the result of a SET ioctl and only root can do that, any future access 1640 * as the result of a SET ioctl and only root can do that, any future access
1614 * to this "disk" is essentially as root. Note that credentials may change 1641 * to this "disk" is essentially as root. Note that credentials may change
1615 * if some other uid can write directly to the mapped file (NFS). 1642 * if some other uid can write directly to the mapped file (NFS).
1616 */ 1643 */
1617static int 1644static int
1618vndsetcred(struct vnd_softc *vnd, kauth_cred_t cred) 1645vndsetcred(struct vnd_softc *vnd, kauth_cred_t cred)
1619{ 1646{
1620 struct uio auio; 1647 struct uio auio;
1621 struct iovec aiov; 1648 struct iovec aiov;
1622 char *tmpbuf; 1649 char *tmpbuf;
1623 int error; 1650 int error;
1624 1651
1625 vnd->sc_cred = kauth_cred_dup(cred); 1652 vnd->sc_cred = kauth_cred_dup(cred);
1626 tmpbuf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK); 1653 tmpbuf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK);
1627 1654
1628 /* XXX: Horrible kludge to establish credentials for NFS */ 1655 /* XXX: Horrible kludge to establish credentials for NFS */
1629 aiov.iov_base = tmpbuf; 1656 aiov.iov_base = tmpbuf;
1630 aiov.iov_len = min(DEV_BSIZE, dbtob(vnd->sc_size)); 1657 aiov.iov_len = min(DEV_BSIZE, dbtob(vnd->sc_size));
1631 auio.uio_iov = &aiov; 1658 auio.uio_iov = &aiov;
1632 auio.uio_iovcnt = 1; 1659 auio.uio_iovcnt = 1;
1633 auio.uio_offset = 0; 1660 auio.uio_offset = 0;
1634 auio.uio_rw = UIO_READ; 1661 auio.uio_rw = UIO_READ;
1635 auio.uio_resid = aiov.iov_len; 1662 auio.uio_resid = aiov.iov_len;
1636 UIO_SETUP_SYSSPACE(&auio); 1663 UIO_SETUP_SYSSPACE(&auio);
1637 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 1664 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY);
1638 error = VOP_READ(vnd->sc_vp, &auio, 0, vnd->sc_cred); 1665 error = VOP_READ(vnd->sc_vp, &auio, 0, vnd->sc_cred);
1639 if (error == 0) { 1666 if (error == 0) {
1640 /* 1667 /*
1641 * Because vnd does all IO directly through the vnode 1668 * Because vnd does all IO directly through the vnode
1642 * we need to flush (at least) the buffer from the above 1669 * we need to flush (at least) the buffer from the above
1643 * VOP_READ from the buffer cache to prevent cache 1670 * VOP_READ from the buffer cache to prevent cache
1644 * incoherencies. Also, be careful to write dirty 1671 * incoherencies. Also, be careful to write dirty
1645 * buffers back to stable storage. 1672 * buffers back to stable storage.
1646 */ 1673 */
1647 error = vinvalbuf(vnd->sc_vp, V_SAVE, vnd->sc_cred, 1674 error = vinvalbuf(vnd->sc_vp, V_SAVE, vnd->sc_cred,
1648 curlwp, 0, 0); 1675 curlwp, 0, 0);
1649 } 1676 }
1650 VOP_UNLOCK(vnd->sc_vp); 1677 VOP_UNLOCK(vnd->sc_vp);
1651 1678
1652 free(tmpbuf, M_TEMP); 1679 free(tmpbuf, M_TEMP);
1653 return error; 1680 return error;
1654} 1681}
1655 1682
1656/* 1683/*
1657 * Set maxactive based on FS type 1684 * Set maxactive based on FS type
1658 */ 1685 */
1659static void 1686static void
1660vndthrottle(struct vnd_softc *vnd, struct vnode *vp) 1687vndthrottle(struct vnd_softc *vnd, struct vnode *vp)
1661{ 1688{
1662 1689
1663 if (vp->v_tag == VT_NFS) 1690 if (vp->v_tag == VT_NFS)
1664 vnd->sc_maxactive = 2; 1691 vnd->sc_maxactive = 2;
1665 else 1692 else
1666 vnd->sc_maxactive = 8; 1693 vnd->sc_maxactive = 8;
1667 1694
1668 if (vnd->sc_maxactive < 1) 1695 if (vnd->sc_maxactive < 1)
1669 vnd->sc_maxactive = 1; 1696 vnd->sc_maxactive = 1;
1670} 1697}
1671 1698
1672#if 0 1699#if 0
1673static void 1700static void
1674vndshutdown(void) 1701vndshutdown(void)
1675{ 1702{
1676 struct vnd_softc *vnd; 1703 struct vnd_softc *vnd;
1677 1704
1678 for (vnd = &vnd_softc[0]; vnd < &vnd_softc[numvnd]; vnd++) 1705 for (vnd = &vnd_softc[0]; vnd < &vnd_softc[numvnd]; vnd++)
1679 if (vnd->sc_flags & VNF_INITED) 1706 if (vnd->sc_flags & VNF_INITED)
1680 vndclear(vnd); 1707 vndclear(vnd);
1681} 1708}
1682#endif 1709#endif
1683 1710
1684static void 1711static void
1685vndclear(struct vnd_softc *vnd, int myminor) 1712vndclear(struct vnd_softc *vnd, int myminor)
1686{ 1713{
1687 struct vnode *vp = vnd->sc_vp; 1714 struct vnode *vp = vnd->sc_vp;
1688 int fflags = FREAD; 1715 int fflags = FREAD;
1689 int bmaj, cmaj, i, mn; 1716 int bmaj, cmaj, i, mn;
1690 int s; 1717 int s;
1691 1718
1692#ifdef DEBUG 1719#ifdef DEBUG
1693 if (vnddebug & VDB_FOLLOW) 1720 if (vnddebug & VDB_FOLLOW)
1694 printf("vndclear(%p): vp %p\n", vnd, vp); 1721 printf("vndclear(%p): vp %p\n", vnd, vp);
1695#endif 1722#endif
1696 /* locate the major number */ 1723 /* locate the major number */
1697 bmaj = bdevsw_lookup_major(&vnd_bdevsw); 1724 bmaj = bdevsw_lookup_major(&vnd_bdevsw);
1698 cmaj = cdevsw_lookup_major(&vnd_cdevsw); 1725 cmaj = cdevsw_lookup_major(&vnd_cdevsw);
1699 1726
1700 /* Nuke the vnodes for any open instances */ 1727 /* Nuke the vnodes for any open instances */
1701 for (i = 0; i < MAXPARTITIONS; i++) { 1728 for (i = 0; i < MAXPARTITIONS; i++) {
1702 mn = DISKMINOR(device_unit(vnd->sc_dev), i); 1729 mn = DISKMINOR(device_unit(vnd->sc_dev), i);
1703 vdevgone(bmaj, mn, mn, VBLK); 1730 vdevgone(bmaj, mn, mn, VBLK);
1704 if (mn != myminor) /* XXX avoid to kill own vnode */ 1731 if (mn != myminor) /* XXX avoid to kill own vnode */
1705 vdevgone(cmaj, mn, mn, VCHR); 1732 vdevgone(cmaj, mn, mn, VCHR);
1706 } 1733 }
1707 1734
1708 if ((vnd->sc_flags & VNF_READONLY) == 0) 1735 if ((vnd->sc_flags & VNF_READONLY) == 0)
1709 fflags |= FWRITE; 1736 fflags |= FWRITE;
1710 1737
1711 s = splbio(); 1738 s = splbio();
1712 bufq_drain(vnd->sc_tab); 1739 bufq_drain(vnd->sc_tab);
1713 splx(s); 1740 splx(s);
1714 1741
1715 vnd->sc_flags |= VNF_VUNCONF; 1742 vnd->sc_flags |= VNF_VUNCONF;
1716 wakeup(&vnd->sc_tab); 1743 wakeup(&vnd->sc_tab);
1717 while (vnd->sc_flags & VNF_KTHREAD) 1744 while (vnd->sc_flags & VNF_KTHREAD)
1718 tsleep(&vnd->sc_kthread, PRIBIO, "vnthr", 0); 1745 tsleep(&vnd->sc_kthread, PRIBIO, "vnthr", 0);
1719 1746
1720#ifdef VND_COMPRESSION 1747#ifdef VND_COMPRESSION
1721 /* free the compressed file buffers */ 1748 /* free the compressed file buffers */
1722 if (vnd->sc_flags & VNF_COMP) { 1749 if (vnd->sc_flags & VNF_COMP) {
1723 if (vnd->sc_comp_offsets) { 1750 if (vnd->sc_comp_offsets) {
1724 free(vnd->sc_comp_offsets, M_DEVBUF); 1751 free(vnd->sc_comp_offsets, M_DEVBUF);
1725 vnd->sc_comp_offsets = NULL; 1752 vnd->sc_comp_offsets = NULL;
1726 } 1753 }
1727 if (vnd->sc_comp_buff) { 1754 if (vnd->sc_comp_buff) {
1728 free(vnd->sc_comp_buff, M_DEVBUF); 1755 free(vnd->sc_comp_buff, M_DEVBUF);
1729 vnd->sc_comp_buff = NULL; 1756 vnd->sc_comp_buff = NULL;
1730 } 1757 }
1731 if (vnd->sc_comp_decombuf) { 1758 if (vnd->sc_comp_decombuf) {
1732 free(vnd->sc_comp_decombuf, M_DEVBUF); 1759 free(vnd->sc_comp_decombuf, M_DEVBUF);
1733 vnd->sc_comp_decombuf = NULL; 1760 vnd->sc_comp_decombuf = NULL;
1734 } 1761 }
1735 } 1762 }
1736#endif /* VND_COMPRESSION */ 1763#endif /* VND_COMPRESSION */
1737 vnd->sc_flags &= 1764 vnd->sc_flags &=
1738 ~(VNF_INITED | VNF_READONLY | VNF_VLABEL 1765 ~(VNF_INITED | VNF_READONLY | VNF_VLABEL
1739 | VNF_VUNCONF | VNF_COMP | VNF_CLEARING); 1766 | VNF_VUNCONF | VNF_COMP | VNF_CLEARING);
1740 if (vp == NULL) 1767 if (vp == NULL)
1741 panic("vndclear: null vp"); 1768 panic("vndclear: null vp");
1742 (void) vn_close(vp, fflags, vnd->sc_cred); 1769 (void) vn_close(vp, fflags, vnd->sc_cred);
1743 kauth_cred_free(vnd->sc_cred); 1770 kauth_cred_free(vnd->sc_cred);
1744 vnd->sc_vp = NULL; 1771 vnd->sc_vp = NULL;
1745 vnd->sc_cred = NULL; 1772 vnd->sc_cred = NULL;
1746 vnd->sc_size = 0; 1773 vnd->sc_size = 0;
1747} 1774}
1748 1775
1749static int 1776static int
1750vndsize(dev_t dev) 1777vndsize(dev_t dev)
1751{ 1778{
1752 struct vnd_softc *sc; 1779 struct vnd_softc *sc;
1753 struct disklabel *lp; 1780 struct disklabel *lp;
1754 int part, unit, omask; 1781 int part, unit, omask;
1755 int size; 1782 int size;
1756 1783
1757 unit = vndunit(dev); 1784 unit = vndunit(dev);
1758 sc = device_lookup_private(&vnd_cd, unit); 1785 sc = device_lookup_private(&vnd_cd, unit);
1759 if (sc == NULL) 1786 if (sc == NULL)
1760 return -1; 1787 return -1;
1761 1788
1762 if ((sc->sc_flags & VNF_INITED) == 0) 1789 if ((sc->sc_flags & VNF_INITED) == 0)
1763 return -1; 1790 return -1;
1764 1791
1765 part = DISKPART(dev); 1792 part = DISKPART(dev);
1766 omask = sc->sc_dkdev.dk_openmask & (1 << part); 1793 omask = sc->sc_dkdev.dk_openmask & (1 << part);
1767 lp = sc->sc_dkdev.dk_label; 1794 lp = sc->sc_dkdev.dk_label;
1768 1795
1769 if (omask == 0 && vndopen(dev, 0, S_IFBLK, curlwp)) /* XXX */ 1796 if (omask == 0 && vndopen(dev, 0, S_IFBLK, curlwp)) /* XXX */
1770 return -1; 1797 return -1;
1771 1798
1772 if (lp->d_partitions[part].p_fstype != FS_SWAP) 1799 if (lp->d_partitions[part].p_fstype != FS_SWAP)
1773 size = -1; 1800 size = -1;
1774 else 1801 else
1775 size = lp->d_partitions[part].p_size * 1802 size = lp->d_partitions[part].p_size *
1776 (lp->d_secsize / DEV_BSIZE); 1803 (lp->d_secsize / DEV_BSIZE);
1777 1804
1778 if (omask == 0 && vndclose(dev, 0, S_IFBLK, curlwp)) /* XXX */ 1805 if (omask == 0 && vndclose(dev, 0, S_IFBLK, curlwp)) /* XXX */
1779 return -1; 1806 return -1;
1780 1807
1781 return size; 1808 return size;
1782} 1809}
1783 1810
1784static int 1811static int
1785vnddump(dev_t dev, daddr_t blkno, void *va, 1812vnddump(dev_t dev, daddr_t blkno, void *va,
1786 size_t size) 1813 size_t size)
1787{ 1814{
1788 1815
1789 /* Not implemented. */ 1816 /* Not implemented. */
1790 return ENXIO; 1817 return ENXIO;
1791} 1818}
1792 1819
1793static void 1820static void
1794vndgetdefaultlabel(struct vnd_softc *sc, struct disklabel *lp) 1821vndgetdefaultlabel(struct vnd_softc *sc, struct disklabel *lp)
1795{ 1822{
1796 struct vndgeom *vng = &sc->sc_geom; 1823 struct vndgeom *vng = &sc->sc_geom;
1797 struct partition *pp; 1824 struct partition *pp;
1798 1825
1799 memset(lp, 0, sizeof(*lp)); 1826 memset(lp, 0, sizeof(*lp));
1800 1827
1801 if (sc->sc_size > UINT32_MAX) 1828 if (sc->sc_size > UINT32_MAX)
1802 lp->d_secperunit = UINT32_MAX; 1829 lp->d_secperunit = UINT32_MAX;
1803 else 1830 else
1804 lp->d_secperunit = sc->sc_size; 1831 lp->d_secperunit = sc->sc_size;
1805 lp->d_secsize = vng->vng_secsize; 1832 lp->d_secsize = vng->vng_secsize;
1806 lp->d_nsectors = vng->vng_nsectors; 1833 lp->d_nsectors = vng->vng_nsectors;
1807 lp->d_ntracks = vng->vng_ntracks; 1834 lp->d_ntracks = vng->vng_ntracks;
1808 lp->d_ncylinders = vng->vng_ncylinders; 1835 lp->d_ncylinders = vng->vng_ncylinders;
1809 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1836 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1810 1837
1811 strncpy(lp->d_typename, "vnd", sizeof(lp->d_typename)); 1838 strncpy(lp->d_typename, "vnd", sizeof(lp->d_typename));
1812 lp->d_type = DTYPE_VND; 1839 lp->d_type = DTYPE_VND;
1813 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); 1840 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
1814 lp->d_rpm = 3600; 1841 lp->d_rpm = 3600;
1815 lp->d_interleave = 1; 1842 lp->d_interleave = 1;
1816 lp->d_flags = 0; 1843 lp->d_flags = 0;
1817 1844
1818 pp = &lp->d_partitions[RAW_PART]; 1845 pp = &lp->d_partitions[RAW_PART];
1819 pp->p_offset = 0; 1846 pp->p_offset = 0;
1820 pp->p_size = lp->d_secperunit; 1847 pp->p_size = lp->d_secperunit;
1821 pp->p_fstype = FS_UNUSED; 1848 pp->p_fstype = FS_UNUSED;
1822 lp->d_npartitions = RAW_PART + 1; 1849 lp->d_npartitions = RAW_PART + 1;
1823 1850
1824 lp->d_magic = DISKMAGIC; 1851 lp->d_magic = DISKMAGIC;
1825 lp->d_magic2 = DISKMAGIC; 1852 lp->d_magic2 = DISKMAGIC;
1826 lp->d_checksum = dkcksum(lp); 1853 lp->d_checksum = dkcksum(lp);
1827} 1854}
1828 1855
1829/* 1856/*
1830 * Read the disklabel from a vnd. If one is not present, create a fake one. 1857 * Read the disklabel from a vnd. If one is not present, create a fake one.
1831 */ 1858 */
1832static void 1859static void
1833vndgetdisklabel(dev_t dev, struct vnd_softc *sc) 1860vndgetdisklabel(dev_t dev, struct vnd_softc *sc)
1834{ 1861{
1835 const char *errstring; 1862 const char *errstring;
1836 struct disklabel *lp = sc->sc_dkdev.dk_label; 1863 struct disklabel *lp = sc->sc_dkdev.dk_label;
1837 struct cpu_disklabel *clp = sc->sc_dkdev.dk_cpulabel; 1864 struct cpu_disklabel *clp = sc->sc_dkdev.dk_cpulabel;
1838 int i; 1865 int i;
1839 1866
1840 memset(clp, 0, sizeof(*clp)); 1867 memset(clp, 0, sizeof(*clp));
1841 1868
1842 vndgetdefaultlabel(sc, lp); 1869 vndgetdefaultlabel(sc, lp);
1843 1870
1844 /* 1871 /*
1845 * Call the generic disklabel extraction routine. 1872 * Call the generic disklabel extraction routine.
1846 */ 1873 */
1847 errstring = readdisklabel(VNDLABELDEV(dev), vndstrategy, lp, clp); 1874 errstring = readdisklabel(VNDLABELDEV(dev), vndstrategy, lp, clp);
1848 if (errstring) { 1875 if (errstring) {
1849 /* 1876 /*
1850 * Lack of disklabel is common, but we print the warning 1877 * Lack of disklabel is common, but we print the warning
1851 * anyway, since it might contain other useful information. 1878 * anyway, since it might contain other useful information.
1852 */ 1879 */
1853 aprint_normal_dev(sc->sc_dev, "%s\n", errstring); 1880 aprint_normal_dev(sc->sc_dev, "%s\n", errstring);
1854 1881
1855 /* 1882 /*
1856 * For historical reasons, if there's no disklabel 1883 * For historical reasons, if there's no disklabel
1857 * present, all partitions must be FS_BSDFFS and 1884 * present, all partitions must be FS_BSDFFS and
1858 * occupy the entire disk. 1885 * occupy the entire disk.
1859 */ 1886 */
1860 for (i = 0; i < MAXPARTITIONS; i++) { 1887 for (i = 0; i < MAXPARTITIONS; i++) {
1861 /* 1888 /*
1862 * Don't wipe out port specific hack (such as 1889 * Don't wipe out port specific hack (such as
1863 * dos partition hack of i386 port). 1890 * dos partition hack of i386 port).
1864 */ 1891 */
1865 if (lp->d_partitions[i].p_size != 0) 1892 if (lp->d_partitions[i].p_size != 0)
1866 continue; 1893 continue;
1867 1894
1868 lp->d_partitions[i].p_size = lp->d_secperunit; 1895 lp->d_partitions[i].p_size = lp->d_secperunit;
1869 lp->d_partitions[i].p_offset = 0; 1896 lp->d_partitions[i].p_offset = 0;
1870 lp->d_partitions[i].p_fstype = FS_BSDFFS; 1897 lp->d_partitions[i].p_fstype = FS_BSDFFS;
1871 } 1898 }
1872 1899
1873 strncpy(lp->d_packname, "default label", 1900 strncpy(lp->d_packname, "default label",
1874 sizeof(lp->d_packname)); 1901 sizeof(lp->d_packname));
1875 1902
1876 lp->d_npartitions = MAXPARTITIONS; 1903 lp->d_npartitions = MAXPARTITIONS;
1877 lp->d_checksum = dkcksum(lp); 1904 lp->d_checksum = dkcksum(lp);
1878 } 1905 }
1879} 1906}
1880 1907
1881/* 1908/*
1882 * Wait interruptibly for an exclusive lock. 1909 * Wait interruptibly for an exclusive lock.
1883 * 1910 *
1884 * XXX 1911 * XXX
1885 * Several drivers do this; it should be abstracted and made MP-safe. 1912 * Several drivers do this; it should be abstracted and made MP-safe.
1886 */ 1913 */
1887static int 1914static int
1888vndlock(struct vnd_softc *sc) 1915vndlock(struct vnd_softc *sc)
1889{ 1916{
1890 int error; 1917 int error;
1891 1918
1892 while ((sc->sc_flags & VNF_LOCKED) != 0) { 1919 while ((sc->sc_flags & VNF_LOCKED) != 0) {
1893 sc->sc_flags |= VNF_WANTED; 1920 sc->sc_flags |= VNF_WANTED;
1894 if ((error = tsleep(sc, PRIBIO | PCATCH, "vndlck", 0)) != 0) 1921 if ((error = tsleep(sc, PRIBIO | PCATCH, "vndlck", 0)) != 0)
1895 return error; 1922 return error;
1896 } 1923 }
1897 sc->sc_flags |= VNF_LOCKED; 1924 sc->sc_flags |= VNF_LOCKED;
1898 return 0; 1925 return 0;
1899} 1926}
1900 1927
1901/* 1928/*
1902 * Unlock and wake up any waiters. 1929 * Unlock and wake up any waiters.
1903 */ 1930 */
1904static void 1931static void
1905vndunlock(struct vnd_softc *sc) 1932vndunlock(struct vnd_softc *sc)
1906{ 1933{
1907 1934
1908 sc->sc_flags &= ~VNF_LOCKED; 1935 sc->sc_flags &= ~VNF_LOCKED;
1909 if ((sc->sc_flags & VNF_WANTED) != 0) { 1936 if ((sc->sc_flags & VNF_WANTED) != 0) {
1910 sc->sc_flags &= ~VNF_WANTED; 1937 sc->sc_flags &= ~VNF_WANTED;
1911 wakeup(sc); 1938 wakeup(sc);
1912 } 1939 }
1913} 1940}
1914 1941
1915#ifdef VND_COMPRESSION 1942#ifdef VND_COMPRESSION
1916/* compressed file read */ 1943/* compressed file read */
1917static void 1944static void
1918compstrategy(struct buf *bp, off_t bn) 1945compstrategy(struct buf *bp, off_t bn)
1919{ 1946{
1920 int error; 1947 int error;
1921 int unit = vndunit(bp->b_dev); 1948 int unit = vndunit(bp->b_dev);
1922 struct vnd_softc *vnd = 1949 struct vnd_softc *vnd =
1923 device_lookup_private(&vnd_cd, unit); 1950 device_lookup_private(&vnd_cd, unit);
1924 u_int32_t comp_block; 1951 u_int32_t comp_block;
1925 struct uio auio; 1952 struct uio auio;
1926 char *addr; 1953 char *addr;
1927 int s; 1954 int s;
1928 1955
1929 /* set up constants for data move */ 1956 /* set up constants for data move */
1930 auio.uio_rw = UIO_READ; 1957 auio.uio_rw = UIO_READ;
1931 UIO_SETUP_SYSSPACE(&auio); 1958 UIO_SETUP_SYSSPACE(&auio);
1932 1959
1933 /* read, and transfer the data */ 1960 /* read, and transfer the data */
1934 addr = bp->b_data; 1961 addr = bp->b_data;
1935 bp->b_resid = bp->b_bcount; 1962 bp->b_resid = bp->b_bcount;
1936 s = splbio(); 1963 s = splbio();
1937 while (bp->b_resid > 0) { 1964 while (bp->b_resid > 0) {
1938 unsigned length; 1965 unsigned length;
1939 size_t length_in_buffer; 1966 size_t length_in_buffer;
1940 u_int32_t offset_in_buffer; 1967 u_int32_t offset_in_buffer;
1941 struct iovec aiov; 1968 struct iovec aiov;
1942 1969
1943 /* calculate the compressed block number */ 1970 /* calculate the compressed block number */
1944 comp_block = bn / (off_t)vnd->sc_comp_blksz; 1971 comp_block = bn / (off_t)vnd->sc_comp_blksz;
1945 1972
1946 /* check for good block number */ 1973 /* check for good block number */
1947 if (comp_block >= vnd->sc_comp_numoffs) { 1974 if (comp_block >= vnd->sc_comp_numoffs) {
1948 bp->b_error = EINVAL; 1975 bp->b_error = EINVAL;
1949 splx(s); 1976 splx(s);
1950 return; 1977 return;
1951 } 1978 }
1952 1979
1953 /* read in the compressed block, if not in buffer */ 1980 /* read in the compressed block, if not in buffer */
1954 if (comp_block != vnd->sc_comp_buffblk) { 1981 if (comp_block != vnd->sc_comp_buffblk) {
1955 length = vnd->sc_comp_offsets[comp_block + 1] - 1982 length = vnd->sc_comp_offsets[comp_block + 1] -
1956 vnd->sc_comp_offsets[comp_block]; 1983 vnd->sc_comp_offsets[comp_block];
1957 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 1984 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY);
1958 error = vn_rdwr(UIO_READ, vnd->sc_vp, vnd->sc_comp_buff, 1985 error = vn_rdwr(UIO_READ, vnd->sc_vp, vnd->sc_comp_buff,
1959 length, vnd->sc_comp_offsets[comp_block], 1986 length, vnd->sc_comp_offsets[comp_block],
1960 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, vnd->sc_cred, 1987 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, vnd->sc_cred,
1961 NULL, NULL); 1988 NULL, NULL);
1962 if (error) { 1989 if (error) {
1963 bp->b_error = error; 1990 bp->b_error = error;
1964 VOP_UNLOCK(vnd->sc_vp); 1991 VOP_UNLOCK(vnd->sc_vp);
1965 splx(s); 1992 splx(s);
1966 return; 1993 return;
1967 } 1994 }
1968 /* uncompress the buffer */ 1995 /* uncompress the buffer */
1969 vnd->sc_comp_stream.next_in = vnd->sc_comp_buff; 1996 vnd->sc_comp_stream.next_in = vnd->sc_comp_buff;
1970 vnd->sc_comp_stream.avail_in = length; 1997 vnd->sc_comp_stream.avail_in = length;
1971 vnd->sc_comp_stream.next_out = vnd->sc_comp_decombuf; 1998 vnd->sc_comp_stream.next_out = vnd->sc_comp_decombuf;
1972 vnd->sc_comp_stream.avail_out = vnd->sc_comp_blksz; 1999 vnd->sc_comp_stream.avail_out = vnd->sc_comp_blksz;
1973 inflateReset(&vnd->sc_comp_stream); 2000 inflateReset(&vnd->sc_comp_stream);
1974 error = inflate(&vnd->sc_comp_stream, Z_FINISH); 2001 error = inflate(&vnd->sc_comp_stream, Z_FINISH);
1975 if (error != Z_STREAM_END) { 2002 if (error != Z_STREAM_END) {
1976 if (vnd->sc_comp_stream.msg) 2003 if (vnd->sc_comp_stream.msg)
1977 aprint_normal_dev(vnd->sc_dev, 2004 aprint_normal_dev(vnd->sc_dev,
1978 "compressed file, %s\n", 2005 "compressed file, %s\n",
1979 vnd->sc_comp_stream.msg); 2006 vnd->sc_comp_stream.msg);
1980 bp->b_error = EBADMSG; 2007 bp->b_error = EBADMSG;
1981 VOP_UNLOCK(vnd->sc_vp); 2008 VOP_UNLOCK(vnd->sc_vp);
1982 splx(s); 2009 splx(s);
1983 return; 2010 return;
1984 } 2011 }
1985 vnd->sc_comp_buffblk = comp_block; 2012 vnd->sc_comp_buffblk = comp_block;
1986 VOP_UNLOCK(vnd->sc_vp); 2013 VOP_UNLOCK(vnd->sc_vp);
1987 } 2014 }
1988 2015
1989 /* transfer the usable uncompressed data */ 2016 /* transfer the usable uncompressed data */
1990 offset_in_buffer = bn % (off_t)vnd->sc_comp_blksz; 2017 offset_in_buffer = bn % (off_t)vnd->sc_comp_blksz;
1991 length_in_buffer = vnd->sc_comp_blksz - offset_in_buffer; 2018 length_in_buffer = vnd->sc_comp_blksz - offset_in_buffer;
1992 if (length_in_buffer > bp->b_resid) 2019 if (length_in_buffer > bp->b_resid)
1993 length_in_buffer = bp->b_resid; 2020 length_in_buffer = bp->b_resid;
1994 auio.uio_iov = &aiov; 2021 auio.uio_iov = &aiov;
1995 auio.uio_iovcnt = 1; 2022 auio.uio_iovcnt = 1;
1996 aiov.iov_base = addr; 2023 aiov.iov_base = addr;
1997 aiov.iov_len = length_in_buffer; 2024 aiov.iov_len = length_in_buffer;
1998 auio.uio_resid = aiov.iov_len; 2025 auio.uio_resid = aiov.iov_len;
1999 auio.uio_offset = 0; 2026 auio.uio_offset = 0;
2000 error = uiomove(vnd->sc_comp_decombuf + offset_in_buffer, 2027 error = uiomove(vnd->sc_comp_decombuf + offset_in_buffer,
2001 length_in_buffer, &auio); 2028 length_in_buffer, &auio);
2002 if (error) { 2029 if (error) {
2003 bp->b_error = error; 2030 bp->b_error = error;
2004 splx(s); 2031 splx(s);
2005 return; 2032 return;
2006 } 2033 }
2007 2034
2008 bn += length_in_buffer; 2035 bn += length_in_buffer;
2009 addr += length_in_buffer; 2036 addr += length_in_buffer;
2010 bp->b_resid -= length_in_buffer; 2037 bp->b_resid -= length_in_buffer;
2011 } 2038 }
2012 splx(s); 2039 splx(s);
2013} 2040}
2014 2041
2015/* compression memory allocation routines */ 2042/* compression memory allocation routines */
2016static void * 2043static void *
2017vnd_alloc(void *aux, u_int items, u_int siz) 2044vnd_alloc(void *aux, u_int items, u_int siz)
2018{ 2045{
2019 return malloc(items * siz, M_TEMP, M_NOWAIT); 2046 return malloc(items * siz, M_TEMP, M_NOWAIT);
2020} 2047}
2021 2048
2022static void 2049static void
2023vnd_free(void *aux, void *ptr) 2050vnd_free(void *aux, void *ptr)
2024{ 2051{
2025 free(ptr, M_TEMP); 2052 free(ptr, M_TEMP);
2026} 2053}
2027#endif /* VND_COMPRESSION */ 2054#endif /* VND_COMPRESSION */
2028 2055
2029static void 2056static void
2030vnd_set_geometry(struct vnd_softc *vnd) 2057vnd_set_geometry(struct vnd_softc *vnd)
2031{ 2058{
2032 struct disk_geom *dg = &vnd->sc_dkdev.dk_geom; 2059 struct disk_geom *dg = &vnd->sc_dkdev.dk_geom;
2033 2060
2034 memset(dg, 0, sizeof(*dg)); 2061 memset(dg, 0, sizeof(*dg));
2035 2062
2036 dg->dg_secperunit = (int64_t)vnd->sc_geom.vng_nsectors * 2063 dg->dg_secperunit = (int64_t)vnd->sc_geom.vng_nsectors *
2037 vnd->sc_geom.vng_ntracks * vnd->sc_geom.vng_ncylinders; 2064 vnd->sc_geom.vng_ntracks * vnd->sc_geom.vng_ncylinders;
2038 dg->dg_secsize = vnd->sc_geom.vng_secsize; 2065 dg->dg_secsize = vnd->sc_geom.vng_secsize;
2039 dg->dg_nsectors = vnd->sc_geom.vng_nsectors; 2066 dg->dg_nsectors = vnd->sc_geom.vng_nsectors;
2040 dg->dg_ntracks = vnd->sc_geom.vng_ntracks; 2067 dg->dg_ntracks = vnd->sc_geom.vng_ntracks;
2041 dg->dg_ncylinders = vnd->sc_geom.vng_ncylinders; 2068 dg->dg_ncylinders = vnd->sc_geom.vng_ncylinders;
2042 2069
2043#ifdef DEBUG 2070#ifdef DEBUG
2044 if (vnddebug & VDB_LABEL) { 2071 if (vnddebug & VDB_LABEL) {
2045 printf("dg->dg_secperunit: %" PRId64 "\n", dg->dg_secperunit); 2072 printf("dg->dg_secperunit: %" PRId64 "\n", dg->dg_secperunit);
2046 printf("dg->dg_ncylinders: %u\n", dg->dg_ncylinders); 2073 printf("dg->dg_ncylinders: %u\n", dg->dg_ncylinders);
2047 } 2074 }
2048#endif 2075#endif
2049 disk_set_info(vnd->sc_dev, &vnd->sc_dkdev, NULL); 2076 disk_set_info(vnd->sc_dev, &vnd->sc_dkdev, NULL);
2050} 2077}
2051 2078
2052#ifdef _MODULE 2079#ifdef _MODULE
2053 2080
2054#include <sys/module.h> 2081#include <sys/module.h>
2055 2082
2056#ifdef VND_COMPRESSION 2083#ifdef VND_COMPRESSION
2057#define VND_DEPENDS "zlib" 2084#define VND_DEPENDS "zlib"
2058#else 2085#else
2059#define VND_DEPENDS NULL 2086#define VND_DEPENDS NULL
2060#endif 2087#endif
2061 2088
2062MODULE(MODULE_CLASS_DRIVER, vnd, VND_DEPENDS); 2089MODULE(MODULE_CLASS_DRIVER, vnd, VND_DEPENDS);
2063CFDRIVER_DECL(vnd, DV_DISK, NULL); 2090CFDRIVER_DECL(vnd, DV_DISK, NULL);
2064 2091
2065static int 2092static int
2066vnd_modcmd(modcmd_t cmd, void *arg) 2093vnd_modcmd(modcmd_t cmd, void *arg)
2067{ 2094{
2068 int bmajor = -1, cmajor = -1, error = 0; 2095 int bmajor = -1, cmajor = -1, error = 0;
2069  2096
2070 switch (cmd) { 2097 switch (cmd) {
2071 case MODULE_CMD_INIT: 2098 case MODULE_CMD_INIT:
2072 error = config_cfdriver_attach(&vnd_cd); 2099 error = config_cfdriver_attach(&vnd_cd);
2073 if (error) 2100 if (error)
2074 break; 2101 break;
2075 2102
2076 error = config_cfattach_attach(vnd_cd.cd_name, &vnd_ca); 2103 error = config_cfattach_attach(vnd_cd.cd_name, &vnd_ca);
2077 if (error) { 2104 if (error) {
2078 config_cfdriver_detach(&vnd_cd); 2105 config_cfdriver_detach(&vnd_cd);
2079 aprint_error("%s: unable to register cfattach\n", 2106 aprint_error("%s: unable to register cfattach\n",
2080 vnd_cd.cd_name); 2107 vnd_cd.cd_name);
2081 break; 2108 break;
2082 } 2109 }
2083  2110
2084 error = devsw_attach("vnd", &vnd_bdevsw, &bmajor, 2111 error = devsw_attach("vnd", &vnd_bdevsw, &bmajor,
2085 &vnd_cdevsw, &cmajor); 2112 &vnd_cdevsw, &cmajor);
2086 if (error) { 2113 if (error) {
2087 config_cfattach_detach(vnd_cd.cd_name, &vnd_ca); 2114 config_cfattach_detach(vnd_cd.cd_name, &vnd_ca);
2088 config_cfdriver_detach(&vnd_cd); 2115 config_cfdriver_detach(&vnd_cd);
2089 break; 2116 break;
2090 } 2117 }
2091  2118
2092 break; 2119 break;
2093 2120
2094 case MODULE_CMD_FINI: 2121 case MODULE_CMD_FINI:
2095 error = config_cfattach_detach(vnd_cd.cd_name, &vnd_ca); 2122 error = config_cfattach_detach(vnd_cd.cd_name, &vnd_ca);
2096 if (error) 2123 if (error)
2097 break; 2124 break;
2098 config_cfdriver_detach(&vnd_cd); 2125 config_cfdriver_detach(&vnd_cd);
2099 devsw_detach(&vnd_bdevsw, &vnd_cdevsw); 2126 devsw_detach(&vnd_bdevsw, &vnd_cdevsw);
2100 break; 2127 break;
2101 2128
2102 case MODULE_CMD_STAT: 2129 case MODULE_CMD_STAT:
2103 return ENOTTY; 2130 return ENOTTY;
2104 2131
2105 default: 2132 default:
2106 return ENOTTY; 2133 return ENOTTY;
2107 } 2134 }
2108 2135
2109 return error; 2136 return error;
2110} 2137}
2111 2138
2112#endif 2139#endif