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

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

Cache object: 6c00b0aa98fdb7b4998ceb8496cb2984


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