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/ntfs/ntfs_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 /*      $NetBSD: ntfs_vfsops.c,v 1.23 1999/11/15 19:38:14 jdolecek Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 1998, 1999 Semen Ustimenko
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * $FreeBSD: releng/9.2/sys/fs/ntfs/ntfs_vfsops.c 233120 2012-03-18 15:03:02Z kevlo $
   29  */
   30 
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/namei.h>
   35 #include <sys/conf.h>
   36 #include <sys/priv.h>
   37 #include <sys/proc.h>
   38 #include <sys/kernel.h>
   39 #include <sys/vnode.h>
   40 #include <sys/mount.h>
   41 #include <sys/bio.h>
   42 #include <sys/buf.h>
   43 #include <sys/fcntl.h>
   44 #include <sys/malloc.h>
   45 #include <sys/stat.h>
   46 #include <sys/systm.h>
   47 
   48 #include <geom/geom.h>
   49 #include <geom/geom_vfs.h>
   50 
   51 #include <vm/vm.h>
   52 #include <vm/vm_param.h>
   53 #include <vm/vm_page.h>
   54 #include <vm/vm_object.h>
   55 #include <vm/vm_extern.h>
   56 
   57 /*#define NTFS_DEBUG 1*/
   58 #include <fs/ntfs/ntfs.h>
   59 #include <fs/ntfs/ntfs_inode.h>
   60 #include <fs/ntfs/ntfs_subr.h>
   61 #include <fs/ntfs/ntfs_vfsops.h>
   62 #include <fs/ntfs/ntfs_ihash.h>
   63 #include <fs/ntfs/ntfsmount.h>
   64 
   65 static MALLOC_DEFINE(M_NTFSMNT, "ntfs_mount", "NTFS mount structure");
   66 MALLOC_DEFINE(M_NTFSNTNODE,"ntfs_ntnode",  "NTFS ntnode information");
   67 MALLOC_DEFINE(M_NTFSFNODE,"ntfs_fnode",  "NTFS fnode information");
   68 MALLOC_DEFINE(M_NTFSDIR,"ntfs_dir",  "NTFS dir buffer");
   69 
   70 static int      ntfs_mountfs(register struct vnode *, struct mount *, 
   71                                   struct thread *);
   72 static int      ntfs_calccfree(struct ntfsmount *ntmp, cn_t *cfreep);
   73 
   74 static vfs_init_t       ntfs_init;
   75 static vfs_uninit_t     ntfs_uninit;
   76 static vfs_vget_t       ntfs_vget;
   77 static vfs_fhtovp_t     ntfs_fhtovp;
   78 static vfs_cmount_t     ntfs_cmount;
   79 static vfs_mount_t      ntfs_mount;
   80 static vfs_root_t       ntfs_root;
   81 static vfs_statfs_t     ntfs_statfs;
   82 static vfs_unmount_t    ntfs_unmount;
   83 
   84 static b_strategy_t     ntfs_bufstrategy;
   85 
   86 /* 
   87  * Buffer operations for NTFS vnodes.
   88  * We punt on VOP_BMAP, so we need to do
   89  * strategy on the file's vnode rather
   90  * than the underlying device's
   91  */
   92 static struct buf_ops ntfs_vnbufops = {
   93         .bop_name     = "NTFS",
   94         .bop_strategy = ntfs_bufstrategy,
   95 };
   96 
   97 static int
   98 ntfs_init (
   99         struct vfsconf *vcp )
  100 {
  101         ntfs_nthashinit();
  102         ntfs_toupper_init();
  103         return 0;
  104 }
  105 
  106 static int
  107 ntfs_uninit (
  108         struct vfsconf *vcp )
  109 {
  110         ntfs_toupper_destroy();
  111         ntfs_nthashdestroy();
  112         return 0;
  113 }
  114 
  115 static int
  116 ntfs_cmount ( 
  117         struct mntarg *ma,
  118         void *data,
  119         uint64_t flags)
  120 {
  121         struct ntfs_args args;
  122         struct export_args exp;
  123         int error;
  124 
  125         error = copyin(data, &args, sizeof(args));
  126         if (error)
  127                 return (error);
  128         vfs_oexport_conv(&args.export, &exp);
  129         ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN);
  130         ma = mount_arg(ma, "export", &exp, sizeof(exp));
  131         ma = mount_argf(ma, "uid", "%d", args.uid);
  132         ma = mount_argf(ma, "gid", "%d", args.gid);
  133         ma = mount_argf(ma, "mode", "%d", args.mode);
  134         ma = mount_argb(ma, args.flag & NTFS_MFLAG_CASEINS, "nocaseins");
  135         ma = mount_argb(ma, args.flag & NTFS_MFLAG_ALLNAMES, "noallnames");
  136         if (args.flag & NTFS_MFLAG_KICONV) {
  137                 ma = mount_argsu(ma, "cs_ntfs", args.cs_ntfs, 64);
  138                 ma = mount_argsu(ma, "cs_local", args.cs_local, 64);
  139         }
  140 
  141         error = kernel_mount(ma, flags);
  142 
  143         return (error);
  144 }
  145 
  146 static const char *ntfs_opts[] = {
  147         "from", "export", "uid", "gid", "mode", "caseins", "allnames",
  148         "kiconv", "cs_ntfs", "cs_local", NULL
  149 };
  150 
  151 static int
  152 ntfs_mount(struct mount *mp)
  153 {
  154         int err = 0, error;
  155         accmode_t accmode;
  156         struct vnode *devvp;
  157         struct nameidata ndp;
  158         struct thread *td;
  159         char *from;
  160 
  161         td = curthread;
  162         if (vfs_filteropt(mp->mnt_optnew, ntfs_opts))
  163                 return (EINVAL);
  164 
  165         from = vfs_getopts(mp->mnt_optnew, "from", &error);
  166         if (error)      
  167                 return (error);
  168 
  169         /*
  170          * If updating, check whether changing from read-only to
  171          * read/write.
  172          */
  173         if (mp->mnt_flag & MNT_UPDATE) {
  174                 if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) {
  175                         /* Process export requests in vfs_mount.c */
  176                         goto success;
  177                 } else {
  178                         printf("ntfs_mount(): MNT_UPDATE not supported\n");
  179                         err = EINVAL;
  180                         goto error_1;
  181                 }
  182         }
  183 
  184         /*
  185          * Not an update, or updating the name: look up the name
  186          * and verify that it refers to a sensible block device.
  187          */
  188         NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td);
  189         err = namei(&ndp);
  190         if (err) {
  191                 /* can't get devvp!*/
  192                 goto error_1;
  193         }
  194         NDFREE(&ndp, NDF_ONLY_PNBUF);
  195         devvp = ndp.ni_vp;
  196 
  197         if (!vn_isdisk(devvp, &err))  {
  198                 vput(devvp);
  199                 return (err);
  200         }
  201 
  202         /*
  203          * If mount by non-root, then verify that user has necessary
  204          * permissions on the device.
  205          */
  206         accmode = VREAD;
  207         if ((mp->mnt_flag & MNT_RDONLY) == 0)
  208                 accmode |= VWRITE;
  209         err = VOP_ACCESS(devvp, accmode, td->td_ucred, td);
  210         if (err)
  211                 err = priv_check(td, PRIV_VFS_MOUNT_PERM);
  212         if (err) {
  213                 vput(devvp);
  214                 return (err);
  215         }
  216 
  217         if (mp->mnt_flag & MNT_UPDATE) {
  218 #if 0
  219                 /*
  220                  ********************
  221                  * UPDATE
  222                  ********************
  223                  */
  224 
  225                 if (devvp != ntmp->um_devvp)
  226                         err = EINVAL;   /* needs translation */
  227                 vput(devvp);
  228                 if (err)
  229                         return (err);
  230 #endif
  231         } else {
  232                 /*
  233                  ********************
  234                  * NEW MOUNT
  235                  ********************
  236                  */
  237 
  238                 /*
  239                  * Since this is a new mount, we want the names for
  240                  * the device and the mount point copied in.  If an
  241                  * error occurs, the mountpoint is discarded by the
  242                  * upper level code.  Note that vfs_mount() handles
  243                  * copying the mountpoint f_mntonname for us, so we
  244                  * don't have to do it here unless we want to set it
  245                  * to something other than "path" for some rason.
  246                  */
  247                 /* Save "mounted from" info for mount point (NULL pad)*/
  248                 vfs_mountedfrom(mp, from);
  249 
  250                 err = ntfs_mountfs(devvp, mp, td);
  251         }
  252         if (err) {
  253                 vrele(devvp);
  254                 return (err);
  255         }
  256 
  257         goto success;
  258 
  259 error_1:        /* no state to back out*/
  260         /* XXX: missing NDFREE(&ndp, ...) */
  261 
  262 success:
  263         return (err);
  264 }
  265 
  266 /*
  267  * Common code for mount and mountroot
  268  */
  269 int
  270 ntfs_mountfs(devvp, mp, td)
  271         register struct vnode *devvp;
  272         struct mount *mp;
  273         struct thread *td;
  274 {
  275         struct buf *bp;
  276         struct ntfsmount *ntmp;
  277         struct cdev *dev = devvp->v_rdev;
  278         int error, ronly, i, v;
  279         struct vnode *vp;
  280         struct g_consumer *cp;
  281         struct g_provider *pp;
  282         char *cs_ntfs, *cs_local;
  283 
  284         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  285         DROP_GIANT();
  286         g_topology_lock();
  287 
  288         /*
  289          * XXX: Do not allow more than one consumer to open a device
  290          *      associated with a particular GEOM provider.
  291          *      This disables multiple read-only mounts of a device,
  292          *      but it gets rid of panics in vget() when you try to
  293          *      mount the same device more than once.
  294          */
  295         pp = g_dev_getprovider(devvp->v_rdev);
  296         if ((pp != NULL) && ((pp->acr | pp->acw | pp->ace ) != 0)) 
  297                 error = EPERM;
  298         else 
  299                 error = g_vfs_open(devvp, &cp, "ntfs", ronly ? 0 : 1);
  300 
  301         g_topology_unlock();
  302         PICKUP_GIANT();
  303         VOP_UNLOCK(devvp, 0);
  304         if (error)
  305                 return (error);
  306 
  307         bp = NULL;
  308 
  309         error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp);
  310         if (error)
  311                 goto out;
  312         ntmp = malloc( sizeof *ntmp, M_NTFSMNT, M_WAITOK | M_ZERO);
  313         bcopy( bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile) );
  314         /*
  315          * We must not cache the boot block if its size is not exactly
  316          * one cluster in order to avoid confusing the buffer cache when
  317          * the boot file is read later by ntfs_readntvattr_plain(), which
  318          * reads a cluster at a time.
  319          */
  320         if (ntfs_cntob(1) != BBSIZE)
  321                 bp->b_flags |= B_NOCACHE;
  322         brelse( bp );
  323         bp = NULL;
  324 
  325         if (strncmp((const char *)ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
  326                 error = EINVAL;
  327                 dprintf(("ntfs_mountfs: invalid boot block\n"));
  328                 goto out;
  329         }
  330 
  331         {
  332                 int8_t cpr = ntmp->ntm_mftrecsz;
  333                 if( cpr > 0 )
  334                         ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
  335                 else
  336                         ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
  337         }
  338         ntmp->ntm_multiplier = ntmp->ntm_bps / DEV_BSIZE;
  339 
  340         dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
  341                 ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media,
  342                 ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec));
  343         dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
  344                 (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn));
  345 
  346         ntmp->ntm_mountp = mp;
  347         ntmp->ntm_devvp = devvp;
  348         if (vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v) == 1)
  349                 ntmp->ntm_uid = v;
  350         if (vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v) == 1)
  351                 ntmp->ntm_gid = v;
  352         if (vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v) == 1)
  353                 ntmp->ntm_mode = v & ACCESSPERMS;
  354         vfs_flagopt(mp->mnt_optnew,
  355             "caseins", &ntmp->ntm_flag, NTFS_MFLAG_CASEINS);
  356         vfs_flagopt(mp->mnt_optnew,
  357             "allnames", &ntmp->ntm_flag, NTFS_MFLAG_ALLNAMES);
  358         ntmp->ntm_cp = cp;
  359         ntmp->ntm_bo = &devvp->v_bufobj;
  360 
  361         cs_local = vfs_getopts(mp->mnt_optnew, "cs_local", &error);
  362         if (error && error != ENOENT)
  363                 goto out;
  364         cs_ntfs = vfs_getopts(mp->mnt_optnew, "cs_ntfs", &error);
  365         if (error && error != ENOENT)
  366                 goto out;
  367         /* Copy in the 8-bit to Unicode conversion table */
  368         /* Initialize Unicode to 8-bit table from 8toU table */
  369         ntfs_82u_init(ntmp, cs_local, cs_ntfs);
  370         if (cs_local != NULL && cs_ntfs != NULL)
  371                 ntfs_u28_init(ntmp, NULL, cs_local, cs_ntfs);
  372         else
  373                 ntfs_u28_init(ntmp, ntmp->ntm_82u, cs_local, cs_ntfs);
  374 
  375         mp->mnt_data = ntmp;
  376 
  377         dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
  378                 (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
  379                 (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
  380                 ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
  381 
  382         /*
  383          * We read in some system nodes to do not allow 
  384          * reclaim them and to have everytime access to them.
  385          */ 
  386         {
  387                 int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
  388                 for (i=0; i<3; i++) {
  389                         error = VFS_VGET(mp, pi[i], LK_EXCLUSIVE,
  390                                          &(ntmp->ntm_sysvn[pi[i]]));
  391                         if(error)
  392                                 goto out1;
  393                         ntmp->ntm_sysvn[pi[i]]->v_vflag |= VV_SYSTEM;
  394                         VREF(ntmp->ntm_sysvn[pi[i]]);
  395                         vput(ntmp->ntm_sysvn[pi[i]]);
  396                 }
  397         }
  398 
  399         /* read the Unicode lowercase --> uppercase translation table,
  400          * if necessary */
  401         if ((error = ntfs_toupper_use(mp, ntmp)))
  402                 goto out1;
  403 
  404         /*
  405          * Scan $BitMap and count free clusters
  406          */
  407         error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
  408         if(error)
  409                 goto out1;
  410 
  411         /*
  412          * Read and translate to internal format attribute
  413          * definition file. 
  414          */
  415         {
  416                 int num,j;
  417                 struct attrdef ad;
  418 
  419                 /* Open $AttrDef */
  420                 error = VFS_VGET(mp, NTFS_ATTRDEFINO, LK_EXCLUSIVE, &vp );
  421                 if(error) 
  422                         goto out1;
  423 
  424                 /* Count valid entries */
  425                 for(num=0;;num++) {
  426                         error = ntfs_readattr(ntmp, VTONT(vp),
  427                                         NTFS_A_DATA, NULL,
  428                                         num * sizeof(ad), sizeof(ad),
  429                                         &ad, NULL);
  430                         if (error)
  431                                 goto out1;
  432                         if (ad.ad_name[0] == 0)
  433                                 break;
  434                 }
  435 
  436                 /* Alloc memory for attribute definitions */
  437                 ntmp->ntm_ad = malloc(num * sizeof(struct ntvattrdef),
  438                         M_NTFSMNT, M_WAITOK);
  439 
  440                 ntmp->ntm_adnum = num;
  441 
  442                 /* Read them and translate */
  443                 for(i=0;i<num;i++){
  444                         error = ntfs_readattr(ntmp, VTONT(vp),
  445                                         NTFS_A_DATA, NULL,
  446                                         i * sizeof(ad), sizeof(ad),
  447                                         &ad, NULL);
  448                         if (error)
  449                                 goto out1;
  450                         j = 0;
  451                         do {
  452                                 ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
  453                         } while(ad.ad_name[j++]);
  454                         ntmp->ntm_ad[i].ad_namelen = j - 1;
  455                         ntmp->ntm_ad[i].ad_type = ad.ad_type;
  456                 }
  457 
  458                 vput(vp);
  459         }
  460 
  461         mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
  462         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
  463         mp->mnt_maxsymlinklen = 0;
  464         MNT_ILOCK(mp);
  465         mp->mnt_flag |= MNT_LOCAL;
  466         MNT_IUNLOCK(mp);
  467         return (0);
  468 
  469 out1:
  470         for(i=0;i<NTFS_SYSNODESNUM;i++)
  471                 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
  472 
  473         if (vflush(mp, 0, 0, td))
  474                 dprintf(("ntfs_mountfs: vflush failed\n"));
  475 
  476 out:
  477         if (bp)
  478                 brelse(bp);
  479 
  480         DROP_GIANT();
  481         g_topology_lock();
  482         g_vfs_close(cp);
  483         g_topology_unlock();
  484         PICKUP_GIANT();
  485         
  486         return (error);
  487 }
  488 
  489 static int
  490 ntfs_unmount( 
  491         struct mount *mp,
  492         int mntflags)
  493 {
  494         struct thread *td;
  495         struct ntfsmount *ntmp;
  496         int error, flags, i;
  497 
  498         dprintf(("ntfs_unmount: unmounting...\n"));
  499         td = curthread;
  500         ntmp = VFSTONTFS(mp);
  501 
  502         flags = 0;
  503         if(mntflags & MNT_FORCE)
  504                 flags |= FORCECLOSE;
  505 
  506         dprintf(("ntfs_unmount: vflushing...\n"));
  507         error = vflush(mp, 0, flags | SKIPSYSTEM, td);
  508         if (error) {
  509                 printf("ntfs_unmount: vflush failed: %d\n",error);
  510                 return (error);
  511         }
  512 
  513         /* Check if only system vnodes are rest */
  514         for(i=0;i<NTFS_SYSNODESNUM;i++)
  515                  if((ntmp->ntm_sysvn[i]) && 
  516                     (vrefcnt(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY);
  517 
  518         /* Dereference all system vnodes */
  519         for(i=0;i<NTFS_SYSNODESNUM;i++)
  520                  if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
  521 
  522         /* vflush system vnodes */
  523         error = vflush(mp, 0, flags, td);
  524         if (error)
  525                 printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
  526 
  527         vinvalbuf(ntmp->ntm_devvp, V_SAVE, 0, 0);
  528 
  529         DROP_GIANT();
  530         g_topology_lock();
  531         g_vfs_close(ntmp->ntm_cp);
  532         g_topology_unlock();
  533         PICKUP_GIANT();
  534 
  535         vrele(ntmp->ntm_devvp);
  536 
  537         /* free the toupper table, if this has been last mounted ntfs volume */
  538         ntfs_toupper_unuse();
  539 
  540         dprintf(("ntfs_umount: freeing memory...\n"));
  541         ntfs_u28_uninit(ntmp);
  542         ntfs_82u_uninit(ntmp);
  543         mp->mnt_data = NULL;
  544         MNT_ILOCK(mp);
  545         mp->mnt_flag &= ~MNT_LOCAL;
  546         MNT_IUNLOCK(mp);
  547         free(ntmp->ntm_ad, M_NTFSMNT);
  548         free(ntmp, M_NTFSMNT);
  549         return (error);
  550 }
  551 
  552 static int
  553 ntfs_root(
  554         struct mount *mp,
  555         int flags,
  556         struct vnode **vpp)
  557 {
  558         struct vnode *nvp;
  559         int error = 0;
  560 
  561         dprintf(("ntfs_root(): sysvn: %p\n",
  562                 VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]));
  563         error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, LK_EXCLUSIVE, &nvp);
  564         if(error) {
  565                 printf("ntfs_root: VFS_VGET failed: %d\n",error);
  566                 return (error);
  567         }
  568 
  569         *vpp = nvp;
  570         return (0);
  571 }
  572 
  573 static int
  574 ntfs_calccfree(
  575         struct ntfsmount *ntmp,
  576         cn_t *cfreep)
  577 {
  578         struct vnode *vp;
  579         u_int8_t *tmp;
  580         int j, error;
  581         long cfree = 0;
  582         size_t bmsize, i;
  583 
  584         vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
  585 
  586         bmsize = VTOF(vp)->f_size;
  587 
  588         tmp = malloc(bmsize, M_TEMP, M_WAITOK);
  589 
  590         error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
  591                                0, bmsize, tmp, NULL);
  592         if (error)
  593                 goto out;
  594 
  595         for(i=0;i<bmsize;i++)
  596                 for(j=0;j<8;j++)
  597                         if(~tmp[i] & (1 << j)) cfree++;
  598         *cfreep = cfree;
  599 
  600     out:
  601         free(tmp, M_TEMP);
  602         return(error);
  603 }
  604 
  605 static int
  606 ntfs_statfs(
  607         struct mount *mp,
  608         struct statfs *sbp)
  609 {
  610         struct ntfsmount *ntmp = VFSTONTFS(mp);
  611         u_int64_t mftsize,mftallocated;
  612 
  613         dprintf(("ntfs_statfs():\n"));
  614 
  615         mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size;
  616         mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
  617 
  618         sbp->f_type = mp->mnt_vfc->vfc_typenum;
  619         sbp->f_bsize = ntmp->ntm_bps;
  620         sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
  621         sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
  622         sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
  623         sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
  624         sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
  625                        sbp->f_ffree;
  626         sbp->f_flags = mp->mnt_flag;
  627 
  628         return (0);
  629 }
  630 
  631 /*ARGSUSED*/
  632 static int
  633 ntfs_fhtovp(
  634         struct mount *mp,
  635         struct fid *fhp,
  636         int flags,
  637         struct vnode **vpp)
  638 {
  639         struct vnode *nvp;
  640         struct ntfid *ntfhp = (struct ntfid *)fhp;
  641         int error;
  642 
  643         ddprintf(("ntfs_fhtovp(): %d\n", ntfhp->ntfid_ino));
  644 
  645         if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
  646                 *vpp = NULLVP;
  647                 return (error);
  648         }
  649         /* XXX as unlink/rmdir/mkdir/creat are not currently possible
  650          * with NTFS, we don't need to check anything else for now */
  651         *vpp = nvp;
  652         vnode_create_vobject(nvp, VTOF(nvp)->f_size, curthread);
  653         return (0);
  654 }
  655 
  656 int
  657 ntfs_vgetex(
  658         struct mount *mp,
  659         ino_t ino,
  660         u_int32_t attrtype,
  661         char *attrname,
  662         u_long lkflags,
  663         u_long flags,
  664         struct thread *td,
  665         struct vnode **vpp) 
  666 {
  667         int error;
  668         register struct ntfsmount *ntmp;
  669         struct ntnode *ip;
  670         struct fnode *fp;
  671         struct vnode *vp;
  672         enum vtype f_type;
  673 
  674         dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
  675                 ino, attrtype, attrname?attrname:"", (u_long)lkflags,
  676                 (u_long)flags));
  677 
  678         ntmp = VFSTONTFS(mp);
  679         *vpp = NULL;
  680 
  681         /* Get ntnode */
  682         error = ntfs_ntlookup(ntmp, ino, &ip);
  683         if (error) {
  684                 printf("ntfs_vget: ntfs_ntget failed\n");
  685                 return (error);
  686         }
  687 
  688         /* It may be not initialized fully, so force load it */
  689         if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
  690                 error = ntfs_loadntnode(ntmp, ip);
  691                 if(error) {
  692                         printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
  693                                ip->i_number);
  694                         ntfs_ntput(ip);
  695                         return (error);
  696                 }
  697         }
  698 
  699         error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
  700         if (error) {
  701                 printf("ntfs_vget: ntfs_fget failed\n");
  702                 ntfs_ntput(ip);
  703                 return (error);
  704         }
  705 
  706         f_type = VNON;
  707         if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
  708                 if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
  709                     (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
  710                         f_type = VDIR;
  711                 } else if (flags & VG_EXT) {
  712                         f_type = VNON;
  713                         fp->f_size = fp->f_allocated = 0;
  714                 } else {
  715                         f_type = VREG;  
  716 
  717                         error = ntfs_filesize(ntmp, fp, 
  718                                               &fp->f_size, &fp->f_allocated);
  719                         if (error) {
  720                                 ntfs_ntput(ip);
  721                                 return (error);
  722                         }
  723                 }
  724 
  725                 fp->f_flag |= FN_VALID;
  726         }
  727 
  728         if (FTOV(fp)) {
  729                 vget(FTOV(fp), lkflags, td);
  730                 *vpp = FTOV(fp);
  731                 ntfs_ntput(ip);
  732                 return (0);
  733         }
  734 
  735         error = getnewvnode("ntfs", ntmp->ntm_mountp, &ntfs_vnodeops, &vp);
  736         if(error) {
  737                 ntfs_frele(fp);
  738                 ntfs_ntput(ip);
  739                 return (error);
  740         }
  741         /* XXX: Too early for mpsafe fs, lacks vnode lock */
  742         error = insmntque(vp, ntmp->ntm_mountp);
  743         if (error) {
  744                 ntfs_frele(fp);
  745                 ntfs_ntput(ip);
  746                 return (error);
  747         }
  748         dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
  749 
  750         fp->f_vp = vp;
  751         vp->v_data = fp;
  752         vp->v_type = f_type;
  753 
  754         vp->v_bufobj.bo_ops = &ntfs_vnbufops;
  755         vp->v_bufobj.bo_private = vp;
  756 
  757         if (ino == NTFS_ROOTINO)
  758                 vp->v_vflag |= VV_ROOT;
  759 
  760         ntfs_ntput(ip);
  761 
  762         if (lkflags & LK_TYPE_MASK) {
  763                 error = vn_lock(vp, lkflags);
  764                 if (error) {
  765                         vput(vp);
  766                         return (error);
  767                 }
  768         }
  769 
  770         *vpp = vp;
  771         return (0);
  772         
  773 }
  774 
  775 static int
  776 ntfs_vget(
  777         struct mount *mp,
  778         ino_t ino,
  779         int lkflags,
  780         struct vnode **vpp) 
  781 {
  782         return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, lkflags, 0,
  783             curthread, vpp);
  784 }
  785 
  786 static void
  787 ntfs_bufstrategy(struct bufobj *bo, struct buf *bp)
  788 {
  789         struct vnode *vp;
  790         int rc;
  791 
  792         vp = bo->bo_private;
  793         KASSERT(bo == &vp->v_bufobj, ("BO/VP mismatch: vp %p bo %p != %p",
  794             vp, &vp->v_bufobj, bo));
  795         rc = VOP_STRATEGY(vp, bp);
  796         KASSERT(rc == 0, ("NTFS VOP_STRATEGY failed: bp=%p, "
  797                 "vp=%p, rc=%d", bp, vp, rc));
  798 }
  799 
  800 static struct vfsops ntfs_vfsops = {
  801         .vfs_fhtovp =   ntfs_fhtovp,
  802         .vfs_init =     ntfs_init,
  803         .vfs_cmount =   ntfs_cmount,
  804         .vfs_mount =    ntfs_mount,
  805         .vfs_root =     ntfs_root,
  806         .vfs_statfs =   ntfs_statfs,
  807         .vfs_uninit =   ntfs_uninit,
  808         .vfs_unmount =  ntfs_unmount,
  809         .vfs_vget =     ntfs_vget,
  810 };
  811 VFS_SET(ntfs_vfsops, ntfs, 0);
  812 MODULE_VERSION(ntfs, 1);

Cache object: 83042ce2d0a48ce2266113e18a80c017


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