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.2 2003/06/17 04:28:28 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 #define MD_NSECT (10000 * 2)
32 MALLOC_DEFINE(M_MD, "MD disk", "Memory Disk");
33 MALLOC_DEFINE(M_MDSECT, "MD sectors", "Memory Disk Sectors");
36 SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, "");
38 #if defined(MFS_ROOT) && !defined(MD_ROOT)
39 #define MD_ROOT MFS_ROOT
40 #warning "option MFS_ROOT has been superceeded by MD_ROOT"
43 #if defined(MFS_ROOT_SIZE) && !defined(MD_ROOT_SIZE)
44 #define MD_ROOT_SIZE MFS_ROOT_SIZE
45 #warning "option MFS_ROOT_SIZE has been superceeded by MD_ROOT_SIZE"
48 #if defined(MD_ROOT) && defined(MD_ROOT_SIZE)
49 /* Image gets put here: */
50 static u_char mfs_root[MD_ROOT_SIZE*1024] = "MFS Filesystem goes here";
51 static u_char end_mfs_root[] __unused = "MFS Filesystem had better STOP here";
54 static int mdrootready;
56 static void mdcreate_malloc(void);
61 static d_strategy_t mdstrategy;
62 static d_strategy_t mdstrategy_preload;
63 static d_strategy_t mdstrategy_malloc;
64 static d_open_t mdopen;
65 static d_ioctl_t mdioctl;
67 static struct cdevsw md_cdevsw = {
69 /* close */ nullclose,
71 /* write */ physwrite,
75 /* strategy */ mdstrategy,
80 /* flags */ D_DISK | D_CANFREE | D_MEMDISK,
84 static struct cdevsw mddisk_cdevsw;
89 struct buf_queue_head buf_queue;
93 enum {MD_MALLOC, MD_PRELOAD} type;
96 /* MD_MALLOC related fields */
100 /* MD_PRELOAD related fields */
108 mdopen(dev_t dev, int flag, int fmt, struct proc *p)
111 struct disklabel *dl;
114 printf("mdopen(%s %x %x %p)\n",
115 devtoname(dev), flag, fmt, p);
118 if (sc->unit + 1 == mdunits)
121 dl = &sc->disk.d_label;
122 bzero(dl, sizeof(*dl));
123 dl->d_secsize = DEV_BSIZE;
124 dl->d_nsectors = 1024;
126 dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
127 dl->d_secperunit = sc->nsect;
128 dl->d_ncylinders = dl->d_secperunit / dl->d_secpercyl;
133 mdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
137 printf("mdioctl(%s %lx %p %x %p)\n",
138 devtoname(dev), cmd, addr, flags, p);
144 mdstrategy(struct buf *bp)
149 printf("mdstrategy(%p) %s %lx, %d, %ld, %p)\n",
150 bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno,
151 bp->b_bcount / DEV_BSIZE, bp->b_data);
153 sc = bp->b_dev->si_drv1;
154 if (sc->type == MD_MALLOC) {
155 mdstrategy_malloc(bp);
157 mdstrategy_preload(bp);
164 mdstrategy_malloc(struct buf *bp)
168 devstat_trans_flags dop;
169 u_char *secp, **secpp, *dst;
170 unsigned secno, nsec, secval, uc;
173 printf("mdstrategy_malloc(%p) %s %lx, %d, %ld, %p)\n",
174 bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno,
175 bp->b_bcount / DEV_BSIZE, bp->b_data);
177 sc = bp->b_dev->si_drv1;
181 bufqdisksort(&sc->buf_queue, bp);
191 bp = bufq_first(&sc->buf_queue);
193 bufq_remove(&sc->buf_queue, bp);
198 devstat_start_transaction(&sc->stats);
200 if (bp->b_flags & B_FREEBUF)
201 dop = DEVSTAT_NO_DATA;
202 else if (bp->b_flags & B_READ)
207 nsec = bp->b_bcount / DEV_BSIZE;
208 secno = bp->b_pblkno;
212 if (secno < sc->nsecp) {
213 secpp = &sc->secp[secno];
214 if ((u_int)*secpp > 255) {
219 secval = (u_int) *secpp;
227 printf("%lx %p %p %d\n", bp->b_flags, secpp, secp, secval);
229 if (bp->b_flags & B_FREEBUF) {
232 FREE(secp, M_MDSECT);
235 } else if (bp->b_flags & B_READ) {
237 bcopy(secp, dst, DEV_BSIZE);
239 for (i = 0; i < DEV_BSIZE; i++)
242 bzero(dst, DEV_BSIZE);
246 for (i = 1; i < DEV_BSIZE; i++)
249 if (i == DEV_BSIZE && !uc) {
251 FREE(secp, M_MDSECT);
253 *secpp = (u_char *)uc;
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);
261 sc->nsecp = secno + nsec + 1;
262 secpp = &sc->secp[secno];
264 if (i == DEV_BSIZE) {
266 FREE(secp, M_MDSECT);
267 *secpp = (u_char *)uc;
270 MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK);
271 bcopy(dst, secp, DEV_BSIZE);
281 devstat_end_transaction_buf(&sc->stats, bp);
291 mdstrategy_preload(struct buf *bp)
295 devstat_trans_flags dop;
298 printf("mdstrategy_preload(%p) %s %lx, %d, %ld, %p)\n",
299 bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno,
300 bp->b_bcount / DEV_BSIZE, bp->b_data);
302 sc = bp->b_dev->si_drv1;
306 bufqdisksort(&sc->buf_queue, bp);
316 bp = bufq_first(&sc->buf_queue);
318 bufq_remove(&sc->buf_queue, bp);
323 devstat_start_transaction(&sc->stats);
325 if (bp->b_flags & B_FREEBUF) {
326 dop = DEVSTAT_NO_DATA;
327 } else if (bp->b_flags & B_READ) {
329 bcopy(sc->pl_ptr + (bp->b_pblkno << DEV_BSHIFT), bp->b_data, bp->b_bcount);
332 bcopy(bp->b_data, sc->pl_ptr + (bp->b_pblkno << DEV_BSHIFT), bp->b_bcount);
335 devstat_end_transaction_buf(&sc->stats, bp);
348 MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK);
349 bzero(sc, sizeof(*sc));
350 sc->unit = mdunits++;
351 bufq_init(&sc->buf_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;
362 mdcreate_preload(u_char *image, unsigned length)
367 sc->type = MD_PRELOAD;
368 sc->nsect = length / DEV_BSIZE;
377 mdcreate_malloc(void)
382 sc->type = MD_MALLOC;
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 *));
388 printf("md%d: Malloc disk\n", sc->unit);
392 md_drvinit(void *unused)
397 u_char *ptr, *name, *type;
401 mdcreate_preload(mfs_root, MD_ROOT_SIZE*1024);
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);
411 if (strcmp(type, "md_image") && strcmp(type, "mfs_root"))
413 c = preload_search_info(mod, MODINFO_ADDR);
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);
424 SYSINIT(mddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, md_drvinit,NULL)
428 md_takeroot(void *junk)
431 rootdevnames[0] = "ufs:/dev/md0c";
434 SYSINIT(md_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, md_takeroot, NULL);