| Commit | Line | Data |
|---|---|---|
| 984263bc MD |
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: src/sys/dev/md/md.c,v 1.8.2.2 2002/08/19 17:43:34 jdp Exp $ | |
| 10 | * | |
| 11 | */ | |
| 12 | ||
| 984263bc MD |
13 | #include "opt_md.h" /* We have adopted some tasks from MFS */ |
| 14 | ||
| 15 | #include <sys/param.h> | |
| 16 | #include <sys/systm.h> | |
| 17 | #include <sys/buf.h> | |
| 18 | #include <sys/conf.h> | |
| 19 | #include <sys/devicestat.h> | |
| 20 | #include <sys/disk.h> | |
| 21 | #include <sys/kernel.h> | |
| 22 | #include <sys/malloc.h> | |
| 23 | #include <sys/sysctl.h> | |
| 24 | #include <sys/linker.h> | |
| 3020e3be MD |
25 | #include <sys/proc.h> |
| 26 | #include <sys/buf2.h> | |
| fbe276c7 | 27 | #include <sys/thread2.h> |
| 89adea15 | 28 | #include <sys/queue.h> |
| f5d8307c | 29 | #include <sys/udev.h> |
| 984263bc MD |
30 | |
| 31 | #ifndef MD_NSECT | |
| 32 | #define MD_NSECT (10000 * 2) | |
| 33 | #endif | |
| 34 | ||
| 35 | MALLOC_DEFINE(M_MD, "MD disk", "Memory Disk"); | |
| 36 | MALLOC_DEFINE(M_MDSECT, "MD sectors", "Memory Disk Sectors"); | |
| 37 | ||
| 38 | static int md_debug; | |
| 0c52fa62 SG |
39 | SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, |
| 40 | "Enable debug output for memory disk devices"); | |
| 984263bc | 41 | |
| 984263bc MD |
42 | #if defined(MD_ROOT) && defined(MD_ROOT_SIZE) |
| 43 | /* Image gets put here: */ | |
| 44 | static u_char mfs_root[MD_ROOT_SIZE*1024] = "MFS Filesystem goes here"; | |
| 45 | static u_char end_mfs_root[] __unused = "MFS Filesystem had better STOP here"; | |
| 46 | #endif | |
| 47 | ||
| 48 | static int mdrootready; | |
| 49 | ||
| 984263bc MD |
50 | static d_strategy_t mdstrategy; |
| 51 | static d_strategy_t mdstrategy_preload; | |
| 52 | static d_strategy_t mdstrategy_malloc; | |
| 53 | static d_open_t mdopen; | |
| 89adea15 | 54 | static d_close_t mdclose; |
| 984263bc MD |
55 | static d_ioctl_t mdioctl; |
| 56 | ||
| fef8985e | 57 | static struct dev_ops md_ops = { |
| 88abd8b5 | 58 | { "md", 0, D_DISK | D_CANFREE | D_MEMDISK | D_TRACKCLOSE}, |
| fef8985e | 59 | .d_open = mdopen, |
| 89adea15 | 60 | .d_close = mdclose, |
| fef8985e MD |
61 | .d_read = physread, |
| 62 | .d_write = physwrite, | |
| 63 | .d_ioctl = mdioctl, | |
| 64 | .d_strategy = mdstrategy, | |
| 984263bc MD |
65 | }; |
| 66 | ||
| 984263bc MD |
67 | struct md_s { |
| 68 | int unit; | |
| 69 | struct devstat stats; | |
| 81b5c339 | 70 | struct bio_queue_head bio_queue; |
| 984263bc | 71 | struct disk disk; |
| b13267a5 | 72 | cdev_t dev; |
| 984263bc | 73 | int busy; |
| 89adea15 AHJ |
74 | enum { /* Memory disk type */ |
| 75 | MD_MALLOC, | |
| 76 | MD_PRELOAD | |
| 77 | } type; | |
| 984263bc MD |
78 | unsigned nsect; |
| 79 | ||
| 80 | /* MD_MALLOC related fields */ | |
| 81 | unsigned nsecp; | |
| 82 | u_char **secp; | |
| 83 | ||
| 84 | /* MD_PRELOAD related fields */ | |
| 85 | u_char *pl_ptr; | |
| 86 | unsigned pl_len; | |
| 89adea15 | 87 | TAILQ_ENTRY(md_s) link; |
| 984263bc | 88 | }; |
| 89adea15 | 89 | TAILQ_HEAD(mdshead, md_s) mdlist = TAILQ_HEAD_INITIALIZER(mdlist); |
| 984263bc MD |
90 | |
| 91 | static int mdunits; | |
| 89adea15 AHJ |
92 | static int refcnt; |
| 93 | ||
| 94 | static struct md_s *mdcreate(unsigned); | |
| 95 | static void mdcreate_malloc(void); | |
| 96 | static int mdinit(module_t, int, void *); | |
| 97 | static void md_drvinit(void *); | |
| 98 | static int md_drvcleanup(void); | |
| 99 | ||
| 100 | static int | |
| 101 | mdinit(module_t mod, int cmd, void *arg) | |
| 102 | { | |
| 103 | int ret = 0; | |
| 104 | ||
| 105 | switch(cmd) { | |
| 106 | case MOD_LOAD: | |
| 107 | TAILQ_INIT(&mdlist); | |
| 108 | md_drvinit(NULL); | |
| 109 | break; | |
| 110 | case MOD_UNLOAD: | |
| 111 | ret = md_drvcleanup(); | |
| 112 | break; | |
| 113 | default: | |
| 114 | ret = EINVAL; | |
| 115 | break; | |
| 116 | } | |
| 117 | ||
| 118 | return (ret); | |
| 119 | } | |
| 984263bc MD |
120 | |
| 121 | static int | |
| fef8985e | 122 | mdopen(struct dev_open_args *ap) |
| 984263bc | 123 | { |
| b13267a5 | 124 | cdev_t dev = ap->a_head.a_dev; |
| 984263bc | 125 | struct md_s *sc; |
| 984263bc MD |
126 | |
| 127 | if (md_debug) | |
| e3869ec7 | 128 | kprintf("mdopen(%s %x %x)\n", |
| fef8985e | 129 | devtoname(dev), ap->a_oflags, ap->a_devtype); |
| 984263bc MD |
130 | |
| 131 | sc = dev->si_drv1; | |
| 132 | if (sc->unit + 1 == mdunits) | |
| 133 | mdcreate_malloc(); | |
| a688b15c | 134 | |
| 89adea15 AHJ |
135 | atomic_add_int(&refcnt, 1); |
| 136 | return (0); | |
| 137 | } | |
| 138 | ||
| 139 | static int | |
| 140 | mdclose(struct dev_close_args *ap) | |
| 141 | { | |
| 142 | cdev_t dev = ap->a_head.a_dev; | |
| 143 | struct md_s *sc; | |
| 144 | ||
| 145 | if (md_debug) | |
| 146 | kprintf("mdclose(%s %x %x)\n", | |
| 147 | devtoname(dev), ap->a_fflag, ap->a_devtype); | |
| 148 | sc = dev->si_drv1; | |
| 149 | atomic_add_int(&refcnt, -1); | |
| 150 | ||
| 984263bc MD |
151 | return (0); |
| 152 | } | |
| 153 | ||
| 154 | static int | |
| fef8985e | 155 | mdioctl(struct dev_ioctl_args *ap) |
| 984263bc | 156 | { |
| b13267a5 | 157 | cdev_t dev = ap->a_head.a_dev; |
| 984263bc MD |
158 | |
| 159 | if (md_debug) | |
| e3869ec7 | 160 | kprintf("mdioctl(%s %lx %p %x)\n", |
| fef8985e | 161 | devtoname(dev), ap->a_cmd, ap->a_data, ap->a_fflag); |
| 984263bc MD |
162 | |
| 163 | return (ENOIOCTL); | |
| 164 | } | |
| 165 | ||
| fef8985e MD |
166 | static int |
| 167 | mdstrategy(struct dev_strategy_args *ap) | |
| 984263bc | 168 | { |
| b13267a5 | 169 | cdev_t dev = ap->a_head.a_dev; |
| fef8985e | 170 | struct bio *bio = ap->a_bio; |
| 81b5c339 | 171 | struct buf *bp = bio->bio_buf; |
| 984263bc MD |
172 | struct md_s *sc; |
| 173 | ||
| 81b5c339 | 174 | if (md_debug > 1) { |
| e3869ec7 | 175 | kprintf("mdstrategy(%p) %s %08x, %lld, %d, %p)\n", |
| 973c11b9 MD |
176 | bp, devtoname(dev), bp->b_flags, |
| 177 | (long long)bio->bio_offset, | |
| 54078292 | 178 | bp->b_bcount, bp->b_data); |
| 81b5c339 MD |
179 | } |
| 180 | bio->bio_driver_info = dev; | |
| 181 | sc = dev->si_drv1; | |
| 984263bc | 182 | if (sc->type == MD_MALLOC) { |
| fef8985e | 183 | mdstrategy_malloc(ap); |
| 984263bc | 184 | } else { |
| fef8985e | 185 | mdstrategy_preload(ap); |
| 984263bc | 186 | } |
| fef8985e | 187 | return(0); |
| 984263bc MD |
188 | } |
| 189 | ||
| 190 | ||
| fef8985e MD |
191 | static int |
| 192 | mdstrategy_malloc(struct dev_strategy_args *ap) | |
| 984263bc | 193 | { |
| b13267a5 | 194 | cdev_t dev = ap->a_head.a_dev; |
| fef8985e | 195 | struct bio *bio = ap->a_bio; |
| 81b5c339 | 196 | struct buf *bp = bio->bio_buf; |
| 984263bc | 197 | unsigned secno, nsec, secval, uc; |
| 81b5c339 | 198 | u_char *secp, **secpp, *dst; |
| 81b5c339 MD |
199 | struct md_s *sc; |
| 200 | int i; | |
| 984263bc MD |
201 | |
| 202 | if (md_debug > 1) | |
| e3869ec7 | 203 | kprintf("mdstrategy_malloc(%p) %s %08xx, %lld, %d, %p)\n", |
| 973c11b9 MD |
204 | bp, devtoname(dev), bp->b_flags, |
| 205 | (long long)bio->bio_offset, | |
| 54078292 | 206 | bp->b_bcount, bp->b_data); |
| 984263bc | 207 | |
| 81b5c339 | 208 | sc = dev->si_drv1; |
| 984263bc | 209 | |
| fbe276c7 | 210 | crit_enter(); |
| 984263bc | 211 | |
| 81b5c339 | 212 | bioqdisksort(&sc->bio_queue, bio); |
| 984263bc MD |
213 | |
| 214 | if (sc->busy) { | |
| fbe276c7 | 215 | crit_exit(); |
| fef8985e | 216 | return(0); |
| 984263bc MD |
217 | } |
| 218 | ||
| 219 | sc->busy++; | |
| 220 | ||
| 221 | while (1) { | |
| 81b5c339 | 222 | bio = bioq_first(&sc->bio_queue); |
| 31a163d2 MD |
223 | if (bio == NULL) { |
| 224 | crit_exit(); | |
| 984263bc | 225 | break; |
| 31a163d2 MD |
226 | } |
| 227 | crit_exit(); | |
| 228 | bioq_remove(&sc->bio_queue, bio); | |
| 229 | bp = bio->bio_buf; | |
| 984263bc MD |
230 | |
| 231 | devstat_start_transaction(&sc->stats); | |
| 232 | ||
| 8b6f36f5 | 233 | switch (bp->b_cmd) { |
| 10f3fee5 | 234 | case BUF_CMD_FREEBLKS: |
| 10f3fee5 | 235 | case BUF_CMD_READ: |
| 10f3fee5 | 236 | case BUF_CMD_WRITE: |
| 10f3fee5 MD |
237 | break; |
| 238 | default: | |
| 239 | panic("md: bad b_cmd %d", bp->b_cmd); | |
| 240 | } | |
| 984263bc | 241 | |
| 54078292 MD |
242 | nsec = bp->b_bcount >> DEV_BSHIFT; |
| 243 | secno = (unsigned)(bio->bio_offset >> DEV_BSHIFT); | |
| 984263bc MD |
244 | dst = bp->b_data; |
| 245 | while (nsec--) { | |
| 984263bc MD |
246 | if (secno < sc->nsecp) { |
| 247 | secpp = &sc->secp[secno]; | |
| 973c11b9 | 248 | if ((u_int)(uintptr_t)*secpp > 255) { |
| 984263bc MD |
249 | secp = *secpp; |
| 250 | secval = 0; | |
| 251 | } else { | |
| 252 | secp = 0; | |
| 973c11b9 | 253 | secval = (u_int)(uintptr_t)*secpp; |
| 984263bc MD |
254 | } |
| 255 | } else { | |
| 256 | secpp = 0; | |
| 257 | secp = 0; | |
| 258 | secval = 0; | |
| 259 | } | |
| 260 | if (md_debug > 2) | |
| e3869ec7 | 261 | kprintf("%08x %p %p %d\n", bp->b_flags, secpp, secp, secval); |
| 984263bc | 262 | |
| 8b6f36f5 | 263 | switch (bp->b_cmd) { |
| 10f3fee5 | 264 | case BUF_CMD_FREEBLKS: |
| 984263bc MD |
265 | if (secpp) { |
| 266 | if (secp) | |
| 267 | FREE(secp, M_MDSECT); | |
| 268 | *secpp = 0; | |
| 269 | } | |
| 10f3fee5 MD |
270 | break; |
| 271 | case BUF_CMD_READ: | |
| 984263bc MD |
272 | if (secp) { |
| 273 | bcopy(secp, dst, DEV_BSIZE); | |
| 274 | } else if (secval) { | |
| 275 | for (i = 0; i < DEV_BSIZE; i++) | |
| 276 | dst[i] = secval; | |
| 277 | } else { | |
| 278 | bzero(dst, DEV_BSIZE); | |
| 279 | } | |
| 10f3fee5 MD |
280 | break; |
| 281 | case BUF_CMD_WRITE: | |
| 984263bc MD |
282 | uc = dst[0]; |
| 283 | for (i = 1; i < DEV_BSIZE; i++) | |
| 284 | if (dst[i] != uc) | |
| 285 | break; | |
| 286 | if (i == DEV_BSIZE && !uc) { | |
| 287 | if (secp) | |
| 288 | FREE(secp, M_MDSECT); | |
| 289 | if (secpp) | |
| 973c11b9 | 290 | *secpp = (u_char *)(uintptr_t)uc; |
| 984263bc MD |
291 | } else { |
| 292 | if (!secpp) { | |
| e7b4468c | 293 | MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK | M_ZERO); |
| 984263bc MD |
294 | bcopy(sc->secp, secpp, sc->nsecp * sizeof(u_char *)); |
| 295 | FREE(sc->secp, M_MD); | |
| 296 | sc->secp = secpp; | |
| 297 | sc->nsecp = secno + nsec + 1; | |
| 298 | secpp = &sc->secp[secno]; | |
| 299 | } | |
| 300 | if (i == DEV_BSIZE) { | |
| 301 | if (secp) | |
| 302 | FREE(secp, M_MDSECT); | |
| 973c11b9 | 303 | *secpp = (u_char *)(uintptr_t)uc; |
| 984263bc MD |
304 | } else { |
| 305 | if (!secp) | |
| 306 | MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK); | |
| 307 | bcopy(dst, secp, DEV_BSIZE); | |
| 308 | ||
| 309 | *secpp = secp; | |
| 310 | } | |
| 311 | } | |
| 10f3fee5 MD |
312 | break; |
| 313 | default: | |
| 314 | panic("md: bad b_cmd %d", bp->b_cmd); | |
| 315 | ||
| 984263bc MD |
316 | } |
| 317 | secno++; | |
| 318 | dst += DEV_BSIZE; | |
| 319 | } | |
| 320 | bp->b_resid = 0; | |
| 321 | devstat_end_transaction_buf(&sc->stats, bp); | |
| 81b5c339 | 322 | biodone(bio); |
| fbe276c7 | 323 | crit_enter(); |
| 984263bc MD |
324 | } |
| 325 | sc->busy = 0; | |
| fef8985e | 326 | return(0); |
| 984263bc MD |
327 | } |
| 328 | ||
| 329 | ||
| fef8985e MD |
330 | static int |
| 331 | mdstrategy_preload(struct dev_strategy_args *ap) | |
| 984263bc | 332 | { |
| b13267a5 | 333 | cdev_t dev = ap->a_head.a_dev; |
| fef8985e | 334 | struct bio *bio = ap->a_bio; |
| 81b5c339 | 335 | struct buf *bp = bio->bio_buf; |
| 81b5c339 | 336 | struct md_s *sc; |
| 984263bc MD |
337 | |
| 338 | if (md_debug > 1) | |
| e3869ec7 | 339 | kprintf("mdstrategy_preload(%p) %s %08x, %lld, %d, %p)\n", |
| 973c11b9 MD |
340 | bp, devtoname(dev), bp->b_flags, |
| 341 | (long long)bio->bio_offset, | |
| 54078292 | 342 | bp->b_bcount, bp->b_data); |
| 984263bc | 343 | |
| 81b5c339 | 344 | sc = dev->si_drv1; |
| 984263bc | 345 | |
| fbe276c7 | 346 | crit_enter(); |
| 984263bc | 347 | |
| 81b5c339 | 348 | bioqdisksort(&sc->bio_queue, bio); |
| 984263bc MD |
349 | |
| 350 | if (sc->busy) { | |
| fbe276c7 | 351 | crit_exit(); |
| fef8985e | 352 | return(0); |
| 984263bc MD |
353 | } |
| 354 | ||
| 355 | sc->busy++; | |
| 356 | ||
| 357 | while (1) { | |
| 81b5c339 MD |
358 | bio = bioq_first(&sc->bio_queue); |
| 359 | if (bio) | |
| 360 | bioq_remove(&sc->bio_queue, bio); | |
| fbe276c7 | 361 | crit_exit(); |
| 81b5c339 | 362 | if (bio == NULL) |
| 984263bc MD |
363 | break; |
| 364 | ||
| 365 | devstat_start_transaction(&sc->stats); | |
| 366 | ||
| 8b6f36f5 | 367 | switch (bp->b_cmd) { |
| 10f3fee5 | 368 | case BUF_CMD_FREEBLKS: |
| 10f3fee5 MD |
369 | break; |
| 370 | case BUF_CMD_READ: | |
| 54078292 MD |
371 | bcopy(sc->pl_ptr + bio->bio_offset, |
| 372 | bp->b_data, bp->b_bcount); | |
| 10f3fee5 MD |
373 | break; |
| 374 | case BUF_CMD_WRITE: | |
| 54078292 MD |
375 | bcopy(bp->b_data, sc->pl_ptr + bio->bio_offset, |
| 376 | bp->b_bcount); | |
| 10f3fee5 MD |
377 | break; |
| 378 | default: | |
| 379 | panic("md: bad cmd %d\n", bp->b_cmd); | |
| 984263bc MD |
380 | } |
| 381 | bp->b_resid = 0; | |
| 382 | devstat_end_transaction_buf(&sc->stats, bp); | |
| 81b5c339 | 383 | biodone(bio); |
| fbe276c7 | 384 | crit_enter(); |
| 984263bc MD |
385 | } |
| 386 | sc->busy = 0; | |
| fef8985e | 387 | return(0); |
| 984263bc MD |
388 | } |
| 389 | ||
| 390 | static struct md_s * | |
| d34ac8d0 | 391 | mdcreate(unsigned length) |
| 984263bc MD |
392 | { |
| 393 | struct md_s *sc; | |
| cd29885a | 394 | struct disk_info info; |
| 984263bc | 395 | |
| e7b4468c | 396 | MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK | M_ZERO); |
| 984263bc | 397 | sc->unit = mdunits++; |
| 81b5c339 | 398 | bioq_init(&sc->bio_queue); |
| 984263bc MD |
399 | devstat_add_entry(&sc->stats, "md", sc->unit, DEV_BSIZE, |
| 400 | DEVSTAT_NO_ORDERED_TAGS, | |
| 401 | DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER, | |
| 402 | DEVSTAT_PRIORITY_OTHER); | |
| a688b15c | 403 | sc->dev = disk_create(sc->unit, &sc->disk, &md_ops); |
| 984263bc | 404 | sc->dev->si_drv1 = sc; |
| a260c869 | 405 | sc->dev->si_iosize_max = DFLTPHYS; |
| f5d8307c | 406 | disk_setdisktype(&sc->disk, "memory"); |
| a260c869 | 407 | |
| cd29885a MD |
408 | bzero(&info, sizeof(info)); |
| 409 | info.d_media_blksize = DEV_BSIZE; /* mandatory */ | |
| d34ac8d0 | 410 | info.d_media_blocks = length / DEV_BSIZE; |
| cd29885a MD |
411 | |
| 412 | info.d_secpertrack = 1024; /* optional */ | |
| 413 | info.d_nheads = 1; | |
| 414 | info.d_secpercyl = info.d_secpertrack * info.d_nheads; | |
| 415 | info.d_ncylinders = (u_int)(info.d_media_blocks / info.d_secpercyl); | |
| 416 | disk_setdiskinfo(&sc->disk, &info); | |
| 89adea15 | 417 | TAILQ_INSERT_HEAD(&mdlist, sc, link); |
| cd29885a | 418 | |
| 984263bc MD |
419 | return (sc); |
| 420 | } | |
| 421 | ||
| 89adea15 | 422 | |
| 984263bc MD |
423 | static void |
| 424 | mdcreate_preload(u_char *image, unsigned length) | |
| 425 | { | |
| 426 | struct md_s *sc; | |
| 427 | ||
| d34ac8d0 | 428 | sc = mdcreate(length); |
| 984263bc MD |
429 | sc->type = MD_PRELOAD; |
| 430 | sc->nsect = length / DEV_BSIZE; | |
| 431 | sc->pl_ptr = image; | |
| 432 | sc->pl_len = length; | |
| 433 | ||
| 434 | if (sc->unit == 0) | |
| 435 | mdrootready = 1; | |
| 436 | } | |
| 437 | ||
| 438 | static void | |
| 439 | mdcreate_malloc(void) | |
| 440 | { | |
| 441 | struct md_s *sc; | |
| 442 | ||
| 89adea15 | 443 | sc = mdcreate(MD_NSECT*DEV_BSIZE); |
| 984263bc MD |
444 | sc->type = MD_MALLOC; |
| 445 | ||
| 446 | sc->nsect = MD_NSECT; /* for now */ | |
| e7b4468c | 447 | MALLOC(sc->secp, u_char **, sizeof(u_char *), M_MD, M_WAITOK | M_ZERO); |
| 984263bc | 448 | sc->nsecp = 1; |
| e3869ec7 | 449 | kprintf("md%d: Malloc disk\n", sc->unit); |
| 984263bc MD |
450 | } |
| 451 | ||
| 89adea15 AHJ |
452 | static int |
| 453 | md_drvcleanup(void) | |
| 454 | { | |
| 455 | ||
| 456 | int secno; | |
| 457 | struct md_s *sc, *sc_temp; | |
| 458 | ||
| 459 | if (atomic_fetchadd_int(&refcnt, 0) != 0) | |
| 460 | return EBUSY; | |
| 461 | ||
| 462 | /* | |
| 463 | * Go through all the md devices, freeing up all the | |
| 464 | * memory allocated for sectors, and the md_s struct | |
| 465 | * itself. | |
| 466 | */ | |
| 467 | TAILQ_FOREACH_MUTABLE(sc, &mdlist, link, sc_temp) { | |
| 468 | for (secno = 0; secno < sc->nsecp; secno++) { | |
| 469 | if ((u_int)(uintptr_t)sc->secp[secno] > 255) | |
| 470 | FREE(sc->secp[secno], M_MDSECT); | |
| 471 | } | |
| 472 | ||
| 473 | if (sc->dev != NULL) | |
| 474 | disk_destroy(&sc->disk); | |
| 475 | ||
| 476 | devstat_remove_entry(&sc->stats); | |
| 477 | TAILQ_REMOVE(&mdlist, sc, link); | |
| 478 | ||
| 479 | FREE(sc->secp, M_MD); | |
| 480 | FREE(sc, M_MD); | |
| 481 | } | |
| 482 | ||
| 483 | return 0; | |
| 484 | ||
| 485 | } | |
| 486 | ||
| 984263bc MD |
487 | static void |
| 488 | md_drvinit(void *unused) | |
| 489 | { | |
| 490 | ||
| 491 | caddr_t mod; | |
| 492 | caddr_t c; | |
| 493 | u_char *ptr, *name, *type; | |
| 494 | unsigned len; | |
| 495 | ||
| 496 | #ifdef MD_ROOT_SIZE | |
| 497 | mdcreate_preload(mfs_root, MD_ROOT_SIZE*1024); | |
| 498 | #endif | |
| 499 | mod = NULL; | |
| 500 | while ((mod = preload_search_next_name(mod)) != NULL) { | |
| 501 | name = (char *)preload_search_info(mod, MODINFO_NAME); | |
| 502 | type = (char *)preload_search_info(mod, MODINFO_TYPE); | |
| 503 | if (name == NULL) | |
| 504 | continue; | |
| 505 | if (type == NULL) | |
| 506 | continue; | |
| 507 | if (strcmp(type, "md_image") && strcmp(type, "mfs_root")) | |
| 508 | continue; | |
| 509 | c = preload_search_info(mod, MODINFO_ADDR); | |
| 510 | ptr = *(u_char **)c; | |
| 511 | c = preload_search_info(mod, MODINFO_SIZE); | |
| 512 | len = *(unsigned *)c; | |
| e3869ec7 | 513 | kprintf("md%d: Preloaded image <%s> %d bytes at %p\n", |
| 984263bc MD |
514 | mdunits, name, len, ptr); |
| 515 | mdcreate_preload(ptr, len); | |
| 516 | } | |
| 517 | mdcreate_malloc(); | |
| 518 | } | |
| 519 | ||
| 89adea15 | 520 | DEV_MODULE(md, mdinit, NULL); |
| 984263bc MD |
521 | |
| 522 | #ifdef MD_ROOT | |
| 523 | static void | |
| 524 | md_takeroot(void *junk) | |
| 525 | { | |
| 526 | if (mdrootready) | |
| d34ac8d0 | 527 | rootdevnames[0] = "ufs:/dev/md0s0"; |
| 984263bc MD |
528 | } |
| 529 | ||
| 530 | SYSINIT(md_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, md_takeroot, NULL); | |
| 531 | #endif |