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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: dksubr.c,v 1.11.2.1 2004/04/21 03:18:41 jmc 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.11.2.1 2004/04/21 03:18:41 jmc 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/vnode.h>
   51 #include <sys/fcntl.h>
   52 #include <sys/namei.h>
   53 
   54 #include <dev/dkvar.h>
   55 
   56 int     dkdebug = 0;
   57 
   58 #ifdef DEBUG
   59 #define DKDB_FOLLOW     0x1
   60 #define DKDB_INIT       0x2
   61 #define DKDB_VNODE      0x4
   62 
   63 #define IFDEBUG(x,y)            if (dkdebug & (x)) y
   64 #define DPRINTF(x,y)            IFDEBUG(x, printf y)
   65 #define DPRINTF_FOLLOW(y)       DPRINTF(DKDB_FOLLOW, y)
   66 #else
   67 #define IFDEBUG(x,y)
   68 #define DPRINTF(x,y)
   69 #define DPRINTF_FOLLOW(y)
   70 #endif
   71 
   72 #define DKLABELDEV(dev) \
   73         (MAKEDISKDEV(major((dev)), DISKUNIT((dev)), RAW_PART))
   74 
   75 void    dk_makedisklabel(struct dk_intf *, struct dk_softc *);
   76 
   77 void
   78 dk_sc_init(struct dk_softc *dksc, void *osc, char *xname)
   79 {
   80 
   81         memset(dksc, 0x0, sizeof(*dksc));
   82         dksc->sc_osc = osc;
   83         strncpy(dksc->sc_xname, xname, DK_XNAME_SIZE);
   84         dksc->sc_dkdev.dk_name = dksc->sc_xname;
   85         lockinit(&dksc->sc_lock, PRIBIO, "dklk", 0, 0);
   86 }
   87 
   88 /* ARGSUSED */
   89 int
   90 dk_open(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
   91            int flags, int fmt, struct proc *p)
   92 {
   93         struct  disklabel *lp = dksc->sc_dkdev.dk_label;
   94         int     part = DISKPART(dev);
   95         int     pmask = 1 << part;
   96         int     ret = 0;
   97 
   98         DPRINTF_FOLLOW(("dk_open(%s, %p, 0x%x, 0x%x)\n",
   99             di->di_dkname, dksc, dev, flags));
  100 
  101         if ((ret = lockmgr(&dksc->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
  102                 return ret;
  103 
  104         part = DISKPART(dev);
  105         pmask = 1 << part;
  106 
  107         /*
  108          * If we're init'ed and there are no other open partitions then
  109          * update the in-core disklabel.
  110          */
  111         if ((dksc->sc_flags & DKF_INITED) && dksc->sc_dkdev.dk_openmask == 0)
  112                 dk_getdisklabel(di, dksc, dev);
  113 
  114         /* Fail if we can't find the partition. */
  115         if ((part != RAW_PART) &&
  116             (((dksc->sc_flags & DKF_INITED) == 0) ||
  117             ((part >= lp->d_npartitions) ||
  118             (lp->d_partitions[part].p_fstype == FS_UNUSED)))) {
  119                 ret = ENXIO;
  120                 goto done;
  121         }
  122 
  123         /* Mark our unit as open. */
  124         switch (fmt) {
  125         case S_IFCHR:
  126                 dksc->sc_dkdev.dk_copenmask |= pmask;
  127                 break;
  128         case S_IFBLK:
  129                 dksc->sc_dkdev.dk_bopenmask |= pmask;
  130                 break;
  131         }
  132 
  133         dksc->sc_dkdev.dk_openmask =
  134             dksc->sc_dkdev.dk_copenmask | dksc->sc_dkdev.dk_bopenmask;
  135 
  136 done:
  137         lockmgr(&dksc->sc_lock, LK_RELEASE, NULL);
  138         return ret;
  139 }
  140 
  141 /* ARGSUSED */
  142 int
  143 dk_close(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
  144             int flags, int fmt, struct proc *p)
  145 {
  146         int     part = DISKPART(dev);
  147         int     pmask = 1 << part;
  148         int     ret;
  149 
  150         DPRINTF_FOLLOW(("dk_close(%s, %p, 0x%x, 0x%x)\n",
  151             di->di_dkname, dksc, dev, flags));
  152 
  153         if ((ret = lockmgr(&dksc->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
  154                 return ret;
  155 
  156         switch (fmt) {
  157         case S_IFCHR:
  158                 dksc->sc_dkdev.dk_copenmask &= ~pmask;
  159                 break;
  160         case S_IFBLK:
  161                 dksc->sc_dkdev.dk_bopenmask &= ~pmask;
  162                 break;
  163         }
  164         dksc->sc_dkdev.dk_openmask =
  165             dksc->sc_dkdev.dk_copenmask | dksc->sc_dkdev.dk_bopenmask;
  166 
  167         lockmgr(&dksc->sc_lock, LK_RELEASE, NULL);
  168         return 0;
  169 }
  170 
  171 void
  172 dk_strategy(struct dk_intf *di, struct dk_softc *dksc, struct buf *bp)
  173 {
  174         int     s;
  175         int     wlabel;
  176 
  177         DPRINTF_FOLLOW(("dk_strategy(%s, %p, %p)\n",
  178             di->di_dkname, dksc, bp));
  179 
  180         if (!(dksc->sc_flags & DKF_INITED)) {
  181                 DPRINTF_FOLLOW(("dk_stragy: not inited\n"));
  182                 bp->b_error  = ENXIO;
  183                 bp->b_flags |= B_ERROR;
  184                 biodone(bp);
  185                 return;
  186         }
  187 
  188         /* XXX look for some more errors, c.f. ld.c */
  189 
  190         bp->b_resid = bp->b_bcount;
  191 
  192         /* If there is nothing to do, then we are done */
  193         if (bp->b_bcount == 0) {
  194                 biodone(bp);
  195                 return;
  196         }
  197 
  198         wlabel = dksc->sc_flags & (DKF_WLABEL|DKF_LABELLING);
  199         if (DISKPART(bp->b_dev) != RAW_PART &&
  200             bounds_check_with_label(&dksc->sc_dkdev, bp, wlabel) <= 0) {
  201                 biodone(bp);
  202                 return;
  203         }
  204 
  205         /*
  206          * Start the unit by calling the start routine
  207          * provided by the individual driver.
  208          */
  209         s = splbio();
  210         BUFQ_PUT(&dksc->sc_bufq, bp);
  211         dk_start(di, dksc);
  212         splx(s);
  213         return;
  214 }
  215 
  216 void
  217 dk_start(struct dk_intf *di, struct dk_softc *dksc)
  218 {
  219         struct  buf *bp;
  220 
  221         DPRINTF_FOLLOW(("dk_start(%s, %p)\n", di->di_dkname, dksc));
  222 
  223         /* Process the work queue */
  224         while ((bp = BUFQ_GET(&dksc->sc_bufq)) != NULL) {
  225                 if (di->di_diskstart(dksc, bp) != 0) {
  226                         BUFQ_PUT(&dksc->sc_bufq, bp);
  227                         break;
  228                 }
  229         }
  230 }
  231 
  232 void
  233 dk_iodone(struct dk_intf *di, struct dk_softc *dksc)
  234 {
  235 
  236         DPRINTF_FOLLOW(("dk_iodone(%s, %p)\n", di->di_dkname, dksc));
  237 
  238         /* We kick the queue in case we are able to get more work done */
  239         dk_start(di, dksc);
  240 }
  241 
  242 int
  243 dk_size(struct dk_intf *di, struct dk_softc *dksc, dev_t dev)
  244 {
  245         struct  disklabel *lp;
  246         int     is_open;
  247         int     part;
  248         int     size;
  249 
  250         if ((dksc->sc_flags & DKF_INITED) == 0)
  251                 return -1;
  252 
  253         part = DISKPART(dev);
  254         is_open = dksc->sc_dkdev.dk_openmask & (1 << part);
  255 
  256         if (!is_open && di->di_open(dev, 0, S_IFBLK, curproc))
  257                 return -1;
  258 
  259         lp = dksc->sc_dkdev.dk_label;
  260         if (lp->d_partitions[part].p_fstype != FS_SWAP)
  261                 size = -1;
  262         else
  263                 size = lp->d_partitions[part].p_size *
  264                     (lp->d_secsize / DEV_BSIZE);
  265 
  266         if (!is_open && di->di_close(dev, 0, S_IFBLK, curproc))
  267                 return 1;
  268 
  269         return size;
  270 }
  271 
  272 int
  273 dk_ioctl(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
  274             u_long cmd, caddr_t data, int flag, struct proc *p)
  275 {
  276         struct  disklabel *lp;
  277 #ifdef __HAVE_OLD_DISKLABEL
  278         struct  disklabel newlabel;
  279 #endif
  280         int     error = 0;
  281 
  282         DPRINTF_FOLLOW(("dk_ioctl(%s, %p, 0x%x, 0x%lx)\n",
  283             di->di_dkname, dksc, dev, cmd));
  284 
  285         /* ensure that the pseudo disk is open for writes for these commands */
  286         switch (cmd) {
  287         case DIOCSDINFO:
  288         case DIOCWDINFO:
  289 #ifdef __HAVE_OLD_DISKLABEL
  290         case ODIOCSDINFO:
  291         case ODIOCWDINFO:
  292 #endif
  293         case DIOCWLABEL:
  294                 if ((flag & FWRITE) == 0)
  295                         return EBADF;
  296         }
  297 
  298         /* ensure that the pseudo-disk is initialized for these */
  299         switch (cmd) {
  300         case DIOCGDINFO:
  301         case DIOCSDINFO:
  302         case DIOCWDINFO:
  303         case DIOCGPART:
  304         case DIOCWLABEL:
  305         case DIOCGDEFLABEL:
  306 #ifdef __HAVE_OLD_DISKLABEL
  307         case ODIOCGDINFO:
  308         case ODIOCSDINFO:
  309         case ODIOCWDINFO:
  310         case ODIOCGDEFLABEL:
  311 #endif
  312                 if ((dksc->sc_flags & DKF_INITED) == 0)
  313                         return ENXIO;
  314         }
  315 
  316         switch (cmd) {
  317         case DIOCGDINFO:
  318                 *(struct disklabel *)data = *(dksc->sc_dkdev.dk_label);
  319                 break;
  320 
  321 #ifdef __HAVE_OLD_DISKLABEL
  322         case ODIOCGDINFO:
  323                 newlabel = *(dksc->sc_dkdev.dk_label);
  324                 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
  325                         return ENOTTY;
  326                 memcpy(data, &newlabel, sizeof (struct olddisklabel));
  327                 break;
  328 #endif
  329 
  330         case DIOCGPART:
  331                 ((struct partinfo *)data)->disklab = dksc->sc_dkdev.dk_label;
  332                 ((struct partinfo *)data)->part =
  333                     &dksc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
  334                 break;
  335 
  336         case DIOCWDINFO:
  337         case DIOCSDINFO:
  338 #ifdef __HAVE_OLD_DISKLABEL
  339         case ODIOCWDINFO:
  340         case ODIOCSDINFO:
  341 #endif
  342 #ifdef __HAVE_OLD_DISKLABEL
  343                 if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
  344                         memset(&newlabel, 0, sizeof newlabel);
  345                         memcpy(&newlabel, data, sizeof (struct olddisklabel));
  346                         lp = &newlabel;
  347                 } else
  348 #endif
  349                 lp = (struct disklabel *)data;
  350 
  351                 dksc->sc_flags |= DKF_LABELLING;
  352 
  353                 error = setdisklabel(dksc->sc_dkdev.dk_label,
  354                     lp, 0, dksc->sc_dkdev.dk_cpulabel);
  355                 if (error == 0) {
  356                         if (cmd == DIOCWDINFO
  357 #ifdef __HAVE_OLD_DISKLABEL
  358                             || cmd == ODIOCWDINFO
  359 #endif
  360                            )
  361                                 error = writedisklabel(DKLABELDEV(dev),
  362                                     di->di_strategy, dksc->sc_dkdev.dk_label,
  363                                     dksc->sc_dkdev.dk_cpulabel);
  364                 }
  365 
  366                 dksc->sc_flags &= ~DKF_LABELLING;
  367                 break;
  368 
  369         case DIOCWLABEL:
  370                 if (*(int *)data != 0)
  371                         dksc->sc_flags |= DKF_WLABEL;
  372                 else
  373                         dksc->sc_flags &= ~DKF_WLABEL;
  374                 break;
  375 
  376         case DIOCGDEFLABEL:
  377                 dk_getdefaultlabel(di, dksc, (struct disklabel *)data);
  378                 break;
  379 
  380 #ifdef __HAVE_OLD_DISKLABEL
  381         case ODIOCGDEFLABEL:
  382                 dk_getdefaultlabel(di, dksc, &newlabel);
  383                 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
  384                         return ENOTTY;
  385                 memcpy(data, &newlabel, sizeof (struct olddisklabel));
  386                 break;
  387 #endif
  388 
  389         default:
  390                 error = ENOTTY;
  391         }
  392 
  393         return error;
  394 }
  395 
  396 /*
  397  * dk_dump dumps all of physical memory into the partition specified.
  398  * This requires substantially more framework than {s,w}ddump, and hence
  399  * is probably much more fragile.
  400  *
  401  * XXX: we currently do not implement this.
  402  */
  403 
  404 #define DKF_READYFORDUMP        (DKF_INITED|DKF_TAKEDUMP)
  405 #define DKFF_READYFORDUMP(x)    (((x) & DKF_READYFORDUMP) == DKF_READYFORDUMP)
  406 static volatile int     dk_dumping = 0;
  407 
  408 /* ARGSUSED */
  409 int
  410 dk_dump(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
  411            daddr_t blkno, caddr_t va, size_t size)
  412 {
  413 
  414         /*
  415          * ensure that we consider this device to be safe for dumping,
  416          * and that the device is configured.
  417          */
  418         if (!DKFF_READYFORDUMP(dksc->sc_flags))
  419                 return ENXIO;
  420 
  421         /* ensure that we are not already dumping */
  422         if (dk_dumping)
  423                 return EFAULT;
  424         dk_dumping = 1;
  425 
  426         /* XXX: unimplemented */
  427 
  428         dk_dumping = 0;
  429 
  430         /* XXX: actually for now, we are going to leave this alone */
  431         return ENXIO;
  432 }
  433 
  434 /* ARGSUSED */
  435 void
  436 dk_getdefaultlabel(struct dk_intf *di, struct dk_softc *dksc,
  437                       struct disklabel *lp)
  438 {
  439         struct dk_geom *pdg = &dksc->sc_geom;
  440 
  441         memset(lp, 0, sizeof(*lp));
  442 
  443         lp->d_secperunit = dksc->sc_size;
  444         lp->d_secsize = pdg->pdg_secsize;
  445         lp->d_nsectors = pdg->pdg_nsectors;
  446         lp->d_ntracks = pdg->pdg_ntracks;
  447         lp->d_ncylinders = pdg->pdg_ncylinders;
  448         lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
  449 
  450         strncpy(lp->d_typename, di->di_dkname, sizeof(lp->d_typename));
  451         lp->d_type = di->di_dtype;
  452         strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
  453         lp->d_rpm = 3600;
  454         lp->d_interleave = 1;
  455         lp->d_flags = 0;
  456 
  457         lp->d_partitions[RAW_PART].p_offset = 0;
  458         lp->d_partitions[RAW_PART].p_size = dksc->sc_size;
  459         lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
  460         lp->d_npartitions = RAW_PART + 1;
  461 
  462         lp->d_magic = DISKMAGIC;
  463         lp->d_magic2 = DISKMAGIC;
  464         lp->d_checksum = dkcksum(dksc->sc_dkdev.dk_label);
  465 }
  466 
  467 /* ARGSUSED */
  468 void
  469 dk_getdisklabel(struct dk_intf *di, struct dk_softc *dksc, dev_t dev)
  470 {
  471         struct   disklabel *lp = dksc->sc_dkdev.dk_label;
  472         struct   cpu_disklabel *clp = dksc->sc_dkdev.dk_cpulabel;
  473         struct   partition *pp;
  474         int      i;
  475         const char      *errstring;
  476 
  477         memset(clp, 0x0, sizeof(*clp));
  478         dk_getdefaultlabel(di, dksc, lp);
  479         errstring = readdisklabel(DKLABELDEV(dev), di->di_strategy,
  480             dksc->sc_dkdev.dk_label, dksc->sc_dkdev.dk_cpulabel);
  481         if (errstring) {
  482                 dk_makedisklabel(di, dksc);
  483                 if (dksc->sc_flags & DKF_WARNLABEL)
  484                         printf("%s: %s\n", dksc->sc_xname, errstring);
  485                 return;
  486         }
  487 
  488         if ((dksc->sc_flags & DKF_LABELSANITY) == 0)
  489                 return;
  490 
  491         /* Sanity check */
  492         if (lp->d_secperunit != dksc->sc_size)
  493                 printf("WARNING: %s: total sector size in disklabel (%d) "
  494                     "!= the size of %s (%lu)\n", dksc->sc_xname,
  495                     lp->d_secperunit, di->di_dkname, (u_long)dksc->sc_size);
  496 
  497         for (i=0; i < lp->d_npartitions; i++) {
  498                 pp = &lp->d_partitions[i];
  499                 if (pp->p_offset + pp->p_size > dksc->sc_size)
  500                         printf("WARNING: %s: end of partition `%c' exceeds "
  501                             "the size of %s (%lu)\n", dksc->sc_xname,
  502                             'a' + i, di->di_dkname, (u_long)dksc->sc_size);
  503         }
  504 }
  505 
  506 /* ARGSUSED */
  507 void
  508 dk_makedisklabel(struct dk_intf *di, struct dk_softc *dksc)
  509 {
  510         struct  disklabel *lp = dksc->sc_dkdev.dk_label;
  511 
  512         lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS;
  513         strncpy(lp->d_packname, "default label", sizeof(lp->d_packname));
  514         lp->d_checksum = dkcksum(lp);
  515 }
  516 
  517 /* This function is taken from ccd.c:1.76  --rcd */
  518 
  519 /*
  520  * XXX this function looks too generic for dksubr.c, shouldn't we
  521  *     put it somewhere better?
  522  */
  523 
  524 /*
  525  * Lookup the provided name in the filesystem.  If the file exists,
  526  * is a valid block device, and isn't being used by anyone else,
  527  * set *vpp to the file's vnode.
  528  */
  529 int
  530 dk_lookup(path, p, vpp)
  531         char *path;
  532         struct proc *p;
  533         struct vnode **vpp;     /* result */
  534 {
  535         struct nameidata nd;
  536         struct vnode *vp;
  537         struct vattr va;
  538         int error;
  539 
  540         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p);
  541         if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
  542                 DPRINTF((DKDB_FOLLOW|DKDB_INIT),
  543                     ("dk_lookup: vn_open error = %d\n", error));
  544                 return (error);
  545         }
  546         vp = nd.ni_vp;
  547 
  548         if (vp->v_usecount > 1) {
  549                 VOP_UNLOCK(vp, 0);
  550                 (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
  551                 return (EBUSY);
  552         }
  553 
  554         if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) {
  555                 DPRINTF((DKDB_FOLLOW|DKDB_INIT),
  556                     ("dk_lookup: getattr error = %d\n", error));
  557                 VOP_UNLOCK(vp, 0);
  558                 (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
  559                 return (error);
  560         }
  561 
  562         /* XXX: eventually we should handle VREG, too. */
  563         if (va.va_type != VBLK) {
  564                 VOP_UNLOCK(vp, 0);
  565                 (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
  566                 return (ENOTBLK);
  567         }
  568 
  569         IFDEBUG(DKDB_VNODE, vprint("dk_lookup: vnode info", vp));
  570 
  571         VOP_UNLOCK(vp, 0);
  572         *vpp = vp;
  573         return (0);
  574 }

Cache object: a6c818ee4c009e34ed6fb6b6ae0ae49e


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