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/fs/hpfs/hpfs_vfsops.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  * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/namei.h>
   33 #include <sys/conf.h>
   34 #include <sys/proc.h>
   35 #include <sys/kernel.h>
   36 #include <sys/vnode.h>
   37 #include <sys/mount.h>
   38 #include <sys/buf.h>
   39 #include <sys/fcntl.h>
   40 #include <sys/malloc.h>
   41 
   42 #include <vm/vm.h>
   43 #include <vm/vm_param.h>
   44 #if defined(__NetBSD__)
   45 #include <vm/vm_prot.h>
   46 #endif
   47 #include <vm/vm_page.h>
   48 #include <vm/vm_object.h>
   49 #include <vm/vm_extern.h>
   50 
   51 #if defined(__NetBSD__)
   52 #include <miscfs/specfs/specdev.h>
   53 #endif
   54 
   55 #include <fs/hpfs/hpfs.h>
   56 #include <fs/hpfs/hpfsmount.h>
   57 #include <fs/hpfs/hpfs_subr.h>
   58 
   59 #if defined(__FreeBSD__)
   60 MALLOC_DEFINE(M_HPFSMNT, "HPFS mount", "HPFS mount structure");
   61 MALLOC_DEFINE(M_HPFSNO, "HPFS node", "HPFS node structure");
   62 #endif
   63 
   64 static int      hpfs_root __P((struct mount *, struct vnode **));
   65 static int      hpfs_statfs __P((struct mount *, struct statfs *,
   66                                  struct proc *));
   67 static int      hpfs_unmount __P((struct mount *, int, struct proc *));
   68 static int      hpfs_vget __P((struct mount *mp, ino_t ino,
   69                                struct vnode **vpp));
   70 static int      hpfs_mountfs __P((register struct vnode *, struct mount *, 
   71                                   struct hpfs_args *, struct proc *));
   72 static int      hpfs_vptofh __P((struct vnode *, struct fid *));
   73 static int      hpfs_fhtovp __P((struct mount *, struct fid *,
   74                                  struct vnode **));
   75 
   76 #if !defined(__FreeBSD__)
   77 static int      hpfs_quotactl __P((struct mount *, int, uid_t, caddr_t,
   78                                    struct proc *));
   79 static int      hpfs_start __P((struct mount *, int, struct proc *));
   80 static int      hpfs_sync __P((struct mount *, int, struct ucred *,
   81                                struct proc *));
   82 #endif
   83 
   84 #if defined(__FreeBSD__)
   85 struct sockaddr;
   86 static int      hpfs_mount __P((struct mount *, char *, caddr_t,
   87                                 struct nameidata *, struct proc *));
   88 static int      hpfs_init __P((struct vfsconf *));
   89 static int      hpfs_checkexp __P((struct mount *, struct sockaddr *,
   90                                    int *, struct ucred **));
   91 #else /* defined(__NetBSD__) */
   92 static int      hpfs_mount __P((struct mount *, const char *, void *,
   93                                 struct nameidata *, struct proc *));
   94 static void     hpfs_init __P((void));
   95 static int      hpfs_mountroot __P((void));
   96 static int      hpfs_sysctl __P((int *, u_int, void *, size_t *, void *,
   97                                  size_t, struct proc *));
   98 static int      hpfs_checkexp __P((struct mount *, struct mbuf *,
   99                                    int *, struct ucred **));
  100 #endif
  101 
  102 /*ARGSUSED*/
  103 static int
  104 hpfs_checkexp(mp, nam, exflagsp, credanonp)
  105 #if defined(__FreeBSD__)
  106         register struct mount *mp;
  107         struct sockaddr *nam;
  108         int *exflagsp;
  109         struct ucred **credanonp;
  110 #else /* defined(__NetBSD__) */
  111         register struct mount *mp;
  112         struct mbuf *nam;
  113         int *exflagsp;
  114         struct ucred **credanonp;
  115 #endif
  116 {
  117         register struct netcred *np;
  118         register struct hpfsmount *hpm = VFSTOHPFS(mp);
  119 
  120         /*
  121          * Get the export permission structure for this <mp, client> tuple.
  122          */
  123         np = vfs_export_lookup(mp, &hpm->hpm_export, nam);
  124         if (np == NULL)
  125                 return (EACCES);
  126 
  127         *exflagsp = np->netc_exflags;
  128         *credanonp = &np->netc_anon;
  129         return (0);
  130 }
  131 
  132 #if !defined(__FreeBSD__)
  133 /*ARGSUSED*/
  134 static int
  135 hpfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
  136         int *name;
  137         u_int namelen;
  138         void *oldp;
  139         size_t *oldlenp;
  140         void *newp;
  141         size_t newlen;
  142         struct proc *p;
  143 {
  144         return (EINVAL);
  145 }
  146 
  147 static int
  148 hpfs_mountroot()
  149 {
  150         return (EINVAL);
  151 }
  152 #endif
  153 
  154 #if defined(__FreeBSD__)
  155 static int
  156 hpfs_init (
  157         struct vfsconf *vcp )
  158 #else /* defined(__NetBSD__) */
  159 static void
  160 hpfs_init ()
  161 #endif
  162 {
  163         dprintf(("hpfs_init():\n"));
  164         
  165         hpfs_hphashinit();
  166 #if defined(__FreeBSD__)
  167         return 0;
  168 #endif
  169 }
  170 
  171 static int
  172 hpfs_mount ( 
  173         struct mount *mp,
  174 #if defined(__FreeBSD__)
  175         char *path,
  176         caddr_t data,
  177 #else /* defined(__NetBSD__) */
  178         const char *path,
  179         void *data,
  180 #endif
  181         struct nameidata *ndp,
  182         struct proc *p )
  183 {
  184         u_int           size;
  185         int             err = 0;
  186         struct vnode    *devvp;
  187         struct hpfs_args args;
  188         struct hpfsmount *hpmp = 0;
  189 
  190         dprintf(("hpfs_mount():\n"));
  191         /*
  192          ***
  193          * Mounting non-root file system or updating a file system
  194          ***
  195          */
  196 
  197         /* copy in user arguments*/
  198         err = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args));
  199         if (err)
  200                 goto error_1;           /* can't get arguments*/
  201 
  202         /*
  203          * If updating, check whether changing from read-only to
  204          * read/write; if there is no device name, that's all we do.
  205          */
  206         if (mp->mnt_flag & MNT_UPDATE) {
  207                 dprintf(("hpfs_mount: MNT_UPDATE: "));
  208 
  209                 hpmp = VFSTOHPFS(mp);
  210 
  211                 if (args.fspec == 0) {
  212                         dprintf(("export 0x%x\n",args.export.ex_flags));
  213                         err = vfs_export(mp, &hpmp->hpm_export, &args.export);
  214                         if (err) {
  215                                 printf("hpfs_mount: vfs_export failed %d\n",
  216                                         err);
  217                         }
  218                         goto success;
  219                 } else {
  220                         dprintf(("name [FAILED]\n"));
  221                         err = EINVAL;
  222                         goto success;
  223                 }
  224                 dprintf(("\n"));
  225         }
  226 
  227         /*
  228          * Not an update, or updating the name: look up the name
  229          * and verify that it refers to a sensible block device.
  230          */
  231         NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
  232         err = namei(ndp);
  233         if (err) {
  234                 /* can't get devvp!*/
  235                 goto error_1;
  236         }
  237 
  238         devvp = ndp->ni_vp;
  239 
  240 #if defined(__FreeBSD__)
  241         if (!vn_isdisk(devvp, &err)) 
  242                 goto error_2;
  243 #else /* defined(__NetBSD__) */
  244         if (devvp->v_type != VBLK) {
  245                 err = ENOTBLK;
  246                 goto error_2;
  247         }
  248         if (major(devvp->v_rdev) >= nblkdev) {
  249                 err = ENXIO;
  250                 goto error_2;
  251         }
  252 #endif
  253 
  254         /*
  255          ********************
  256          * NEW MOUNT
  257          ********************
  258          */
  259 
  260         /*
  261          * Since this is a new mount, we want the names for
  262          * the device and the mount point copied in.  If an
  263          * error occurs,  the mountpoint is discarded by the
  264          * upper level code.
  265          */
  266         /* Save "last mounted on" info for mount point (NULL pad)*/
  267         copyinstr(      path,                           /* mount point*/
  268                         mp->mnt_stat.f_mntonname,       /* save area*/
  269                         MNAMELEN - 1,                   /* max size*/
  270                         &size);                         /* real size*/
  271         bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
  272 
  273         /* Save "mounted from" info for mount point (NULL pad)*/
  274         copyinstr(      args.fspec,                     /* device name*/
  275                         mp->mnt_stat.f_mntfromname,     /* save area*/
  276                         MNAMELEN - 1,                   /* max size*/
  277                         &size);                         /* real size*/
  278         bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  279 
  280         err = hpfs_mountfs(devvp, mp, &args, p);
  281         if (err)
  282                 goto error_2;
  283 
  284         /*
  285          * Initialize FS stat information in mount struct; uses both
  286          * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
  287          *
  288          * This code is common to root and non-root mounts
  289          */
  290         (void)VFS_STATFS(mp, &mp->mnt_stat, p);
  291 
  292         goto success;
  293 
  294 
  295 error_2:        /* error with devvp held*/
  296 
  297         /* release devvp before failing*/
  298         vrele(devvp);
  299 
  300 error_1:        /* no state to back out*/
  301 
  302 success:
  303         return( err);
  304 }
  305 
  306 /*
  307  * Common code for mount and mountroot
  308  */
  309 int
  310 hpfs_mountfs(devvp, mp, argsp, p)
  311         register struct vnode *devvp;
  312         struct mount *mp;
  313         struct hpfs_args *argsp;
  314         struct proc *p;
  315 {
  316         int error, ncount, ronly;
  317         struct sublock *sup;
  318         struct spblock *spp;
  319         struct hpfsmount *hpmp;
  320         struct buf *bp = NULL;
  321         struct vnode *vp;
  322         dev_t dev = devvp->v_rdev;
  323 
  324         dprintf(("hpfs_mountfs():\n"));
  325         /*
  326          * Disallow multiple mounts of the same device.
  327          * Disallow mounting of a device that is currently in use
  328          * (except for root, which might share swap device for miniroot).
  329          * Flush out any old buffers remaining from a previous use.
  330          */
  331         error = vfs_mountedon(devvp);
  332         if (error)
  333                 return (error);
  334         ncount = vcount(devvp);
  335 #if defined(__FreeBSD__)
  336         if (devvp->v_object)
  337                 ncount -= 1;
  338 #endif
  339         if (ncount > 1 && devvp != rootvp)
  340                 return (EBUSY);
  341 
  342 #if defined(__FreeBSD__)
  343         VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p);
  344         error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
  345         VOP__UNLOCK(devvp, 0, p);
  346 #else
  347         error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
  348 #endif
  349         if (error)
  350                 return (error);
  351 
  352         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  353         VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p);
  354         error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
  355         VOP__UNLOCK(devvp, 0, p);
  356         if (error)
  357                 return (error);
  358 
  359         /*
  360          * Do actual mount
  361          */
  362         hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK);
  363         bzero(hpmp, sizeof(struct hpfsmount));
  364 
  365         /* Read in SuperBlock */
  366         error = bread(devvp, SUBLOCK, SUSIZE, NOCRED, &bp);
  367         if (error)
  368                 goto failed;
  369         bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock));
  370         brelse(bp); bp = NULL;
  371 
  372         /* Read in SpareBlock */
  373         error = bread(devvp, SPBLOCK, SPSIZE, NOCRED, &bp);
  374         if (error)
  375                 goto failed;
  376         bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock));
  377         brelse(bp); bp = NULL;
  378 
  379         sup = &hpmp->hpm_su;
  380         spp = &hpmp->hpm_sp;
  381 
  382         /* Check magic */
  383         if (sup->su_magic != SU_MAGIC) {
  384                 printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n");
  385                 error = EINVAL;
  386                 goto failed;
  387         }
  388         if (spp->sp_magic != SP_MAGIC) {
  389                 printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n");
  390                 error = EINVAL;
  391                 goto failed;
  392         }
  393 
  394         mp->mnt_data = (qaddr_t)hpmp;
  395         hpmp->hpm_devvp = devvp;
  396         hpmp->hpm_dev = devvp->v_rdev;
  397         hpmp->hpm_mp = mp;
  398         hpmp->hpm_uid = argsp->uid;
  399         hpmp->hpm_gid = argsp->gid;
  400         hpmp->hpm_mode = argsp->mode;
  401 
  402         error = hpfs_bminit(hpmp);
  403         if (error)
  404                 goto failed;
  405 
  406         error = hpfs_cpinit(hpmp, argsp);
  407         if (error) {
  408                 hpfs_bmdeinit(hpmp);
  409                 goto failed;
  410         }
  411 
  412         error = hpfs_root(mp, &vp);
  413         if (error) {
  414                 hpfs_cpdeinit(hpmp);
  415                 hpfs_bmdeinit(hpmp);
  416                 goto failed;
  417         }
  418 
  419         vput(vp);
  420 
  421 #if defined(__FreeBSD__)
  422         mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev);
  423         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
  424 #else
  425         mp->mnt_stat.f_fsid.val[0] = (long)dev;
  426         mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_HPFS);
  427 #endif
  428         mp->mnt_maxsymlinklen = 0;
  429         mp->mnt_flag |= MNT_LOCAL;
  430         devvp->v_specmountpoint = mp;
  431         return (0);
  432 
  433 failed:
  434         if (bp)
  435                 brelse (bp);
  436         mp->mnt_data = (qaddr_t)NULL;
  437 #if defined(__FreeBSD__)
  438         devvp->v_specmountpoint = NULL;
  439 #else
  440         devvp->v_specflags &= ~SI_MOUNTEDON;
  441 #endif
  442         (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
  443         return (error);
  444 }
  445 
  446 #if !defined(__FreeBSD__)
  447 static int
  448 hpfs_start (
  449         struct mount *mp,
  450         int flags,
  451         struct proc *p )
  452 {
  453         return (0);
  454 }
  455 #endif
  456 
  457 static int
  458 hpfs_unmount( 
  459         struct mount *mp,
  460         int mntflags,
  461         struct proc *p)
  462 {
  463         int error, flags, ronly;
  464         register struct hpfsmount *hpmp = VFSTOHPFS(mp);
  465 
  466         dprintf(("hpfs_unmount():\n"));
  467 
  468         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  469 
  470         flags = 0;
  471         if(mntflags & MNT_FORCE)
  472                 flags |= FORCECLOSE;
  473 
  474         dprintf(("hpfs_unmount: vflushing...\n"));
  475         
  476         error = vflush(mp, 0, flags);
  477         if (error) {
  478                 printf("hpfs_unmount: vflush failed: %d\n",error);
  479                 return (error);
  480         }
  481 
  482 #if defined(__FreeBSD__)
  483         hpmp->hpm_devvp->v_specmountpoint = NULL;
  484 #else
  485         hpmp->hpm_devvp->v_specflags &= ~SI_MOUNTEDON;
  486 #endif
  487 
  488         vinvalbuf(hpmp->hpm_devvp, V_SAVE, NOCRED, p, 0, 0);
  489         error = VOP_CLOSE(hpmp->hpm_devvp, ronly ? FREAD : FREAD|FWRITE,
  490                 NOCRED, p);
  491 
  492         vrele(hpmp->hpm_devvp);
  493 
  494         dprintf(("hpfs_umount: freeing memory...\n"));
  495         hpfs_cpdeinit(hpmp);
  496         hpfs_bmdeinit(hpmp);
  497         mp->mnt_data = (qaddr_t)0;
  498         mp->mnt_flag &= ~MNT_LOCAL;
  499         FREE(hpmp, M_HPFSMNT);
  500 
  501         return (0);
  502 }
  503 
  504 static int
  505 hpfs_root(
  506         struct mount *mp,
  507         struct vnode **vpp )
  508 {
  509         int error = 0;
  510         struct hpfsmount *hpmp = VFSTOHPFS(mp);
  511 
  512         dprintf(("hpfs_root():\n"));
  513         error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, vpp);
  514         if(error) {
  515                 printf("hpfs_root: VFS_VGET failed: %d\n",error);
  516                 return (error);
  517         }
  518 
  519         return (error);
  520 }
  521 
  522 static int
  523 hpfs_statfs(
  524         struct mount *mp,
  525         struct statfs *sbp,
  526         struct proc *p)
  527 {
  528         struct hpfsmount *hpmp = VFSTOHPFS(mp);
  529 
  530         dprintf(("hpfs_statfs(): HPFS%d.%d\n",
  531                 hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver));
  532 
  533 #if defined(__FreeBSD__)
  534         sbp->f_type = mp->mnt_vfc->vfc_typenum;
  535 #else /* defined(__NetBSD__) */
  536         sbp->f_type = 0;
  537 #endif
  538         sbp->f_bsize = DEV_BSIZE;
  539         sbp->f_iosize = DEV_BSIZE;
  540         sbp->f_blocks = hpmp->hpm_su.su_btotal;
  541         sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail;
  542         sbp->f_ffree = 0;
  543         sbp->f_files = 0;
  544         if (sbp != &mp->mnt_stat) {
  545                 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
  546                         (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
  547                 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
  548                         (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
  549         }
  550         sbp->f_flags = mp->mnt_flag;
  551         
  552         return (0);
  553 }
  554 
  555 #if !defined(__FreeBSD__)
  556 static int
  557 hpfs_sync (
  558         struct mount *mp,
  559         int waitfor,
  560         struct ucred *cred,
  561         struct proc *p)
  562 {
  563         return (0);
  564 }
  565 
  566 static int
  567 hpfs_quotactl ( 
  568         struct mount *mp,
  569         int cmds,
  570         uid_t uid,
  571         caddr_t arg,
  572         struct proc *p)
  573 {
  574         printf("hpfs_quotactl():\n");
  575         return (EOPNOTSUPP);
  576 }
  577 #endif
  578 
  579 /*ARGSUSED*/
  580 static int
  581 hpfs_fhtovp(
  582         struct mount *mp,
  583         struct fid *fhp,
  584         struct vnode **vpp)
  585 {
  586         struct vnode *nvp;
  587         struct hpfid *hpfhp = (struct hpfid *)fhp;
  588         int error;
  589 
  590         if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, &nvp)) != 0) {
  591                 *vpp = NULLVP;
  592                 return (error);
  593         }
  594         /* XXX as unlink/rmdir/mkdir/creat are not currently possible
  595          * with HPFS, we don't need to check anything else for now */
  596         *vpp = nvp;
  597 
  598         return (0);
  599 }
  600 
  601 static int
  602 hpfs_vptofh(
  603         struct vnode *vp,
  604         struct fid *fhp)
  605 {
  606         register struct hpfsnode *hpp;
  607         register struct hpfid *hpfhp;
  608 
  609         hpp = VTOHP(vp);
  610         hpfhp = (struct hpfid *)fhp;
  611         hpfhp->hpfid_len = sizeof(struct hpfid);
  612         hpfhp->hpfid_ino = hpp->h_no;
  613         /* hpfhp->hpfid_gen = hpp->h_gen; */
  614         return (0);
  615 }
  616 
  617 static int
  618 hpfs_vget(
  619         struct mount *mp,
  620         ino_t ino,
  621         struct vnode **vpp) 
  622 {
  623         struct hpfsmount *hpmp = VFSTOHPFS(mp);
  624         struct vnode *vp;
  625         struct hpfsnode *hp;
  626         struct buf *bp;
  627         struct proc *p = curproc;       /* XXX */
  628         int error;
  629 
  630         dprintf(("hpfs_vget(0x%x): ",ino));
  631 
  632         *vpp = NULL;
  633         hp = NULL;
  634         vp = NULL;
  635 
  636         if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, p)) != NULL) {
  637                 dprintf(("hashed\n"));
  638                 return (0);
  639         }
  640 
  641         /*
  642          * We have to lock node creation for a while,
  643          * but then we have to call getnewvnode(), 
  644          * this may cause hpfs_reclaim() to be called,
  645          * this may need to VOP_VGET() parent dir for
  646          * update reasons, and if parent is not in
  647          * hash, we have to lock node creation...
  648          * To solve this, we MALLOC, getnewvnode and init while
  649          * not locked (probability of node appearence
  650          * at that time is little, and anyway - we'll
  651          * check for it).
  652          */
  653         MALLOC(hp, struct hpfsnode *, sizeof(struct hpfsnode), 
  654                 M_HPFSNO, M_WAITOK);
  655 
  656         error = getnewvnode(VT_HPFS, hpmp->hpm_mp, hpfs_vnodeop_p, &vp);
  657         if (error) {
  658                 printf("hpfs_vget: can't get new vnode\n");
  659                 FREE(hp, M_HPFSNO);
  660                 return (error);
  661         }
  662 
  663         dprintf(("prenew "));
  664 
  665         vp->v_data = hp;
  666 
  667         if (ino == (ino_t)hpmp->hpm_su.su_rootfno) 
  668                 vp->v_flag |= VROOT;
  669 
  670         simple_lock_init(&hp->h_interlock);
  671         lockinit(&hp->h_lock, PINOD, "hpnode", VLKTIMEOUT, 0);
  672 
  673         hp->h_flag = H_INVAL;
  674         hp->h_vp = vp;
  675         hp->h_hpmp = hpmp;
  676         hp->h_no = ino;
  677         hp->h_dev = hpmp->hpm_dev;
  678         hp->h_uid = hpmp->hpm_uid;
  679         hp->h_gid = hpmp->hpm_uid;
  680         hp->h_mode = hpmp->hpm_mode;
  681         hp->h_devvp = hpmp->hpm_devvp;
  682         VREF(hp->h_devvp);
  683 
  684         error = VN_LOCK(vp, LK_EXCLUSIVE, p);
  685         if (error) {
  686                 vput(vp);
  687                 return (error);
  688         }
  689 
  690         do {
  691                 if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, p)) != NULL) {
  692                         dprintf(("hashed2\n"));
  693                         vput(vp);
  694                         return (0);
  695                 }
  696         } while(LOCKMGR(&hpfs_hphash_lock,LK_EXCLUSIVE|LK_SLEEPFAIL,NULL,NULL));
  697 
  698         hpfs_hphashins(hp);
  699 
  700         LOCKMGR(&hpfs_hphash_lock, LK_RELEASE, NULL, NULL);
  701 
  702         error = bread(hpmp->hpm_devvp, ino, FNODESIZE, NOCRED, &bp);
  703         if (error) {
  704                 printf("hpfs_vget: can't read ino %d\n",ino);
  705                 vput(vp);
  706                 return (error);
  707         }
  708         bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode));
  709         brelse(bp);
  710 
  711         if (hp->h_fn.fn_magic != FN_MAGIC) {
  712                 printf("hpfs_vget: MAGIC DOESN'T MATCH\n");
  713                 vput(vp);
  714                 return (EINVAL);
  715         }
  716 
  717         vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG;
  718         hp->h_flag &= ~H_INVAL;
  719 
  720         *vpp = vp;
  721 
  722         return (0);
  723 }
  724 
  725 #if defined(__FreeBSD__)
  726 static struct vfsops hpfs_vfsops = {
  727         hpfs_mount,
  728         vfs_stdstart,
  729         hpfs_unmount,
  730         hpfs_root,
  731         vfs_stdquotactl,
  732         hpfs_statfs,
  733         vfs_stdsync,
  734         hpfs_vget,
  735         hpfs_fhtovp,
  736         hpfs_checkexp,
  737         hpfs_vptofh,
  738         hpfs_init,
  739         vfs_stduninit,
  740         vfs_stdextattrctl,
  741 };
  742 VFS_SET(hpfs_vfsops, hpfs, 0);
  743 #else /* defined(__NetBSD__) */
  744 extern struct vnodeopv_desc hpfs_vnodeop_opv_desc;
  745 
  746 struct vnodeopv_desc *hpfs_vnodeopv_descs[] = {
  747         &hpfs_vnodeop_opv_desc,
  748         NULL,
  749 };
  750 
  751 struct vfsops hpfs_vfsops = {
  752         MOUNT_HPFS,
  753         hpfs_mount,
  754         hpfs_start,
  755         hpfs_unmount,
  756         hpfs_root,
  757         hpfs_quotactl,
  758         hpfs_statfs,
  759         hpfs_sync,
  760         hpfs_vget,
  761         hpfs_fhtovp,
  762         hpfs_vptofh,
  763         hpfs_init,
  764         hpfs_sysctl,
  765         hpfs_mountroot,
  766         hpfs_checkexp,
  767         hpfs_vnodeopv_descs,
  768 };
  769 #endif

Cache object: c94d1891893ee5a2639d3c4d48065b91


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