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.4 2003/06/23 17:55: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>
31 #define MD_NSECT (10000 * 2)
34 MALLOC_DEFINE(M_MD, "MD disk", "Memory Disk");
35 MALLOC_DEFINE(M_MDSECT, "MD sectors", "Memory Disk Sectors");
38 SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, "");
40 #if defined(MFS_ROOT) && !defined(MD_ROOT)
41 #define MD_ROOT MFS_ROOT
42 #warning "option MFS_ROOT has been superceeded by MD_ROOT"
45 #if defined(MFS_ROOT_SIZE) && !defined(MD_ROOT_SIZE)
46 #define MD_ROOT_SIZE MFS_ROOT_SIZE
47 #warning "option MFS_ROOT_SIZE has been superceeded by MD_ROOT_SIZE"
50 #if defined(MD_ROOT) && defined(MD_ROOT_SIZE)
51 /* Image gets put here: */
52 static u_char mfs_root[MD_ROOT_SIZE*1024] = "MFS Filesystem goes here";
53 static u_char end_mfs_root[] __unused = "MFS Filesystem had better STOP here";
56 static int mdrootready;
58 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 = {
71 /* close */ nullclose,
73 /* write */ physwrite,
77 /* strategy */ mdstrategy,
82 /* flags */ D_DISK | D_CANFREE | D_MEMDISK,
86 static struct cdevsw mddisk_cdevsw;
91 struct buf_queue_head buf_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(struct buf *bp)
151 printf("mdstrategy(%p) %s %lx, %d, %ld, %p)\n",
152 bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno,
153 bp->b_bcount / DEV_BSIZE, bp->b_data);
155 sc = bp->b_dev->si_drv1;
156 if (sc->type == MD_MALLOC) {
157 mdstrategy_malloc(bp);
159 mdstrategy_preload(bp);
166 mdstrategy_malloc(struct buf *bp)
170 devstat_trans_flags dop;
171 u_char *secp, **secpp, *dst;
172 unsigned secno, nsec, secval, uc;
175 printf("mdstrategy_malloc(%p) %s %lx, %d, %ld, %p)\n",
176 bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno,
177 bp->b_bcount / DEV_BSIZE, bp->b_data);
179 sc = bp->b_dev->si_drv1;
183 bufqdisksort(&sc->buf_queue, bp);
193 bp = bufq_first(&sc->buf_queue);
195 bufq_remove(&sc->buf_queue, bp);
200 devstat_start_transaction(&sc->stats);
202 if (bp->b_flags & B_FREEBUF)
203 dop = DEVSTAT_NO_DATA;
204 else if (bp->b_flags & B_READ)
209 nsec = bp->b_bcount / DEV_BSIZE;
210 secno = bp->b_pblkno;
214 if (secno < sc->nsecp) {
215 secpp = &sc->secp[secno];
216 if ((u_int)*secpp > 255) {
221 secval = (u_int) *secpp;
229 printf("%lx %p %p %d\n", bp->b_flags, secpp, secp, secval);
231 if (bp->b_flags & B_FREEBUF) {
234 FREE(secp, M_MDSECT);
237 } else if (bp->b_flags & B_READ) {
239 bcopy(secp, dst, DEV_BSIZE);
241 for (i = 0; i < DEV_BSIZE; i++)
244 bzero(dst, DEV_BSIZE);
248 for (i = 1; i < DEV_BSIZE; i++)
251 if (i == DEV_BSIZE && !uc) {
253 FREE(secp, M_MDSECT);
255 *secpp = (u_char *)uc;
258 MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK);
259 bzero(secpp, (secno + nsec + 1) * sizeof(u_char *));
260 bcopy(sc->secp, secpp, sc->nsecp * sizeof(u_char *));
261 FREE(sc->secp, M_MD);
263 sc->nsecp = secno + nsec + 1;
264 secpp = &sc->secp[secno];
266 if (i == DEV_BSIZE) {
268 FREE(secp, M_MDSECT);
269 *secpp = (u_char *)uc;
272 MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK);
273 bcopy(dst, secp, DEV_BSIZE);
283 devstat_end_transaction_buf(&sc->stats, bp);
293 mdstrategy_preload(struct buf *bp)
297 devstat_trans_flags dop;
300 printf("mdstrategy_preload(%p) %s %lx, %d, %ld, %p)\n",
301 bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno,
302 bp->b_bcount / DEV_BSIZE, bp->b_data);
304 sc = bp->b_dev->si_drv1;
308 bufqdisksort(&sc->buf_queue, bp);
318 bp = bufq_first(&sc->buf_queue);
320 bufq_remove(&sc->buf_queue, bp);
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 + (bp->b_pblkno << DEV_BSHIFT), bp->b_data, bp->b_bcount);
334 bcopy(bp->b_data, sc->pl_ptr + (bp->b_pblkno << DEV_BSHIFT), bp->b_bcount);
337 devstat_end_transaction_buf(&sc->stats, bp);
350 MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK);
351 bzero(sc, sizeof(*sc));
352 sc->unit = mdunits++;
353 bufq_init(&sc->buf_queue);
354 devstat_add_entry(&sc->stats, "md", sc->unit, DEV_BSIZE,
355 DEVSTAT_NO_ORDERED_TAGS,
356 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
357 DEVSTAT_PRIORITY_OTHER);
358 sc->dev = disk_create(sc->unit, &sc->disk, 0, &md_cdevsw, &mddisk_cdevsw);
359 sc->dev->si_drv1 = sc;
364 mdcreate_preload(u_char *image, unsigned length)
369 sc->type = MD_PRELOAD;
370 sc->nsect = length / DEV_BSIZE;
379 mdcreate_malloc(void)
384 sc->type = MD_MALLOC;
386 sc->nsect = MD_NSECT; /* for now */
387 MALLOC(sc->secp, u_char **, sizeof(u_char *), M_MD, M_WAITOK);
388 bzero(sc->secp, sizeof(u_char *));
390 printf("md%d: Malloc disk\n", sc->unit);
394 md_drvinit(void *unused)
399 u_char *ptr, *name, *type;
403 mdcreate_preload(mfs_root, MD_ROOT_SIZE*1024);
406 while ((mod = preload_search_next_name(mod)) != NULL) {
407 name = (char *)preload_search_info(mod, MODINFO_NAME);
408 type = (char *)preload_search_info(mod, MODINFO_TYPE);
413 if (strcmp(type, "md_image") && strcmp(type, "mfs_root"))
415 c = preload_search_info(mod, MODINFO_ADDR);
417 c = preload_search_info(mod, MODINFO_SIZE);
418 len = *(unsigned *)c;
419 printf("md%d: Preloaded image <%s> %d bytes at %p\n",
420 mdunits, name, len, ptr);
421 mdcreate_preload(ptr, len);
426 SYSINIT(mddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, md_drvinit,NULL)
430 md_takeroot(void *junk)
433 rootdevnames[0] = "ufs:/dev/md0c";
436 SYSINIT(md_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, md_takeroot, NULL);