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/5.1/sys/fs/ntfs/ntfs_vfsops.c 112119 2003-03-11 22:15:10Z kan $
   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/systm.h>
   45 
   46 #include <vm/vm.h>
   47 #include <vm/vm_param.h>
   48 #include <vm/vm_page.h>
   49 #include <vm/vm_object.h>
   50 #include <vm/vm_extern.h>
   51 
   52 /*#define NTFS_DEBUG 1*/
   53 #include <fs/ntfs/ntfs.h>
   54 #include <fs/ntfs/ntfs_inode.h>
   55 #include <fs/ntfs/ntfs_subr.h>
   56 #include <fs/ntfs/ntfs_vfsops.h>
   57 #include <fs/ntfs/ntfs_ihash.h>
   58 #include <fs/ntfs/ntfsmount.h>
   59 
   60 MALLOC_DEFINE(M_NTFSMNT, "NTFS mount", "NTFS mount structure");
   61 MALLOC_DEFINE(M_NTFSNTNODE,"NTFS ntnode",  "NTFS ntnode information");
   62 MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode",  "NTFS fnode information");
   63 MALLOC_DEFINE(M_NTFSDIR,"NTFS dir",  "NTFS dir buffer");
   64 
   65 struct sockaddr;
   66 
   67 static int      ntfs_root(struct mount *, struct vnode **);
   68 static int      ntfs_statfs(struct mount *, struct statfs *, struct thread *);
   69 static int      ntfs_unmount(struct mount *, int, struct thread *);
   70 static int      ntfs_vget(struct mount *mp, ino_t ino, int lkflags,
   71                                struct vnode **vpp);
   72 static int      ntfs_mountfs(register struct vnode *, struct mount *, 
   73                                   struct ntfs_args *, struct thread *);
   74 static int      ntfs_vptofh(struct vnode *, struct fid *);
   75 static int      ntfs_fhtovp(struct mount *, struct fid *, struct vnode **);
   76 static int      ntfs_mount(struct mount *, char *, caddr_t,
   77                                 struct nameidata *, struct thread *);
   78 static int      ntfs_init(struct vfsconf *);
   79 
   80 static int
   81 ntfs_init (
   82         struct vfsconf *vcp )
   83 {
   84         ntfs_nthashinit();
   85         ntfs_toupper_init();
   86         return 0;
   87 }
   88 
   89 static int
   90 ntfs_uninit (
   91         struct vfsconf *vcp )
   92 {
   93         ntfs_toupper_destroy();
   94         ntfs_nthashdestroy();
   95         return 0;
   96 }
   97 
   98 static int
   99 ntfs_mount ( 
  100         struct mount *mp,
  101         char *path,
  102         caddr_t data,
  103         struct nameidata *ndp,
  104         struct thread *td )
  105 {
  106         size_t          size;
  107         int             err = 0;
  108         struct vnode    *devvp;
  109         struct ntfs_args args;
  110 
  111         /*
  112          * Use NULL path to flag a root mount
  113          */
  114         if( path == NULL) {
  115                 /*
  116                  ***
  117                  * Mounting root filesystem
  118                  ***
  119                  */
  120         
  121                 /* Get vnode for root device*/
  122                 if( bdevvp( rootdev, &rootvp))
  123                         panic("ntfs_mountroot: can't setup bdevvp for root");
  124 
  125                 /*
  126                  * FS specific handling
  127                  */
  128                 mp->mnt_flag |= MNT_RDONLY;     /* XXX globally applicable?*/
  129 
  130                 /*
  131                  * Attempt mount
  132                  */
  133                 if( ( err = ntfs_mountfs(rootvp, mp, &args, td)) != 0) {
  134                         /* fs specific cleanup (if any)*/
  135                         goto error_1;
  136                 }
  137 
  138                 goto dostatfs;          /* success*/
  139 
  140         }
  141 
  142         /*
  143          ***
  144          * Mounting non-root filesystem or updating a filesystem
  145          ***
  146          */
  147 
  148         /* copy in user arguments*/
  149         err = copyin(data, (caddr_t)&args, sizeof (struct ntfs_args));
  150         if (err)
  151                 goto error_1;           /* can't get arguments*/
  152 
  153         /*
  154          * If updating, check whether changing from read-only to
  155          * read/write; if there is no device name, that's all we do.
  156          */
  157         if (mp->mnt_flag & MNT_UPDATE) {
  158                 /* if not updating name...*/
  159                 if (args.fspec == 0) {
  160                         /*
  161                          * Process export requests.  Jumping to "success"
  162                          * will return the vfs_export() error code.
  163                          */
  164                         err = vfs_export(mp, &args.export);
  165                         goto success;
  166                 }
  167 
  168                 printf("ntfs_mount(): MNT_UPDATE not supported\n");
  169                 err = EINVAL;
  170                 goto error_1;
  171         }
  172 
  173         /*
  174          * Not an update, or updating the name: look up the name
  175          * and verify that it refers to a sensible block device.
  176          */
  177         NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, td);
  178         err = namei(ndp);
  179         if (err) {
  180                 /* can't get devvp!*/
  181                 goto error_1;
  182         }
  183         NDFREE(ndp, NDF_ONLY_PNBUF);
  184         devvp = ndp->ni_vp;
  185 
  186         if (!vn_isdisk(devvp, &err)) 
  187                 goto error_2;
  188         if (mp->mnt_flag & MNT_UPDATE) {
  189 #if 0
  190                 /*
  191                  ********************
  192                  * UPDATE
  193                  ********************
  194                  */
  195 
  196                 if (devvp != ntmp->um_devvp)
  197                         err = EINVAL;   /* needs translation */
  198                 else
  199                         vrele(devvp);
  200                 /*
  201                  * Update device name only on success
  202                  */
  203                 if( !err) {
  204                         /* Save "mounted from" info for mount point (NULL pad)*/
  205                         copyinstr(      args.fspec,
  206                                         mp->mnt_stat.f_mntfromname,
  207                                         MNAMELEN - 1,
  208                                         &size);
  209                         bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  210                 }
  211 #endif
  212         } else {
  213                 /*
  214                  ********************
  215                  * NEW MOUNT
  216                  ********************
  217                  */
  218 
  219                 /*
  220                  * Since this is a new mount, we want the names for
  221                  * the device and the mount point copied in.  If an
  222                  * error occurs, the mountpoint is discarded by the
  223                  * upper level code.  Note that vfs_mount() handles
  224                  * copying the mountpoint f_mntonname for us, so we
  225                  * don't have to do it here unless we want to set it
  226                  * to something other than "path" for some rason.
  227                  */
  228                 /* Save "mounted from" info for mount point (NULL pad)*/
  229                 copyinstr(      args.fspec,                     /* device name*/
  230                                 mp->mnt_stat.f_mntfromname,     /* save area*/
  231                                 MNAMELEN - 1,                   /* max size*/
  232                                 &size);                         /* real size*/
  233                 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  234 
  235                 err = ntfs_mountfs(devvp, mp, &args, td);
  236         }
  237         if (err) {
  238                 goto error_2;
  239         }
  240 
  241 dostatfs:
  242         /*
  243          * Initialize FS stat information in mount struct; uses both
  244          * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
  245          *
  246          * This code is common to root and non-root mounts
  247          */
  248         (void)VFS_STATFS(mp, &mp->mnt_stat, td);
  249 
  250         goto success;
  251 
  252 
  253 error_2:        /* error with devvp held*/
  254 
  255         /* release devvp before failing*/
  256         vrele(devvp);
  257 
  258 error_1:        /* no state to back out*/
  259 
  260 success:
  261         return(err);
  262 }
  263 
  264 /*
  265  * Common code for mount and mountroot
  266  */
  267 int
  268 ntfs_mountfs(devvp, mp, argsp, td)
  269         register struct vnode *devvp;
  270         struct mount *mp;
  271         struct ntfs_args *argsp;
  272         struct thread *td;
  273 {
  274         struct buf *bp;
  275         struct ntfsmount *ntmp;
  276         dev_t dev = devvp->v_rdev;
  277         int error, ronly, ncount, i;
  278         struct vnode *vp;
  279 
  280         /*
  281          * Disallow multiple mounts of the same device.
  282          * Disallow mounting of a device that is currently in use
  283          * (except for root, which might share swap device for miniroot).
  284          * Flush out any old buffers remaining from a previous use.
  285          */
  286         error = vfs_mountedon(devvp);
  287         if (error)
  288                 return (error);
  289         ncount = vcount(devvp);
  290         if (devvp->v_object)
  291                 ncount -= 1;
  292         if (ncount > 1 && devvp != rootvp)
  293                 return (EBUSY);
  294         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
  295         error = vinvalbuf(devvp, V_SAVE, td->td_ucred, td, 0, 0);
  296         VOP_UNLOCK(devvp, 0, td);
  297         if (error)
  298                 return (error);
  299 
  300         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  301         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
  302         error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td);
  303         VOP_UNLOCK(devvp, 0, td);
  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         brelse( bp );
  315         bp = NULL;
  316 
  317         if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
  318                 error = EINVAL;
  319                 dprintf(("ntfs_mountfs: invalid boot block\n"));
  320                 goto out;
  321         }
  322 
  323         {
  324                 int8_t cpr = ntmp->ntm_mftrecsz;
  325                 if( cpr > 0 )
  326                         ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
  327                 else
  328                         ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
  329         }
  330         dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
  331                 ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media,
  332                 ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec));
  333         dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
  334                 (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn));
  335 
  336         ntmp->ntm_mountp = mp;
  337         ntmp->ntm_dev = dev;
  338         ntmp->ntm_devvp = devvp;
  339         ntmp->ntm_uid = argsp->uid;
  340         ntmp->ntm_gid = argsp->gid;
  341         ntmp->ntm_mode = argsp->mode;
  342         ntmp->ntm_flag = argsp->flag;
  343 
  344         /* Copy in the 8-bit to Unicode conversion table */
  345         if (argsp->flag & NTFSMNT_U2WTABLE) {
  346                 ntfs_82u_init(ntmp, argsp->u2w);
  347         } else {
  348                 ntfs_82u_init(ntmp, NULL);
  349         }
  350 
  351         /* Initialize Unicode to 8-bit table from 8toU table */
  352         ntfs_u28_init(ntmp, ntmp->ntm_82u);
  353 
  354         mp->mnt_data = (qaddr_t)ntmp;
  355 
  356         dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
  357                 (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
  358                 (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
  359                 ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
  360 
  361         /*
  362          * We read in some system nodes to do not allow 
  363          * reclaim them and to have everytime access to them.
  364          */ 
  365         {
  366                 int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
  367                 for (i=0; i<3; i++) {
  368                         error = VFS_VGET(mp, pi[i], LK_EXCLUSIVE,
  369                                          &(ntmp->ntm_sysvn[pi[i]]));
  370                         if(error)
  371                                 goto out1;
  372                         ntmp->ntm_sysvn[pi[i]]->v_vflag |= VV_SYSTEM;
  373                         VREF(ntmp->ntm_sysvn[pi[i]]);
  374                         vput(ntmp->ntm_sysvn[pi[i]]);
  375                 }
  376         }
  377 
  378         /* read the Unicode lowercase --> uppercase translation table,
  379          * if necessary */
  380         if ((error = ntfs_toupper_use(mp, ntmp)))
  381                 goto out1;
  382 
  383         /*
  384          * Scan $BitMap and count free clusters
  385          */
  386         error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
  387         if(error)
  388                 goto out1;
  389 
  390         /*
  391          * Read and translate to internal format attribute
  392          * definition file. 
  393          */
  394         {
  395                 int num,j;
  396                 struct attrdef ad;
  397 
  398                 /* Open $AttrDef */
  399                 error = VFS_VGET(mp, NTFS_ATTRDEFINO, LK_EXCLUSIVE, &vp );
  400                 if(error) 
  401                         goto out1;
  402 
  403                 /* Count valid entries */
  404                 for(num=0;;num++) {
  405                         error = ntfs_readattr(ntmp, VTONT(vp),
  406                                         NTFS_A_DATA, NULL,
  407                                         num * sizeof(ad), sizeof(ad),
  408                                         &ad, NULL);
  409                         if (error)
  410                                 goto out1;
  411                         if (ad.ad_name[0] == 0)
  412                                 break;
  413                 }
  414 
  415                 /* Alloc memory for attribute definitions */
  416                 MALLOC(ntmp->ntm_ad, struct ntvattrdef *,
  417                         num * sizeof(struct ntvattrdef),
  418                         M_NTFSMNT, M_WAITOK);
  419 
  420                 ntmp->ntm_adnum = num;
  421 
  422                 /* Read them and translate */
  423                 for(i=0;i<num;i++){
  424                         error = ntfs_readattr(ntmp, VTONT(vp),
  425                                         NTFS_A_DATA, NULL,
  426                                         i * sizeof(ad), sizeof(ad),
  427                                         &ad, NULL);
  428                         if (error)
  429                                 goto out1;
  430                         j = 0;
  431                         do {
  432                                 ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
  433                         } while(ad.ad_name[j++]);
  434                         ntmp->ntm_ad[i].ad_namelen = j - 1;
  435                         ntmp->ntm_ad[i].ad_type = ad.ad_type;
  436                 }
  437 
  438                 vput(vp);
  439         }
  440 
  441         mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
  442         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
  443         mp->mnt_maxsymlinklen = 0;
  444         mp->mnt_flag |= MNT_LOCAL;
  445         devvp->v_rdev->si_mountpoint = mp;
  446         return (0);
  447 
  448 out1:
  449         for(i=0;i<NTFS_SYSNODESNUM;i++)
  450                 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
  451 
  452         if (vflush(mp, 0, 0))
  453                 dprintf(("ntfs_mountfs: vflush failed\n"));
  454 
  455 out:
  456         devvp->v_rdev->si_mountpoint = NULL;
  457         if (bp)
  458                 brelse(bp);
  459 
  460         (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, td);
  461         
  462         return (error);
  463 }
  464 
  465 static int
  466 ntfs_unmount( 
  467         struct mount *mp,
  468         int mntflags,
  469         struct thread *td)
  470 {
  471         struct ntfsmount *ntmp;
  472         int error, ronly, flags, i;
  473 
  474         dprintf(("ntfs_unmount: unmounting...\n"));
  475         ntmp = VFSTONTFS(mp);
  476 
  477         flags = 0;
  478         if(mntflags & MNT_FORCE)
  479                 flags |= FORCECLOSE;
  480 
  481         dprintf(("ntfs_unmount: vflushing...\n"));
  482         error = vflush(mp, 0, flags | SKIPSYSTEM);
  483         if (error) {
  484                 printf("ntfs_unmount: vflush failed: %d\n",error);
  485                 return (error);
  486         }
  487 
  488         /* Check if only system vnodes are rest */
  489         for(i=0;i<NTFS_SYSNODESNUM;i++)
  490                  if((ntmp->ntm_sysvn[i]) && 
  491                     (vrefcnt(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY);
  492 
  493         /* Dereference all system vnodes */
  494         for(i=0;i<NTFS_SYSNODESNUM;i++)
  495                  if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
  496 
  497         /* vflush system vnodes */
  498         error = vflush(mp, 0, flags);
  499         if (error)
  500                 printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
  501 
  502         /* Check if the type of device node isn't VBAD before
  503          * touching v_cdev.  If the device vnode is revoked, the
  504          * field is NULL and touching it causes null pointer derefercence.
  505          */
  506         if (ntmp->ntm_devvp->v_type != VBAD)
  507                 ntmp->ntm_devvp->v_rdev->si_mountpoint = NULL;
  508 
  509         vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, td, 0, 0);
  510 
  511         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  512         error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE,
  513                 NOCRED, td);
  514 
  515         vrele(ntmp->ntm_devvp);
  516 
  517         /* free the toupper table, if this has been last mounted ntfs volume */
  518         ntfs_toupper_unuse();
  519 
  520         dprintf(("ntfs_umount: freeing memory...\n"));
  521         ntfs_u28_uninit(ntmp);
  522         ntfs_82u_uninit(ntmp);
  523         mp->mnt_data = (qaddr_t)0;
  524         mp->mnt_flag &= ~MNT_LOCAL;
  525         FREE(ntmp->ntm_ad, M_NTFSMNT);
  526         FREE(ntmp, M_NTFSMNT);
  527         return (error);
  528 }
  529 
  530 static int
  531 ntfs_root(
  532         struct mount *mp,
  533         struct vnode **vpp )
  534 {
  535         struct vnode *nvp;
  536         int error = 0;
  537 
  538         dprintf(("ntfs_root(): sysvn: %p\n",
  539                 VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]));
  540         error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, LK_EXCLUSIVE, &nvp);
  541         if(error) {
  542                 printf("ntfs_root: VFS_VGET failed: %d\n",error);
  543                 return (error);
  544         }
  545 
  546         *vpp = nvp;
  547         return (0);
  548 }
  549 
  550 int
  551 ntfs_calccfree(
  552         struct ntfsmount *ntmp,
  553         cn_t *cfreep)
  554 {
  555         struct vnode *vp;
  556         u_int8_t *tmp;
  557         int j, error;
  558         long cfree = 0;
  559         size_t bmsize, i;
  560 
  561         vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
  562 
  563         bmsize = VTOF(vp)->f_size;
  564 
  565         MALLOC(tmp, u_int8_t *, bmsize, M_TEMP, M_WAITOK);
  566 
  567         error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
  568                                0, bmsize, tmp, NULL);
  569         if (error)
  570                 goto out;
  571 
  572         for(i=0;i<bmsize;i++)
  573                 for(j=0;j<8;j++)
  574                         if(~tmp[i] & (1 << j)) cfree++;
  575         *cfreep = cfree;
  576 
  577     out:
  578         FREE(tmp, M_TEMP);
  579         return(error);
  580 }
  581 
  582 static int
  583 ntfs_statfs(
  584         struct mount *mp,
  585         struct statfs *sbp,
  586         struct thread *td)
  587 {
  588         struct ntfsmount *ntmp = VFSTONTFS(mp);
  589         u_int64_t mftsize,mftallocated;
  590 
  591         dprintf(("ntfs_statfs():\n"));
  592 
  593         mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size;
  594         mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
  595 
  596         sbp->f_type = mp->mnt_vfc->vfc_typenum;
  597         sbp->f_bsize = ntmp->ntm_bps;
  598         sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
  599         sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
  600         sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
  601         sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
  602         sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
  603                        sbp->f_ffree;
  604         if (sbp != &mp->mnt_stat) {
  605                 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
  606                         (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
  607                 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
  608                         (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
  609         }
  610         sbp->f_flags = mp->mnt_flag;
  611 
  612         return (0);
  613 }
  614 
  615 /*ARGSUSED*/
  616 static int
  617 ntfs_fhtovp(
  618         struct mount *mp,
  619         struct fid *fhp,
  620         struct vnode **vpp)
  621 {
  622         struct vnode *nvp;
  623         struct ntfid *ntfhp = (struct ntfid *)fhp;
  624         int error;
  625 
  626         ddprintf(("ntfs_fhtovp(): %d\n", ntfhp->ntfid_ino));
  627 
  628         if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
  629                 *vpp = NULLVP;
  630                 return (error);
  631         }
  632         /* XXX as unlink/rmdir/mkdir/creat are not currently possible
  633          * with NTFS, we don't need to check anything else for now */
  634         *vpp = nvp;
  635 
  636         return (0);
  637 }
  638 
  639 static int
  640 ntfs_vptofh(
  641         struct vnode *vp,
  642         struct fid *fhp)
  643 {
  644         register struct ntnode *ntp;
  645         register struct ntfid *ntfhp;
  646 
  647         ddprintf(("ntfs_fhtovp(): %p\n", vp));
  648 
  649         ntp = VTONT(vp);
  650         ntfhp = (struct ntfid *)fhp;
  651         ntfhp->ntfid_len = sizeof(struct ntfid);
  652         ntfhp->ntfid_ino = ntp->i_number;
  653         /* ntfhp->ntfid_gen = ntp->i_gen; */
  654         return (0);
  655 }
  656 
  657 int
  658 ntfs_vgetex(
  659         struct mount *mp,
  660         ino_t ino,
  661         u_int32_t attrtype,
  662         char *attrname,
  663         u_long lkflags,
  664         u_long flags,
  665         struct thread *td,
  666         struct vnode **vpp) 
  667 {
  668         int error;
  669         register struct ntfsmount *ntmp;
  670         struct ntnode *ip;
  671         struct fnode *fp;
  672         struct vnode *vp;
  673         enum vtype f_type;
  674 
  675         dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
  676                 ino, attrtype, attrname?attrname:"", (u_long)lkflags,
  677                 (u_long)flags ));
  678 
  679         ntmp = VFSTONTFS(mp);
  680         *vpp = NULL;
  681 
  682         /* Get ntnode */
  683         error = ntfs_ntlookup(ntmp, ino, &ip);
  684         if (error) {
  685                 printf("ntfs_vget: ntfs_ntget failed\n");
  686                 return (error);
  687         }
  688 
  689         /* It may be not initialized fully, so force load it */
  690         if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
  691                 error = ntfs_loadntnode(ntmp, ip);
  692                 if(error) {
  693                         printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
  694                                ip->i_number);
  695                         ntfs_ntput(ip);
  696                         return (error);
  697                 }
  698         }
  699 
  700         error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
  701         if (error) {
  702                 printf("ntfs_vget: ntfs_fget failed\n");
  703                 ntfs_ntput(ip);
  704                 return (error);
  705         }
  706 
  707         f_type = VNON;
  708         if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
  709                 if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
  710                     (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
  711                         f_type = VDIR;
  712                 } else if (flags & VG_EXT) {
  713                         f_type = VNON;
  714                         fp->f_size = fp->f_allocated = 0;
  715                 } else {
  716                         f_type = VREG;  
  717 
  718                         error = ntfs_filesize(ntmp, fp, 
  719                                               &fp->f_size, &fp->f_allocated);
  720                         if (error) {
  721                                 ntfs_ntput(ip);
  722                                 return (error);
  723                         }
  724                 }
  725 
  726                 fp->f_flag |= FN_VALID;
  727         }
  728 
  729         if (FTOV(fp)) {
  730                 vget(FTOV(fp), lkflags, td);
  731                 *vpp = FTOV(fp);
  732                 ntfs_ntput(ip);
  733                 return (0);
  734         }
  735 
  736         error = getnewvnode("ntfs", ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
  737         if(error) {
  738                 ntfs_frele(fp);
  739                 ntfs_ntput(ip);
  740                 return (error);
  741         }
  742         dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
  743 
  744         fp->f_vp = vp;
  745         vp->v_data = fp;
  746         vp->v_type = f_type;
  747 
  748         if (ino == NTFS_ROOTINO)
  749                 vp->v_vflag |= VV_ROOT;
  750 
  751         ntfs_ntput(ip);
  752 
  753         if (lkflags & LK_TYPE_MASK) {
  754                 error = vn_lock(vp, lkflags, td);
  755                 if (error) {
  756                         vput(vp);
  757                         return (error);
  758                 }
  759         }
  760 
  761         *vpp = vp;
  762         return (0);
  763         
  764 }
  765 
  766 static int
  767 ntfs_vget(
  768         struct mount *mp,
  769         ino_t ino,
  770         int lkflags,
  771         struct vnode **vpp) 
  772 {
  773         return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, lkflags, 0,
  774             curthread, vpp);
  775 }
  776 
  777 static struct vfsops ntfs_vfsops = {
  778         ntfs_mount,
  779         vfs_stdstart,
  780         ntfs_unmount,
  781         ntfs_root,
  782         vfs_stdquotactl,
  783         ntfs_statfs,
  784         vfs_stdnosync,
  785         ntfs_vget,
  786         ntfs_fhtovp,
  787         vfs_stdcheckexp,
  788         ntfs_vptofh,
  789         ntfs_init,
  790         ntfs_uninit,
  791         vfs_stdextattrctl,
  792 };
  793 VFS_SET(ntfs_vfsops, ntfs, 0);

Cache object: ee61b3d60b588afa00ab5a8dd4a4b747


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