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
;
95 struct disk_info info
;
99 kprintf("mdopen(%s %x %x)\n",
100 devtoname(dev
), ap
->a_oflags
, ap
->a_devtype
);
103 if (sc
->unit
+ 1 == mdunits
)
106 bzero(&info
, sizeof(info
));
107 info
.d_media_blksize
= DEV_BSIZE
; /* mandatory */
108 info
.d_media_blocks
= sc
->nsect
;
110 info
.d_secpertrack
= 1024; /* optional */
112 info
.d_secpercyl
= info
.d_secpertrack
* info
.d_nheads
;
113 info
.d_ncylinders
= (u_int
)(info
.d_media_blocks
/ info
.d_secpercyl
);
114 disk_setdiskinfo(&sc
->disk
, &info
);
120 mdioctl(struct dev_ioctl_args
*ap
)
122 cdev_t dev
= ap
->a_head
.a_dev
;
125 kprintf("mdioctl(%s %lx %p %x)\n",
126 devtoname(dev
), ap
->a_cmd
, ap
->a_data
, ap
->a_fflag
);
132 mdstrategy(struct dev_strategy_args
*ap
)
134 cdev_t dev
= ap
->a_head
.a_dev
;
135 struct bio
*bio
= ap
->a_bio
;
136 struct buf
*bp
= bio
->bio_buf
;
140 kprintf("mdstrategy(%p) %s %08x, %lld, %d, %p)\n",
141 bp
, devtoname(dev
), bp
->b_flags
,
142 (long long)bio
->bio_offset
,
143 bp
->b_bcount
, bp
->b_data
);
145 bio
->bio_driver_info
= dev
;
147 if (sc
->type
== MD_MALLOC
) {
148 mdstrategy_malloc(ap
);
150 mdstrategy_preload(ap
);
157 mdstrategy_malloc(struct dev_strategy_args
*ap
)
159 cdev_t dev
= ap
->a_head
.a_dev
;
160 struct bio
*bio
= ap
->a_bio
;
161 struct buf
*bp
= bio
->bio_buf
;
162 unsigned secno
, nsec
, secval
, uc
;
163 u_char
*secp
, **secpp
, *dst
;
168 kprintf("mdstrategy_malloc(%p) %s %08xx, %lld, %d, %p)\n",
169 bp
, devtoname(dev
), bp
->b_flags
,
170 (long long)bio
->bio_offset
,
171 bp
->b_bcount
, bp
->b_data
);
177 bioqdisksort(&sc
->bio_queue
, bio
);
187 bio
= bioq_first(&sc
->bio_queue
);
193 bioq_remove(&sc
->bio_queue
, bio
);
196 devstat_start_transaction(&sc
->stats
);
199 case BUF_CMD_FREEBLKS
:
204 panic("md: bad b_cmd %d", bp
->b_cmd
);
207 nsec
= bp
->b_bcount
>> DEV_BSHIFT
;
208 secno
= (unsigned)(bio
->bio_offset
>> DEV_BSHIFT
);
211 if (secno
< sc
->nsecp
) {
212 secpp
= &sc
->secp
[secno
];
213 if ((u_int
)(uintptr_t)*secpp
> 255) {
218 secval
= (u_int
)(uintptr_t)*secpp
;
226 kprintf("%08x %p %p %d\n", bp
->b_flags
, secpp
, secp
, secval
);
229 case BUF_CMD_FREEBLKS
:
232 FREE(secp
, M_MDSECT
);
238 bcopy(secp
, dst
, DEV_BSIZE
);
240 for (i
= 0; i
< DEV_BSIZE
; i
++)
243 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
*)(uintptr_t)uc
;
258 MALLOC(secpp
, u_char
**, (secno
+ nsec
+ 1) * sizeof(u_char
*), M_MD
, M_WAITOK
| M_ZERO
);
259 bcopy(sc
->secp
, secpp
, sc
->nsecp
* sizeof(u_char
*));
260 FREE(sc
->secp
, M_MD
);
262 sc
->nsecp
= secno
+ nsec
+ 1;
263 secpp
= &sc
->secp
[secno
];
265 if (i
== DEV_BSIZE
) {
267 FREE(secp
, M_MDSECT
);
268 *secpp
= (u_char
*)(uintptr_t)uc
;
271 MALLOC(secp
, u_char
*, DEV_BSIZE
, M_MDSECT
, M_WAITOK
);
272 bcopy(dst
, secp
, DEV_BSIZE
);
279 panic("md: bad b_cmd %d", bp
->b_cmd
);
286 devstat_end_transaction_buf(&sc
->stats
, bp
);
296 mdstrategy_preload(struct dev_strategy_args
*ap
)
298 cdev_t dev
= ap
->a_head
.a_dev
;
299 struct bio
*bio
= ap
->a_bio
;
300 struct buf
*bp
= bio
->bio_buf
;
304 kprintf("mdstrategy_preload(%p) %s %08x, %lld, %d, %p)\n",
305 bp
, devtoname(dev
), bp
->b_flags
,
306 (long long)bio
->bio_offset
,
307 bp
->b_bcount
, bp
->b_data
);
313 bioqdisksort(&sc
->bio_queue
, bio
);
323 bio
= bioq_first(&sc
->bio_queue
);
325 bioq_remove(&sc
->bio_queue
, bio
);
330 devstat_start_transaction(&sc
->stats
);
333 case BUF_CMD_FREEBLKS
:
336 bcopy(sc
->pl_ptr
+ bio
->bio_offset
,
337 bp
->b_data
, bp
->b_bcount
);
340 bcopy(bp
->b_data
, sc
->pl_ptr
+ bio
->bio_offset
,
344 panic("md: bad cmd %d\n", bp
->b_cmd
);
347 devstat_end_transaction_buf(&sc
->stats
, bp
);
356 mdcreate(unsigned length
)
359 struct disk_info info
;
361 MALLOC(sc
, struct md_s
*,sizeof(*sc
), M_MD
, M_WAITOK
| M_ZERO
);
362 sc
->unit
= mdunits
++;
363 bioq_init(&sc
->bio_queue
);
364 devstat_add_entry(&sc
->stats
, "md", sc
->unit
, DEV_BSIZE
,
365 DEVSTAT_NO_ORDERED_TAGS
,
366 DEVSTAT_TYPE_DIRECT
| DEVSTAT_TYPE_IF_OTHER
,
367 DEVSTAT_PRIORITY_OTHER
);
368 sc
->dev
= disk_create(sc
->unit
, &sc
->disk
, &md_ops
);
369 sc
->dev
->si_drv1
= sc
;
370 sc
->dev
->si_iosize_max
= DFLTPHYS
;
372 bzero(&info
, sizeof(info
));
373 info
.d_media_blksize
= DEV_BSIZE
; /* mandatory */
374 info
.d_media_blocks
= length
/ DEV_BSIZE
;
376 info
.d_secpertrack
= 1024; /* optional */
378 info
.d_secpercyl
= info
.d_secpertrack
* info
.d_nheads
;
379 info
.d_ncylinders
= (u_int
)(info
.d_media_blocks
/ info
.d_secpercyl
);
380 disk_setdiskinfo(&sc
->disk
, &info
);
386 mdcreate_preload(u_char
*image
, unsigned length
)
390 sc
= mdcreate(length
);
391 sc
->type
= MD_PRELOAD
;
392 sc
->nsect
= length
/ DEV_BSIZE
;
401 mdcreate_malloc(void)
406 sc
->type
= MD_MALLOC
;
408 sc
->nsect
= MD_NSECT
; /* for now */
409 MALLOC(sc
->secp
, u_char
**, sizeof(u_char
*), M_MD
, M_WAITOK
| M_ZERO
);
411 kprintf("md%d: Malloc disk\n", sc
->unit
);
415 md_drvinit(void *unused
)
420 u_char
*ptr
, *name
, *type
;
424 mdcreate_preload(mfs_root
, MD_ROOT_SIZE
*1024);
427 while ((mod
= preload_search_next_name(mod
)) != NULL
) {
428 name
= (char *)preload_search_info(mod
, MODINFO_NAME
);
429 type
= (char *)preload_search_info(mod
, MODINFO_TYPE
);
434 if (strcmp(type
, "md_image") && strcmp(type
, "mfs_root"))
436 c
= preload_search_info(mod
, MODINFO_ADDR
);
438 c
= preload_search_info(mod
, MODINFO_SIZE
);
439 len
= *(unsigned *)c
;
440 kprintf("md%d: Preloaded image <%s> %d bytes at %p\n",
441 mdunits
, name
, len
, ptr
);
442 mdcreate_preload(ptr
, len
);
447 SYSINIT(mddev
,SI_SUB_DRIVERS
,SI_ORDER_MIDDLE
+CDEV_MAJOR
, md_drvinit
,NULL
)
451 md_takeroot(void *junk
)
454 rootdevnames
[0] = "ufs:/dev/md0s0";
457 SYSINIT(md_root
, SI_SUB_MOUNT_ROOT
, SI_ORDER_FIRST
, md_takeroot
, NULL
);