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/dksubr.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 /* $NetBSD: dksubr.c,v 1.27.2.1 2007/07/01 17:09:24 bouyer Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe and Roland C. Dowdeswell.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.27.2.1 2007/07/01 17:09:24 bouyer Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/stat.h>
   45 #include <sys/proc.h>
   46 #include <sys/ioctl.h>
   47 #include <sys/device.h>
   48 #include <sys/disk.h>
   49 #include <sys/disklabel.h>
   50 #include <sys/buf.h>
   51 #include <sys/bufq.h>
   52 #include <sys/vnode.h>
   53 #include <sys/fcntl.h>
   54 #include <sys/namei.h>
   55 
   56 #include <dev/dkvar.h>
   57 
   58 int     dkdebug = 0;
   59 
   60 #ifdef DEBUG
   61 #define DKDB_FOLLOW     0x1
   62 #define DKDB_INIT       0x2
   63 #define DKDB_VNODE      0x4
   64 
   65 #define IFDEBUG(x,y)            if (dkdebug & (x)) y
   66 #define DPRINTF(x,y)            IFDEBUG(x, printf y)
   67 #define DPRINTF_FOLLOW(y)       DPRINTF(DKDB_FOLLOW, y)
   68 #else
   69 #define IFDEBUG(x,y)
   70 #define DPRINTF(x,y)
   71 #define DPRINTF_FOLLOW(y)
   72 #endif
   73 
   74 #define DKLABELDEV(dev) \
   75         (MAKEDISKDEV(major((dev)), DISKUNIT((dev)), RAW_PART))
   76 
   77 static void     dk_makedisklabel(struct dk_intf *, struct dk_softc *);
   78 
   79 void
   80 dk_sc_init(struct dk_softc *dksc, void *osc, char *xname)
   81 {
   82 
   83         memset(dksc, 0x0, sizeof(*dksc));
   84         dksc->sc_osc = osc;
   85         strncpy(dksc->sc_xname, xname, DK_XNAME_SIZE);
   86         dksc->sc_dkdev.dk_name = dksc->sc_xname;
   87 }
   88 
   89 /* ARGSUSED */
   90 int
   91 dk_open(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
   92     int flags, int fmt, struct lwp *l)
   93 {
   94         struct  disklabel *lp = dksc->sc_dkdev.dk_label;
   95         int     part = DISKPART(dev);
   96         int     pmask = 1 << part;
   97         int     ret = 0;
   98         struct disk *dk = &dksc->sc_dkdev;
   99 
  100         DPRINTF_FOLLOW(("dk_open(%s, %p, 0x%x, 0x%x)\n",
  101             di->di_dkname, dksc, dev, flags));
  102 
  103         if ((ret = lockmgr(&dk->dk_openlock, LK_EXCLUSIVE, NULL)) != 0)
  104                 return ret;
  105 
  106         part = DISKPART(dev);
  107 
  108         /*
  109          * If there are wedges, and this is not RAW_PART, then we
  110          * need to fail.
  111          */
  112         if (dk->dk_nwedges != 0 && part != RAW_PART) {
  113                 ret = EBUSY;
  114                 goto done;
  115         }
  116 
  117         pmask = 1 << part;
  118 
  119         /*
  120          * If we're init'ed and there are no other open partitions then
  121          * update the in-core disklabel.
  122          */
  123         if ((dksc->sc_flags & DKF_INITED)) {
  124                 if (dk->dk_openmask == 0) {
  125                         dk_getdisklabel(di, dksc, dev);
  126                 }
  127                 /* XXX re-discover wedges? */
  128         }
  129 
  130         /* Fail if we can't find the partition. */
  131         if ((part != RAW_PART) &&
  132             (((dksc->sc_flags & DKF_INITED) == 0) ||
  133             ((part >= lp->d_npartitions) ||
  134             (lp->d_partitions[part].p_fstype == FS_UNUSED)))) {
  135                 ret = ENXIO;
  136                 goto done;
  137         }
  138 
  139         /* Mark our unit as open. */
  140         switch (fmt) {
  141         case S_IFCHR:
  142                 dk->dk_copenmask |= pmask;
  143                 break;
  144         case S_IFBLK:
  145                 dk->dk_bopenmask |= pmask;
  146                 break;
  147         }
  148 
  149         dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
  150 
  151 done:
  152         lockmgr(&dk->dk_openlock, LK_RELEASE, NULL);
  153         return ret;
  154 }
  155 
  156 /* ARGSUSED */
  157 int
  158 dk_close(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
  159     int flags, int fmt, struct lwp *l)
  160 {
  161         int     part = DISKPART(dev);
  162         int     pmask = 1 << part;
  163         int     ret;
  164         struct disk *dk = &dksc->sc_dkdev;
  165 
  166         DPRINTF_FOLLOW(("dk_close(%s, %p, 0x%x, 0x%x)\n",
  167             di->di_dkname, dksc, dev, flags));
  168 
  169         if ((ret = lockmgr(&dk->dk_openlock, LK_EXCLUSIVE, NULL)) != 0)
  170                 return ret;
  171 
  172         switch (fmt) {
  173         case S_IFCHR:
  174                 dk->dk_copenmask &= ~pmask;
  175                 break;
  176         case S_IFBLK:
  177                 dk->dk_bopenmask &= ~pmask;
  178                 break;
  179         }
  180         dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
  181 
  182         lockmgr(&dk->dk_openlock, LK_RELEASE, NULL);
  183         return 0;
  184 }
  185 
  186 void
  187 dk_strategy(struct dk_intf *di, struct dk_softc *dksc, struct buf *bp)
  188 {
  189         int     s;
  190         int     wlabel;
  191         daddr_t blkno;
  192 
  193         DPRINTF_FOLLOW(("dk_strategy(%s, %p, %p)\n",
  194             di->di_dkname, dksc, bp));
  195 
  196         if (!(dksc->sc_flags & DKF_INITED)) {
  197                 DPRINTF_FOLLOW(("dk_strategy: not inited\n"));
  198                 bp->b_error  = ENXIO;
  199                 bp->b_flags |= B_ERROR;
  200                 biodone(bp);
  201                 return;
  202         }
  203 
  204         /* XXX look for some more errors, c.f. ld.c */
  205 
  206         bp->b_resid = bp->b_bcount;
  207 
  208         /* If there is nothing to do, then we are done */
  209         if (bp->b_bcount == 0) {
  210                 biodone(bp);
  211                 return;
  212         }
  213 
  214         wlabel = dksc->sc_flags & (DKF_WLABEL|DKF_LABELLING);
  215         if (DISKPART(bp->b_dev) != RAW_PART &&
  216             bounds_check_with_label(&dksc->sc_dkdev, bp, wlabel) <= 0) {
  217                 biodone(bp);
  218                 return;
  219         }
  220 
  221         blkno = bp->b_blkno;
  222         if (DISKPART(bp->b_dev) != RAW_PART) {
  223                 struct partition *pp;
  224 
  225                 pp =
  226                     &dksc->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)];
  227                 blkno += pp->p_offset;
  228         }
  229         bp->b_rawblkno = blkno;
  230 
  231         /*
  232          * Start the unit by calling the start routine
  233          * provided by the individual driver.
  234          */
  235         s = splbio();
  236         BUFQ_PUT(dksc->sc_bufq, bp);
  237         dk_start(di, dksc);
  238         splx(s);
  239         return;
  240 }
  241 
  242 void
  243 dk_start(struct dk_intf *di, struct dk_softc *dksc)
  244 {
  245         struct  buf *bp;
  246 
  247         DPRINTF_FOLLOW(("dk_start(%s, %p)\n", di->di_dkname, dksc));
  248 
  249         /* Process the work queue */
  250         while ((bp = BUFQ_GET(dksc->sc_bufq)) != NULL) {
  251                 if (di->di_diskstart(dksc, bp) != 0) {
  252                         BUFQ_PUT(dksc->sc_bufq, bp);
  253                         break;
  254                 }
  255         }
  256 }
  257 
  258 void
  259 dk_iodone(struct dk_intf *di, struct dk_softc *dksc)
  260 {
  261 
  262         DPRINTF_FOLLOW(("dk_iodone(%s, %p)\n", di->di_dkname, dksc));
  263 
  264         /* We kick the queue in case we are able to get more work done */
  265         dk_start(di, dksc);
  266 }
  267 
  268 int
  269 dk_size(struct dk_intf *di, struct dk_softc *dksc, dev_t dev)
  270 {
  271         struct  disklabel *lp;
  272         int     is_open;
  273         int     part;
  274         int     size;
  275 
  276         if ((dksc->sc_flags & DKF_INITED) == 0)
  277                 return -1;
  278 
  279         part = DISKPART(dev);
  280         is_open = dksc->sc_dkdev.dk_openmask & (1 << part);
  281 
  282         if (!is_open && di->di_open(dev, 0, S_IFBLK, curlwp))
  283                 return -1;
  284 
  285         lp = dksc->sc_dkdev.dk_label;
  286         if (lp->d_partitions[part].p_fstype != FS_SWAP)
  287                 size = -1;
  288         else
  289                 size = lp->d_partitions[part].p_size *
  290                     (lp->d_secsize / DEV_BSIZE);
  291 
  292         if (!is_open && di->di_close(dev, 0, S_IFBLK, curlwp))
  293                 return 1;
  294 
  295         return size;
  296 }
  297 
  298 int
  299 dk_ioctl(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
  300             u_long cmd, caddr_t data, int flag, struct lwp *l)
  301 {
  302         struct  disklabel *lp;
  303         struct  disk *dk;
  304 #ifdef __HAVE_OLD_DISKLABEL
  305         struct  disklabel newlabel;
  306 #endif
  307         int     error = 0;
  308 
  309         DPRINTF_FOLLOW(("dk_ioctl(%s, %p, 0x%x, 0x%lx)\n",
  310             di->di_dkname, dksc, dev, cmd));
  311 
  312         /* ensure that the pseudo disk is open for writes for these commands */
  313         switch (cmd) {
  314         case DIOCSDINFO:
  315         case DIOCWDINFO:
  316 #ifdef __HAVE_OLD_DISKLABEL
  317         case ODIOCSDINFO:
  318         case ODIOCWDINFO:
  319 #endif
  320         case DIOCWLABEL:
  321                 if ((flag & FWRITE) == 0)
  322                         return EBADF;
  323         }
  324 
  325         /* ensure that the pseudo-disk is initialized for these */
  326         switch (cmd) {
  327         case DIOCGDINFO:
  328         case DIOCSDINFO:
  329         case DIOCWDINFO:
  330         case DIOCGPART:
  331         case DIOCWLABEL:
  332         case DIOCGDEFLABEL:
  333 #ifdef __HAVE_OLD_DISKLABEL
  334         case ODIOCGDINFO:
  335         case ODIOCSDINFO:
  336         case ODIOCWDINFO:
  337         case ODIOCGDEFLABEL:
  338 #endif
  339                 if ((dksc->sc_flags & DKF_INITED) == 0)
  340                         return ENXIO;
  341         }
  342 
  343         switch (cmd) {
  344         case DIOCGDINFO:
  345                 *(struct disklabel *)data = *(dksc->sc_dkdev.dk_label);
  346                 break;
  347 
  348 #ifdef __HAVE_OLD_DISKLABEL
  349         case ODIOCGDINFO:
  350                 newlabel = *(dksc->sc_dkdev.dk_label);
  351                 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
  352                         return ENOTTY;
  353                 memcpy(data, &newlabel, sizeof (struct olddisklabel));
  354                 break;
  355 #endif
  356 
  357         case DIOCGPART:
  358                 ((struct partinfo *)data)->disklab = dksc->sc_dkdev.dk_label;
  359                 ((struct partinfo *)data)->part =
  360                     &dksc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
  361                 break;
  362 
  363         case DIOCWDINFO:
  364         case DIOCSDINFO:
  365 #ifdef __HAVE_OLD_DISKLABEL
  366         case ODIOCWDINFO:
  367         case ODIOCSDINFO:
  368 #endif
  369 #ifdef __HAVE_OLD_DISKLABEL
  370                 if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
  371                         memset(&newlabel, 0, sizeof newlabel);
  372                         memcpy(&newlabel, data, sizeof (struct olddisklabel));
  373                         lp = &newlabel;
  374                 } else
  375 #endif
  376                 lp = (struct disklabel *)data;
  377 
  378                 dk = &dksc->sc_dkdev;
  379                 error = lockmgr(&dk->dk_openlock, LK_EXCLUSIVE, NULL);
  380                 if (error) {
  381                         break;
  382                 }
  383 
  384                 dksc->sc_flags |= DKF_LABELLING;
  385 
  386                 error = setdisklabel(dksc->sc_dkdev.dk_label,
  387                     lp, 0, dksc->sc_dkdev.dk_cpulabel);
  388                 if (error == 0) {
  389                         if (cmd == DIOCWDINFO
  390 #ifdef __HAVE_OLD_DISKLABEL
  391                             || cmd == ODIOCWDINFO
  392 #endif
  393                            )
  394                                 error = writedisklabel(DKLABELDEV(dev),
  395                                     di->di_strategy, dksc->sc_dkdev.dk_label,
  396                                     dksc->sc_dkdev.dk_cpulabel);
  397                 }
  398 
  399                 dksc->sc_flags &= ~DKF_LABELLING;
  400                 error = lockmgr(&dk->dk_openlock, LK_RELEASE, NULL);
  401                 break;
  402 
  403         case DIOCWLABEL:
  404                 if (*(int *)data != 0)
  405                         dksc->sc_flags |= DKF_WLABEL;
  406                 else
  407                         dksc->sc_flags &= ~DKF_WLABEL;
  408                 break;
  409 
  410         case DIOCGDEFLABEL:
  411                 dk_getdefaultlabel(di, dksc, (struct disklabel *)data);
  412                 break;
  413 
  414 #ifdef __HAVE_OLD_DISKLABEL
  415         case ODIOCGDEFLABEL:
  416                 dk_getdefaultlabel(di, dksc, &newlabel);
  417                 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
  418                         return ENOTTY;
  419                 memcpy(data, &newlabel, sizeof (struct olddisklabel));
  420                 break;
  421 #endif
  422 
  423         case DIOCAWEDGE:
  424             {
  425                 struct dkwedge_info *dkw = (void *)data;
  426 
  427                 if ((flag & FWRITE) == 0)
  428                         return (EBADF);
  429 
  430                 /* If the ioctl happens here, the parent is us. */
  431                 strcpy(dkw->dkw_parent, dksc->sc_dkdev.dk_name);
  432                 return (dkwedge_add(dkw));
  433             }
  434 
  435         case DIOCDWEDGE:
  436             {
  437                 struct dkwedge_info *dkw = (void *)data;
  438 
  439                 if ((flag & FWRITE) == 0)
  440                         return (EBADF);
  441 
  442                 /* If the ioctl happens here, the parent is us. */
  443                 strcpy(dkw->dkw_parent, dksc->sc_dkdev.dk_name);
  444                 return (dkwedge_del(dkw));
  445             }
  446 
  447         case DIOCLWEDGES:
  448             {
  449                 struct dkwedge_list *dkwl = (void *)data;
  450 
  451                 return (dkwedge_list(&dksc->sc_dkdev, dkwl, l));
  452             }
  453 
  454         case DIOCGSTRATEGY:
  455             {
  456                 struct disk_strategy *dks = (void *)data;
  457                 int s;
  458 
  459                 s = splbio();
  460                 strlcpy(dks->dks_name, bufq_getstrategyname(dksc->sc_bufq),
  461                     sizeof(dks->dks_name));
  462                 splx(s);
  463                 dks->dks_paramlen = 0;
  464 
  465                 return 0;
  466             }
  467         
  468         case DIOCSSTRATEGY:
  469             {
  470                 struct disk_strategy *dks = (void *)data;
  471                 struct bufq_state *new;
  472                 struct bufq_state *old;
  473                 int s;
  474 
  475                 if ((flag & FWRITE) == 0) {
  476                         return EBADF;
  477                 }
  478                 if (dks->dks_param != NULL) {
  479                         return EINVAL;
  480                 }
  481                 dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
  482                 error = bufq_alloc(&new, dks->dks_name,
  483                     BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
  484                 if (error) {
  485                         return error;
  486                 }
  487                 s = splbio();
  488                 old = dksc->sc_bufq;
  489                 bufq_move(new, old);
  490                 dksc->sc_bufq = new;
  491                 splx(s);
  492                 bufq_free(old);
  493 
  494                 return 0;
  495             }
  496 
  497         default:
  498                 error = ENOTTY;
  499         }
  500 
  501         return error;
  502 }
  503 
  504 /*
  505  * dk_dump dumps all of physical memory into the partition specified.
  506  * This requires substantially more framework than {s,w}ddump, and hence
  507  * is probably much more fragile.
  508  *
  509  * XXX: we currently do not implement this.
  510  */
  511 
  512 #define DKF_READYFORDUMP        (DKF_INITED|DKF_TAKEDUMP)
  513 #define DKFF_READYFORDUMP(x)    (((x) & DKF_READYFORDUMP) == DKF_READYFORDUMP)
  514 static volatile int     dk_dumping = 0;
  515 
  516 /* ARGSUSED */
  517 int
  518 dk_dump(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
  519     daddr_t blkno, caddr_t va, size_t size)
  520 {
  521 
  522         /*
  523          * ensure that we consider this device to be safe for dumping,
  524          * and that the device is configured.
  525          */
  526         if (!DKFF_READYFORDUMP(dksc->sc_flags))
  527                 return ENXIO;
  528 
  529         /* ensure that we are not already dumping */
  530         if (dk_dumping)
  531                 return EFAULT;
  532         dk_dumping = 1;
  533 
  534         /* XXX: unimplemented */
  535 
  536         dk_dumping = 0;
  537 
  538         /* XXX: actually for now, we are going to leave this alone */
  539         return ENXIO;
  540 }
  541 
  542 /* ARGSUSED */
  543 void
  544 dk_getdefaultlabel(struct dk_intf *di, struct dk_softc *dksc,
  545                       struct disklabel *lp)
  546 {
  547         struct dk_geom *pdg = &dksc->sc_geom;
  548 
  549         memset(lp, 0, sizeof(*lp));
  550 
  551         lp->d_secperunit = dksc->sc_size;
  552         lp->d_secsize = pdg->pdg_secsize;
  553         lp->d_nsectors = pdg->pdg_nsectors;
  554         lp->d_ntracks = pdg->pdg_ntracks;
  555         lp->d_ncylinders = pdg->pdg_ncylinders;
  556         lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
  557 
  558         strncpy(lp->d_typename, di->di_dkname, sizeof(lp->d_typename));
  559         lp->d_type = di->di_dtype;
  560         strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
  561         lp->d_rpm = 3600;
  562         lp->d_interleave = 1;
  563         lp->d_flags = 0;
  564 
  565         lp->d_partitions[RAW_PART].p_offset = 0;
  566         lp->d_partitions[RAW_PART].p_size = dksc->sc_size;
  567         lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
  568         lp->d_npartitions = RAW_PART + 1;
  569 
  570         lp->d_magic = DISKMAGIC;
  571         lp->d_magic2 = DISKMAGIC;
  572         lp->d_checksum = dkcksum(dksc->sc_dkdev.dk_label);
  573 }
  574 
  575 /* ARGSUSED */
  576 void
  577 dk_getdisklabel(struct dk_intf *di, struct dk_softc *dksc, dev_t dev)
  578 {
  579         struct   disklabel *lp = dksc->sc_dkdev.dk_label;
  580         struct   cpu_disklabel *clp = dksc->sc_dkdev.dk_cpulabel;
  581         struct   partition *pp;
  582         int      i;
  583         const char      *errstring;
  584 
  585         memset(clp, 0x0, sizeof(*clp));
  586         dk_getdefaultlabel(di, dksc, lp);
  587         errstring = readdisklabel(DKLABELDEV(dev), di->di_strategy,
  588             dksc->sc_dkdev.dk_label, dksc->sc_dkdev.dk_cpulabel);
  589         if (errstring) {
  590                 dk_makedisklabel(di, dksc);
  591                 if (dksc->sc_flags & DKF_WARNLABEL)
  592                         printf("%s: %s\n", dksc->sc_xname, errstring);
  593                 return;
  594         }
  595 
  596         if ((dksc->sc_flags & DKF_LABELSANITY) == 0)
  597                 return;
  598 
  599         /* Sanity check */
  600         if (lp->d_secperunit != dksc->sc_size)
  601                 printf("WARNING: %s: total sector size in disklabel (%d) "
  602                     "!= the size of %s (%lu)\n", dksc->sc_xname,
  603                     lp->d_secperunit, di->di_dkname, (u_long)dksc->sc_size);
  604 
  605         for (i=0; i < lp->d_npartitions; i++) {
  606                 pp = &lp->d_partitions[i];
  607                 if (pp->p_offset + pp->p_size > dksc->sc_size)
  608                         printf("WARNING: %s: end of partition `%c' exceeds "
  609                             "the size of %s (%lu)\n", dksc->sc_xname,
  610                             'a' + i, di->di_dkname, (u_long)dksc->sc_size);
  611         }
  612 }
  613 
  614 /* ARGSUSED */
  615 static void
  616 dk_makedisklabel(struct dk_intf *di, struct dk_softc *dksc)
  617 {
  618         struct  disklabel *lp = dksc->sc_dkdev.dk_label;
  619 
  620         lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS;
  621         strncpy(lp->d_packname, "default label", sizeof(lp->d_packname));
  622         lp->d_checksum = dkcksum(lp);
  623 }
  624 
  625 /* This function is taken from ccd.c:1.76  --rcd */
  626 
  627 /*
  628  * XXX this function looks too generic for dksubr.c, shouldn't we
  629  *     put it somewhere better?
  630  */
  631 
  632 /*
  633  * Lookup the provided name in the filesystem.  If the file exists,
  634  * is a valid block device, and isn't being used by anyone else,
  635  * set *vpp to the file's vnode.
  636  */
  637 int
  638 dk_lookup(const char *path, struct lwp *l, struct vnode **vpp,
  639     enum uio_seg segflg)
  640 {
  641         struct nameidata nd;
  642         struct vnode *vp;
  643         struct vattr va;
  644         int     error;
  645 
  646         if (l == NULL)
  647                 return ESRCH;   /* Is ESRCH the best choice? */
  648 
  649         NDINIT(&nd, LOOKUP, FOLLOW, segflg, path, l);
  650         if ((error = vn_open(&nd, FREAD | FWRITE, 0)) != 0) {
  651                 DPRINTF((DKDB_FOLLOW|DKDB_INIT),
  652                     ("dk_lookup: vn_open error = %d\n", error));
  653                 return error;
  654         }
  655 
  656         vp = nd.ni_vp;
  657         if ((error = VOP_GETATTR(vp, &va, l->l_cred, l)) != 0) {
  658                 DPRINTF((DKDB_FOLLOW|DKDB_INIT),
  659                     ("dk_lookup: getattr error = %d\n", error));
  660                 goto out;
  661         }
  662 
  663         /* XXX: eventually we should handle VREG, too. */
  664         if (va.va_type != VBLK) {
  665                 error = ENOTBLK;
  666                 goto out;
  667         }
  668 
  669         /* XXX: wedges have a writecount of 1; this is disgusting */
  670         if (vp->v_usecount > 1 + (major(va.va_rdev) == 168)) {
  671                 error = EBUSY;
  672                 goto out;
  673         }
  674 
  675         IFDEBUG(DKDB_VNODE, vprint("dk_lookup: vnode info", vp));
  676 
  677         VOP_UNLOCK(vp, 0);
  678         *vpp = vp;
  679         return 0;
  680 out:
  681         VOP_UNLOCK(vp, 0);
  682         (void) vn_close(vp, FREAD | FWRITE, l->l_cred, l);
  683         return error;
  684 }

Cache object: 2d86383257201e7effbb56f721ea670b


[ 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.