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.20 2008/09/07 08:09:39 swildner Exp $
14 #include "opt_md.h" /* We have adopted some tasks from MFS */
16 #include <sys/param.h>
17 #include <sys/systm.h>
20 #include <sys/devicestat.h>
22 #include <sys/kernel.h>
23 #include <sys/malloc.h>
24 #include <sys/sysctl.h>
25 #include <sys/linker.h>
28 #include <sys/thread2.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(MD_ROOT) && defined(MD_ROOT_SIZE)
41 /* Image gets put here: */
42 static u_char mfs_root
[MD_ROOT_SIZE
*1024] = "MFS Filesystem goes here";
43 static u_char end_mfs_root
[] __unused
= "MFS Filesystem had better STOP here";
46 static int mdrootready
;
48 static void mdcreate_malloc(void);
52 static d_strategy_t mdstrategy
;
53 static d_strategy_t mdstrategy_preload
;
54 static d_strategy_t mdstrategy_malloc
;
55 static d_open_t mdopen
;
56 static d_ioctl_t mdioctl
;
58 static struct dev_ops md_ops
= {
59 { "md", CDEV_MAJOR
, D_DISK
| D_CANFREE
| D_MEMDISK
},
65 .d_strategy
= mdstrategy
,
71 struct bio_queue_head bio_queue
;
75 enum {MD_MALLOC
, MD_PRELOAD
} type
;
78 /* MD_MALLOC related fields */
82 /* MD_PRELOAD related fields */
90 mdopen(struct dev_open_args
*ap
)
92 cdev_t dev
= ap
->a_head
.a_dev
;
94 struct disk_info info
;
97 kprintf("mdopen(%s %x %x)\n",
98 devtoname(dev
), ap
->a_oflags
, ap
->a_devtype
);
101 if (sc
->unit
+ 1 == mdunits
)
104 bzero(&info
, sizeof(info
));
105 info
.d_media_blksize
= DEV_BSIZE
; /* mandatory */
106 info
.d_media_blocks
= sc
->nsect
;
108 info
.d_secpertrack
= 1024; /* optional */
110 info
.d_secpercyl
= info
.d_secpertrack
* info
.d_nheads
;
111 info
.d_ncylinders
= (u_int
)(info
.d_media_blocks
/ info
.d_secpercyl
);
112 disk_setdiskinfo(&sc
->disk
, &info
);
118 mdioctl(struct dev_ioctl_args
*ap
)
120 cdev_t dev
= ap
->a_head
.a_dev
;
123 kprintf("mdioctl(%s %lx %p %x)\n",
124 devtoname(dev
), ap
->a_cmd
, ap
->a_data
, ap
->a_fflag
);
130 mdstrategy(struct dev_strategy_args
*ap
)
132 cdev_t dev
= ap
->a_head
.a_dev
;
133 struct bio
*bio
= ap
->a_bio
;
134 struct buf
*bp
= bio
->bio_buf
;
138 kprintf("mdstrategy(%p) %s %08x, %lld, %d, %p)\n",
139 bp
, devtoname(dev
), bp
->b_flags
,
140 (long long)bio
->bio_offset
,
141 bp
->b_bcount
, bp
->b_data
);
143 bio
->bio_driver_info
= dev
;
145 if (sc
->type
== MD_MALLOC
) {
146 mdstrategy_malloc(ap
);
148 mdstrategy_preload(ap
);
155 mdstrategy_malloc(struct dev_strategy_args
*ap
)
157 cdev_t dev
= ap
->a_head
.a_dev
;
158 struct bio
*bio
= ap
->a_bio
;
159 struct buf
*bp
= bio
->bio_buf
;
160 unsigned secno
, nsec
, secval
, uc
;
161 u_char
*secp
, **secpp
, *dst
;
166 kprintf("mdstrategy_malloc(%p) %s %08xx, %lld, %d, %p)\n",
167 bp
, devtoname(dev
), bp
->b_flags
,
168 (long long)bio
->bio_offset
,
169 bp
->b_bcount
, bp
->b_data
);
175 bioqdisksort(&sc
->bio_queue
, bio
);
185 bio
= bioq_first(&sc
->bio_queue
);
191 bioq_remove(&sc
->bio_queue
, bio
);
194 devstat_start_transaction(&sc
->stats
);
197 case BUF_CMD_FREEBLKS
:
202 panic("md: bad b_cmd %d", bp
->b_cmd
);
205 nsec
= bp
->b_bcount
>> DEV_BSHIFT
;
206 secno
= (unsigned)(bio
->bio_offset
>> DEV_BSHIFT
);
209 if (secno
< sc
->nsecp
) {
210 secpp
= &sc
->secp
[secno
];
211 if ((u_int
)(uintptr_t)*secpp
> 255) {
216 secval
= (u_int
)(uintptr_t)*secpp
;
224 kprintf("%08x %p %p %d\n", bp
->b_flags
, secpp
, secp
, secval
);
227 case BUF_CMD_FREEBLKS
:
230 FREE(secp
, M_MDSECT
);
236 bcopy(secp
, dst
, DEV_BSIZE
);
238 for (i
= 0; i
< DEV_BSIZE
; i
++)
241 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
*)(uintptr_t)uc
;
256 MALLOC(secpp
, u_char
**, (secno
+ nsec
+ 1) * sizeof(u_char
*), M_MD
, M_WAITOK
| M_ZERO
);
257 bcopy(sc
->secp
, secpp
, sc
->nsecp
* sizeof(u_char
*));
258 FREE(sc
->secp
, M_MD
);
260 sc
->nsecp
= secno
+ nsec
+ 1;
261 secpp
= &sc
->secp
[secno
];
263 if (i
== DEV_BSIZE
) {
265 FREE(secp
, M_MDSECT
);
266 *secpp
= (u_char
*)(uintptr_t)uc
;
269 MALLOC(secp
, u_char
*, DEV_BSIZE
, M_MDSECT
, M_WAITOK
);
270 bcopy(dst
, secp
, DEV_BSIZE
);
277 panic("md: bad b_cmd %d", bp
->b_cmd
);
284 devstat_end_transaction_buf(&sc
->stats
, bp
);
294 mdstrategy_preload(struct dev_strategy_args
*ap
)
296 cdev_t dev
= ap
->a_head
.a_dev
;
297 struct bio
*bio
= ap
->a_bio
;
298 struct buf
*bp
= bio
->bio_buf
;
302 kprintf("mdstrategy_preload(%p) %s %08x, %lld, %d, %p)\n",
303 bp
, devtoname(dev
), bp
->b_flags
,
304 (long long)bio
->bio_offset
,
305 bp
->b_bcount
, bp
->b_data
);
311 bioqdisksort(&sc
->bio_queue
, bio
);
321 bio
= bioq_first(&sc
->bio_queue
);
323 bioq_remove(&sc
->bio_queue
, bio
);
328 devstat_start_transaction(&sc
->stats
);
331 case BUF_CMD_FREEBLKS
:
334 bcopy(sc
->pl_ptr
+ bio
->bio_offset
,
335 bp
->b_data
, bp
->b_bcount
);
338 bcopy(bp
->b_data
, sc
->pl_ptr
+ bio
->bio_offset
,
342 panic("md: bad cmd %d\n", bp
->b_cmd
);
345 devstat_end_transaction_buf(&sc
->stats
, bp
);
358 MALLOC(sc
, struct md_s
*,sizeof(*sc
), M_MD
, M_WAITOK
| M_ZERO
);
359 sc
->unit
= mdunits
++;
360 bioq_init(&sc
->bio_queue
);
361 devstat_add_entry(&sc
->stats
, "md", sc
->unit
, DEV_BSIZE
,
362 DEVSTAT_NO_ORDERED_TAGS
,
363 DEVSTAT_TYPE_DIRECT
| DEVSTAT_TYPE_IF_OTHER
,
364 DEVSTAT_PRIORITY_OTHER
);
365 sc
->dev
= disk_create(sc
->unit
, &sc
->disk
, &md_ops
);
366 sc
->dev
->si_drv1
= sc
;
367 sc
->dev
->si_iosize_max
= DFLTPHYS
;
373 mdcreate_preload(u_char
*image
, unsigned length
)
378 sc
->type
= MD_PRELOAD
;
379 sc
->nsect
= length
/ DEV_BSIZE
;
388 mdcreate_malloc(void)
393 sc
->type
= MD_MALLOC
;
395 sc
->nsect
= MD_NSECT
; /* for now */
396 MALLOC(sc
->secp
, u_char
**, sizeof(u_char
*), M_MD
, M_WAITOK
| M_ZERO
);
398 kprintf("md%d: Malloc disk\n", sc
->unit
);
402 md_drvinit(void *unused
)
407 u_char
*ptr
, *name
, *type
;
411 mdcreate_preload(mfs_root
, MD_ROOT_SIZE
*1024);
414 while ((mod
= preload_search_next_name(mod
)) != NULL
) {
415 name
= (char *)preload_search_info(mod
, MODINFO_NAME
);
416 type
= (char *)preload_search_info(mod
, MODINFO_TYPE
);
421 if (strcmp(type
, "md_image") && strcmp(type
, "mfs_root"))
423 c
= preload_search_info(mod
, MODINFO_ADDR
);
425 c
= preload_search_info(mod
, MODINFO_SIZE
);
426 len
= *(unsigned *)c
;
427 kprintf("md%d: Preloaded image <%s> %d bytes at %p\n",
428 mdunits
, name
, len
, ptr
);
429 mdcreate_preload(ptr
, len
);
434 SYSINIT(mddev
,SI_SUB_DRIVERS
,SI_ORDER_MIDDLE
+CDEV_MAJOR
, md_drvinit
,NULL
)
438 md_takeroot(void *junk
)
441 rootdevnames
[0] = "ufs:/dev/md0c";
444 SYSINIT(md_root
, SI_SUB_MOUNT_ROOT
, SI_ORDER_FIRST
, md_takeroot
, NULL
);