]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/md/md.c
Start each of the license/copyright comments with /*-, minor shuffle of lines
[FreeBSD/FreeBSD.git] / sys / dev / md / md.c
1 /*-
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  *
9  * $FreeBSD$
10  *
11  */
12
13 /*-
14  * The following functions are based in the vn(4) driver: mdstart_swap(),
15  * mdstart_vnode(), mdcreate_swap(), mdcreate_vnode() and mddestroy(),
16  * and as such under the following copyright:
17  *
18  * Copyright (c) 1988 University of Utah.
19  * Copyright (c) 1990, 1993
20  *      The Regents of the University of California.  All rights reserved.
21  *
22  * This code is derived from software contributed to Berkeley by
23  * the Systems Programming Group of the University of Utah Computer
24  * Science Department.
25  *
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted provided that the following conditions
28  * are met:
29  * 1. Redistributions of source code must retain the above copyright
30  *    notice, this list of conditions and the following disclaimer.
31  * 2. Redistributions in binary form must reproduce the above copyright
32  *    notice, this list of conditions and the following disclaimer in the
33  *    documentation and/or other materials provided with the distribution.
34  * 4. Neither the name of the University nor the names of its contributors
35  *    may be used to endorse or promote products derived from this software
36  *    without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
39  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
42  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  *
50  * from: Utah Hdr: vn.c 1.13 94/04/02
51  *
52  *      from: @(#)vn.c  8.6 (Berkeley) 4/1/94
53  * From: src/sys/dev/vn/vn.c,v 1.122 2000/12/16 16:06:03
54  */
55
56 #include "opt_geom.h"
57 #include "opt_md.h"
58
59 #include <sys/param.h>
60 #include <sys/systm.h>
61 #include <sys/bio.h>
62 #include <sys/conf.h>
63 #include <sys/fcntl.h>
64 #include <sys/kernel.h>
65 #include <sys/kthread.h>
66 #include <sys/linker.h>
67 #include <sys/lock.h>
68 #include <sys/malloc.h>
69 #include <sys/mdioctl.h>
70 #include <sys/mutex.h>
71 #include <sys/namei.h>
72 #include <sys/proc.h>
73 #include <sys/queue.h>
74 #include <sys/sched.h>
75 #include <sys/sf_buf.h>
76 #include <sys/sysctl.h>
77 #include <sys/vnode.h>
78
79 #include <geom/geom.h>
80
81 #include <vm/vm.h>
82 #include <vm/vm_object.h>
83 #include <vm/vm_page.h>
84 #include <vm/vm_pager.h>
85 #include <vm/swap_pager.h>
86 #include <vm/uma.h>
87
88 #define MD_MODVER 1
89
90 #define MD_SHUTDOWN 0x10000     /* Tell worker thread to terminate. */
91
92 #ifndef MD_NSECT
93 #define MD_NSECT (10000 * 2)
94 #endif
95
96 static MALLOC_DEFINE(M_MD, "MD disk", "Memory Disk");
97 static MALLOC_DEFINE(M_MDSECT, "MD sectors", "Memory Disk Sectors");
98
99 static int md_debug;
100 SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, "");
101
102 #if defined(MD_ROOT) && defined(MD_ROOT_SIZE)
103 /* Image gets put here: */
104 static u_char mfs_root[MD_ROOT_SIZE*1024] = "MFS Filesystem goes here";
105 static u_char end_mfs_root[] __unused = "MFS Filesystem had better STOP here";
106 #endif
107
108 static g_init_t g_md_init;
109 static g_fini_t g_md_fini;
110 static g_start_t g_md_start;
111 static g_access_t g_md_access;
112
113 static int      mdunits;
114 static struct cdev *status_dev = 0;
115
116 static d_ioctl_t mdctlioctl;
117
118 static struct cdevsw mdctl_cdevsw = {
119         .d_version =    D_VERSION,
120         .d_flags =      D_NEEDGIANT,
121         .d_ioctl =      mdctlioctl,
122         .d_name =       MD_NAME,
123 };
124
125 struct g_class g_md_class = {
126         .name = "MD",
127         .version = G_VERSION,
128         .init = g_md_init,
129         .fini = g_md_fini,
130         .start = g_md_start,
131         .access = g_md_access,
132 };
133
134 DECLARE_GEOM_CLASS(g_md_class, g_md);
135
136
137 static LIST_HEAD(, md_s) md_softc_list = LIST_HEAD_INITIALIZER(&md_softc_list);
138
139 #define NINDIR  (PAGE_SIZE / sizeof(uintptr_t))
140 #define NMASK   (NINDIR-1)
141 static int nshift;
142
143 struct indir {
144         uintptr_t       *array;
145         u_int           total;
146         u_int           used;
147         u_int           shift;
148 };
149
150 struct md_s {
151         int unit;
152         LIST_ENTRY(md_s) list;
153         struct bio_queue_head bio_queue;
154         struct mtx queue_mtx;
155         struct cdev *dev;
156         enum md_types type;
157         off_t mediasize;
158         unsigned sectorsize;
159         unsigned opencount;
160         unsigned fwheads;
161         unsigned fwsectors;
162         unsigned flags;
163         char name[20];
164         struct proc *procp;
165         struct g_geom *gp;
166         struct g_provider *pp;
167
168         /* MD_MALLOC related fields */
169         struct indir *indir;
170         uma_zone_t uma;
171
172         /* MD_PRELOAD related fields */
173         u_char *pl_ptr;
174         size_t pl_len;
175
176         /* MD_VNODE related fields */
177         struct vnode *vnode;
178         char file[PATH_MAX];
179         struct ucred *cred;
180
181         /* MD_SWAP related fields */
182         vm_object_t object;
183 };
184
185 static int mddestroy(struct md_s *sc, struct thread *td);
186
187 static struct indir *
188 new_indir(u_int shift)
189 {
190         struct indir *ip;
191
192         ip = malloc(sizeof *ip, M_MD, M_NOWAIT | M_ZERO);
193         if (ip == NULL)
194                 return (NULL);
195         ip->array = malloc(sizeof(uintptr_t) * NINDIR,
196             M_MDSECT, M_NOWAIT | M_ZERO);
197         if (ip->array == NULL) {
198                 free(ip, M_MD);
199                 return (NULL);
200         }
201         ip->total = NINDIR;
202         ip->shift = shift;
203         return (ip);
204 }
205
206 static void
207 del_indir(struct indir *ip)
208 {
209
210         free(ip->array, M_MDSECT);
211         free(ip, M_MD);
212 }
213
214 static void
215 destroy_indir(struct md_s *sc, struct indir *ip)
216 {
217         int i;
218
219         for (i = 0; i < NINDIR; i++) {
220                 if (!ip->array[i])
221                         continue;
222                 if (ip->shift)
223                         destroy_indir(sc, (struct indir*)(ip->array[i]));
224                 else if (ip->array[i] > 255)
225                         uma_zfree(sc->uma, (void *)(ip->array[i]));
226         }
227         del_indir(ip);
228 }
229
230 /*
231  * This function does the math and alloctes the top level "indir" structure
232  * for a device of "size" sectors.
233  */
234
235 static struct indir *
236 dimension(off_t size)
237 {
238         off_t rcnt;
239         struct indir *ip;
240         int i, layer;
241
242         rcnt = size;
243         layer = 0;
244         while (rcnt > NINDIR) {
245                 rcnt /= NINDIR;
246                 layer++;
247         }
248         /* figure out log2(NINDIR) */
249         for (i = NINDIR, nshift = -1; i; nshift++)
250                 i >>= 1;
251
252         /*
253          * XXX: the top layer is probably not fully populated, so we allocate
254          * too much space for ip->array in here.
255          */
256         ip = malloc(sizeof *ip, M_MD, M_WAITOK | M_ZERO);
257         ip->array = malloc(sizeof(uintptr_t) * NINDIR,
258             M_MDSECT, M_WAITOK | M_ZERO);
259         ip->total = NINDIR;
260         ip->shift = layer * nshift;
261         return (ip);
262 }
263
264 /*
265  * Read a given sector
266  */
267
268 static uintptr_t
269 s_read(struct indir *ip, off_t offset)
270 {
271         struct indir *cip;
272         int idx;
273         uintptr_t up;
274
275         if (md_debug > 1)
276                 printf("s_read(%jd)\n", (intmax_t)offset);
277         up = 0;
278         for (cip = ip; cip != NULL;) {
279                 if (cip->shift) {
280                         idx = (offset >> cip->shift) & NMASK;
281                         up = cip->array[idx];
282                         cip = (struct indir *)up;
283                         continue;
284                 }
285                 idx = offset & NMASK;
286                 return (cip->array[idx]);
287         }
288         return (0);
289 }
290
291 /*
292  * Write a given sector, prune the tree if the value is 0
293  */
294
295 static int
296 s_write(struct indir *ip, off_t offset, uintptr_t ptr)
297 {
298         struct indir *cip, *lip[10];
299         int idx, li;
300         uintptr_t up;
301
302         if (md_debug > 1)
303                 printf("s_write(%jd, %p)\n", (intmax_t)offset, (void *)ptr);
304         up = 0;
305         li = 0;
306         cip = ip;
307         for (;;) {
308                 lip[li++] = cip;
309                 if (cip->shift) {
310                         idx = (offset >> cip->shift) & NMASK;
311                         up = cip->array[idx];
312                         if (up != 0) {
313                                 cip = (struct indir *)up;
314                                 continue;
315                         }
316                         /* Allocate branch */
317                         cip->array[idx] =
318                             (uintptr_t)new_indir(cip->shift - nshift);
319                         if (cip->array[idx] == 0)
320                                 return (ENOSPC);
321                         cip->used++;
322                         up = cip->array[idx];
323                         cip = (struct indir *)up;
324                         continue;
325                 }
326                 /* leafnode */
327                 idx = offset & NMASK;
328                 up = cip->array[idx];
329                 if (up != 0)
330                         cip->used--;
331                 cip->array[idx] = ptr;
332                 if (ptr != 0)
333                         cip->used++;
334                 break;
335         }
336         if (cip->used != 0 || li == 1)
337                 return (0);
338         li--;
339         while (cip->used == 0 && cip != ip) {
340                 li--;
341                 idx = (offset >> lip[li]->shift) & NMASK;
342                 up = lip[li]->array[idx];
343                 KASSERT(up == (uintptr_t)cip, ("md screwed up"));
344                 del_indir(cip);
345                 lip[li]->array[idx] = 0;
346                 lip[li]->used--;
347                 cip = lip[li];
348         }
349         return (0);
350 }
351
352
353 static int
354 g_md_access(struct g_provider *pp, int r, int w, int e)
355 {
356         struct md_s *sc;
357
358         sc = pp->geom->softc;
359         if (sc == NULL)
360                 return (ENXIO);
361         r += pp->acr;
362         w += pp->acw;
363         e += pp->ace;
364         if ((pp->acr + pp->acw + pp->ace) == 0 && (r + w + e) > 0) {
365                 sc->opencount = 1;
366         } else if ((pp->acr + pp->acw + pp->ace) > 0 && (r + w + e) == 0) {
367                 sc->opencount = 0;
368         }
369         return (0);
370 }
371
372 static void
373 g_md_start(struct bio *bp)
374 {
375         struct md_s *sc;
376
377         sc = bp->bio_to->geom->softc;
378         mtx_lock(&sc->queue_mtx);
379         bioq_disksort(&sc->bio_queue, bp);
380         mtx_unlock(&sc->queue_mtx);
381         wakeup(sc);
382 }
383
384
385
386 static int
387 mdstart_malloc(struct md_s *sc, struct bio *bp)
388 {
389         int i, error;
390         u_char *dst;
391         off_t secno, nsec, uc;
392         uintptr_t sp, osp;
393
394         nsec = bp->bio_length / sc->sectorsize;
395         secno = bp->bio_offset / sc->sectorsize;
396         dst = bp->bio_data;
397         error = 0;
398         while (nsec--) {
399                 osp = s_read(sc->indir, secno);
400                 if (bp->bio_cmd == BIO_DELETE) {
401                         if (osp != 0)
402                                 error = s_write(sc->indir, secno, 0);
403                 } else if (bp->bio_cmd == BIO_READ) {
404                         if (osp == 0)
405                                 bzero(dst, sc->sectorsize);
406                         else if (osp <= 255)
407                                 for (i = 0; i < sc->sectorsize; i++)
408                                         dst[i] = osp;
409                         else
410                                 bcopy((void *)osp, dst, sc->sectorsize);
411                         osp = 0;
412                 } else if (bp->bio_cmd == BIO_WRITE) {
413                         if (sc->flags & MD_COMPRESS) {
414                                 uc = dst[0];
415                                 for (i = 1; i < sc->sectorsize; i++)
416                                         if (dst[i] != uc)
417                                                 break;
418                         } else {
419                                 i = 0;
420                                 uc = 0;
421                         }
422                         if (i == sc->sectorsize) {
423                                 if (osp != uc)
424                                         error = s_write(sc->indir, secno, uc);
425                         } else {
426                                 if (osp <= 255) {
427                                         sp = (uintptr_t)uma_zalloc(sc->uma,
428                                             M_NOWAIT);
429                                         if (sp == 0) {
430                                                 error = ENOSPC;
431                                                 break;
432                                         }
433                                         bcopy(dst, (void *)sp, sc->sectorsize);
434                                         error = s_write(sc->indir, secno, sp);
435                                 } else {
436                                         bcopy(dst, (void *)osp, sc->sectorsize);
437                                         osp = 0;
438                                 }
439                         }
440                 } else {
441                         error = EOPNOTSUPP;
442                 }
443                 if (osp > 255)
444                         uma_zfree(sc->uma, (void*)osp);
445                 if (error != 0)
446                         break;
447                 secno++;
448                 dst += sc->sectorsize;
449         }
450         bp->bio_resid = 0;
451         return (error);
452 }
453
454 static int
455 mdstart_preload(struct md_s *sc, struct bio *bp)
456 {
457
458         switch (bp->bio_cmd) {
459         case BIO_READ:
460                 bcopy(sc->pl_ptr + bp->bio_offset, bp->bio_data,
461                     bp->bio_length);
462                 break;
463         case BIO_WRITE:
464                 bcopy(bp->bio_data, sc->pl_ptr + bp->bio_offset,
465                     bp->bio_length);
466                 break;
467         }
468         bp->bio_resid = 0;
469         return (0);
470 }
471
472 static int
473 mdstart_vnode(struct md_s *sc, struct bio *bp)
474 {
475         int error;
476         struct uio auio;
477         struct iovec aiov;
478         struct mount *mp;
479
480         /*
481          * VNODE I/O
482          *
483          * If an error occurs, we set BIO_ERROR but we do not set
484          * B_INVAL because (for a write anyway), the buffer is
485          * still valid.
486          */
487
488         bzero(&auio, sizeof(auio));
489
490         aiov.iov_base = bp->bio_data;
491         aiov.iov_len = bp->bio_length;
492         auio.uio_iov = &aiov;
493         auio.uio_iovcnt = 1;
494         auio.uio_offset = (vm_ooffset_t)bp->bio_offset;
495         auio.uio_segflg = UIO_SYSSPACE;
496         if(bp->bio_cmd == BIO_READ)
497                 auio.uio_rw = UIO_READ;
498         else if(bp->bio_cmd == BIO_WRITE)
499                 auio.uio_rw = UIO_WRITE;
500         else
501                 panic("wrong BIO_OP in mdstart_vnode");
502         auio.uio_resid = bp->bio_length;
503         auio.uio_td = curthread;
504         /*
505          * When reading set IO_DIRECT to try to avoid double-caching
506          * the data.  When writing IO_DIRECT is not optimal.
507          */
508         if (bp->bio_cmd == BIO_READ) {
509                 vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY, curthread);
510                 error = VOP_READ(sc->vnode, &auio, IO_DIRECT, sc->cred);
511                 VOP_UNLOCK(sc->vnode, 0, curthread);
512         } else {
513                 (void) vn_start_write(sc->vnode, &mp, V_WAIT);
514                 vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY, curthread);
515                 error = VOP_WRITE(sc->vnode, &auio,
516                     sc->flags & MD_ASYNC ? 0 : IO_SYNC, sc->cred);
517                 VOP_UNLOCK(sc->vnode, 0, curthread);
518                 vn_finished_write(mp);
519         }
520         bp->bio_resid = auio.uio_resid;
521         return (error);
522 }
523
524 static int
525 mdstart_swap(struct md_s *sc, struct bio *bp)
526 {
527         struct sf_buf *sf;
528         int rv, offs, len, lastend;
529         vm_pindex_t i, lastp;
530         vm_page_t m;
531         u_char *p;
532
533         p = bp->bio_data;
534
535         /*
536          * offs is the ofset at whih to start operating on the
537          * next (ie, first) page.  lastp is the last page on
538          * which we're going to operate.  lastend is the ending
539          * position within that last page (ie, PAGE_SIZE if
540          * we're operating on complete aligned pages).
541          */
542         offs = bp->bio_offset % PAGE_SIZE;
543         lastp = (bp->bio_offset + bp->bio_length - 1) / PAGE_SIZE;
544         lastend = (bp->bio_offset + bp->bio_length - 1) % PAGE_SIZE + 1;
545
546         rv = VM_PAGER_OK;
547         VM_OBJECT_LOCK(sc->object);
548         vm_object_pip_add(sc->object, 1);
549         for (i = bp->bio_offset / PAGE_SIZE; i <= lastp; i++) {
550                 len = ((i == lastp) ? lastend : PAGE_SIZE) - offs;
551
552                 m = vm_page_grab(sc->object, i,
553                     VM_ALLOC_NORMAL|VM_ALLOC_RETRY);
554                 VM_OBJECT_UNLOCK(sc->object);
555                 sf = sf_buf_alloc(m, 0);
556                 VM_OBJECT_LOCK(sc->object);
557                 if (bp->bio_cmd == BIO_READ) {
558                         if (m->valid != VM_PAGE_BITS_ALL)
559                                 rv = vm_pager_get_pages(sc->object, &m, 1, 0);
560                         if (rv == VM_PAGER_ERROR) {
561                                 sf_buf_free(sf);
562                                 vm_page_lock_queues();
563                                 vm_page_wakeup(m);
564                                 vm_page_unlock_queues();
565                                 break;
566                         }
567                         bcopy((void *)(sf_buf_kva(sf) + offs), p, len);
568                 } else if (bp->bio_cmd == BIO_WRITE) {
569                         if (len != PAGE_SIZE && m->valid != VM_PAGE_BITS_ALL)
570                                 rv = vm_pager_get_pages(sc->object, &m, 1, 0);
571                         if (rv == VM_PAGER_ERROR) {
572                                 sf_buf_free(sf);
573                                 vm_page_lock_queues();
574                                 vm_page_wakeup(m);
575                                 vm_page_unlock_queues();
576                                 break;
577                         }
578                         bcopy(p, (void *)(sf_buf_kva(sf) + offs), len);
579                         m->valid = VM_PAGE_BITS_ALL;
580 #if 0
581                 } else if (bp->bio_cmd == BIO_DELETE) {
582                         if (len != PAGE_SIZE && m->valid != VM_PAGE_BITS_ALL)
583                                 rv = vm_pager_get_pages(sc->object, &m, 1, 0);
584                         if (rv == VM_PAGER_ERROR) {
585                                 sf_buf_free(sf);
586                                 vm_page_lock_queues();
587                                 vm_page_wakeup(m);
588                                 vm_page_unlock_queues();
589                                 break;
590                         }
591                         bzero((void *)(sf_buf_kva(sf) + offs), len);
592                         vm_page_dirty(m);
593                         m->valid = VM_PAGE_BITS_ALL;
594 #endif
595                 }
596                 sf_buf_free(sf);
597                 vm_page_lock_queues();
598                 vm_page_wakeup(m);
599                 vm_page_activate(m);
600                 if (bp->bio_cmd == BIO_WRITE)
601                         vm_page_dirty(m);
602                 vm_page_unlock_queues();
603
604                 /* Actions on further pages start at offset 0 */
605                 p += PAGE_SIZE - offs;
606                 offs = 0;
607 #if 0
608 if (bootverbose || bp->bio_offset / PAGE_SIZE < 17)
609 printf("wire_count %d busy %d flags %x hold_count %d act_count %d queue %d valid %d dirty %d @ %d\n",
610     m->wire_count, m->busy, 
611     m->flags, m->hold_count, m->act_count, m->queue, m->valid, m->dirty, i);
612 #endif
613         }
614         vm_object_pip_subtract(sc->object, 1);
615         vm_object_set_writeable_dirty(sc->object);
616         VM_OBJECT_UNLOCK(sc->object);
617         return (rv != VM_PAGER_ERROR ? 0 : ENOSPC);
618 }
619
620 static void
621 md_kthread(void *arg)
622 {
623         struct md_s *sc;
624         struct bio *bp;
625         int error, hasgiant;
626
627         sc = arg;
628         mtx_lock_spin(&sched_lock);
629         sched_prio(curthread, PRIBIO);
630         mtx_unlock_spin(&sched_lock);
631
632         switch (sc->type) {
633         case MD_VNODE:
634                 mtx_lock(&Giant);
635                 hasgiant = 1;
636                 break;
637         case MD_MALLOC:
638         case MD_PRELOAD:
639         case MD_SWAP:
640         default:
641                 hasgiant = 0;
642                 break;
643         }
644         
645         for (;;) {
646                 mtx_lock(&sc->queue_mtx);
647                 bp = bioq_takefirst(&sc->bio_queue);
648                 if (!bp) {
649                         if (sc->flags & MD_SHUTDOWN) {
650                                 mtx_unlock(&sc->queue_mtx);
651                                 sc->procp = NULL;
652                                 wakeup(&sc->procp);
653                                 if (hasgiant)
654                                         mtx_unlock(&Giant);
655                                 kthread_exit(0);
656                         }
657                         msleep(sc, &sc->queue_mtx, PRIBIO | PDROP, "mdwait", 0);
658                         continue;
659                 }
660                 mtx_unlock(&sc->queue_mtx);
661                 if (bp->bio_cmd == BIO_GETATTR) {
662                         if (sc->fwsectors && sc->fwheads &&
663                             (g_handleattr_int(bp, "GEOM::fwsectors",
664                             sc->fwsectors) ||
665                             g_handleattr_int(bp, "GEOM::fwheads",
666                             sc->fwheads)))
667                                 error = -1;
668                         else
669                                 error = EOPNOTSUPP;
670                 } else {
671                         switch (sc->type) {
672                         case MD_MALLOC:
673                                 error = mdstart_malloc(sc, bp);
674                                 break;
675                         case MD_PRELOAD:
676                                 error = mdstart_preload(sc, bp);
677                                 break;
678                         case MD_VNODE:
679                                 error = mdstart_vnode(sc, bp);
680                                 break;
681                         case MD_SWAP:
682                                 error = mdstart_swap(sc, bp);
683                                 break;
684                         default:
685                                 panic("Impossible md(type)");
686                                 break;
687                         }
688                 }
689
690                 if (error != -1) {
691                         bp->bio_completed = bp->bio_length;
692                         g_io_deliver(bp, error);
693                 }
694         }
695 }
696
697 static struct md_s *
698 mdfind(int unit)
699 {
700         struct md_s *sc;
701
702         /* XXX: LOCK(unique unit numbers) */
703         LIST_FOREACH(sc, &md_softc_list, list) {
704                 if (sc->unit == unit)
705                         break;
706         }
707         /* XXX: UNLOCK(unique unit numbers) */
708         return (sc);
709 }
710
711 static struct md_s *
712 mdnew(int unit)
713 {
714         struct md_s *sc;
715         int error, max = -1;
716
717         /* XXX: LOCK(unique unit numbers) */
718         LIST_FOREACH(sc, &md_softc_list, list) {
719                 if (sc->unit == unit) {
720                         /* XXX: UNLOCK(unique unit numbers) */
721                         return (NULL);
722                 }
723                 if (sc->unit > max)
724                         max = sc->unit;
725         }
726         if (unit == -1)
727                 unit = max + 1;
728         sc = (struct md_s *)malloc(sizeof *sc, M_MD, M_WAITOK | M_ZERO);
729         sc->unit = unit;
730         bioq_init(&sc->bio_queue);
731         mtx_init(&sc->queue_mtx, "md bio queue", NULL, MTX_DEF);
732         sprintf(sc->name, "md%d", unit);
733         error = kthread_create(md_kthread, sc, &sc->procp, 0, 0,"%s", sc->name);
734         if (error != 0) {
735                 free(sc, M_MD);
736                 return (NULL);
737         }
738         LIST_INSERT_HEAD(&md_softc_list, sc, list);
739         /* XXX: UNLOCK(unique unit numbers) */
740         return (sc);
741 }
742
743 static void
744 mdinit(struct md_s *sc)
745 {
746
747         struct g_geom *gp;
748         struct g_provider *pp;
749
750         DROP_GIANT();
751         g_topology_lock();
752         gp = g_new_geomf(&g_md_class, "md%d", sc->unit);
753         gp->softc = sc;
754         pp = g_new_providerf(gp, "md%d", sc->unit);
755         pp->mediasize = sc->mediasize;
756         pp->sectorsize = sc->sectorsize;
757         sc->gp = gp;
758         sc->pp = pp;
759         g_error_provider(pp, 0);
760         g_topology_unlock();
761         PICKUP_GIANT();
762 }
763
764 /*
765  * XXX: we should check that the range they feed us is mapped.
766  * XXX: we should implement read-only.
767  */
768
769 static int
770 mdcreate_preload(struct md_s *sc, struct md_ioctl *mdio)
771 {
772
773         if (mdio->md_options & ~(MD_AUTOUNIT | MD_FORCE))
774                 return (EINVAL);
775         sc->flags = mdio->md_options & MD_FORCE;
776         /* Cast to pointer size, then to pointer to avoid warning */
777         sc->pl_ptr = (u_char *)(uintptr_t)mdio->md_base;
778         sc->pl_len = (size_t)sc->mediasize;
779         return (0);
780 }
781
782
783 static int
784 mdcreate_malloc(struct md_s *sc, struct md_ioctl *mdio)
785 {
786         uintptr_t sp;
787         int error;
788         off_t u;
789
790         error = 0;
791         if (mdio->md_options & ~(MD_AUTOUNIT | MD_COMPRESS | MD_RESERVE))
792                 return (EINVAL);
793         if (mdio->md_sectorsize != 0 && !powerof2(mdio->md_sectorsize))
794                 return (EINVAL);
795         /* Compression doesn't make sense if we have reserved space */
796         if (mdio->md_options & MD_RESERVE)
797                 mdio->md_options &= ~MD_COMPRESS;
798         if (mdio->md_fwsectors != 0)
799                 sc->fwsectors = mdio->md_fwsectors;
800         if (mdio->md_fwheads != 0)
801                 sc->fwheads = mdio->md_fwheads;
802         sc->flags = mdio->md_options & (MD_COMPRESS | MD_FORCE);
803         sc->indir = dimension(sc->mediasize / sc->sectorsize);
804         sc->uma = uma_zcreate(sc->name, sc->sectorsize, NULL, NULL, NULL, NULL,
805             0x1ff, 0);
806         if (mdio->md_options & MD_RESERVE) {
807                 off_t nsectors;
808
809                 nsectors = sc->mediasize / sc->sectorsize;
810                 for (u = 0; u < nsectors; u++) {
811                         sp = (uintptr_t)uma_zalloc(sc->uma, M_NOWAIT | M_ZERO);
812                         if (sp != 0)
813                                 error = s_write(sc->indir, u, sp);
814                         else
815                                 error = ENOMEM;
816                         if (error != 0)
817                                 break;
818                 }
819         }
820         if (error != 0)
821                 uma_zdestroy(sc->uma);
822         return (error);
823 }
824
825
826 static int
827 mdsetcred(struct md_s *sc, struct ucred *cred)
828 {
829         char *tmpbuf;
830         int error = 0;
831
832         /*
833          * Set credits in our softc
834          */
835
836         if (sc->cred)
837                 crfree(sc->cred);
838         sc->cred = crhold(cred);
839
840         /*
841          * Horrible kludge to establish credentials for NFS  XXX.
842          */
843
844         if (sc->vnode) {
845                 struct uio auio;
846                 struct iovec aiov;
847
848                 tmpbuf = malloc(sc->sectorsize, M_TEMP, M_WAITOK);
849                 bzero(&auio, sizeof(auio));
850
851                 aiov.iov_base = tmpbuf;
852                 aiov.iov_len = sc->sectorsize;
853                 auio.uio_iov = &aiov;
854                 auio.uio_iovcnt = 1;
855                 auio.uio_offset = 0;
856                 auio.uio_rw = UIO_READ;
857                 auio.uio_segflg = UIO_SYSSPACE;
858                 auio.uio_resid = aiov.iov_len;
859                 vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY, curthread);
860                 error = VOP_READ(sc->vnode, &auio, 0, sc->cred);
861                 VOP_UNLOCK(sc->vnode, 0, curthread);
862                 free(tmpbuf, M_TEMP);
863         }
864         return (error);
865 }
866
867 static int
868 mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
869 {
870         struct vattr vattr;
871         struct nameidata nd;
872         int error, flags;
873
874         error = copyinstr(mdio->md_file, sc->file, sizeof(sc->file), NULL);
875         if (error != 0)
876                 return (error);
877         flags = FREAD|FWRITE;
878         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, sc->file, td);
879         error = vn_open(&nd, &flags, 0, -1);
880         if (error != 0) {
881                 NDFREE(&nd, NDF_ONLY_PNBUF);
882                 if (error != EACCES && error != EPERM && error != EROFS)
883                         return (error);
884                 flags &= ~FWRITE;
885                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, sc->file, td);
886                 error = vn_open(&nd, &flags, 0, -1);
887         }
888         NDFREE(&nd, NDF_ONLY_PNBUF);
889         if (error != 0)
890                 return (error);
891         if (nd.ni_vp->v_type != VREG ||
892             (error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred, td))) {
893                 VOP_UNLOCK(nd.ni_vp, 0, td);
894                 (void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
895                 return (error ? error : EINVAL);
896         }
897         VOP_UNLOCK(nd.ni_vp, 0, td);
898
899         if (mdio->md_fwsectors != 0)
900                 sc->fwsectors = mdio->md_fwsectors;
901         if (mdio->md_fwheads != 0)
902                 sc->fwheads = mdio->md_fwheads;
903         sc->flags = mdio->md_options & (MD_FORCE | MD_ASYNC);
904         if (!(flags & FWRITE))
905                 sc->flags |= MD_READONLY;
906         sc->vnode = nd.ni_vp;
907
908         error = mdsetcred(sc, td->td_ucred);
909         if (error != 0) {
910                 (void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
911                 return (error);
912         }
913         return (0);
914 }
915
916 static void
917 md_zapit(void *p, int cancel)
918 {
919         if (cancel)
920                 return;
921         g_wither_geom(p, ENXIO);
922 }
923
924 static int
925 mddestroy(struct md_s *sc, struct thread *td)
926 {
927
928         GIANT_REQUIRED;
929
930         mtx_destroy(&sc->queue_mtx);
931         if (sc->gp) {
932                 sc->gp->softc = NULL;
933                 g_waitfor_event(md_zapit, sc->gp, M_WAITOK, sc->gp, NULL);
934                 sc->gp = NULL;
935                 sc->pp = NULL;
936         }
937         sc->flags |= MD_SHUTDOWN;
938         wakeup(sc);
939         while (sc->procp != NULL)
940                 tsleep(&sc->procp, PRIBIO, "mddestroy", hz / 10);
941         if (sc->vnode != NULL)
942                 (void)vn_close(sc->vnode, sc->flags & MD_READONLY ?
943                     FREAD : (FREAD|FWRITE), sc->cred, td);
944         if (sc->cred != NULL)
945                 crfree(sc->cred);
946         if (sc->object != NULL) {
947                 vm_object_deallocate(sc->object);
948         }
949         if (sc->indir)
950                 destroy_indir(sc, sc->indir);
951         if (sc->uma)
952                 uma_zdestroy(sc->uma);
953
954         /* XXX: LOCK(unique unit numbers) */
955         LIST_REMOVE(sc, list);
956         /* XXX: UNLOCK(unique unit numbers) */
957         free(sc, M_MD);
958         return (0);
959 }
960
961 static int
962 mdcreate_swap(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
963 {
964         vm_ooffset_t npage;
965         int error;
966
967         GIANT_REQUIRED;
968
969         /*
970          * Range check.  Disallow negative sizes or any size less then the
971          * size of a page.  Then round to a page.
972          */
973         if (sc->mediasize == 0 || (sc->mediasize % PAGE_SIZE) != 0)
974                 return (EDOM);
975
976         /*
977          * Allocate an OBJT_SWAP object.
978          *
979          * Note the truncation.
980          */
981
982         npage = mdio->md_mediasize / PAGE_SIZE;
983         if (mdio->md_fwsectors != 0)
984                 sc->fwsectors = mdio->md_fwsectors;
985         if (mdio->md_fwheads != 0)
986                 sc->fwheads = mdio->md_fwheads;
987         sc->object = vm_pager_allocate(OBJT_SWAP, NULL, PAGE_SIZE * npage,
988             VM_PROT_DEFAULT, 0);
989         if (sc->object == NULL)
990                 return (ENOMEM);
991         sc->flags = mdio->md_options & MD_FORCE;
992         if (mdio->md_options & MD_RESERVE) {
993                 if (swap_pager_reserve(sc->object, 0, npage) < 0) {
994                         vm_object_deallocate(sc->object);
995                         sc->object = NULL;
996                         return (EDOM);
997                 }
998         }
999         error = mdsetcred(sc, td->td_ucred);
1000         if (error != 0) {
1001                 vm_object_deallocate(sc->object);
1002                 sc->object = NULL;
1003         }
1004         return (error);
1005 }
1006
1007 static int
1008 mddetach(int unit, struct thread *td)
1009 {
1010         struct md_s *sc;
1011
1012         sc = mdfind(unit);
1013         if (sc == NULL)
1014                 return (ENOENT);
1015         if (sc->opencount != 0 && !(sc->flags & MD_FORCE))
1016                 return (EBUSY);
1017         switch(sc->type) {
1018         case MD_VNODE:
1019         case MD_SWAP:
1020         case MD_MALLOC:
1021         case MD_PRELOAD:
1022                 return (mddestroy(sc, td));
1023         default:
1024                 return (EOPNOTSUPP);
1025         }
1026 }
1027
1028 static int
1029 mdctlioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
1030 {
1031         struct md_ioctl *mdio;
1032         struct md_s *sc;
1033         int error, i;
1034
1035         if (md_debug)
1036                 printf("mdctlioctl(%s %lx %p %x %p)\n",
1037                         devtoname(dev), cmd, addr, flags, td);
1038
1039         /*
1040          * We assert the version number in the individual ioctl
1041          * handlers instead of out here because (a) it is possible we
1042          * may add another ioctl in the future which doesn't read an
1043          * mdio, and (b) the correct return value for an unknown ioctl
1044          * is ENOIOCTL, not EINVAL.
1045          */
1046         mdio = (struct md_ioctl *)addr;
1047         switch (cmd) {
1048         case MDIOCATTACH:
1049                 if (mdio->md_version != MDIOVERSION)
1050                         return (EINVAL);
1051                 switch (mdio->md_type) {
1052                 case MD_MALLOC:
1053                 case MD_PRELOAD:
1054                 case MD_VNODE:
1055                 case MD_SWAP:
1056                         break;
1057                 default:
1058                         return (EINVAL);
1059                 }
1060                 if (mdio->md_options & MD_AUTOUNIT) {
1061                         sc = mdnew(-1);
1062                         mdio->md_unit = sc->unit;
1063                 } else {
1064                         sc = mdnew(mdio->md_unit);
1065                         if (sc == NULL)
1066                                 return (EBUSY);
1067                 }
1068                 sc->type = mdio->md_type;
1069                 sc->mediasize = mdio->md_mediasize;
1070                 if (mdio->md_sectorsize == 0)
1071                         sc->sectorsize = DEV_BSIZE;
1072                 else
1073                         sc->sectorsize = mdio->md_sectorsize;
1074                 error = EDOOFUS;
1075                 switch (sc->type) {
1076                 case MD_MALLOC:
1077                         error = mdcreate_malloc(sc, mdio);
1078                         break;
1079                 case MD_PRELOAD:
1080                         error = mdcreate_preload(sc, mdio);
1081                         break;
1082                 case MD_VNODE:
1083                         error = mdcreate_vnode(sc, mdio, td);
1084                         break;
1085                 case MD_SWAP:
1086                         error = mdcreate_swap(sc, mdio, td);
1087                         break;
1088                 }
1089                 if (error != 0) {
1090                         mddestroy(sc, td);
1091                         return (error);
1092                 }
1093                 mdinit(sc);
1094                 return (0);
1095         case MDIOCDETACH:
1096                 if (mdio->md_version != MDIOVERSION)
1097                         return (EINVAL);
1098                 if (mdio->md_mediasize != 0 || mdio->md_options != 0)
1099                         return (EINVAL);
1100                 return (mddetach(mdio->md_unit, td));
1101         case MDIOCQUERY:
1102                 if (mdio->md_version != MDIOVERSION)
1103                         return (EINVAL);
1104                 sc = mdfind(mdio->md_unit);
1105                 if (sc == NULL)
1106                         return (ENOENT);
1107                 mdio->md_type = sc->type;
1108                 mdio->md_options = sc->flags;
1109                 mdio->md_mediasize = sc->mediasize;
1110                 mdio->md_sectorsize = sc->sectorsize;
1111                 if (sc->type == MD_VNODE) {
1112                         error = copyout(sc->file, mdio->md_file,
1113                             strlen(sc->file) + 1);
1114                         if (error != 0)
1115                                 return (error);
1116                 }
1117                 return (0);
1118         case MDIOCLIST:
1119                 if (mdio->md_version != MDIOVERSION)
1120                         return (EINVAL);
1121                 i = 1;
1122                 LIST_FOREACH(sc, &md_softc_list, list) {
1123                         if (i == MDNPAD - 1)
1124                                 mdio->md_pad[i] = -1;
1125                         else
1126                                 mdio->md_pad[i++] = sc->unit;
1127                 }
1128                 mdio->md_pad[0] = i - 1;
1129                 return (0);
1130         default:
1131                 return (ENOIOCTL);
1132         };
1133         return (ENOIOCTL);
1134 }
1135
1136 static void
1137 md_preloaded(u_char *image, size_t length)
1138 {
1139         struct md_s *sc;
1140
1141         sc = mdnew(-1);
1142         if (sc == NULL)
1143                 return;
1144         sc->type = MD_PRELOAD;
1145         sc->mediasize = length;
1146         sc->sectorsize = DEV_BSIZE;
1147         sc->pl_ptr = image;
1148         sc->pl_len = length;
1149 #ifdef MD_ROOT
1150         if (sc->unit == 0)
1151                 rootdevnames[0] = "ufs:/dev/md0";
1152 #endif
1153         mdinit(sc);
1154 }
1155
1156 static void
1157 g_md_init(struct g_class *mp __unused)
1158 {
1159
1160         caddr_t mod;
1161         caddr_t c;
1162         u_char *ptr, *name, *type;
1163         unsigned len;
1164
1165         mod = NULL;
1166         g_topology_unlock();
1167 #ifdef MD_ROOT_SIZE
1168         md_preloaded(mfs_root, MD_ROOT_SIZE*1024);
1169 #endif
1170         while ((mod = preload_search_next_name(mod)) != NULL) {
1171                 name = (char *)preload_search_info(mod, MODINFO_NAME);
1172                 type = (char *)preload_search_info(mod, MODINFO_TYPE);
1173                 if (name == NULL)
1174                         continue;
1175                 if (type == NULL)
1176                         continue;
1177                 if (strcmp(type, "md_image") && strcmp(type, "mfs_root"))
1178                         continue;
1179                 c = preload_search_info(mod, MODINFO_ADDR);
1180                 ptr = *(u_char **)c;
1181                 c = preload_search_info(mod, MODINFO_SIZE);
1182                 len = *(size_t *)c;
1183                 printf("%s%d: Preloaded image <%s> %d bytes at %p\n",
1184                     MD_NAME, mdunits, name, len, ptr);
1185                 md_preloaded(ptr, len);
1186         }
1187         status_dev = make_dev(&mdctl_cdevsw, 0xffff00ff, UID_ROOT, GID_WHEEL,
1188             0600, MDCTL_NAME);
1189         g_topology_lock();
1190 }
1191
1192 static void
1193 g_md_fini(struct g_class *mp __unused)
1194 {
1195
1196         if (status_dev != NULL)
1197                 destroy_dev(status_dev);
1198 }