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