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 * ----------------------------------------------------------------------------
9 * $FreeBSD: src/sys/dev/md/md.c,v 1.8.2.2 2002/08/19 17:43:34 jdp Exp $
10 * $DragonFly: src/sys/dev/disk/md/md.c,v 1.10 2006/03/24 18:35:32 dillon Exp $
14 #include "opt_mfs.h" /* We have adopted some tasks from MFS */
15 #include "opt_md.h" /* We have adopted some tasks from MFS */
17 #include <sys/param.h>
18 #include <sys/systm.h>
21 #include <sys/devicestat.h>
23 #include <sys/kernel.h>
24 #include <sys/malloc.h>
25 #include <sys/sysctl.h>
26 #include <sys/linker.h>
29 #include <sys/thread2.h>
32 #define MD_NSECT (10000 * 2)
35 MALLOC_DEFINE(M_MD, "MD disk", "Memory Disk");
36 MALLOC_DEFINE(M_MDSECT, "MD sectors", "Memory Disk Sectors");
39 SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, "");
41 #if defined(MFS_ROOT) && !defined(MD_ROOT)
42 #define MD_ROOT MFS_ROOT
43 #warning "option MFS_ROOT has been superceeded by MD_ROOT"
46 #if defined(MFS_ROOT_SIZE) && !defined(MD_ROOT_SIZE)
47 #define MD_ROOT_SIZE MFS_ROOT_SIZE
48 #warning "option MFS_ROOT_SIZE has been superceeded by MD_ROOT_SIZE"
51 #if defined(MD_ROOT) && defined(MD_ROOT_SIZE)
52 /* Image gets put here: */
53 static u_char mfs_root[MD_ROOT_SIZE*1024] = "MFS Filesystem goes here";
54 static u_char end_mfs_root[] __unused = "MFS Filesystem had better STOP here";
57 static int mdrootready;
59 static void mdcreate_malloc(void);
63 static d_strategy_t mdstrategy;
64 static d_strategy_t mdstrategy_preload;
65 static d_strategy_t mdstrategy_malloc;
66 static d_open_t mdopen;
67 static d_ioctl_t mdioctl;
69 static struct cdevsw md_cdevsw = {
72 /* flags */ D_DISK | D_CANFREE | D_MEMDISK,
77 /* close */ nullclose,
79 /* write */ physwrite,
83 /* strategy */ mdstrategy,
91 struct bio_queue_head bio_queue;
95 enum {MD_MALLOC, MD_PRELOAD} type;
98 /* MD_MALLOC related fields */
102 /* MD_PRELOAD related fields */
110 mdopen(dev_t dev, int flag, int fmt, struct thread *td)
113 struct disklabel *dl;
116 printf("mdopen(%s %x %x %p)\n",
117 devtoname(dev), flag, fmt, td);
120 if (sc->unit + 1 == mdunits)
123 dl = &sc->disk.d_label;
124 bzero(dl, sizeof(*dl));
125 dl->d_secsize = DEV_BSIZE;
126 dl->d_nsectors = 1024;
128 dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
129 dl->d_secperunit = sc->nsect;
130 dl->d_ncylinders = dl->d_secperunit / dl->d_secpercyl;
135 mdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
139 printf("mdioctl(%s %lx %p %x %p)\n",
140 devtoname(dev), cmd, addr, flags, td);
146 mdstrategy(dev_t dev, struct bio *bio)
148 struct buf *bp = bio->bio_buf;
152 printf("mdstrategy(%p) %s %08x, %lld, %d, %p)\n",
153 bp, devtoname(dev), bp->b_flags, bio->bio_offset,
154 bp->b_bcount, bp->b_data);
156 bio->bio_driver_info = dev;
158 if (sc->type == MD_MALLOC) {
159 mdstrategy_malloc(dev, bio);
161 mdstrategy_preload(dev, bio);
167 mdstrategy_malloc(dev_t dev, struct bio *bio)
169 struct buf *bp = bio->bio_buf;
170 unsigned secno, nsec, secval, uc;
171 u_char *secp, **secpp, *dst;
172 devstat_trans_flags dop;
177 printf("mdstrategy_malloc(%p) %s %08xx, %lld, %d, %p)\n",
178 bp, devtoname(dev), bp->b_flags, bio->bio_offset,
179 bp->b_bcount, bp->b_data);
185 bioqdisksort(&sc->bio_queue, bio);
195 bio = bioq_first(&sc->bio_queue);
197 bioq_remove(&sc->bio_queue, bio);
202 devstat_start_transaction(&sc->stats);
204 if (bp->b_flags & B_FREEBUF)
205 dop = DEVSTAT_NO_DATA;
206 else if (bp->b_flags & B_READ)
211 nsec = bp->b_bcount >> DEV_BSHIFT;
212 secno = (unsigned)(bio->bio_offset >> DEV_BSHIFT);
215 if (secno < sc->nsecp) {
216 secpp = &sc->secp[secno];
217 if ((u_int)*secpp > 255) {
222 secval = (u_int) *secpp;
230 printf("%08x %p %p %d\n", bp->b_flags, secpp, secp, secval);
232 if (bp->b_flags & B_FREEBUF) {
235 FREE(secp, M_MDSECT);
238 } else if (bp->b_flags & B_READ) {
240 bcopy(secp, dst, DEV_BSIZE);
242 for (i = 0; i < DEV_BSIZE; i++)
245 bzero(dst, DEV_BSIZE);
249 for (i = 1; i < DEV_BSIZE; i++)
252 if (i == DEV_BSIZE && !uc) {
254 FREE(secp, M_MDSECT);
256 *secpp = (u_char *)uc;
259 MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK);
260 bzero(secpp, (secno + nsec + 1) * sizeof(u_char *));
261 bcopy(sc->secp, secpp, sc->nsecp * sizeof(u_char *));
262 FREE(sc->secp, M_MD);
264 sc->nsecp = secno + nsec + 1;
265 secpp = &sc->secp[secno];
267 if (i == DEV_BSIZE) {
269 FREE(secp, M_MDSECT);
270 *secpp = (u_char *)uc;
273 MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK);
274 bcopy(dst, secp, DEV_BSIZE);
284 devstat_end_transaction_buf(&sc->stats, bp);
293 mdstrategy_preload(dev_t dev, struct bio *bio)
295 struct buf *bp = bio->bio_buf;
296 devstat_trans_flags dop;
300 printf("mdstrategy_preload(%p) %s %08x, %lld, %d, %p)\n",
301 bp, devtoname(dev), bp->b_flags, bio->bio_offset,
302 bp->b_bcount, bp->b_data);
308 bioqdisksort(&sc->bio_queue, bio);
318 bio = bioq_first(&sc->bio_queue);
320 bioq_remove(&sc->bio_queue, bio);
325 devstat_start_transaction(&sc->stats);
327 if (bp->b_flags & B_FREEBUF) {
328 dop = DEVSTAT_NO_DATA;
329 } else if (bp->b_flags & B_READ) {
331 bcopy(sc->pl_ptr + bio->bio_offset,
332 bp->b_data, bp->b_bcount);
335 bcopy(bp->b_data, sc->pl_ptr + bio->bio_offset,
339 devstat_end_transaction_buf(&sc->stats, bp);
351 MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK);
352 bzero(sc, sizeof(*sc));
353 sc->unit = mdunits++;
354 bioq_init(&sc->bio_queue);
355 devstat_add_entry(&sc->stats, "md", sc->unit, DEV_BSIZE,
356 DEVSTAT_NO_ORDERED_TAGS,
357 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
358 DEVSTAT_PRIORITY_OTHER);
359 sc->dev = disk_create(sc->unit, &sc->disk, 0, &md_cdevsw);
360 sc->dev->si_drv1 = sc;
365 mdcreate_preload(u_char *image, unsigned length)
370 sc->type = MD_PRELOAD;
371 sc->nsect = length / DEV_BSIZE;
380 mdcreate_malloc(void)
385 sc->type = MD_MALLOC;
387 sc->nsect = MD_NSECT; /* for now */
388 MALLOC(sc->secp, u_char **, sizeof(u_char *), M_MD, M_WAITOK);
389 bzero(sc->secp, sizeof(u_char *));
391 printf("md%d: Malloc disk\n", sc->unit);
395 md_drvinit(void *unused)
400 u_char *ptr, *name, *type;
404 mdcreate_preload(mfs_root, MD_ROOT_SIZE*1024);
407 while ((mod = preload_search_next_name(mod)) != NULL) {
408 name = (char *)preload_search_info(mod, MODINFO_NAME);
409 type = (char *)preload_search_info(mod, MODINFO_TYPE);
414 if (strcmp(type, "md_image") && strcmp(type, "mfs_root"))
416 c = preload_search_info(mod, MODINFO_ADDR);
418 c = preload_search_info(mod, MODINFO_SIZE);
419 len = *(unsigned *)c;
420 printf("md%d: Preloaded image <%s> %d bytes at %p\n",
421 mdunits, name, len, ptr);
422 mdcreate_preload(ptr, len);
427 SYSINIT(mddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, md_drvinit,NULL)
431 md_takeroot(void *junk)
434 rootdevnames[0] = "ufs:/dev/md0c";
437 SYSINIT(md_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, md_takeroot, NULL);