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.8 2005/06/06 22:51:54 corecode 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 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)
296 devstat_trans_flags dop;
299 printf("mdstrategy_preload(%p) %s %lx, %d, %ld, %p)\n",
300 bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno,
301 bp->b_bcount / DEV_BSIZE, bp->b_data);
303 sc = bp->b_dev->si_drv1;
307 bufqdisksort(&sc->buf_queue, bp);
317 bp = bufq_first(&sc->buf_queue);
319 bufq_remove(&sc->buf_queue, bp);
324 devstat_start_transaction(&sc->stats);
326 if (bp->b_flags & B_FREEBUF) {
327 dop = DEVSTAT_NO_DATA;
328 } else if (bp->b_flags & B_READ) {
330 bcopy(sc->pl_ptr + (bp->b_pblkno << DEV_BSHIFT), bp->b_data, bp->b_bcount);
333 bcopy(bp->b_data, sc->pl_ptr + (bp->b_pblkno << DEV_BSHIFT), bp->b_bcount);
336 devstat_end_transaction_buf(&sc->stats, bp);
349 MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK);
350 bzero(sc, sizeof(*sc));
351 sc->unit = mdunits++;
352 bufq_init(&sc->buf_queue);
353 devstat_add_entry(&sc->stats, "md", sc->unit, DEV_BSIZE,
354 DEVSTAT_NO_ORDERED_TAGS,
355 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
356 DEVSTAT_PRIORITY_OTHER);
357 sc->dev = disk_create(sc->unit, &sc->disk, 0, &md_cdevsw);
358 sc->dev->si_drv1 = sc;
363 mdcreate_preload(u_char *image, unsigned length)
368 sc->type = MD_PRELOAD;
369 sc->nsect = length / DEV_BSIZE;
378 mdcreate_malloc(void)
383 sc->type = MD_MALLOC;
385 sc->nsect = MD_NSECT; /* for now */
386 MALLOC(sc->secp, u_char **, sizeof(u_char *), M_MD, M_WAITOK);
387 bzero(sc->secp, sizeof(u_char *));
389 printf("md%d: Malloc disk\n", sc->unit);
393 md_drvinit(void *unused)
398 u_char *ptr, *name, *type;
402 mdcreate_preload(mfs_root, MD_ROOT_SIZE*1024);
405 while ((mod = preload_search_next_name(mod)) != NULL) {
406 name = (char *)preload_search_info(mod, MODINFO_NAME);
407 type = (char *)preload_search_info(mod, MODINFO_TYPE);
412 if (strcmp(type, "md_image") && strcmp(type, "mfs_root"))
414 c = preload_search_info(mod, MODINFO_ADDR);
416 c = preload_search_info(mod, MODINFO_SIZE);
417 len = *(unsigned *)c;
418 printf("md%d: Preloaded image <%s> %d bytes at %p\n",
419 mdunits, name, len, ptr);
420 mdcreate_preload(ptr, len);
425 SYSINIT(mddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, md_drvinit,NULL)
429 md_takeroot(void *junk)
432 rootdevnames[0] = "ufs:/dev/md0c";
435 SYSINIT(md_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, md_takeroot, NULL);