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

Cache object: d3d6636279018a32adfde5e2f4602324


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