This source file includes following definitions.
- vndencrypt
- vndattach
- vndopen
- vndgetdisklabel
- vndclose
- vndstrategy
- vndstart
- vndiodone
- vndread
- vndwrite
- vndioctl
- vndsetcred
- vndshutdown
- vndclear
- vndsize
- vnddump
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/namei.h>
66 #include <sys/proc.h>
67 #include <sys/errno.h>
68 #include <sys/buf.h>
69 #include <sys/malloc.h>
70 #include <sys/pool.h>
71 #include <sys/ioctl.h>
72 #include <sys/disklabel.h>
73 #include <sys/device.h>
74 #include <sys/disk.h>
75 #include <sys/stat.h>
76 #include <sys/mount.h>
77 #include <sys/vnode.h>
78 #include <sys/file.h>
79 #include <sys/rwlock.h>
80 #include <sys/uio.h>
81 #include <sys/conf.h>
82
83 #include <crypto/blf.h>
84
85 #include <miscfs/specfs/specdev.h>
86
87 #include <dev/vndioctl.h>
88
89 #ifdef VNDDEBUG
90 int dovndcluster = 1;
91 int vnddebug = 0x00;
92 #define VDB_FOLLOW 0x01
93 #define VDB_INIT 0x02
94 #define VDB_IO 0x04
95 #define DNPRINTF(f, p...) do { if ((f) & vnddebug) printf(p); } while (0)
96 #else
97 #define DNPRINTF(f, p...)
98 #endif
99
100
101
102
103
104 #define vndunit(x) DISKUNIT(makedev(major(x), minor(x) & 0x7ff))
105 #define vndsimple(x) (minor(x) & 0x800)
106
107
108 #define VNDLABELDEV(dev) \
109 makedev(major(dev), DISKMINOR(vndunit(dev), RAW_PART) | \
110 (vndsimple(dev) ? 0x800 : 0))
111
112 struct vndbuf {
113 struct buf vb_buf;
114 struct buf *vb_obp;
115 };
116
117
118
119
120 struct pool vndbufpl;
121
122 #define getvndbuf() pool_get(&vndbufpl, PR_WAITOK)
123 #define putvndbuf(vbp) pool_put(&vndbufpl, vbp);
124
125 struct vnd_softc {
126 struct device sc_dev;
127 struct disk sc_dk;
128
129 char sc_file[VNDNLEN];
130 int sc_flags;
131 size_t sc_size;
132 struct vnode *sc_vp;
133 struct ucred *sc_cred;
134 struct buf sc_tab;
135 blf_ctx *sc_keyctx;
136 struct rwlock sc_rwlock;
137 };
138
139
140 #define VNF_ALIVE 0x0001
141 #define VNF_INITED 0x0002
142 #define VNF_LABELLING 0x0100
143 #define VNF_WLABEL 0x0200
144 #define VNF_HAVELABEL 0x0400
145 #define VNF_SIMPLE 0x1000
146 #define VNF_READONLY 0x2000
147
148 #define VNDRW(v) ((v)->sc_flags & VNF_READONLY ? FREAD : FREAD|FWRITE)
149
150 struct vnd_softc *vnd_softc;
151 int numvnd = 0;
152
153 struct dkdriver vnddkdriver = { vndstrategy };
154
155
156 void vndattach(int);
157
158 void vndclear(struct vnd_softc *);
159 void vndstart(struct vnd_softc *);
160 int vndsetcred(struct vnd_softc *, struct ucred *);
161 void vndiodone(struct buf *);
162 void vndshutdown(void);
163 void vndgetdisklabel(dev_t, struct vnd_softc *);
164 void vndencrypt(struct vnd_softc *, caddr_t, size_t, daddr64_t, int);
165
166 #define vndlock(sc) rw_enter(&sc->sc_rwlock, RW_WRITE|RW_INTR)
167 #define vndunlock(sc) rw_exit_write(&sc->sc_rwlock)
168
169 void
170 vndencrypt(struct vnd_softc *vnd, caddr_t addr, size_t size, daddr64_t off,
171 int encrypt)
172 {
173 int i, bsize;
174 u_char iv[8];
175
176 bsize = dbtob(1);
177 for (i = 0; i < size/bsize; i++) {
178 bzero(iv, sizeof(iv));
179 bcopy((u_char *)&off, iv, sizeof(off));
180 blf_ecb_encrypt(vnd->sc_keyctx, iv, sizeof(iv));
181 if (encrypt)
182 blf_cbc_encrypt(vnd->sc_keyctx, iv, addr, bsize);
183 else
184 blf_cbc_decrypt(vnd->sc_keyctx, iv, addr, bsize);
185
186 addr += bsize;
187 off++;
188 }
189 }
190
191 void
192 vndattach(int num)
193 {
194 char *mem;
195 u_long size;
196 int i;
197
198 if (num <= 0)
199 return;
200 size = num * sizeof(struct vnd_softc);
201 mem = malloc(size, M_DEVBUF, M_NOWAIT);
202 if (mem == NULL) {
203 printf("WARNING: no memory for vnode disks\n");
204 return;
205 }
206 bzero(mem, size);
207 vnd_softc = (struct vnd_softc *)mem;
208 for (i = 0; i < num; i++) {
209 rw_init(&vnd_softc[i].sc_rwlock, "vndlock");
210 }
211 numvnd = num;
212
213 pool_init(&vndbufpl, sizeof(struct vndbuf), 0, 0, 0, "vndbufpl", NULL);
214 pool_setlowat(&vndbufpl, 16);
215 pool_sethiwat(&vndbufpl, 1024);
216 }
217
218 int
219 vndopen(dev_t dev, int flags, int mode, struct proc *p)
220 {
221 int unit = vndunit(dev);
222 struct vnd_softc *sc;
223 int error = 0, part, pmask;
224
225 DNPRINTF(VDB_FOLLOW, "vndopen(%x, %x, %x, %p)\n", dev, flags, mode, p);
226
227 if (unit >= numvnd)
228 return (ENXIO);
229 sc = &vnd_softc[unit];
230
231 if ((error = vndlock(sc)) != 0)
232 return (error);
233
234 if ((flags & FWRITE) && (sc->sc_flags & VNF_READONLY)) {
235 error = EROFS;
236 goto bad;
237 }
238
239 if ((sc->sc_flags & VNF_INITED) &&
240 (sc->sc_flags & VNF_HAVELABEL) == 0) {
241 sc->sc_flags |= VNF_HAVELABEL;
242 vndgetdisklabel(dev, sc);
243 }
244
245 part = DISKPART(dev);
246 pmask = 1 << part;
247
248
249
250
251
252 if (sc->sc_dk.dk_openmask) {
253 if (((sc->sc_flags & VNF_SIMPLE) != 0) !=
254 (vndsimple(dev) != 0) && (flags & FWRITE)) {
255 error = EBUSY;
256 goto bad;
257 }
258 } else if (vndsimple(dev))
259 sc->sc_flags |= VNF_SIMPLE;
260 else
261 sc->sc_flags &= ~VNF_SIMPLE;
262
263
264 if (part != RAW_PART &&
265 ((sc->sc_flags & VNF_HAVELABEL) == 0 ||
266 part >= sc->sc_dk.dk_label->d_npartitions ||
267 sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
268 error = ENXIO;
269 goto bad;
270 }
271
272
273 switch (mode) {
274 case S_IFCHR:
275 sc->sc_dk.dk_copenmask |= pmask;
276 break;
277
278 case S_IFBLK:
279 sc->sc_dk.dk_bopenmask |= pmask;
280 break;
281 }
282 sc->sc_dk.dk_openmask =
283 sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
284
285 error = 0;
286 bad:
287 vndunlock(sc);
288 return (error);
289 }
290
291
292
293
294 void
295 vndgetdisklabel(dev_t dev, struct vnd_softc *sc)
296 {
297 struct disklabel *lp = sc->sc_dk.dk_label;
298 char *errstring = NULL;
299
300 bzero(lp, sizeof(struct disklabel));
301
302 lp->d_secsize = 512;
303 lp->d_ntracks = 1;
304 lp->d_nsectors = 100;
305 lp->d_ncylinders = sc->sc_size / 100;
306 lp->d_secpercyl = 100;
307
308 strncpy(lp->d_typename, "vnd device", sizeof(lp->d_typename));
309 lp->d_type = DTYPE_VND;
310 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
311 DL_SETDSIZE(lp, sc->sc_size);
312 lp->d_rpm = 3600;
313 lp->d_interleave = 1;
314 lp->d_flags = 0;
315 lp->d_version = 1;
316
317 lp->d_magic = DISKMAGIC;
318 lp->d_magic2 = DISKMAGIC;
319 lp->d_checksum = dkcksum(lp);
320
321
322 errstring = readdisklabel(VNDLABELDEV(dev), vndstrategy, lp, 0);
323 if (errstring) {
324 DNPRINTF(VDB_IO, "%s: %s\n", sc->sc_dev.dv_xname,
325 errstring);
326 return;
327 }
328 }
329
330 int
331 vndclose(dev_t dev, int flags, int mode, struct proc *p)
332 {
333 int unit = vndunit(dev);
334 struct vnd_softc *sc;
335 int error = 0, part;
336
337 DNPRINTF(VDB_FOLLOW, "vndclose(%x, %x, %x, %p)\n", dev, flags, mode, p);
338
339 if (unit >= numvnd)
340 return (ENXIO);
341 sc = &vnd_softc[unit];
342
343 if ((error = vndlock(sc)) != 0)
344 return (error);
345
346 part = DISKPART(dev);
347
348
349 switch (mode) {
350 case S_IFCHR:
351 sc->sc_dk.dk_copenmask &= ~(1 << part);
352 break;
353
354 case S_IFBLK:
355 sc->sc_dk.dk_bopenmask &= ~(1 << part);
356 break;
357 }
358 sc->sc_dk.dk_openmask =
359 sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
360
361 vndunlock(sc);
362 return (0);
363 }
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378 void
379 vndstrategy(struct buf *bp)
380 {
381 int unit = vndunit(bp->b_dev);
382 struct vnd_softc *vnd = &vnd_softc[unit];
383 struct vndbuf *nbp;
384 int bsize;
385 off_t bn;
386 caddr_t addr;
387 size_t resid;
388 int sz, flags, error, s;
389 struct iovec aiov;
390 struct uio auio;
391 struct proc *p = curproc;
392
393 DNPRINTF(VDB_FOLLOW, "vndstrategy(%p): unit %d\n", bp, unit);
394
395 if ((vnd->sc_flags & VNF_INITED) == 0) {
396 bp->b_error = ENXIO;
397 bp->b_flags |= B_ERROR;
398 s = splbio();
399 biodone(bp);
400 splx(s);
401 return;
402 }
403
404 bn = bp->b_blkno;
405 bp->b_resid = bp->b_bcount;
406
407 if (bn < 0) {
408 bp->b_error = EINVAL;
409 bp->b_flags |= B_ERROR;
410 s = splbio();
411 biodone(bp);
412 splx(s);
413 return;
414 }
415
416
417 if (vnd->sc_flags & VNF_HAVELABEL) {
418 if (bounds_check_with_label(bp, vnd->sc_dk.dk_label, 1) <= 0) {
419 s = splbio();
420 biodone(bp);
421 splx(s);
422 return;
423 }
424
425
426
427
428 bp->b_resid = bp->b_bcount;
429 }
430
431 sz = howmany(bp->b_bcount, DEV_BSIZE);
432
433
434 if (vndsimple(bp->b_dev)) {
435
436 for (;;) {
437 int part = DISKPART(bp->b_dev);
438 daddr64_t off = DL_GETPOFFSET(&vnd->sc_dk.dk_label->d_partitions[part]);
439
440 aiov.iov_base = bp->b_data;
441 auio.uio_resid = aiov.iov_len = bp->b_bcount;
442 auio.uio_iov = &aiov;
443 auio.uio_iovcnt = 1;
444 auio.uio_offset = dbtob((off_t)(bp->b_blkno + off));
445 auio.uio_segflg = UIO_SYSSPACE;
446 auio.uio_procp = p;
447
448 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY, p);
449 if (bp->b_flags & B_READ) {
450 auio.uio_rw = UIO_READ;
451 bp->b_error = VOP_READ(vnd->sc_vp, &auio, 0,
452 vnd->sc_cred);
453 if (vnd->sc_keyctx)
454 vndencrypt(vnd, bp->b_data,
455 bp->b_bcount, bp->b_blkno, 0);
456 } else {
457 if (vnd->sc_keyctx)
458 vndencrypt(vnd, bp->b_data,
459 bp->b_bcount, bp->b_blkno, 1);
460 auio.uio_rw = UIO_WRITE;
461
462
463
464
465 bp->b_error = VOP_WRITE(vnd->sc_vp, &auio,
466 IO_NOLIMIT, vnd->sc_cred);
467
468 if (vnd->sc_keyctx)
469 vndencrypt(vnd, bp->b_data,
470 bp->b_bcount, bp->b_blkno, 0);
471 }
472 VOP_UNLOCK(vnd->sc_vp, 0, p);
473 if (bp->b_error)
474 bp->b_flags |= B_ERROR;
475 bp->b_resid = auio.uio_resid;
476 s = splbio();
477 biodone(bp);
478 splx(s);
479
480
481 if (!vnd->sc_tab.b_active)
482 return;
483
484
485
486
487
488 s = splbio();
489 bp = vnd->sc_tab.b_actf;
490 vnd->sc_tab.b_actf = bp->b_actf;
491 vnd->sc_tab.b_active--;
492 splx(s);
493 }
494 }
495
496
497 bn += DL_GETPOFFSET(&vnd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]);
498 bn = dbtob(bn);
499 bsize = vnd->sc_vp->v_mount->mnt_stat.f_iosize;
500 addr = bp->b_data;
501 flags = bp->b_flags | B_CALL;
502 for (resid = bp->b_resid; resid; resid -= sz) {
503 struct vnode *vp;
504 daddr64_t nbn;
505 int off, s, nra;
506
507 nra = 0;
508 vn_lock(vnd->sc_vp, LK_RETRY | LK_EXCLUSIVE, p);
509 error = VOP_BMAP(vnd->sc_vp, bn / bsize, &vp, &nbn, &nra);
510 VOP_UNLOCK(vnd->sc_vp, 0, p);
511 if (error == 0 && (long)nbn == -1)
512 error = EIO;
513 #ifdef VNDDEBUG
514 if (!dovndcluster)
515 nra = 0;
516 #endif
517
518 if ((off = bn % bsize) != 0)
519 sz = bsize - off;
520 else
521 sz = (1 + nra) * bsize;
522 if (resid < sz)
523 sz = resid;
524
525 DNPRINTF(VDB_IO, "vndstrategy: vp %p/%p bn %x/%x sz %x\n",
526 vnd->sc_vp, vp, bn, nbn, sz);
527
528 s = splbio();
529 nbp = getvndbuf();
530 splx(s);
531 nbp->vb_buf.b_flags = flags;
532 nbp->vb_buf.b_bcount = sz;
533 nbp->vb_buf.b_bufsize = bp->b_bufsize;
534 nbp->vb_buf.b_error = 0;
535 if (vp->v_type == VBLK || vp->v_type == VCHR)
536 nbp->vb_buf.b_dev = vp->v_rdev;
537 else
538 nbp->vb_buf.b_dev = NODEV;
539 nbp->vb_buf.b_data = addr;
540 nbp->vb_buf.b_blkno = nbn + btodb(off);
541 nbp->vb_buf.b_proc = bp->b_proc;
542 nbp->vb_buf.b_iodone = vndiodone;
543 nbp->vb_buf.b_vp = vp;
544 nbp->vb_buf.b_dirtyoff = bp->b_dirtyoff;
545 nbp->vb_buf.b_dirtyend = bp->b_dirtyend;
546 nbp->vb_buf.b_validoff = bp->b_validoff;
547 nbp->vb_buf.b_validend = bp->b_validend;
548 LIST_INIT(&nbp->vb_buf.b_dep);
549
550
551 nbp->vb_obp = bp;
552
553
554
555
556
557
558
559
560
561
562
563
564 if (error) {
565 nbp->vb_buf.b_error = error;
566 nbp->vb_buf.b_flags |= B_ERROR;
567 bp->b_resid -= (resid - sz);
568 s = splbio();
569
570 if ((nbp->vb_buf.b_flags & B_READ) == 0)
571 nbp->vb_buf.b_vp->v_numoutput++;
572 biodone(&nbp->vb_buf);
573 splx(s);
574 return;
575 }
576
577
578
579 nbp->vb_buf.b_cylinder = nbp->vb_buf.b_blkno;
580 s = splbio();
581 disksort(&vnd->sc_tab, &nbp->vb_buf);
582 vnd->sc_tab.b_active++;
583 vndstart(vnd);
584 splx(s);
585 bn += sz;
586 addr += sz;
587 }
588 }
589
590
591
592
593
594
595
596 void
597 vndstart(struct vnd_softc *vnd)
598 {
599 struct buf *bp;
600
601
602
603
604
605 bp = vnd->sc_tab.b_actf;
606 vnd->sc_tab.b_actf = bp->b_actf;
607
608 DNPRINTF(VDB_IO,
609 "vndstart(%d): bp %p vp %p blkno %x addr %p cnt %lx\n",
610 vnd-vnd_softc, bp, bp->b_vp, bp->b_blkno, bp->b_data,
611 bp->b_bcount);
612
613
614 disk_busy(&vnd->sc_dk);
615
616 if ((bp->b_flags & B_READ) == 0)
617 bp->b_vp->v_numoutput++;
618 VOP_STRATEGY(bp);
619 }
620
621 void
622 vndiodone(struct buf *bp)
623 {
624 struct vndbuf *vbp = (struct vndbuf *) bp;
625 struct buf *pbp = vbp->vb_obp;
626 struct vnd_softc *vnd = &vnd_softc[vndunit(pbp->b_dev)];
627
628 splassert(IPL_BIO);
629
630 DNPRINTF(VDB_IO,
631 "vndiodone(%d): vbp %p vp %p blkno %x addr %p cnt %lx\n",
632 vnd-vnd_softc, vbp, vbp->vb_buf.b_vp, vbp->vb_buf.b_blkno,
633 vbp->vb_buf.b_data, vbp->vb_buf.b_bcount);
634
635 if (vbp->vb_buf.b_error) {
636 DNPRINTF(VDB_IO, "vndiodone: vbp %p error %d\n", vbp,
637 vbp->vb_buf.b_error);
638
639 pbp->b_flags |= B_ERROR;
640 pbp->b_error = biowait(&vbp->vb_buf);
641 }
642 pbp->b_resid -= vbp->vb_buf.b_bcount;
643 putvndbuf(vbp);
644 if (vnd->sc_tab.b_active) {
645 disk_unbusy(&vnd->sc_dk, (pbp->b_bcount - pbp->b_resid),
646 (pbp->b_flags & B_READ));
647 if (!vnd->sc_tab.b_actf)
648 vnd->sc_tab.b_active--;
649 }
650 if (pbp->b_resid == 0) {
651 DNPRINTF(VDB_IO, "vndiodone: pbp %p iodone\n", pbp);
652 biodone(pbp);
653 }
654
655 }
656
657
658 int
659 vndread(dev_t dev, struct uio *uio, int flags)
660 {
661 int unit = vndunit(dev);
662 struct vnd_softc *sc;
663
664 DNPRINTF(VDB_FOLLOW, "vndread(%x, %p)\n", dev, uio);
665
666 if (unit >= numvnd)
667 return (ENXIO);
668 sc = &vnd_softc[unit];
669
670 if ((sc->sc_flags & VNF_INITED) == 0)
671 return (ENXIO);
672
673 return (physio(vndstrategy, NULL, dev, B_READ, minphys, uio));
674 }
675
676
677 int
678 vndwrite(dev_t dev, struct uio *uio, int flags)
679 {
680 int unit = vndunit(dev);
681 struct vnd_softc *sc;
682
683 DNPRINTF(VDB_FOLLOW, "vndwrite(%x, %p)\n", dev, uio);
684
685 if (unit >= numvnd)
686 return (ENXIO);
687 sc = &vnd_softc[unit];
688
689 if ((sc->sc_flags & VNF_INITED) == 0)
690 return (ENXIO);
691
692 return (physio(vndstrategy, NULL, dev, B_WRITE, minphys, uio));
693 }
694
695
696 int
697 vndioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
698 {
699 int unit = vndunit(dev);
700 struct vnd_softc *vnd;
701 struct vnd_ioctl *vio;
702 struct vnd_user *vnu;
703 struct vattr vattr;
704 struct nameidata nd;
705 int error, part, pmask, s;
706
707 DNPRINTF(VDB_FOLLOW, "vndioctl(%x, %lx, %p, %x, %p): unit %d\n",
708 dev, cmd, addr, flag, p, unit);
709
710 error = suser(p, 0);
711 if (error)
712 return (error);
713 if (unit >= numvnd)
714 return (ENXIO);
715
716 vnd = &vnd_softc[unit];
717 vio = (struct vnd_ioctl *)addr;
718 switch (cmd) {
719
720 case VNDIOCSET:
721 if (vnd->sc_flags & VNF_INITED)
722 return (EBUSY);
723 if (!(vnd->sc_flags & VNF_SIMPLE) && vio->vnd_keylen)
724 return (EINVAL);
725
726 if ((error = vndlock(vnd)) != 0)
727 return (error);
728
729 if ((error = copyinstr(vio->vnd_file, vnd->sc_file,
730 sizeof(vnd->sc_file), NULL))) {
731 vndunlock(vnd);
732 return (error);
733 }
734
735 bzero(vnd->sc_dev.dv_xname, sizeof(vnd->sc_dev.dv_xname));
736 if (snprintf(vnd->sc_dev.dv_xname, sizeof(vnd->sc_dev.dv_xname),
737 "vnd%d", unit) >= sizeof(vnd->sc_dev.dv_xname)) {
738 printf("VNDIOCSET: device name too long\n");
739 vndunlock(vnd);
740 return(ENXIO);
741 }
742
743
744
745
746
747
748 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vnd_file, p);
749 vnd->sc_flags &= ~VNF_READONLY;
750 error = vn_open(&nd, FREAD|FWRITE, 0);
751 if (error == EROFS) {
752 vnd->sc_flags |= VNF_READONLY;
753 error = vn_open(&nd, FREAD, 0);
754 }
755 if (error) {
756 vndunlock(vnd);
757 return (error);
758 }
759
760 error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
761 if (error) {
762 VOP_UNLOCK(nd.ni_vp, 0, p);
763 (void) vn_close(nd.ni_vp, VNDRW(vnd), p->p_ucred, p);
764 vndunlock(vnd);
765 return (error);
766 }
767 VOP_UNLOCK(nd.ni_vp, 0, p);
768 vnd->sc_vp = nd.ni_vp;
769 vnd->sc_size = btodb(vattr.va_size);
770 if ((error = vndsetcred(vnd, p->p_ucred)) != 0) {
771 (void) vn_close(nd.ni_vp, VNDRW(vnd), p->p_ucred, p);
772 vndunlock(vnd);
773 return (error);
774 }
775
776 if (vio->vnd_keylen > 0) {
777 char key[BLF_MAXUTILIZED];
778
779 if (vio->vnd_keylen > sizeof(key))
780 vio->vnd_keylen = sizeof(key);
781
782 if ((error = copyin(vio->vnd_key, key,
783 vio->vnd_keylen)) != 0) {
784 (void) vn_close(nd.ni_vp, VNDRW(vnd),
785 p->p_ucred, p);
786 vndunlock(vnd);
787 return (error);
788 }
789
790 vnd->sc_keyctx = malloc(sizeof(*vnd->sc_keyctx), M_DEVBUF,
791 M_WAITOK);
792 blf_key(vnd->sc_keyctx, key, vio->vnd_keylen);
793 bzero(key, vio->vnd_keylen);
794 } else
795 vnd->sc_keyctx = NULL;
796
797 vio->vnd_size = dbtob((off_t)vnd->sc_size);
798 vnd->sc_flags |= VNF_INITED;
799
800 DNPRINTF(VDB_INIT, "vndioctl: SET vp %p size %llx\n",
801 vnd->sc_vp, (unsigned long long)vnd->sc_size);
802
803
804 vnd->sc_dk.dk_driver = &vnddkdriver;
805 vnd->sc_dk.dk_name = vnd->sc_dev.dv_xname;
806 disk_attach(&vnd->sc_dk);
807
808 vndunlock(vnd);
809
810 break;
811
812 case VNDIOCCLR:
813 if ((vnd->sc_flags & VNF_INITED) == 0)
814 return (ENXIO);
815
816 if ((error = vndlock(vnd)) != 0)
817 return (error);
818
819
820
821
822
823
824 part = DISKPART(dev);
825 pmask = (1 << part);
826 if ((vnd->sc_dk.dk_openmask & ~pmask) ||
827 ((vnd->sc_dk.dk_bopenmask & pmask) &&
828 (vnd->sc_dk.dk_copenmask & pmask))) {
829 vndunlock(vnd);
830 return (EBUSY);
831 }
832
833 vndclear(vnd);
834 DNPRINTF(VDB_INIT, "vndioctl: CLRed\n");
835
836
837 if (vnd->sc_keyctx) {
838 bzero(vnd->sc_keyctx, sizeof(*vnd->sc_keyctx));
839 free(vnd->sc_keyctx, M_DEVBUF);
840 }
841
842
843 disk_detach(&vnd->sc_dk);
844
845
846 s = splhigh();
847 vndunlock(vnd);
848 bzero(vnd, sizeof(struct vnd_softc));
849 splx(s);
850 break;
851
852 case VNDIOCGET:
853 vnu = (struct vnd_user *)addr;
854
855 if (vnu->vnu_unit == -1)
856 vnu->vnu_unit = unit;
857 if (vnu->vnu_unit >= numvnd)
858 return (ENXIO);
859 if (vnu->vnu_unit < 0)
860 return (EINVAL);
861
862 vnd = &vnd_softc[vnu->vnu_unit];
863
864 if (vnd->sc_flags & VNF_INITED) {
865 error = VOP_GETATTR(vnd->sc_vp, &vattr, p->p_ucred, p);
866 if (error)
867 return (error);
868
869 strlcpy(vnu->vnu_file, vnd->sc_file,
870 sizeof(vnu->vnu_file));
871 vnu->vnu_dev = vattr.va_fsid;
872 vnu->vnu_ino = vattr.va_fileid;
873 } else {
874 vnu->vnu_dev = 0;
875 vnu->vnu_ino = 0;
876 }
877
878 break;
879
880 case DIOCGDINFO:
881 if ((vnd->sc_flags & VNF_HAVELABEL) == 0)
882 return (ENOTTY);
883 *(struct disklabel *)addr = *(vnd->sc_dk.dk_label);
884 return (0);
885
886 case DIOCGPART:
887 if ((vnd->sc_flags & VNF_HAVELABEL) == 0)
888 return (ENOTTY);
889 ((struct partinfo *)addr)->disklab = vnd->sc_dk.dk_label;
890 ((struct partinfo *)addr)->part =
891 &vnd->sc_dk.dk_label->d_partitions[DISKPART(dev)];
892 return (0);
893
894 case DIOCWDINFO:
895 case DIOCSDINFO:
896 if ((vnd->sc_flags & VNF_HAVELABEL) == 0)
897 return (ENOTTY);
898 if ((flag & FWRITE) == 0)
899 return (EBADF);
900
901 if ((error = vndlock(vnd)) != 0)
902 return (error);
903 vnd->sc_flags |= VNF_LABELLING;
904
905 error = setdisklabel(vnd->sc_dk.dk_label,
906 (struct disklabel *)addr, 0);
907 if (error == 0) {
908 if (cmd == DIOCWDINFO)
909 error = writedisklabel(VNDLABELDEV(dev),
910 vndstrategy, vnd->sc_dk.dk_label);
911 }
912
913 vnd->sc_flags &= ~VNF_LABELLING;
914 vndunlock(vnd);
915 return (error);
916
917 case DIOCWLABEL:
918 if ((flag & FWRITE) == 0)
919 return (EBADF);
920 if (*(int *)addr)
921 vnd->sc_flags |= VNF_WLABEL;
922 else
923 vnd->sc_flags &= ~VNF_WLABEL;
924 return (0);
925
926 default:
927 return (ENOTTY);
928 }
929
930 return (0);
931 }
932
933
934
935
936
937
938
939 int
940 vndsetcred(struct vnd_softc *vnd, struct ucred *cred)
941 {
942 struct uio auio;
943 struct iovec aiov;
944 char *tmpbuf;
945 int error;
946 struct proc *p = curproc;
947
948 vnd->sc_cred = crdup(cred);
949 tmpbuf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK);
950
951
952 aiov.iov_base = tmpbuf;
953 aiov.iov_len = MIN(DEV_BSIZE, dbtob((off_t)vnd->sc_size));
954 auio.uio_iov = &aiov;
955 auio.uio_iovcnt = 1;
956 auio.uio_offset = 0;
957 auio.uio_rw = UIO_READ;
958 auio.uio_segflg = UIO_SYSSPACE;
959 auio.uio_resid = aiov.iov_len;
960 vn_lock(vnd->sc_vp, LK_RETRY | LK_EXCLUSIVE, p);
961 error = VOP_READ(vnd->sc_vp, &auio, 0, vnd->sc_cred);
962 VOP_UNLOCK(vnd->sc_vp, 0, p);
963
964 free(tmpbuf, M_TEMP);
965 return (error);
966 }
967
968 void
969 vndshutdown(void)
970 {
971 struct vnd_softc *vnd;
972
973 for (vnd = &vnd_softc[0]; vnd < &vnd_softc[numvnd]; vnd++)
974 if (vnd->sc_flags & VNF_INITED)
975 vndclear(vnd);
976 }
977
978 void
979 vndclear(struct vnd_softc *vnd)
980 {
981 struct vnode *vp = vnd->sc_vp;
982 struct proc *p = curproc;
983
984 DNPRINTF(VDB_FOLLOW, "vndclear(%p): vp %p\n", vnd, vp);
985
986 vnd->sc_flags &= ~VNF_INITED;
987 if (vp == NULL)
988 panic("vndioctl: null vp");
989 (void) vn_close(vp, VNDRW(vnd), vnd->sc_cred, p);
990 crfree(vnd->sc_cred);
991 vnd->sc_vp = NULL;
992 vnd->sc_cred = NULL;
993 vnd->sc_size = 0;
994 }
995
996 daddr64_t
997 vndsize(dev_t dev)
998 {
999 int unit = vndunit(dev);
1000 struct vnd_softc *vnd = &vnd_softc[unit];
1001
1002 if (unit >= numvnd || (vnd->sc_flags & VNF_INITED) == 0)
1003 return (-1);
1004 return (vnd->sc_size);
1005 }
1006
1007 int
1008 vnddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
1009 {
1010
1011
1012 return (ENXIO);
1013 }