The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/md/md.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    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  * ----------------------------------------------------------------------------
    8  *
    9  * $FreeBSD$
   10  *
   11  */
   12 
   13 #include "opt_mfs.h"            /* We have adopted some tasks from MFS */
   14 #include "opt_md.h"             /* We have adopted some tasks from MFS */
   15 
   16 #include <sys/param.h>
   17 #include <sys/systm.h>
   18 #include <sys/buf.h>
   19 #include <sys/conf.h>
   20 #include <sys/devicestat.h>
   21 #include <sys/disk.h>
   22 #include <sys/kernel.h>
   23 #include <sys/malloc.h>
   24 #include <sys/sysctl.h>
   25 #include <sys/linker.h>
   26 
   27 #ifndef MD_NSECT
   28 #define MD_NSECT (10000 * 2)
   29 #endif
   30 
   31 MALLOC_DEFINE(M_MD, "MD disk", "Memory Disk");
   32 MALLOC_DEFINE(M_MDSECT, "MD sectors", "Memory Disk Sectors");
   33 
   34 static int md_debug;
   35 SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, "");
   36 
   37 #if defined(MFS_ROOT) && !defined(MD_ROOT)
   38 #define MD_ROOT MFS_ROOT
   39 #warning "option MFS_ROOT has been superceeded by MD_ROOT"
   40 #endif
   41 
   42 #if defined(MFS_ROOT_SIZE) && !defined(MD_ROOT_SIZE)
   43 #define MD_ROOT_SIZE MFS_ROOT_SIZE
   44 #warning "option MFS_ROOT_SIZE has been superceeded by MD_ROOT_SIZE"
   45 #endif
   46 
   47 #if defined(MD_ROOT) && defined(MD_ROOT_SIZE)
   48 /* Image gets put here: */
   49 static u_char mfs_root[MD_ROOT_SIZE*1024] = "MFS Filesystem goes here";
   50 static u_char end_mfs_root[] __unused = "MFS Filesystem had better STOP here";
   51 #endif
   52 
   53 static int mdrootready;
   54 
   55 static void mdcreate_malloc(void);
   56 
   57 #define CDEV_MAJOR      95
   58 #define BDEV_MAJOR      22
   59 
   60 static d_strategy_t mdstrategy;
   61 static d_strategy_t mdstrategy_preload;
   62 static d_strategy_t mdstrategy_malloc;
   63 static d_open_t mdopen;
   64 static d_ioctl_t mdioctl;
   65 
   66 static struct cdevsw md_cdevsw = {
   67         /* open */      mdopen,
   68         /* close */     nullclose,
   69         /* read */      physread,
   70         /* write */     physwrite,
   71         /* ioctl */     mdioctl,
   72         /* poll */      nopoll,
   73         /* mmap */      nommap,
   74         /* strategy */  mdstrategy,
   75         /* name */      "md",
   76         /* maj */       CDEV_MAJOR,
   77         /* dump */      nodump,
   78         /* psize */     nopsize,
   79         /* flags */     D_DISK | D_CANFREE | D_MEMDISK,
   80         /* bmaj */      BDEV_MAJOR
   81 };
   82 
   83 static struct cdevsw mddisk_cdevsw;
   84 
   85 struct md_s {
   86         int unit;
   87         struct devstat stats;
   88         struct buf_queue_head buf_queue;
   89         struct disk disk;
   90         dev_t dev;
   91         int busy;
   92         enum {MD_MALLOC, MD_PRELOAD} type;
   93         unsigned nsect;
   94 
   95         /* MD_MALLOC related fields */
   96         unsigned nsecp;
   97         u_char **secp;
   98 
   99         /* MD_PRELOAD related fields */
  100         u_char *pl_ptr;
  101         unsigned pl_len;
  102 };
  103 
  104 static int mdunits;
  105 
  106 static int
  107 mdopen(dev_t dev, int flag, int fmt, struct proc *p)
  108 {
  109         struct md_s *sc;
  110         struct disklabel *dl;
  111 
  112         if (md_debug)
  113                 printf("mdopen(%s %x %x %p)\n",
  114                         devtoname(dev), flag, fmt, p);
  115 
  116         sc = dev->si_drv1;
  117         if (sc->unit + 1 == mdunits)
  118                 mdcreate_malloc();
  119 
  120         dl = &sc->disk.d_label;
  121         bzero(dl, sizeof(*dl));
  122         dl->d_secsize = DEV_BSIZE;
  123         dl->d_nsectors = 1024;
  124         dl->d_ntracks = 1;
  125         dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
  126         dl->d_secperunit = sc->nsect;
  127         dl->d_ncylinders = dl->d_secperunit / dl->d_secpercyl;
  128         return (0);
  129 }
  130 
  131 static int
  132 mdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
  133 {
  134 
  135         if (md_debug)
  136                 printf("mdioctl(%s %lx %p %x %p)\n",
  137                         devtoname(dev), cmd, addr, flags, p);
  138 
  139         return (ENOIOCTL);
  140 }
  141 
  142 static void
  143 mdstrategy(struct buf *bp)
  144 {
  145         struct md_s *sc;
  146 
  147         if (md_debug > 1)
  148                 printf("mdstrategy(%p) %s %lx, %d, %ld, %p)\n",
  149                     bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno, 
  150                     bp->b_bcount / DEV_BSIZE, bp->b_data);
  151 
  152         sc = bp->b_dev->si_drv1;
  153         if (sc->type == MD_MALLOC) {
  154                 mdstrategy_malloc(bp);
  155         } else {
  156                 mdstrategy_preload(bp);
  157         }
  158         return;
  159 }
  160 
  161 
  162 static void
  163 mdstrategy_malloc(struct buf *bp)
  164 {
  165         int s, i;
  166         struct md_s *sc;
  167         devstat_trans_flags dop;
  168         u_char *secp, **secpp, *dst;
  169         unsigned secno, nsec, secval, uc;
  170 
  171         if (md_debug > 1)
  172                 printf("mdstrategy_malloc(%p) %s %lx, %d, %ld, %p)\n",
  173                     bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno, 
  174                     bp->b_bcount / DEV_BSIZE, bp->b_data);
  175 
  176         sc = bp->b_dev->si_drv1;
  177 
  178         s = splbio();
  179 
  180         bufqdisksort(&sc->buf_queue, bp);
  181 
  182         if (sc->busy) {
  183                 splx(s);
  184                 return;
  185         }
  186 
  187         sc->busy++;
  188         
  189         while (1) {
  190                 bp = bufq_first(&sc->buf_queue);
  191                 if (bp)
  192                         bufq_remove(&sc->buf_queue, bp);
  193                 splx(s);
  194                 if (!bp)
  195                         break;
  196 
  197                 devstat_start_transaction(&sc->stats);
  198 
  199                 if (bp->b_flags & B_FREEBUF) 
  200                         dop = DEVSTAT_NO_DATA;
  201                 else if (bp->b_flags & B_READ)
  202                         dop = DEVSTAT_READ;
  203                 else
  204                         dop = DEVSTAT_WRITE;
  205 
  206                 nsec = bp->b_bcount / DEV_BSIZE;
  207                 secno = bp->b_pblkno;
  208                 dst = bp->b_data;
  209                 while (nsec--) {
  210 
  211                         if (secno < sc->nsecp) {
  212                                 secpp = &sc->secp[secno];
  213                                 if ((u_int)*secpp > 255) {
  214                                         secp = *secpp;
  215                                         secval = 0;
  216                                 } else {
  217                                         secp = 0;
  218                                         secval = (u_int) *secpp;
  219                                 }
  220                         } else {
  221                                 secpp = 0;
  222                                 secp = 0;
  223                                 secval = 0;
  224                         }
  225                         if (md_debug > 2)
  226                                 printf("%lx %p %p %d\n", bp->b_flags, secpp, secp, secval);
  227 
  228                         if (bp->b_flags & B_FREEBUF) {
  229                                 if (secpp) {
  230                                         if (secp)
  231                                                 FREE(secp, M_MDSECT);
  232                                         *secpp = 0;
  233                                 }
  234                         } else if (bp->b_flags & B_READ) {
  235                                 if (secp) {
  236                                         bcopy(secp, dst, DEV_BSIZE);
  237                                 } else if (secval) {
  238                                         for (i = 0; i < DEV_BSIZE; i++)
  239                                                 dst[i] = secval;
  240                                 } else {
  241                                         bzero(dst, DEV_BSIZE);
  242                                 }
  243                         } else {
  244                                 uc = dst[0];
  245                                 for (i = 1; i < DEV_BSIZE; i++) 
  246                                         if (dst[i] != uc)
  247                                                 break;
  248                                 if (i == DEV_BSIZE && !uc) {
  249                                         if (secp)
  250                                                 FREE(secp, M_MDSECT);
  251                                         if (secpp)
  252                                                 *secpp = (u_char *)uc;
  253                                 } else {
  254                                         if (!secpp) {
  255                                                 MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK);
  256                                                 bzero(secpp, (secno + nsec + 1) * sizeof(u_char *));
  257                                                 bcopy(sc->secp, secpp, sc->nsecp * sizeof(u_char *));
  258                                                 FREE(sc->secp, M_MD);
  259                                                 sc->secp = secpp;
  260                                                 sc->nsecp = secno + nsec + 1;
  261                                                 secpp = &sc->secp[secno];
  262                                         }
  263                                         if (i == DEV_BSIZE) {
  264                                                 if (secp)
  265                                                         FREE(secp, M_MDSECT);
  266                                                 *secpp = (u_char *)uc;
  267                                         } else {
  268                                                 if (!secp) 
  269                                                         MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK);
  270                                                 bcopy(dst, secp, DEV_BSIZE);
  271 
  272                                                 *secpp = secp;
  273                                         }
  274                                 }
  275                         }
  276                         secno++;
  277                         dst += DEV_BSIZE;
  278                 }
  279                 bp->b_resid = 0;
  280                 devstat_end_transaction_buf(&sc->stats, bp);
  281                 biodone(bp);
  282                 s = splbio();
  283         }
  284         sc->busy = 0;
  285         return;
  286 }
  287 
  288 
  289 static void
  290 mdstrategy_preload(struct buf *bp)
  291 {
  292         int s;
  293         struct md_s *sc;
  294         devstat_trans_flags dop;
  295 
  296         if (md_debug > 1)
  297                 printf("mdstrategy_preload(%p) %s %lx, %d, %ld, %p)\n",
  298                     bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno, 
  299                     bp->b_bcount / DEV_BSIZE, bp->b_data);
  300 
  301         sc = bp->b_dev->si_drv1;
  302 
  303         s = splbio();
  304 
  305         bufqdisksort(&sc->buf_queue, bp);
  306 
  307         if (sc->busy) {
  308                 splx(s);
  309                 return;
  310         }
  311 
  312         sc->busy++;
  313         
  314         while (1) {
  315                 bp = bufq_first(&sc->buf_queue);
  316                 if (bp)
  317                         bufq_remove(&sc->buf_queue, bp);
  318                 splx(s);
  319                 if (!bp)
  320                         break;
  321 
  322                 devstat_start_transaction(&sc->stats);
  323 
  324                 if (bp->b_flags & B_FREEBUF) {
  325                         dop = DEVSTAT_NO_DATA;
  326                 } else if (bp->b_flags & B_READ) {
  327                         dop = DEVSTAT_READ;
  328                         bcopy(sc->pl_ptr + (bp->b_pblkno << DEV_BSHIFT), bp->b_data, bp->b_bcount);
  329                 } else {
  330                         dop = DEVSTAT_WRITE;
  331                         bcopy(bp->b_data, sc->pl_ptr + (bp->b_pblkno << DEV_BSHIFT), bp->b_bcount);
  332                 }
  333                 bp->b_resid = 0;
  334                 devstat_end_transaction_buf(&sc->stats, bp);
  335                 biodone(bp);
  336                 s = splbio();
  337         }
  338         sc->busy = 0;
  339         return;
  340 }
  341 
  342 static struct md_s *
  343 mdcreate(void)
  344 {
  345         struct md_s *sc;
  346 
  347         MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK);
  348         bzero(sc, sizeof(*sc));
  349         sc->unit = mdunits++;
  350         bufq_init(&sc->buf_queue);
  351         devstat_add_entry(&sc->stats, "md", sc->unit, DEV_BSIZE,
  352                 DEVSTAT_NO_ORDERED_TAGS, 
  353                 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
  354                 DEVSTAT_PRIORITY_OTHER);
  355         sc->dev = disk_create(sc->unit, &sc->disk, 0, &md_cdevsw, &mddisk_cdevsw);
  356         sc->dev->si_drv1 = sc;
  357         return (sc);
  358 }
  359 
  360 static void
  361 mdcreate_preload(u_char *image, unsigned length)
  362 {
  363         struct md_s *sc;
  364 
  365         sc = mdcreate();
  366         sc->type = MD_PRELOAD;
  367         sc->nsect = length / DEV_BSIZE;
  368         sc->pl_ptr = image;
  369         sc->pl_len = length;
  370 
  371         if (sc->unit == 0) 
  372                 mdrootready = 1;
  373 }
  374 
  375 static void
  376 mdcreate_malloc(void)
  377 {
  378         struct md_s *sc;
  379 
  380         sc = mdcreate();
  381         sc->type = MD_MALLOC;
  382 
  383         sc->nsect = MD_NSECT;   /* for now */
  384         MALLOC(sc->secp, u_char **, sizeof(u_char *), M_MD, M_WAITOK);
  385         bzero(sc->secp, sizeof(u_char *));
  386         sc->nsecp = 1;
  387         printf("md%d: Malloc disk\n", sc->unit);
  388 }
  389 
  390 static void
  391 md_drvinit(void *unused)
  392 {
  393 
  394         caddr_t mod;
  395         caddr_t c;
  396         u_char *ptr, *name, *type;
  397         unsigned len;
  398 
  399 #ifdef MD_ROOT_SIZE
  400         mdcreate_preload(mfs_root, MD_ROOT_SIZE*1024);
  401 #endif
  402         mod = NULL;
  403         while ((mod = preload_search_next_name(mod)) != NULL) {
  404                 name = (char *)preload_search_info(mod, MODINFO_NAME);
  405                 type = (char *)preload_search_info(mod, MODINFO_TYPE);
  406                 if (name == NULL)
  407                         continue;
  408                 if (type == NULL)
  409                         continue;
  410                 if (strcmp(type, "md_image") && strcmp(type, "mfs_root"))
  411                         continue;
  412                 c = preload_search_info(mod, MODINFO_ADDR);
  413                 ptr = *(u_char **)c;
  414                 c = preload_search_info(mod, MODINFO_SIZE);
  415                 len = *(unsigned *)c;
  416                 printf("md%d: Preloaded image <%s> %d bytes at %p\n",
  417                    mdunits, name, len, ptr);
  418                 mdcreate_preload(ptr, len);
  419         } 
  420         mdcreate_malloc();
  421 }
  422 
  423 SYSINIT(mddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, md_drvinit,NULL)
  424 
  425 #ifdef MD_ROOT
  426 static void
  427 md_takeroot(void *junk)
  428 {
  429         if (mdrootready)
  430                 rootdevnames[0] = "ufs:/dev/md0c";
  431 }
  432 
  433 SYSINIT(md_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, md_takeroot, NULL);
  434 #endif

Cache object: 3f438d81010b6edeca516fbea81ac659


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.