Deleted Added
full compact
md.c (59249) md.c (60041)
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 *
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: head/sys/dev/md/md.c 59249 2000-04-15 05:54:02Z phk $
9 * $FreeBSD: head/sys/dev/md/md.c 60041 2000-05-05 09:59:14Z phk $
10 *
11 */
12
13#include "opt_mfs.h" /* We have adopted some tasks from MFS */
14#include "opt_md.h" /* We have adopted some tasks from MFS */
15
16#include <sys/param.h>
17#include <sys/systm.h>
10 *
11 */
12
13#include "opt_mfs.h" /* We have adopted some tasks from MFS */
14#include "opt_md.h" /* We have adopted some tasks from MFS */
15
16#include <sys/param.h>
17#include <sys/systm.h>
18#include <sys/buf.h>
18#include <sys/bio.h>
19#include <sys/conf.h>
20#include <sys/devicestat.h>
21#include <sys/disk.h>
22#include <sys/kernel.h>
23#include <sys/malloc.h>
24#include <sys/sysctl.h>
25#include <sys/linker.h>
26
27#ifndef MDNSECT
28#define MDNSECT (10000 * 2)
29#endif
30
31MALLOC_DEFINE(M_MD, "MD disk", "Memory Disk");
32MALLOC_DEFINE(M_MDSECT, "MD sectors", "Memory Disk Sectors");
33
34static int md_debug;
35SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, "");
36
37#if defined(MFS_ROOT) && !defined(MD_ROOT)
38#define MD_ROOT MFS_ROOT
39#warning "option MFS_ROOT has been superceeded by MD_ROOT"
40#endif
41
42#if defined(MFS_ROOT_SIZE) && !defined(MD_ROOT_SIZE)
43#define MD_ROOT_SIZE MFS_ROOT_SIZE
44#warning "option MFS_ROOT_SIZE has been superceeded by MD_ROOT_SIZE"
45#endif
46
47#if defined(MD_ROOT) && defined(MD_ROOT_SIZE)
48/* Image gets put here: */
49static u_char mfs_root[MD_ROOT_SIZE*1024] = "MFS Filesystem goes here";
50static u_char end_mfs_root[] __unused = "MFS Filesystem had better STOP here";
51#endif
52
53static int mdrootready;
54
55#define CDEV_MAJOR 95
56#define BDEV_MAJOR 22
57
58static d_strategy_t mdstrategy;
59static d_strategy_t mdstrategy_preload;
60static d_strategy_t mdstrategy_malloc;
61static d_open_t mdopen;
62static d_ioctl_t mdioctl;
63
64static struct cdevsw md_cdevsw = {
65 /* open */ mdopen,
66 /* close */ nullclose,
67 /* read */ physread,
68 /* write */ physwrite,
69 /* ioctl */ mdioctl,
70 /* poll */ nopoll,
71 /* mmap */ nommap,
72 /* strategy */ mdstrategy,
73 /* name */ "md",
74 /* maj */ CDEV_MAJOR,
75 /* dump */ nodump,
76 /* psize */ nopsize,
77 /* flags */ D_DISK | D_CANFREE | D_MEMDISK,
78 /* bmaj */ BDEV_MAJOR
79};
80
81struct md_s {
82 int unit;
83 struct devstat stats;
84 struct bio_queue_head bio_queue;
85 struct disk disk;
86 dev_t dev;
87 int busy;
88 enum {MD_MALLOC, MD_PRELOAD} type;
89 unsigned nsect;
90 struct cdevsw devsw;
91
92 /* MD_MALLOC related fields */
93 unsigned nsecp;
94 u_char **secp;
95
96 /* MD_PRELOAD related fields */
97 u_char *pl_ptr;
98 unsigned pl_len;
99};
100
101static int mdunits;
102
103static int
104mdopen(dev_t dev, int flag, int fmt, struct proc *p)
105{
106 struct md_s *sc;
107 struct disklabel *dl;
108
109 if (md_debug)
110 printf("mdopen(%s %x %x %p)\n",
111 devtoname(dev), flag, fmt, p);
112
113 sc = dev->si_drv1;
114
115 dl = &sc->disk.d_label;
116 bzero(dl, sizeof(*dl));
117 dl->d_secsize = DEV_BSIZE;
118 dl->d_nsectors = 1024;
119 dl->d_ntracks = 1;
120 dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
121 dl->d_secperunit = sc->nsect;
122 dl->d_ncylinders = dl->d_secperunit / dl->d_secpercyl;
123 return (0);
124}
125
126static int
127mdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
128{
129
130 if (md_debug)
131 printf("mdioctl(%s %lx %p %x %p)\n",
132 devtoname(dev), cmd, addr, flags, p);
133
134 return (ENOIOCTL);
135}
136
137static void
138mdstrategy(struct bio *bp)
139{
140 struct md_s *sc;
141
142 if (md_debug > 1)
143 printf("mdstrategy(%p) %s %x, %d, %ld, %p)\n",
144 bp, devtoname(bp->bio_dev), bp->bio_flags, bp->bio_blkno,
145 bp->bio_bcount / DEV_BSIZE, bp->bio_data);
146
147 sc = bp->bio_dev->si_drv1;
148 if (sc->type == MD_MALLOC) {
149 mdstrategy_malloc(bp);
150 } else {
151 mdstrategy_preload(bp);
152 }
153 return;
154}
155
156
157static void
158mdstrategy_malloc(struct bio *bp)
159{
160 int s, i;
161 struct md_s *sc;
162 devstat_trans_flags dop;
163 u_char *secp, **secpp, *dst;
164 unsigned secno, nsec, secval, uc;
165
166 if (md_debug > 1)
167 printf("mdstrategy_malloc(%p) %s %x, %d, %ld, %p)\n",
168 bp, devtoname(bp->bio_dev), bp->bio_flags, bp->bio_blkno,
169 bp->bio_bcount / DEV_BSIZE, bp->bio_data);
170
171 sc = bp->bio_dev->si_drv1;
172
173 s = splbio();
174
175 bioqdisksort(&sc->bio_queue, bp);
176
177 if (sc->busy) {
178 splx(s);
179 return;
180 }
181
182 sc->busy++;
183
184 while (1) {
185 bp = bioq_first(&sc->bio_queue);
186 if (bp)
187 bioq_remove(&sc->bio_queue, bp);
188 splx(s);
189 if (!bp)
190 break;
191
192 devstat_start_transaction(&sc->stats);
193
194 if (bp->bio_cmd == BIO_DELETE)
195 dop = DEVSTAT_NO_DATA;
196 else if (bp->bio_cmd == BIO_READ)
197 dop = DEVSTAT_READ;
198 else
199 dop = DEVSTAT_WRITE;
200
201 nsec = bp->bio_bcount / DEV_BSIZE;
202 secno = bp->bio_pblkno;
203 dst = bp->bio_data;
204 while (nsec--) {
205
206 if (secno < sc->nsecp) {
207 secpp = &sc->secp[secno];
208 if ((u_int)*secpp > 255) {
209 secp = *secpp;
210 secval = 0;
211 } else {
212 secp = 0;
213 secval = (u_int) *secpp;
214 }
215 } else {
216 secpp = 0;
217 secp = 0;
218 secval = 0;
219 }
220 if (md_debug > 2)
221 printf("%x %p %p %d\n",
222 bp->bio_flags, secpp, secp, secval);
223
224 if (bp->bio_cmd == BIO_DELETE) {
225 if (secpp) {
226 if (secp)
227 FREE(secp, M_MDSECT);
228 *secpp = 0;
229 }
230 } else if (bp->bio_cmd == BIO_READ) {
231 if (secp) {
232 bcopy(secp, dst, DEV_BSIZE);
233 } else if (secval) {
234 for (i = 0; i < DEV_BSIZE; i++)
235 dst[i] = secval;
236 } else {
237 bzero(dst, DEV_BSIZE);
238 }
239 } else {
240 uc = dst[0];
241 for (i = 1; i < DEV_BSIZE; i++)
242 if (dst[i] != uc)
243 break;
244 if (i == DEV_BSIZE && !uc) {
245 if (secp)
246 FREE(secp, M_MDSECT);
247 if (secpp)
248 *secpp = (u_char *)uc;
249 } else {
250 if (!secpp) {
251 MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK);
252 bzero(secpp, (secno + nsec + 1) * sizeof(u_char *));
253 bcopy(sc->secp, secpp, sc->nsecp * sizeof(u_char *));
254 FREE(sc->secp, M_MD);
255 sc->secp = secpp;
256 sc->nsecp = secno + nsec + 1;
257 secpp = &sc->secp[secno];
258 }
259 if (i == DEV_BSIZE) {
260 if (secp)
261 FREE(secp, M_MDSECT);
262 *secpp = (u_char *)uc;
263 } else {
264 if (!secp)
265 MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK);
266 bcopy(dst, secp, DEV_BSIZE);
267
268 *secpp = secp;
269 }
270 }
271 }
272 secno++;
273 dst += DEV_BSIZE;
274 }
275 bp->bio_resid = 0;
276 devstat_end_transaction_bio(&sc->stats, bp);
277 biodone(bp);
278 s = splbio();
279 }
280 sc->busy = 0;
281 return;
282}
283
284
285static void
286mdstrategy_preload(struct bio *bp)
287{
288 int s;
289 struct md_s *sc;
290 devstat_trans_flags dop;
291
292 if (md_debug > 1)
293 printf("mdstrategy_preload(%p) %s %x, %d, %ld, %p)\n",
294 bp, devtoname(bp->bio_dev), bp->bio_flags, bp->bio_blkno,
295 bp->bio_bcount / DEV_BSIZE, bp->bio_data);
296
297 sc = bp->bio_dev->si_drv1;
298
299 s = splbio();
300
301 bioqdisksort(&sc->bio_queue, bp);
302
303 if (sc->busy) {
304 splx(s);
305 return;
306 }
307
308 sc->busy++;
309
310 while (1) {
311 bp = bioq_first(&sc->bio_queue);
312 if (bp)
313 bioq_remove(&sc->bio_queue, bp);
314 splx(s);
315 if (!bp)
316 break;
317
318 devstat_start_transaction(&sc->stats);
319
320 if (bp->bio_cmd == BIO_DELETE) {
321 dop = DEVSTAT_NO_DATA;
322 } else if (bp->bio_cmd == BIO_READ) {
323 dop = DEVSTAT_READ;
324 bcopy(sc->pl_ptr + (bp->bio_pblkno << DEV_BSHIFT), bp->bio_data, bp->bio_bcount);
325 } else {
326 dop = DEVSTAT_WRITE;
327 bcopy(bp->bio_data, sc->pl_ptr + (bp->bio_pblkno << DEV_BSHIFT), bp->bio_bcount);
328 }
329 bp->bio_resid = 0;
330 devstat_end_transaction_bio(&sc->stats, bp);
331 biodone(bp);
332 s = splbio();
333 }
334 sc->busy = 0;
335 return;
336}
337
338static struct md_s *
339mdcreate(struct cdevsw *devsw)
340{
341 struct md_s *sc;
342
343 MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK);
344 bzero(sc, sizeof(*sc));
345 sc->unit = mdunits++;
346 bioq_init(&sc->bio_queue);
347 devstat_add_entry(&sc->stats, "md", sc->unit, DEV_BSIZE,
348 DEVSTAT_NO_ORDERED_TAGS,
349 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
350 DEVSTAT_PRIORITY_OTHER);
351 sc->dev = disk_create(sc->unit, &sc->disk, 0, devsw, &sc->devsw);
352 sc->dev->si_drv1 = sc;
353 return (sc);
354}
355
356static void
357mdcreate_preload(u_char *image, unsigned length)
358{
359 struct md_s *sc;
360
361 sc = mdcreate(&md_cdevsw);
362 sc->type = MD_PRELOAD;
363 sc->nsect = length / DEV_BSIZE;
364 sc->pl_ptr = image;
365 sc->pl_len = length;
366
367 if (sc->unit == 0)
368 mdrootready = 1;
369}
370
371static void
372mdcreate_malloc(void)
373{
374 struct md_s *sc;
375
376 sc = mdcreate(&md_cdevsw);
377 sc->type = MD_MALLOC;
378
379 sc->nsect = MDNSECT; /* for now */
380 MALLOC(sc->secp, u_char **, sizeof(u_char *), M_MD, M_WAITOK);
381 bzero(sc->secp, sizeof(u_char *));
382 sc->nsecp = 1;
383}
384
385static void
386md_drvinit(void *unused)
387{
388
389 caddr_t mod;
390 caddr_t c;
391 u_char *ptr, *name, *type;
392 unsigned len;
393
394#ifdef MD_ROOT_SIZE
395 mdcreate_preload(mfs_root, MD_ROOT_SIZE*1024);
396#endif
397 mod = NULL;
398 while ((mod = preload_search_next_name(mod)) != NULL) {
399 name = (char *)preload_search_info(mod, MODINFO_NAME);
400 type = (char *)preload_search_info(mod, MODINFO_TYPE);
401 if (name == NULL)
402 continue;
403 if (type == NULL)
404 continue;
405 if (strcmp(type, "md_image") && strcmp(type, "mfs_root"))
406 continue;
407 c = preload_search_info(mod, MODINFO_ADDR);
408 ptr = *(u_char **)c;
409 c = preload_search_info(mod, MODINFO_SIZE);
410 len = *(unsigned *)c;
411 printf("md%d: Preloaded image <%s> %d bytes at %p\n",
412 mdunits, name, len, ptr);
413 mdcreate_preload(ptr, len);
414 }
415 printf("md%d: Malloc disk\n", mdunits);
416 mdcreate_malloc();
417}
418
419SYSINIT(mddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, md_drvinit,NULL)
420
421#ifdef MD_ROOT
422static void
423md_takeroot(void *junk)
424{
425 if (mdrootready)
426 rootdevnames[0] = "ufs:/dev/md0c";
427}
428
429SYSINIT(md_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, md_takeroot, NULL);
430#endif
19#include <sys/conf.h>
20#include <sys/devicestat.h>
21#include <sys/disk.h>
22#include <sys/kernel.h>
23#include <sys/malloc.h>
24#include <sys/sysctl.h>
25#include <sys/linker.h>
26
27#ifndef MDNSECT
28#define MDNSECT (10000 * 2)
29#endif
30
31MALLOC_DEFINE(M_MD, "MD disk", "Memory Disk");
32MALLOC_DEFINE(M_MDSECT, "MD sectors", "Memory Disk Sectors");
33
34static int md_debug;
35SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, "");
36
37#if defined(MFS_ROOT) && !defined(MD_ROOT)
38#define MD_ROOT MFS_ROOT
39#warning "option MFS_ROOT has been superceeded by MD_ROOT"
40#endif
41
42#if defined(MFS_ROOT_SIZE) && !defined(MD_ROOT_SIZE)
43#define MD_ROOT_SIZE MFS_ROOT_SIZE
44#warning "option MFS_ROOT_SIZE has been superceeded by MD_ROOT_SIZE"
45#endif
46
47#if defined(MD_ROOT) && defined(MD_ROOT_SIZE)
48/* Image gets put here: */
49static u_char mfs_root[MD_ROOT_SIZE*1024] = "MFS Filesystem goes here";
50static u_char end_mfs_root[] __unused = "MFS Filesystem had better STOP here";
51#endif
52
53static int mdrootready;
54
55#define CDEV_MAJOR 95
56#define BDEV_MAJOR 22
57
58static d_strategy_t mdstrategy;
59static d_strategy_t mdstrategy_preload;
60static d_strategy_t mdstrategy_malloc;
61static d_open_t mdopen;
62static d_ioctl_t mdioctl;
63
64static struct cdevsw md_cdevsw = {
65 /* open */ mdopen,
66 /* close */ nullclose,
67 /* read */ physread,
68 /* write */ physwrite,
69 /* ioctl */ mdioctl,
70 /* poll */ nopoll,
71 /* mmap */ nommap,
72 /* strategy */ mdstrategy,
73 /* name */ "md",
74 /* maj */ CDEV_MAJOR,
75 /* dump */ nodump,
76 /* psize */ nopsize,
77 /* flags */ D_DISK | D_CANFREE | D_MEMDISK,
78 /* bmaj */ BDEV_MAJOR
79};
80
81struct md_s {
82 int unit;
83 struct devstat stats;
84 struct bio_queue_head bio_queue;
85 struct disk disk;
86 dev_t dev;
87 int busy;
88 enum {MD_MALLOC, MD_PRELOAD} type;
89 unsigned nsect;
90 struct cdevsw devsw;
91
92 /* MD_MALLOC related fields */
93 unsigned nsecp;
94 u_char **secp;
95
96 /* MD_PRELOAD related fields */
97 u_char *pl_ptr;
98 unsigned pl_len;
99};
100
101static int mdunits;
102
103static int
104mdopen(dev_t dev, int flag, int fmt, struct proc *p)
105{
106 struct md_s *sc;
107 struct disklabel *dl;
108
109 if (md_debug)
110 printf("mdopen(%s %x %x %p)\n",
111 devtoname(dev), flag, fmt, p);
112
113 sc = dev->si_drv1;
114
115 dl = &sc->disk.d_label;
116 bzero(dl, sizeof(*dl));
117 dl->d_secsize = DEV_BSIZE;
118 dl->d_nsectors = 1024;
119 dl->d_ntracks = 1;
120 dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
121 dl->d_secperunit = sc->nsect;
122 dl->d_ncylinders = dl->d_secperunit / dl->d_secpercyl;
123 return (0);
124}
125
126static int
127mdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
128{
129
130 if (md_debug)
131 printf("mdioctl(%s %lx %p %x %p)\n",
132 devtoname(dev), cmd, addr, flags, p);
133
134 return (ENOIOCTL);
135}
136
137static void
138mdstrategy(struct bio *bp)
139{
140 struct md_s *sc;
141
142 if (md_debug > 1)
143 printf("mdstrategy(%p) %s %x, %d, %ld, %p)\n",
144 bp, devtoname(bp->bio_dev), bp->bio_flags, bp->bio_blkno,
145 bp->bio_bcount / DEV_BSIZE, bp->bio_data);
146
147 sc = bp->bio_dev->si_drv1;
148 if (sc->type == MD_MALLOC) {
149 mdstrategy_malloc(bp);
150 } else {
151 mdstrategy_preload(bp);
152 }
153 return;
154}
155
156
157static void
158mdstrategy_malloc(struct bio *bp)
159{
160 int s, i;
161 struct md_s *sc;
162 devstat_trans_flags dop;
163 u_char *secp, **secpp, *dst;
164 unsigned secno, nsec, secval, uc;
165
166 if (md_debug > 1)
167 printf("mdstrategy_malloc(%p) %s %x, %d, %ld, %p)\n",
168 bp, devtoname(bp->bio_dev), bp->bio_flags, bp->bio_blkno,
169 bp->bio_bcount / DEV_BSIZE, bp->bio_data);
170
171 sc = bp->bio_dev->si_drv1;
172
173 s = splbio();
174
175 bioqdisksort(&sc->bio_queue, bp);
176
177 if (sc->busy) {
178 splx(s);
179 return;
180 }
181
182 sc->busy++;
183
184 while (1) {
185 bp = bioq_first(&sc->bio_queue);
186 if (bp)
187 bioq_remove(&sc->bio_queue, bp);
188 splx(s);
189 if (!bp)
190 break;
191
192 devstat_start_transaction(&sc->stats);
193
194 if (bp->bio_cmd == BIO_DELETE)
195 dop = DEVSTAT_NO_DATA;
196 else if (bp->bio_cmd == BIO_READ)
197 dop = DEVSTAT_READ;
198 else
199 dop = DEVSTAT_WRITE;
200
201 nsec = bp->bio_bcount / DEV_BSIZE;
202 secno = bp->bio_pblkno;
203 dst = bp->bio_data;
204 while (nsec--) {
205
206 if (secno < sc->nsecp) {
207 secpp = &sc->secp[secno];
208 if ((u_int)*secpp > 255) {
209 secp = *secpp;
210 secval = 0;
211 } else {
212 secp = 0;
213 secval = (u_int) *secpp;
214 }
215 } else {
216 secpp = 0;
217 secp = 0;
218 secval = 0;
219 }
220 if (md_debug > 2)
221 printf("%x %p %p %d\n",
222 bp->bio_flags, secpp, secp, secval);
223
224 if (bp->bio_cmd == BIO_DELETE) {
225 if (secpp) {
226 if (secp)
227 FREE(secp, M_MDSECT);
228 *secpp = 0;
229 }
230 } else if (bp->bio_cmd == BIO_READ) {
231 if (secp) {
232 bcopy(secp, dst, DEV_BSIZE);
233 } else if (secval) {
234 for (i = 0; i < DEV_BSIZE; i++)
235 dst[i] = secval;
236 } else {
237 bzero(dst, DEV_BSIZE);
238 }
239 } else {
240 uc = dst[0];
241 for (i = 1; i < DEV_BSIZE; i++)
242 if (dst[i] != uc)
243 break;
244 if (i == DEV_BSIZE && !uc) {
245 if (secp)
246 FREE(secp, M_MDSECT);
247 if (secpp)
248 *secpp = (u_char *)uc;
249 } else {
250 if (!secpp) {
251 MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK);
252 bzero(secpp, (secno + nsec + 1) * sizeof(u_char *));
253 bcopy(sc->secp, secpp, sc->nsecp * sizeof(u_char *));
254 FREE(sc->secp, M_MD);
255 sc->secp = secpp;
256 sc->nsecp = secno + nsec + 1;
257 secpp = &sc->secp[secno];
258 }
259 if (i == DEV_BSIZE) {
260 if (secp)
261 FREE(secp, M_MDSECT);
262 *secpp = (u_char *)uc;
263 } else {
264 if (!secp)
265 MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK);
266 bcopy(dst, secp, DEV_BSIZE);
267
268 *secpp = secp;
269 }
270 }
271 }
272 secno++;
273 dst += DEV_BSIZE;
274 }
275 bp->bio_resid = 0;
276 devstat_end_transaction_bio(&sc->stats, bp);
277 biodone(bp);
278 s = splbio();
279 }
280 sc->busy = 0;
281 return;
282}
283
284
285static void
286mdstrategy_preload(struct bio *bp)
287{
288 int s;
289 struct md_s *sc;
290 devstat_trans_flags dop;
291
292 if (md_debug > 1)
293 printf("mdstrategy_preload(%p) %s %x, %d, %ld, %p)\n",
294 bp, devtoname(bp->bio_dev), bp->bio_flags, bp->bio_blkno,
295 bp->bio_bcount / DEV_BSIZE, bp->bio_data);
296
297 sc = bp->bio_dev->si_drv1;
298
299 s = splbio();
300
301 bioqdisksort(&sc->bio_queue, bp);
302
303 if (sc->busy) {
304 splx(s);
305 return;
306 }
307
308 sc->busy++;
309
310 while (1) {
311 bp = bioq_first(&sc->bio_queue);
312 if (bp)
313 bioq_remove(&sc->bio_queue, bp);
314 splx(s);
315 if (!bp)
316 break;
317
318 devstat_start_transaction(&sc->stats);
319
320 if (bp->bio_cmd == BIO_DELETE) {
321 dop = DEVSTAT_NO_DATA;
322 } else if (bp->bio_cmd == BIO_READ) {
323 dop = DEVSTAT_READ;
324 bcopy(sc->pl_ptr + (bp->bio_pblkno << DEV_BSHIFT), bp->bio_data, bp->bio_bcount);
325 } else {
326 dop = DEVSTAT_WRITE;
327 bcopy(bp->bio_data, sc->pl_ptr + (bp->bio_pblkno << DEV_BSHIFT), bp->bio_bcount);
328 }
329 bp->bio_resid = 0;
330 devstat_end_transaction_bio(&sc->stats, bp);
331 biodone(bp);
332 s = splbio();
333 }
334 sc->busy = 0;
335 return;
336}
337
338static struct md_s *
339mdcreate(struct cdevsw *devsw)
340{
341 struct md_s *sc;
342
343 MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK);
344 bzero(sc, sizeof(*sc));
345 sc->unit = mdunits++;
346 bioq_init(&sc->bio_queue);
347 devstat_add_entry(&sc->stats, "md", sc->unit, DEV_BSIZE,
348 DEVSTAT_NO_ORDERED_TAGS,
349 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
350 DEVSTAT_PRIORITY_OTHER);
351 sc->dev = disk_create(sc->unit, &sc->disk, 0, devsw, &sc->devsw);
352 sc->dev->si_drv1 = sc;
353 return (sc);
354}
355
356static void
357mdcreate_preload(u_char *image, unsigned length)
358{
359 struct md_s *sc;
360
361 sc = mdcreate(&md_cdevsw);
362 sc->type = MD_PRELOAD;
363 sc->nsect = length / DEV_BSIZE;
364 sc->pl_ptr = image;
365 sc->pl_len = length;
366
367 if (sc->unit == 0)
368 mdrootready = 1;
369}
370
371static void
372mdcreate_malloc(void)
373{
374 struct md_s *sc;
375
376 sc = mdcreate(&md_cdevsw);
377 sc->type = MD_MALLOC;
378
379 sc->nsect = MDNSECT; /* for now */
380 MALLOC(sc->secp, u_char **, sizeof(u_char *), M_MD, M_WAITOK);
381 bzero(sc->secp, sizeof(u_char *));
382 sc->nsecp = 1;
383}
384
385static void
386md_drvinit(void *unused)
387{
388
389 caddr_t mod;
390 caddr_t c;
391 u_char *ptr, *name, *type;
392 unsigned len;
393
394#ifdef MD_ROOT_SIZE
395 mdcreate_preload(mfs_root, MD_ROOT_SIZE*1024);
396#endif
397 mod = NULL;
398 while ((mod = preload_search_next_name(mod)) != NULL) {
399 name = (char *)preload_search_info(mod, MODINFO_NAME);
400 type = (char *)preload_search_info(mod, MODINFO_TYPE);
401 if (name == NULL)
402 continue;
403 if (type == NULL)
404 continue;
405 if (strcmp(type, "md_image") && strcmp(type, "mfs_root"))
406 continue;
407 c = preload_search_info(mod, MODINFO_ADDR);
408 ptr = *(u_char **)c;
409 c = preload_search_info(mod, MODINFO_SIZE);
410 len = *(unsigned *)c;
411 printf("md%d: Preloaded image <%s> %d bytes at %p\n",
412 mdunits, name, len, ptr);
413 mdcreate_preload(ptr, len);
414 }
415 printf("md%d: Malloc disk\n", mdunits);
416 mdcreate_malloc();
417}
418
419SYSINIT(mddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, md_drvinit,NULL)
420
421#ifdef MD_ROOT
422static void
423md_takeroot(void *junk)
424{
425 if (mdrootready)
426 rootdevnames[0] = "ufs:/dev/md0c";
427}
428
429SYSINIT(md_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, md_takeroot, NULL);
430#endif