LCOV - code coverage report
Current view: top level - ntfs - ntfs_vfsops.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 311 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ntfs_vfsops.c,v 1.61 2018/05/27 06:02:15 visa Exp $   */
       2             : /*      $NetBSD: ntfs_vfsops.c,v 1.7 2003/04/24 07:50:19 christos Exp $ */
       3             : 
       4             : /*-
       5             :  * Copyright (c) 1998, 1999 Semen Ustimenko
       6             :  * All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      18             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      21             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27             :  * SUCH DAMAGE.
      28             :  *
      29             :  *      Id: ntfs_vfsops.c,v 1.7 1999/05/31 11:28:30 phk Exp
      30             :  */
      31             : 
      32             : #include <sys/param.h>
      33             : #include <sys/systm.h>
      34             : #include <sys/namei.h>
      35             : #include <sys/proc.h>
      36             : #include <sys/kernel.h>
      37             : #include <sys/vnode.h>
      38             : #include <sys/lock.h>
      39             : #include <sys/mount.h>
      40             : #include <sys/buf.h>
      41             : #include <sys/disk.h>
      42             : #include <sys/fcntl.h>
      43             : #include <sys/malloc.h>
      44             : #include <sys/device.h>
      45             : #include <sys/conf.h>
      46             : #include <sys/specdev.h>
      47             : 
      48             : /*#define NTFS_DEBUG 1*/
      49             : #include <ntfs/ntfs.h>
      50             : #include <ntfs/ntfs_inode.h>
      51             : #include <ntfs/ntfs_subr.h>
      52             : #include <ntfs/ntfs_vfsops.h>
      53             : #include <ntfs/ntfs_ihash.h>
      54             : 
      55             : int     ntfs_mount(struct mount *, const char *, void *,
      56             :                                 struct nameidata *, struct proc *);
      57             : int     ntfs_quotactl(struct mount *, int, uid_t, caddr_t,
      58             :                                    struct proc *);
      59             : int     ntfs_root(struct mount *, struct vnode **);
      60             : int     ntfs_start(struct mount *, int, struct proc *);
      61             : int     ntfs_statfs(struct mount *, struct statfs *,
      62             :                                  struct proc *);
      63             : int     ntfs_sync(struct mount *, int, int, struct ucred *,
      64             :                                struct proc *);
      65             : int     ntfs_unmount(struct mount *, int, struct proc *);
      66             : int     ntfs_vget(struct mount *mp, ino_t ino,
      67             :                                struct vnode **vpp);
      68             : int     ntfs_mountfs(struct vnode *, struct mount *, 
      69             :                                   struct ntfs_args *, struct proc *);
      70             : int     ntfs_vptofh(struct vnode *, struct fid *);
      71             : 
      72             : int     ntfs_init(struct vfsconf *);
      73             : int     ntfs_fhtovp(struct mount *, struct fid *,
      74             :                              struct vnode **);
      75             : int     ntfs_checkexp(struct mount *, struct mbuf *,
      76             :                                int *, struct ucred **);
      77             : int     ntfs_sysctl(int *, u_int, void *, size_t *, void *,
      78             :                              size_t, struct proc *);
      79             : 
      80             : /*
      81             :  * Verify a remote client has export rights and return these rights via.
      82             :  * exflagsp and credanonp.
      83             :  */
      84             : int
      85           0 : ntfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
      86             :     struct ucred **credanonp)
      87             : {
      88             :         struct netcred *np;
      89           0 :         struct ntfsmount *ntm = VFSTONTFS(mp);
      90             : 
      91             :         /*
      92             :          * Get the export permission structure for this <mp, client> tuple.
      93             :          */
      94           0 :         np = vfs_export_lookup(mp, &ntm->ntm_export, nam);
      95           0 :         if (np == NULL)
      96           0 :                 return (EACCES);
      97             : 
      98           0 :         *exflagsp = np->netc_exflags;
      99           0 :         *credanonp = &np->netc_anon;
     100           0 :         return (0);
     101           0 : }
     102             : 
     103             : int
     104           0 : ntfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     105             :     size_t newlen, struct proc *p)
     106             : {
     107           0 :         return (EINVAL);
     108             : }
     109             : 
     110             : int
     111           0 : ntfs_init(struct vfsconf *vcp)
     112             : {
     113           0 :         return 0;
     114             : }
     115             : 
     116             : int
     117           0 : ntfs_mount(struct mount *mp, const char *path, void *data,
     118             :     struct nameidata *ndp, struct proc *p)
     119             : {
     120             :         int             err = 0;
     121             :         struct vnode    *devvp;
     122           0 :         struct ntfs_args *args = data;
     123           0 :         char fname[MNAMELEN];
     124           0 :         char fspec[MNAMELEN];
     125             : 
     126           0 :         ntfs_nthashinit();
     127             : 
     128             :         /*
     129             :          ***
     130             :          * Mounting non-root file system or updating a file system
     131             :          ***
     132             :          */
     133             : 
     134             :         /*
     135             :          * If updating, check whether changing from read-only to
     136             :          * read/write; if there is no device name, that's all we do.
     137             :          */
     138           0 :         if (mp->mnt_flag & MNT_UPDATE) {
     139             :                 /* if not updating name...*/
     140           0 :                 if (args && args->fspec == NULL) {
     141             :                         /*
     142             :                          * Process export requests.  Jumping to "success"
     143             :                          * will return the vfs_export() error code.
     144             :                          */
     145           0 :                         struct ntfsmount *ntm = VFSTONTFS(mp);
     146           0 :                         err = vfs_export(mp, &ntm->ntm_export, &args->export_info);
     147             :                         goto success;
     148             :                 }
     149             : 
     150           0 :                 printf("ntfs_mount(): MNT_UPDATE not supported\n");
     151             :                 err = EINVAL;
     152           0 :                 goto error_1;
     153             :         }
     154             : 
     155             :         /*
     156             :          * Not an update, or updating the name: look up the name
     157             :          * and verify that it refers to a sensible block device.
     158             :          */
     159           0 :         err = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
     160           0 :         if (err)
     161             :                 goto error_1;
     162             : 
     163           0 :         if (disk_map(fspec, fname, sizeof(fname), DM_OPENBLCK) == -1)
     164           0 :                 bcopy(fspec, fname, sizeof(fname));
     165             : 
     166           0 :         NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p);
     167           0 :         err = namei(ndp);
     168           0 :         if (err) {
     169             :                 /* can't get devvp!*/
     170             :                 goto error_1;
     171             :         }
     172             : 
     173           0 :         devvp = ndp->ni_vp;
     174             : 
     175           0 :         if (devvp->v_type != VBLK) {
     176             :                 err = ENOTBLK;
     177           0 :                 goto error_2;
     178             :         }
     179             : 
     180           0 :         if (major(devvp->v_rdev) >= nblkdev) {
     181             :                 err = ENXIO;
     182           0 :                 goto error_2;
     183             :         }
     184             : 
     185           0 :         if (mp->mnt_flag & MNT_UPDATE) {
     186             : #if 0
     187             :                 /*
     188             :                  ********************
     189             :                  * UPDATE
     190             :                  ********************
     191             :                  */
     192             : 
     193             :                 if (devvp != ntmp->um_devvp)
     194             :                         err = EINVAL;   /* needs translation */
     195             :                 else
     196             :                         vrele(devvp);
     197             :                 /*
     198             :                  * Update device name only on success
     199             :                  */
     200             :                 if( !err) {
     201             :                         err = set_statfs_info(NULL, UIO_USERSPACE, args->fspec,
     202             :                             UIO_USERSPACE, mp, p);
     203             :                 }
     204             : #endif
     205             :         } else {
     206             :                 /*
     207             :                  ********************
     208             :                  * NEW MOUNT
     209             :                  ********************
     210             :                  */
     211             : 
     212             :                 /*
     213             :                  * Since this is a new mount, we want the names for
     214             :                  * the device and the mount point copied in.  If an
     215             :                  * error occurs,  the mountpoint is discarded by the
     216             :                  * upper level code.
     217             :                  */
     218             :                 /* Save "last mounted on" info for mount point (NULL pad)*/
     219           0 :                 bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
     220           0 :                 strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
     221           0 :                 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
     222           0 :                 strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN);
     223           0 :                 bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN);
     224           0 :                 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
     225           0 :                 bcopy(args, &mp->mnt_stat.mount_info.ntfs_args, sizeof(*args));
     226           0 :                 if ( !err) {
     227           0 :                         err = ntfs_mountfs(devvp, mp, args, p);
     228           0 :                 }
     229             :         }
     230           0 :         if (err) {
     231             :                 goto error_2;
     232             :         }
     233             : 
     234             :         /*
     235             :          * Initialize FS stat information in mount struct; uses both
     236             :          * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
     237             :          *
     238             :          * This code is common to root and non-root mounts
     239             :          */
     240           0 :         (void)VFS_STATFS(mp, &mp->mnt_stat, p);
     241             : 
     242           0 :         goto success;
     243             : 
     244             : 
     245             : error_2:        /* error with devvp held*/
     246             : 
     247             :         /* release devvp before failing*/
     248           0 :         vrele(devvp);
     249             : 
     250             : error_1:        /* no state to back out*/
     251             : 
     252             : success:
     253           0 :         return(err);
     254           0 : }
     255             : 
     256             : /*
     257             :  * Common code for mount and mountroot
     258             :  */
     259             : int
     260           0 : ntfs_mountfs(struct vnode *devvp, struct mount *mp, struct ntfs_args *argsp,
     261             :     struct proc *p)
     262             : {
     263           0 :         struct buf *bp;
     264             :         struct ntfsmount *ntmp = NULL;
     265           0 :         dev_t dev = devvp->v_rdev;
     266             :         int error, ncount, i;
     267           0 :         struct vnode *vp;
     268             : 
     269             :         /*
     270             :          * Disallow multiple mounts of the same device.
     271             :          * Disallow mounting of a device that is currently in use
     272             :          * (except for root, which might share swap device for miniroot).
     273             :          * Flush out any old buffers remaining from a previous use.
     274             :          */
     275           0 :         error = vfs_mountedon(devvp);
     276           0 :         if (error)
     277           0 :                 return (error);
     278           0 :         ncount = vcount(devvp);
     279           0 :         if (ncount > 1 && devvp != rootvp)
     280           0 :                 return (EBUSY);
     281           0 :         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     282           0 :         error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
     283           0 :         VOP_UNLOCK(devvp);
     284           0 :         if (error)
     285           0 :                 return (error);
     286             : 
     287           0 :         error = VOP_OPEN(devvp, FREAD, FSCRED, p);
     288           0 :         if (error)
     289           0 :                 return (error);
     290             : 
     291           0 :         bp = NULL;
     292             : 
     293           0 :         error = bread(devvp, BBLOCK, BBSIZE, &bp);
     294           0 :         if (error)
     295             :                 goto out;
     296           0 :         ntmp = malloc(sizeof *ntmp, M_NTFSMNT, M_WAITOK | M_ZERO);
     297           0 :         bcopy(bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile));
     298           0 :         brelse(bp);
     299           0 :         bp = NULL;
     300             : 
     301           0 :         if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
     302             :                 error = EINVAL;
     303             :                 DPRINTF("ntfs_mountfs: invalid boot block\n");
     304           0 :                 goto out;
     305             :         }
     306             : 
     307             :         {
     308           0 :                 int8_t cpr = ntmp->ntm_mftrecsz;
     309           0 :                 if( cpr > 0 )
     310           0 :                         ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
     311             :                 else
     312           0 :                         ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
     313             :         }
     314             :         DPRINTF("ntfs_mountfs(): bps: %u, spc: %u, media: %x, "
     315             :             "mftrecsz: %u (%u sects)\n", ntmp->ntm_bps, ntmp->ntm_spc,
     316             :             ntmp->ntm_bootfile.bf_media, ntmp->ntm_mftrecsz,
     317             :             ntmp->ntm_bpmftrec);
     318             :         DPRINTF("ntfs_mountfs(): mftcn: 0x%llx|0x%llx\n",
     319             :             ntmp->ntm_mftcn, ntmp->ntm_mftmirrcn);
     320             : 
     321           0 :         ntmp->ntm_mountp = mp;
     322           0 :         ntmp->ntm_dev = dev;
     323           0 :         ntmp->ntm_devvp = devvp;
     324           0 :         ntmp->ntm_uid = argsp->uid;
     325           0 :         ntmp->ntm_gid = argsp->gid;
     326           0 :         ntmp->ntm_mode = argsp->mode;
     327           0 :         ntmp->ntm_flag = argsp->flag;
     328           0 :         mp->mnt_data = ntmp;
     329           0 :         TAILQ_INIT(&ntmp->ntm_ntnodeq);
     330             : 
     331             :         /* set file name encode/decode hooks XXX utf-8 only for now */
     332           0 :         ntmp->ntm_wget = ntfs_utf8_wget;
     333           0 :         ntmp->ntm_wput = ntfs_utf8_wput;
     334           0 :         ntmp->ntm_wcmp = ntfs_utf8_wcmp;
     335             : 
     336             :         DPRINTF("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
     337             :             (ntmp->ntm_flag & NTFS_MFLAG_CASEINS) ? "insens." : "sens.",
     338             :             (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES) ? " allnames," : "",
     339             :             ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode);
     340             : 
     341             :         /*
     342             :          * We read in some system nodes to do not allow 
     343             :          * reclaim them and to have everytime access to them.
     344             :          */ 
     345             :         {
     346           0 :                 int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
     347           0 :                 for (i=0; i<3; i++) {
     348           0 :                         error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]]));
     349           0 :                         if(error)
     350           0 :                                 goto out1;
     351           0 :                         ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM;
     352           0 :                         vref(ntmp->ntm_sysvn[pi[i]]);
     353           0 :                         vput(ntmp->ntm_sysvn[pi[i]]);
     354             :                 }
     355           0 :         }
     356             : 
     357             :         /* read the Unicode lowercase --> uppercase translation table,
     358             :          * if necessary */
     359           0 :         if ((error = ntfs_toupper_use(mp, ntmp, p)))
     360             :                 goto out1;
     361             : 
     362             :         /*
     363             :          * Scan $BitMap and count free clusters
     364             :          */
     365           0 :         error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
     366           0 :         if(error)
     367             :                 goto out1;
     368             : 
     369             :         /*
     370             :          * Read and translate to internal format attribute
     371             :          * definition file. 
     372             :          */
     373             :         {
     374             :                 int num,j;
     375           0 :                 struct attrdef ad;
     376             : 
     377             :                 /* Open $AttrDef */
     378           0 :                 error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp );
     379           0 :                 if(error) 
     380           0 :                         goto out1;
     381             : 
     382             :                 /* Count valid entries */
     383           0 :                 for(num = 0; ; num++) {
     384           0 :                         error = ntfs_readattr(ntmp, VTONT(vp),
     385           0 :                             NTFS_A_DATA, NULL, num * sizeof(ad), sizeof(ad),
     386             :                             &ad, NULL);
     387           0 :                         if (error)
     388           0 :                                 goto out1;
     389           0 :                         if (ad.ad_name[0] == 0)
     390             :                                 break;
     391             :                 }
     392             : 
     393             :                 /* Alloc memory for attribute definitions */
     394           0 :                 ntmp->ntm_ad = mallocarray(num, sizeof(struct ntvattrdef),
     395             :                     M_NTFSMNT, M_WAITOK);
     396             : 
     397           0 :                 ntmp->ntm_adnum = num;
     398             : 
     399             :                 /* Read them and translate */
     400           0 :                 for(i = 0; i < num; i++){
     401           0 :                         error = ntfs_readattr(ntmp, VTONT(vp),
     402           0 :                             NTFS_A_DATA, NULL, i * sizeof(ad), sizeof(ad),
     403             :                             &ad, NULL);
     404           0 :                         if (error)
     405           0 :                                 goto out1;
     406             :                         j = 0;
     407           0 :                         do {
     408           0 :                                 ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
     409           0 :                         } while(ad.ad_name[j++]);
     410           0 :                         ntmp->ntm_ad[i].ad_namelen = j - 1;
     411           0 :                         ntmp->ntm_ad[i].ad_type = ad.ad_type;
     412             :                 }
     413             : 
     414           0 :                 vput(vp);
     415           0 :         }
     416             : 
     417           0 :         mp->mnt_stat.f_fsid.val[0] = dev;
     418           0 :         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
     419           0 :         mp->mnt_stat.f_namemax = NTFS_MAXFILENAME;
     420           0 :         mp->mnt_flag |= MNT_LOCAL;
     421           0 :         devvp->v_specmountpoint = mp;
     422           0 :         return (0);
     423             : 
     424             : out1:
     425           0 :         for (i = 0; i < NTFS_SYSNODESNUM; i++)
     426           0 :                 if (ntmp->ntm_sysvn[i])
     427           0 :                         vrele(ntmp->ntm_sysvn[i]);
     428             : 
     429           0 :         if (vflush(mp,NULLVP,0))
     430             :                 DPRINTF("ntfs_mountfs: vflush failed\n");
     431             : 
     432             : out:
     433           0 :         if (devvp->v_specinfo)
     434           0 :                 devvp->v_specmountpoint = NULL;
     435           0 :         if (bp)
     436           0 :                 brelse(bp);
     437             : 
     438           0 :         if (ntmp != NULL) {
     439           0 :                 if (ntmp->ntm_ad != NULL)
     440           0 :                         free(ntmp->ntm_ad, M_NTFSMNT, 0);
     441           0 :                 free(ntmp, M_NTFSMNT, 0);
     442           0 :                 mp->mnt_data = NULL;
     443           0 :         }
     444             : 
     445             :         /* lock the device vnode before calling VOP_CLOSE() */
     446           0 :         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     447           0 :         (void)VOP_CLOSE(devvp, FREAD, NOCRED, p);
     448           0 :         VOP_UNLOCK(devvp);
     449             :         
     450           0 :         return (error);
     451           0 : }
     452             : 
     453             : int
     454           0 : ntfs_start(struct mount *mp, int flags, struct proc *p)
     455             : {
     456           0 :         return (0);
     457             : }
     458             : 
     459             : int
     460           0 : ntfs_unmount(struct mount *mp, int mntflags, struct proc *p)
     461             : {
     462             :         struct ntfsmount *ntmp;
     463             :         int error, flags, i;
     464             : 
     465             :         DPRINTF("ntfs_unmount: unmounting...\n");
     466           0 :         ntmp = VFSTONTFS(mp);
     467             : 
     468             :         flags = 0;
     469           0 :         if(mntflags & MNT_FORCE)
     470           0 :                 flags |= FORCECLOSE;
     471             : 
     472             :         DPRINTF("ntfs_unmount: vflushing...\n");
     473           0 :         error = vflush(mp,NULLVP,flags | SKIPSYSTEM);
     474           0 :         if (error) {
     475             :                 DPRINTF("ntfs_unmount: vflush failed: %d\n", error);
     476           0 :                 return (error);
     477             :         }
     478             : 
     479             :         /* Check if system vnodes are still referenced */
     480           0 :         for(i=0;i<NTFS_SYSNODESNUM;i++) {
     481           0 :                 if(((mntflags & MNT_FORCE) == 0) && (ntmp->ntm_sysvn[i] &&
     482           0 :                     ntmp->ntm_sysvn[i]->v_usecount > 1))
     483           0 :                         return (EBUSY);
     484             :         }
     485             : 
     486             :         /* Dereference all system vnodes */
     487           0 :         for(i=0;i<NTFS_SYSNODESNUM;i++)
     488           0 :                  if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
     489             : 
     490             :         /* vflush system vnodes */
     491           0 :         error = vflush(mp,NULLVP,flags);
     492           0 :         if (error) {
     493             :                 /* XXX should this be panic() ? */
     494           0 :                 printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
     495           0 :         }
     496             : 
     497             :         /* Check if the type of device node isn't VBAD before
     498             :          * touching v_specinfo.  If the device vnode is revoked, the
     499             :          * field is NULL and touching it causes null pointer derefercence.
     500             :          */
     501           0 :         if (ntmp->ntm_devvp->v_type != VBAD)
     502           0 :                 ntmp->ntm_devvp->v_specmountpoint = NULL;
     503             : 
     504             :         /* lock the device vnode before calling VOP_CLOSE() */
     505           0 :         vn_lock(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY);
     506           0 :         vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, p, 0, 0);
     507           0 :         (void)VOP_CLOSE(ntmp->ntm_devvp, FREAD, NOCRED, p);
     508           0 :         vput(ntmp->ntm_devvp);
     509             : 
     510             :         /* free the toupper table, if this has been last mounted ntfs volume */
     511           0 :         ntfs_toupper_unuse(p);
     512             : 
     513             :         DPRINTF("ntfs_unmount: freeing memory...\n");
     514           0 :         free(ntmp->ntm_ad, M_NTFSMNT, 0);
     515           0 :         free(ntmp, M_NTFSMNT, 0);
     516           0 :         mp->mnt_data = NULL;
     517           0 :         mp->mnt_flag &= ~MNT_LOCAL;
     518           0 :         return (0);
     519           0 : }
     520             : 
     521             : int
     522           0 : ntfs_root(struct mount *mp, struct vnode **vpp)
     523             : {
     524           0 :         struct vnode *nvp;
     525             :         int error = 0;
     526             : 
     527             :         DPRINTF("ntfs_root(): sysvn: %p\n",
     528             :             VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]);
     529           0 :         error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp);
     530           0 :         if(error) {
     531           0 :                 printf("ntfs_root: VFS_VGET failed: %d\n",error);
     532           0 :                 return (error);
     533             :         }
     534             : 
     535           0 :         *vpp = nvp;
     536           0 :         return (0);
     537           0 : }
     538             : 
     539             : /*
     540             :  * Do operations associated with quotas, not supported
     541             :  */
     542             : int
     543           0 : ntfs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
     544             :     struct proc *p)
     545             : {
     546           0 :         return EOPNOTSUPP;
     547             : }
     548             : 
     549             : int
     550           0 : ntfs_calccfree(struct ntfsmount *ntmp, cn_t *cfreep)
     551             : {
     552             :         struct vnode *vp;
     553             :         u_int8_t *tmp;
     554             :         int j, error;
     555             :         cn_t cfree = 0;
     556             :         uint64_t bmsize, offset;
     557             :         size_t chunksize, i;
     558             : 
     559           0 :         vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
     560             : 
     561           0 :         bmsize = VTOF(vp)->f_size;
     562             : 
     563           0 :         if (bmsize > 1024 * 1024)
     564           0 :                 chunksize = 1024 * 1024;
     565             :         else
     566             :                 chunksize = bmsize;
     567             : 
     568           0 :         tmp = malloc(chunksize, M_TEMP, M_WAITOK);
     569             : 
     570           0 :         for (offset = 0; offset < bmsize; offset += chunksize) {
     571           0 :                 if (chunksize > bmsize - offset)
     572           0 :                         chunksize = bmsize - offset;
     573             : 
     574           0 :                 error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
     575             :                     offset, chunksize, tmp, NULL);
     576           0 :                 if (error)
     577             :                         goto out;
     578             : 
     579           0 :                 for (i = 0; i < chunksize; i++)
     580           0 :                         for (j = 0; j < 8; j++)
     581           0 :                                 if (~tmp[i] & (1 << j))
     582           0 :                                         cfree++;
     583             :         }
     584             : 
     585           0 :         *cfreep = cfree;
     586             : 
     587             :     out:
     588           0 :         free(tmp, M_TEMP, 0);
     589           0 :         return(error);
     590             : }
     591             : 
     592             : int
     593           0 : ntfs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
     594             : {
     595           0 :         struct ntfsmount *ntmp = VFSTONTFS(mp);
     596             :         u_int64_t mftallocated;
     597             : 
     598             :         DPRINTF("ntfs_statfs():\n");
     599             : 
     600           0 :         mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
     601             : 
     602           0 :         sbp->f_bsize = ntmp->ntm_bps;
     603           0 :         sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
     604           0 :         sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
     605           0 :         sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
     606           0 :         sbp->f_ffree = sbp->f_favail = sbp->f_bfree / ntmp->ntm_bpmftrec;
     607           0 :         sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
     608             :                        sbp->f_ffree;
     609           0 :         copy_statfs_info(sbp, mp);
     610             : 
     611           0 :         return (0);
     612             : }
     613             : 
     614             : int
     615           0 : ntfs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p)
     616             : {
     617             :         /*DPRINTF("ntfs_sync():\n");*/
     618           0 :         return (0);
     619             : }
     620             : 
     621             : int
     622           0 : ntfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
     623             : {
     624           0 :         struct ntfid *ntfhp = (struct ntfid *)fhp;
     625             :         int error;
     626             : 
     627             :         DDPRINTF("ntfs_fhtovp(): %s: %u\n",
     628             :             mp->mnt_stat.f_mntonname, ntfhp->ntfid_ino);
     629             : 
     630           0 :         error = ntfs_vgetex(mp, ntfhp->ntfid_ino, ntfhp->ntfid_attr, NULL,
     631           0 :                         LK_EXCLUSIVE | LK_RETRY, 0, curproc, vpp); /* XXX */
     632           0 :         if (error != 0) {
     633           0 :                 *vpp = NULLVP;
     634           0 :                 return (error);
     635             :         }
     636             : 
     637             :         /* XXX as unlink/rmdir/mkdir/creat are not currently possible
     638             :          * with NTFS, we don't need to check anything else for now */
     639           0 :         return (0);
     640           0 : }
     641             : 
     642             : int
     643           0 : ntfs_vptofh(struct vnode *vp, struct fid *fhp)
     644             : {
     645             :         struct ntnode *ntp;
     646             :         struct ntfid *ntfhp;
     647             :         struct fnode *fn;
     648             : 
     649             :         DDPRINTF("ntfs_fhtovp(): %s: %p\n",
     650             :             vp->v_mount->mnt_stat.f_mntonname, vp);
     651             : 
     652           0 :         fn = VTOF(vp);
     653           0 :         ntp = VTONT(vp);
     654           0 :         ntfhp = (struct ntfid *)fhp;
     655           0 :         ntfhp->ntfid_len = sizeof(struct ntfid);
     656           0 :         ntfhp->ntfid_ino = ntp->i_number;
     657           0 :         ntfhp->ntfid_attr = fn->f_attrtype;
     658             : #ifdef notyet
     659             :         ntfhp->ntfid_gen = ntp->i_gen;
     660             : #endif
     661           0 :         return (0);
     662             : }
     663             : 
     664             : int
     665           0 : ntfs_vgetex(struct mount *mp, ntfsino_t ino, u_int32_t attrtype, char *attrname,
     666             :     u_long lkflags, u_long flags, struct proc *p, struct vnode **vpp) 
     667             : {
     668             :         int error;
     669             :         struct ntfsmount *ntmp;
     670           0 :         struct ntnode *ip;
     671           0 :         struct fnode *fp;
     672           0 :         struct vnode *vp;
     673             :         enum vtype f_type;
     674             : 
     675             :         DPRINTF("ntfs_vgetex: ino: %u, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
     676             :             ino, attrtype, attrname ? attrname : "", lkflags, flags);
     677             : 
     678           0 :         ntmp = VFSTONTFS(mp);
     679           0 :         *vpp = NULL;
     680             : 
     681             :         /* Get ntnode */
     682           0 :         error = ntfs_ntlookup(ntmp, ino, &ip, p);
     683           0 :         if (error) {
     684           0 :                 printf("ntfs_vget: ntfs_ntget failed\n");
     685           0 :                 return (error);
     686             :         }
     687             : 
     688             :         /* It may be not initialized fully, so force load it */
     689           0 :         if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
     690           0 :                 error = ntfs_loadntnode(ntmp, ip);
     691           0 :                 if(error) {
     692           0 :                         printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
     693           0 :                                ip->i_number);
     694           0 :                         ntfs_ntput(ip, p);
     695             : 
     696           0 :                         return (error);
     697             :                 }
     698             :         }
     699             : 
     700           0 :         error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
     701           0 :         if (error) {
     702           0 :                 printf("ntfs_vget: ntfs_fget failed\n");
     703           0 :                 ntfs_ntput(ip, p);
     704             : 
     705           0 :                 return (error);
     706             :         }
     707             : 
     708           0 :         if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
     709           0 :                 if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
     710           0 :                     (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
     711             :                         f_type = VDIR;
     712           0 :                 } else if (flags & VG_EXT) {
     713             :                         f_type = VNON;
     714           0 :                         fp->f_size = fp->f_allocated = 0;
     715           0 :                 } else {
     716             :                         f_type = VREG;  
     717             : 
     718           0 :                         error = ntfs_filesize(ntmp, fp, 
     719           0 :                                               &fp->f_size, &fp->f_allocated);
     720           0 :                         if (error) {
     721           0 :                                 ntfs_ntput(ip, p);
     722             : 
     723           0 :                                 return (error);
     724             :                         }
     725             :                 }
     726             : 
     727           0 :                 fp->f_flag |= FN_VALID;
     728           0 :         }
     729             : 
     730             :         /*
     731             :          * We may be calling vget() now. To avoid potential deadlock, we need
     732             :          * to release ntnode lock, since due to locking order vnode
     733             :          * lock has to be acquired first.
     734             :          * ntfs_fget() bumped ntnode usecount, so ntnode won't be recycled
     735             :          * prematurely.
     736             :          */
     737           0 :         ntfs_ntput(ip, p);
     738             : 
     739           0 :         if (FTOV(fp)) {
     740             :                 /* vget() returns error if the vnode has been recycled */
     741           0 :                 if (vget(FTOV(fp), lkflags) == 0) {
     742           0 :                         *vpp = FTOV(fp);
     743           0 :                         return (0);
     744             :                 }
     745             :         }
     746             : 
     747           0 :         error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, &ntfs_vops, &vp);
     748           0 :         if(error) {
     749           0 :                 ntfs_frele(fp);
     750           0 :                 ntfs_ntput(ip, p);
     751             : 
     752           0 :                 return (error);
     753             :         }
     754             :         DPRINTF("ntfs_vget: vnode: %p for ntnode: %u\n", vp, ino);
     755             : 
     756           0 :         fp->f_vp = vp;
     757           0 :         vp->v_data = fp;
     758           0 :         vp->v_type = f_type;
     759             : 
     760           0 :         if (ino == NTFS_ROOTINO)
     761           0 :                 vp->v_flag |= VROOT;
     762             : 
     763           0 :         if (lkflags & LK_TYPE_MASK) {
     764           0 :                 error = vn_lock(vp, lkflags);
     765           0 :                 if (error) {
     766           0 :                         vput(vp);
     767           0 :                         return (error);
     768             :                 }
     769             :         }
     770             : 
     771           0 :         *vpp = vp;
     772           0 :         return (0);
     773           0 : }
     774             : 
     775             : int
     776           0 : ntfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) 
     777             : {
     778           0 :         if (ino > (ntfsino_t)-1)
     779           0 :                 panic("ntfs_vget: alien ino_t %llu", (unsigned long long)ino);
     780           0 :         return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL,
     781           0 :                         LK_EXCLUSIVE | LK_RETRY, 0, curproc, vpp); /* XXX */
     782             : }
     783             : 
     784             : const struct vfsops ntfs_vfsops = {
     785             :         ntfs_mount,
     786             :         ntfs_start,
     787             :         ntfs_unmount,
     788             :         ntfs_root,
     789             :         ntfs_quotactl,
     790             :         ntfs_statfs,
     791             :         ntfs_sync,
     792             :         ntfs_vget,
     793             :         ntfs_fhtovp,
     794             :         ntfs_vptofh,
     795             :         ntfs_init,
     796             :         ntfs_sysctl,
     797             :         ntfs_checkexp,
     798             : };

Generated by: LCOV version 1.13