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.47 2006/11/16 01:33:35 christos 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  *      Id: ntfs_vfsops.c,v 1.7 1999/05/31 11:28:30 phk Exp
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __KERNEL_RCSID(0, "$NetBSD: ntfs_vfsops.c,v 1.47 2006/11/16 01:33:35 christos Exp $");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/namei.h>
   37 #include <sys/proc.h>
   38 #include <sys/kernel.h>
   39 #include <sys/vnode.h>
   40 #include <sys/mount.h>
   41 #include <sys/buf.h>
   42 #include <sys/fcntl.h>
   43 #include <sys/malloc.h>
   44 #include <sys/sysctl.h>
   45 #include <sys/device.h>
   46 #include <sys/conf.h>
   47 #include <sys/kauth.h>
   48 
   49 #if defined(__NetBSD__)
   50 #include <uvm/uvm_extern.h>
   51 #else
   52 #include <vm/vm.h>
   53 #endif
   54 
   55 #include <miscfs/specfs/specdev.h>
   56 
   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 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 #if defined(__FreeBSD__)
   70 static int      ntfs_mount(struct mount *, char *, caddr_t,
   71                                 struct nameidata *, struct proc *);
   72 #else
   73 static int      ntfs_mount(struct mount *, const char *, void *,
   74                                 struct nameidata *, struct lwp *);
   75 #endif
   76 static int      ntfs_quotactl(struct mount *, int, uid_t, void *,
   77                                    struct lwp *);
   78 static int      ntfs_root(struct mount *, struct vnode **);
   79 static int      ntfs_start(struct mount *, int, struct lwp *);
   80 static int      ntfs_statvfs(struct mount *, struct statvfs *,
   81                                  struct lwp *);
   82 static int      ntfs_sync(struct mount *, int, kauth_cred_t,
   83                                struct lwp *);
   84 static int      ntfs_unmount(struct mount *, int, struct lwp *);
   85 static int      ntfs_vget(struct mount *mp, ino_t ino,
   86                                struct vnode **vpp);
   87 static int      ntfs_mountfs(struct vnode *, struct mount *,
   88                                   struct ntfs_args *, struct lwp *);
   89 static int      ntfs_vptofh(struct vnode *, struct fid *, size_t *);
   90 
   91 #if defined(__FreeBSD__)
   92 static int      ntfs_init(struct vfsconf *);
   93 static int      ntfs_fhtovp(struct mount *, struct fid *,
   94                                  struct sockaddr *, struct vnode **,
   95                                  int *, struct ucred **);
   96 #elif defined(__NetBSD__)
   97 static void     ntfs_init(void);
   98 static void     ntfs_reinit(void);
   99 static void     ntfs_done(void);
  100 static int      ntfs_fhtovp(struct mount *, struct fid *,
  101                                  struct vnode **);
  102 static int      ntfs_mountroot(void);
  103 #else
  104 static int      ntfs_init(void);
  105 static int      ntfs_fhtovp(struct mount *, struct fid *,
  106                                  struct mbuf *, struct vnode **,
  107                                  int *, kauth_cred_t *);
  108 #endif
  109 
  110 static const struct genfs_ops ntfs_genfsops = {
  111         .gop_write = genfs_compat_gop_write,
  112 };
  113 
  114 #ifdef __NetBSD__
  115 
  116 SYSCTL_SETUP(sysctl_vfs_ntfs_setup, "sysctl vfs.ntfs subtree setup")
  117 {
  118 
  119         sysctl_createv(clog, 0, NULL, NULL,
  120                        CTLFLAG_PERMANENT,
  121                        CTLTYPE_NODE, "vfs", NULL,
  122                        NULL, 0, NULL, 0,
  123                        CTL_VFS, CTL_EOL);
  124         sysctl_createv(clog, 0, NULL, NULL,
  125                        CTLFLAG_PERMANENT,
  126                        CTLTYPE_NODE, "ntfs",
  127                        SYSCTL_DESCR("NTFS file system"),
  128                        NULL, 0, NULL, 0,
  129                        CTL_VFS, 20, CTL_EOL);
  130         /*
  131          * XXX the "20" above could be dynamic, thereby eliminating
  132          * one more instance of the "number to vfs" mapping problem,
  133          * but "20" is the order as taken from sys/mount.h
  134          */
  135 }
  136 
  137 static int
  138 ntfs_mountroot()
  139 {
  140         struct mount *mp;
  141         struct lwp *l = curlwp; /* XXX */
  142         int error;
  143         struct ntfs_args args;
  144 
  145         if (device_class(root_device) != DV_DISK)
  146                 return (ENODEV);
  147 
  148         if ((error = vfs_rootmountalloc(MOUNT_NTFS, "root_device", &mp))) {
  149                 vrele(rootvp);
  150                 return (error);
  151         }
  152 
  153         args.flag = 0;
  154         args.uid = 0;
  155         args.gid = 0;
  156         args.mode = 0777;
  157 
  158         if ((error = ntfs_mountfs(rootvp, mp, &args, l)) != 0) {
  159                 mp->mnt_op->vfs_refcount--;
  160                 vfs_unbusy(mp);
  161                 free(mp, M_MOUNT);
  162                 return (error);
  163         }
  164 
  165         simple_lock(&mountlist_slock);
  166         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  167         simple_unlock(&mountlist_slock);
  168         (void)ntfs_statvfs(mp, &mp->mnt_stat, l);
  169         vfs_unbusy(mp);
  170         return (0);
  171 }
  172 
  173 static void
  174 ntfs_init()
  175 {
  176 #ifdef _LKM
  177         malloc_type_attach(M_NTFSMNT);
  178         malloc_type_attach(M_NTFSNTNODE);
  179         malloc_type_attach(M_NTFSFNODE);
  180         malloc_type_attach(M_NTFSDIR);
  181         malloc_type_attach(M_NTFSNTHASH);
  182         malloc_type_attach(M_NTFSNTVATTR);
  183         malloc_type_attach(M_NTFSRDATA);
  184         malloc_type_attach(M_NTFSDECOMP);
  185         malloc_type_attach(M_NTFSRUN);
  186 #endif
  187         ntfs_nthashinit();
  188         ntfs_toupper_init();
  189 }
  190 
  191 static void
  192 ntfs_reinit()
  193 {
  194         ntfs_nthashreinit();
  195 }
  196 
  197 static void
  198 ntfs_done()
  199 {
  200         ntfs_nthashdone();
  201 #ifdef _LKM
  202         malloc_type_detach(M_NTFSMNT);
  203         malloc_type_detach(M_NTFSNTNODE);
  204         malloc_type_detach(M_NTFSFNODE);
  205         malloc_type_detach(M_NTFSDIR);
  206         malloc_type_detach(M_NTFSNTHASH);
  207         malloc_type_detach(M_NTFSNTVATTR);
  208         malloc_type_detach(M_NTFSRDATA);
  209         malloc_type_detach(M_NTFSDECOMP);
  210         malloc_type_detach(M_NTFSRUN);
  211 #endif
  212 }
  213 
  214 #elif defined(__FreeBSD__)
  215 
  216 static int
  217 ntfs_init (
  218         struct vfsconf *vcp )
  219 {
  220         ntfs_nthashinit();
  221         ntfs_toupper_init();
  222         return 0;
  223 }
  224 
  225 #endif /* NetBSD */
  226 
  227 static int
  228 ntfs_mount (
  229         struct mount *mp,
  230 #if defined(__FreeBSD__)
  231         char *path,
  232         caddr_t data,
  233 #else
  234         const char *path,
  235         void *data,
  236 #endif
  237         struct nameidata *ndp,
  238 #if defined(__FreeBSD__)
  239         struct proc *p )
  240 #else
  241         struct lwp *l )
  242 #endif
  243 {
  244         int             err = 0, flags;
  245         struct vnode    *devvp;
  246         struct ntfs_args args;
  247 
  248         if (mp->mnt_flag & MNT_GETARGS) {
  249                 struct ntfsmount *ntmp = VFSTONTFS(mp);
  250                 if (ntmp == NULL)
  251                         return EIO;
  252                 args.fspec = NULL;
  253                 args.uid = ntmp->ntm_uid;
  254                 args.gid = ntmp->ntm_gid;
  255                 args.mode = ntmp->ntm_mode;
  256                 args.flag = ntmp->ntm_flag;
  257                 return copyout(&args, data, sizeof(args));
  258         }
  259         /*
  260          ***
  261          * Mounting non-root file system or updating a file system
  262          ***
  263          */
  264 
  265         /* copy in user arguments*/
  266         err = copyin(data, &args, sizeof (struct ntfs_args));
  267         if (err)
  268                 return (err);           /* can't get arguments*/
  269 
  270         /*
  271          * If updating, check whether changing from read-only to
  272          * read/write; if there is no device name, that's all we do.
  273          */
  274         if (mp->mnt_flag & MNT_UPDATE) {
  275                 printf("ntfs_mount(): MNT_UPDATE not supported\n");
  276                 return (EINVAL);
  277         }
  278 
  279         /*
  280          * Not an update, or updating the name: look up the name
  281          * and verify that it refers to a sensible block device.
  282          */
  283 #ifdef __FreeBSD__
  284         NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
  285 #else
  286         NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, l);
  287 #endif
  288         err = namei(ndp);
  289         if (err) {
  290                 /* can't get devvp!*/
  291                 return (err);
  292         }
  293 
  294         devvp = ndp->ni_vp;
  295 
  296         if (devvp->v_type != VBLK) {
  297                 err = ENOTBLK;
  298                 goto fail;
  299         }
  300 #ifdef __FreeBSD__
  301         if (bdevsw(devvp->v_rdev) == NULL) {
  302 #else
  303         if (bdevsw_lookup(devvp->v_rdev) == NULL) {
  304 #endif
  305                 err = ENXIO;
  306                 goto fail;
  307         }
  308         if (mp->mnt_flag & MNT_UPDATE) {
  309 #if 0
  310                 /*
  311                  ********************
  312                  * UPDATE
  313                  ********************
  314                  */
  315 
  316                 if (devvp != ntmp->um_devvp) {
  317                         err = EINVAL;   /* needs translation */
  318                         goto fail;
  319                 }
  320 
  321                 /*
  322                  * Update device name only on success
  323                  */
  324                 err = set_statvfs_info(NULL, UIO_USERSPACE, args.fspec,
  325                     UIO_USERSPACE, mp, p);
  326                 if (err)
  327                         goto fail;
  328 
  329                 vrele(devvp);
  330 #endif
  331         } else {
  332                 /*
  333                  ********************
  334                  * NEW MOUNT
  335                  ********************
  336                  */
  337 
  338                 /*
  339                  * Since this is a new mount, we want the names for
  340                  * the device and the mount point copied in.  If an
  341                  * error occurs,  the mountpoint is discarded by the
  342                  * upper level code.
  343                  */
  344 
  345                 /* Save "last mounted on" info for mount point (NULL pad)*/
  346                 err = set_statvfs_info(path, UIO_USERSPACE, args.fspec,
  347                     UIO_USERSPACE, mp, l);
  348                 if (err)
  349                         goto fail;
  350 
  351                 /*
  352                  * Disallow multiple mounts of the same device.
  353                  * Disallow mounting of a device that is currently in use
  354                  * (except for root, which might share swap device for
  355                  * miniroot).
  356                  */
  357                 err = vfs_mountedon(devvp);
  358                 if (err)
  359                         goto fail;
  360                 if (vcount(devvp) > 1 && devvp != rootvp) {
  361                         err = EBUSY;
  362                         goto fail;
  363                 }
  364                 if (mp->mnt_flag & MNT_RDONLY)
  365                         flags = FREAD;
  366                 else
  367                         flags = FREAD|FWRITE;
  368                 err = VOP_OPEN(devvp, flags, FSCRED, l);
  369                 if (err)
  370                         goto fail;
  371                 err = ntfs_mountfs(devvp, mp, &args, l);
  372                 if (err) {
  373                         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  374                         (void)VOP_CLOSE(devvp, flags, NOCRED, l);
  375                         VOP_UNLOCK(devvp, 0);
  376                         goto fail;
  377                 }
  378         }
  379 
  380 #ifdef __FreeBSD__
  381 dostatvfs:
  382 #endif
  383         /*
  384          * Initialize FS stat information in mount struct; uses both
  385          * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
  386          *
  387          * This code is common to root and non-root mounts
  388          */
  389         (void)VFS_STATVFS(mp, &mp->mnt_stat, l);
  390         return (err);
  391 
  392 fail:
  393         vrele(devvp);
  394         return (err);
  395 }
  396 
  397 /*
  398  * Common code for mount and mountroot
  399  */
  400 int
  401 ntfs_mountfs(devvp, mp, argsp, l)
  402         struct vnode *devvp;
  403         struct mount *mp;
  404         struct ntfs_args *argsp;
  405         struct lwp *l;
  406 {
  407         struct buf *bp;
  408         struct ntfsmount *ntmp;
  409         dev_t dev = devvp->v_rdev;
  410         int error, ronly, i;
  411         struct vnode *vp;
  412 
  413         ntmp = NULL;
  414 
  415         /*
  416          * Flush out any old buffers remaining from a previous use.
  417          */
  418         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  419         error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0);
  420         VOP_UNLOCK(devvp, 0);
  421         if (error)
  422                 return (error);
  423 
  424         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  425 
  426         bp = NULL;
  427 
  428         error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp);
  429         if (error)
  430                 goto out;
  431         ntmp = malloc( sizeof *ntmp, M_NTFSMNT, M_WAITOK );
  432         bzero( ntmp, sizeof *ntmp );
  433         bcopy( bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile) );
  434         brelse( bp );
  435         bp = NULL;
  436 
  437         if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
  438                 error = EINVAL;
  439                 dprintf(("ntfs_mountfs: invalid boot block\n"));
  440                 goto out;
  441         }
  442 
  443         {
  444                 int8_t cpr = ntmp->ntm_mftrecsz;
  445                 if( cpr > 0 )
  446                         ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
  447                 else
  448                         ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
  449         }
  450         dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
  451                 ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media,
  452                 ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec));
  453         dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
  454                 (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn));
  455 
  456         ntmp->ntm_mountp = mp;
  457         ntmp->ntm_dev = dev;
  458         ntmp->ntm_devvp = devvp;
  459         ntmp->ntm_uid = argsp->uid;
  460         ntmp->ntm_gid = argsp->gid;
  461         ntmp->ntm_mode = argsp->mode;
  462         ntmp->ntm_flag = argsp->flag;
  463         mp->mnt_data = ntmp;
  464 
  465         /* set file name encode/decode hooks XXX utf-8 only for now */
  466         ntmp->ntm_wget = ntfs_utf8_wget;
  467         ntmp->ntm_wput = ntfs_utf8_wput;
  468         ntmp->ntm_wcmp = ntfs_utf8_wcmp;
  469 
  470         dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
  471                 (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
  472                 (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
  473                 ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
  474 
  475         /*
  476          * We read in some system nodes to do not allow
  477          * reclaim them and to have everytime access to them.
  478          */
  479         {
  480                 int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
  481                 for (i=0; i<3; i++) {
  482                         error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]]));
  483                         if(error)
  484                                 goto out1;
  485                         ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM;
  486                         VREF(ntmp->ntm_sysvn[pi[i]]);
  487                         vput(ntmp->ntm_sysvn[pi[i]]);
  488                 }
  489         }
  490 
  491         /* read the Unicode lowercase --> uppercase translation table,
  492          * if necessary */
  493         if ((error = ntfs_toupper_use(mp, ntmp)))
  494                 goto out1;
  495 
  496         /*
  497          * Scan $BitMap and count free clusters
  498          */
  499         error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
  500         if(error)
  501                 goto out1;
  502 
  503         /*
  504          * Read and translate to internal format attribute
  505          * definition file.
  506          */
  507         {
  508                 int num,j;
  509                 struct attrdef ad;
  510 
  511                 /* Open $AttrDef */
  512                 error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp );
  513                 if(error)
  514                         goto out1;
  515 
  516                 /* Count valid entries */
  517                 for(num=0;;num++) {
  518                         error = ntfs_readattr(ntmp, VTONT(vp),
  519                                         NTFS_A_DATA, NULL,
  520                                         num * sizeof(ad), sizeof(ad),
  521                                         &ad, NULL);
  522                         if (error)
  523                                 goto out1;
  524                         if (ad.ad_name[0] == 0)
  525                                 break;
  526                 }
  527 
  528                 /* Alloc memory for attribute definitions */
  529                 ntmp->ntm_ad = (struct ntvattrdef *) malloc(
  530                         num * sizeof(struct ntvattrdef),
  531                         M_NTFSMNT, M_WAITOK);
  532 
  533                 ntmp->ntm_adnum = num;
  534 
  535                 /* Read them and translate */
  536                 for(i=0;i<num;i++){
  537                         error = ntfs_readattr(ntmp, VTONT(vp),
  538                                         NTFS_A_DATA, NULL,
  539                                         i * sizeof(ad), sizeof(ad),
  540                                         &ad, NULL);
  541                         if (error)
  542                                 goto out1;
  543                         j = 0;
  544                         do {
  545                                 ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
  546                         } while(ad.ad_name[j++]);
  547                         ntmp->ntm_ad[i].ad_namelen = j - 1;
  548                         ntmp->ntm_ad[i].ad_type = ad.ad_type;
  549                 }
  550 
  551                 vput(vp);
  552         }
  553 
  554 #if defined(__FreeBSD__)
  555         mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
  556         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
  557 #else
  558         mp->mnt_stat.f_fsidx.__fsid_val[0] = dev;
  559         mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_NTFS);
  560         mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
  561         mp->mnt_stat.f_namemax = NTFS_MAXFILENAME;
  562 #endif
  563         mp->mnt_flag |= MNT_LOCAL;
  564         devvp->v_specmountpoint = mp;
  565         return (0);
  566 
  567 out1:
  568         for(i=0;i<NTFS_SYSNODESNUM;i++)
  569                 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
  570 
  571         if (vflush(mp,NULLVP,0)) {
  572                 dprintf(("ntfs_mountfs: vflush failed\n"));
  573         }
  574 out:
  575         devvp->v_specmountpoint = NULL;
  576         if (bp)
  577                 brelse(bp);
  578 
  579         if (error) {
  580                 if (ntmp) {
  581                         if (ntmp->ntm_ad)
  582                                 free(ntmp->ntm_ad, M_NTFSMNT);
  583                         free(ntmp, M_NTFSMNT);
  584                 }
  585         }
  586 
  587         return (error);
  588 }
  589 
  590 static int
  591 ntfs_start (
  592         struct mount *mp,
  593         int flags,
  594         struct lwp *l)
  595 {
  596         return (0);
  597 }
  598 
  599 static int
  600 ntfs_unmount(
  601         struct mount *mp,
  602         int mntflags,
  603         struct lwp *l)
  604 {
  605         struct ntfsmount *ntmp;
  606         int error, ronly = 0, flags, i;
  607 
  608         dprintf(("ntfs_unmount: unmounting...\n"));
  609         ntmp = VFSTONTFS(mp);
  610 
  611         flags = 0;
  612         if(mntflags & MNT_FORCE)
  613                 flags |= FORCECLOSE;
  614 
  615         dprintf(("ntfs_unmount: vflushing...\n"));
  616         error = vflush(mp,NULLVP,flags | SKIPSYSTEM);
  617         if (error) {
  618                 dprintf(("ntfs_unmount: vflush failed: %d\n",error));
  619                 return (error);
  620         }
  621 
  622         /* Check if only system vnodes are rest */
  623         for(i=0;i<NTFS_SYSNODESNUM;i++)
  624                  if((ntmp->ntm_sysvn[i]) &&
  625                     (ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY);
  626 
  627         /* Dereference all system vnodes */
  628         for(i=0;i<NTFS_SYSNODESNUM;i++)
  629                  if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
  630 
  631         /* vflush system vnodes */
  632         error = vflush(mp,NULLVP,flags);
  633         if (error) {
  634                 /* XXX should this be panic() ? */
  635                 printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
  636         }
  637 
  638         /* Check if the type of device node isn't VBAD before
  639          * touching v_specinfo.  If the device vnode is revoked, the
  640          * field is NULL and touching it causes null pointer derefercence.
  641          */
  642         if (ntmp->ntm_devvp->v_type != VBAD)
  643                 ntmp->ntm_devvp->v_specmountpoint = NULL;
  644 
  645         vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, l, 0, 0);
  646 
  647         /* lock the device vnode before calling VOP_CLOSE() */
  648         vn_lock(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY);
  649         error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE,
  650                 NOCRED, l);
  651         VOP_UNLOCK(ntmp->ntm_devvp, 0);
  652 
  653         vrele(ntmp->ntm_devvp);
  654 
  655         /* free the toupper table, if this has been last mounted ntfs volume */
  656         ntfs_toupper_unuse();
  657 
  658         dprintf(("ntfs_umount: freeing memory...\n"));
  659         mp->mnt_data = NULL;
  660         mp->mnt_flag &= ~MNT_LOCAL;
  661         free(ntmp->ntm_ad, M_NTFSMNT);
  662         FREE(ntmp, M_NTFSMNT);
  663         return (error);
  664 }
  665 
  666 static int
  667 ntfs_root(
  668         struct mount *mp,
  669         struct vnode **vpp)
  670 {
  671         struct vnode *nvp;
  672         int error = 0;
  673 
  674         dprintf(("ntfs_root(): sysvn: %p\n",
  675                 VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]));
  676         error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp);
  677         if(error) {
  678                 printf("ntfs_root: VFS_VGET failed: %d\n",error);
  679                 return (error);
  680         }
  681 
  682         *vpp = nvp;
  683         return (0);
  684 }
  685 
  686 /*
  687  * Do operations associated with quotas, not supported
  688  */
  689 /* ARGSUSED */
  690 static int
  691 ntfs_quotactl (
  692         struct mount *mp,
  693         int cmds,
  694         uid_t uid,
  695         void *arg,
  696         struct lwp *l)
  697 {
  698 
  699         return EOPNOTSUPP;
  700 }
  701 
  702 int
  703 ntfs_calccfree(
  704         struct ntfsmount *ntmp,
  705         cn_t *cfreep)
  706 {
  707         struct vnode *vp;
  708         u_int8_t *tmp;
  709         int j, error;
  710         cn_t cfree = 0;
  711         size_t bmsize, i;
  712 
  713         vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
  714 
  715         bmsize = VTOF(vp)->f_size;
  716 
  717         tmp = (u_int8_t *) malloc(bmsize, M_TEMP, M_WAITOK);
  718 
  719         error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
  720                                0, bmsize, tmp, NULL);
  721         if (error)
  722                 goto out;
  723 
  724         for(i=0;i<bmsize;i++)
  725                 for(j=0;j<8;j++)
  726                         if(~tmp[i] & (1 << j)) cfree++;
  727         *cfreep = cfree;
  728 
  729     out:
  730         free(tmp, M_TEMP);
  731         return(error);
  732 }
  733 
  734 static int
  735 ntfs_statvfs(
  736         struct mount *mp,
  737         struct statvfs *sbp,
  738         struct lwp *l)
  739 {
  740         struct ntfsmount *ntmp = VFSTONTFS(mp);
  741         u_int64_t mftallocated;
  742 
  743         dprintf(("ntfs_statvfs():\n"));
  744 
  745         mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
  746 
  747 #if defined(__FreeBSD__)
  748         sbp->f_type = mp->mnt_vfc->vfc_typenum;
  749 #endif
  750         sbp->f_bsize = ntmp->ntm_bps;
  751         sbp->f_frsize = sbp->f_bsize; /* XXX */
  752         sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
  753         sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
  754         sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
  755         sbp->f_ffree = sbp->f_favail = sbp->f_bfree / ntmp->ntm_bpmftrec;
  756         sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
  757             sbp->f_ffree;
  758         sbp->f_fresvd = sbp->f_bresvd = 0; /* XXX */
  759         sbp->f_flag = mp->mnt_flag;
  760         copy_statvfs_info(sbp, mp);
  761         return (0);
  762 }
  763 
  764 static int
  765 ntfs_sync (
  766         struct mount *mp,
  767         int waitfor,
  768         kauth_cred_t cred,
  769         struct lwp *l)
  770 {
  771         /*dprintf(("ntfs_sync():\n"));*/
  772         return (0);
  773 }
  774 
  775 /*ARGSUSED*/
  776 static int
  777 ntfs_fhtovp(
  778 #if defined(__FreeBSD__)
  779         struct mount *mp,
  780         struct fid *fhp,
  781         struct sockaddr *nam,
  782         struct vnode **vpp,
  783         int *exflagsp,
  784         struct ucred **credanonp)
  785 #elif defined(__NetBSD__)
  786         struct mount *mp,
  787         struct fid *fhp,
  788         struct vnode **vpp)
  789 #else
  790         struct mount *mp,
  791         struct fid *fhp,
  792         struct mbuf *nam,
  793         struct vnode **vpp,
  794         int *exflagsp,
  795         struct ucred **credanonp)
  796 #endif
  797 {
  798         struct ntfid ntfh;
  799         int error;
  800 
  801         if (fhp->fid_len != sizeof(struct ntfid))
  802                 return EINVAL;
  803         memcpy(&ntfh, fhp, sizeof(ntfh));
  804         ddprintf(("ntfs_fhtovp(): %s: %llu\n", mp->mnt_stat.f_mntonname,
  805             (unsigned long long)ntfh.ntfid_ino));
  806 
  807         error = ntfs_vgetex(mp, ntfh.ntfid_ino, ntfh.ntfid_attr, NULL,
  808                         LK_EXCLUSIVE | LK_RETRY, 0, vpp);
  809         if (error != 0) {
  810                 *vpp = NULLVP;
  811                 return (error);
  812         }
  813 
  814         /* XXX as unlink/rmdir/mkdir/creat are not currently possible
  815          * with NTFS, we don't need to check anything else for now */
  816         return (0);
  817 }
  818 
  819 static int
  820 ntfs_vptofh(
  821         struct vnode *vp,
  822         struct fid *fhp,
  823         size_t *fh_size)
  824 {
  825         struct ntnode *ntp;
  826         struct ntfid ntfh;
  827         struct fnode *fn;
  828 
  829         if (*fh_size < sizeof(struct ntfid)) {
  830                 *fh_size = sizeof(struct ntfid);
  831                 return E2BIG;
  832         }
  833         *fh_size = sizeof(struct ntfid);
  834 
  835         ddprintf(("ntfs_fhtovp(): %s: %p\n", vp->v_mount->mnt_stat.f_mntonname,
  836                 vp));
  837 
  838         fn = VTOF(vp);
  839         ntp = VTONT(vp);
  840         memset(&ntfh, 0, sizeof(ntfh));
  841         ntfh.ntfid_len = sizeof(struct ntfid);
  842         ntfh.ntfid_ino = ntp->i_number;
  843         ntfh.ntfid_attr = fn->f_attrtype;
  844 #ifdef notyet
  845         ntfh.ntfid_gen = ntp->i_gen;
  846 #endif
  847         memcpy(fhp, &ntfh, sizeof(ntfh));
  848         return (0);
  849 }
  850 
  851 int
  852 ntfs_vgetex(
  853         struct mount *mp,
  854         ino_t ino,
  855         u_int32_t attrtype,
  856         char *attrname,
  857         u_long lkflags,
  858         u_long flags,
  859         struct vnode **vpp)
  860 {
  861         int error;
  862         struct ntfsmount *ntmp;
  863         struct ntnode *ip;
  864         struct fnode *fp;
  865         struct vnode *vp;
  866         enum vtype f_type = VBAD;
  867 
  868         dprintf(("ntfs_vgetex: ino: %llu, attr: 0x%x:%s, lkf: 0x%lx, f:"
  869             " 0x%lx\n", (unsigned long long)ino, attrtype,
  870             attrname ? attrname : "", (u_long)lkflags, (u_long)flags));
  871 
  872         ntmp = VFSTONTFS(mp);
  873         *vpp = NULL;
  874 
  875         /* Get ntnode */
  876         error = ntfs_ntlookup(ntmp, ino, &ip);
  877         if (error) {
  878                 printf("ntfs_vget: ntfs_ntget failed\n");
  879                 return (error);
  880         }
  881 
  882         /* It may be not initialized fully, so force load it */
  883         if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
  884                 error = ntfs_loadntnode(ntmp, ip);
  885                 if(error) {
  886                         printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO:"
  887                             " %llu\n", (unsigned long long)ip->i_number);
  888                         ntfs_ntput(ip);
  889                         return (error);
  890                 }
  891         }
  892 
  893         error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
  894         if (error) {
  895                 printf("ntfs_vget: ntfs_fget failed\n");
  896                 ntfs_ntput(ip);
  897                 return (error);
  898         }
  899 
  900         if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
  901                 if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
  902                     (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
  903                         f_type = VDIR;
  904                 } else if (flags & VG_EXT) {
  905                         f_type = VNON;
  906                         fp->f_size = fp->f_allocated = 0;
  907                 } else {
  908                         f_type = VREG;
  909 
  910                         error = ntfs_filesize(ntmp, fp,
  911                                               &fp->f_size, &fp->f_allocated);
  912                         if (error) {
  913                                 ntfs_ntput(ip);
  914                                 return (error);
  915                         }
  916                 }
  917 
  918                 fp->f_flag |= FN_VALID;
  919         }
  920 
  921         /*
  922          * We may be calling vget() now. To avoid potential deadlock, we need
  923          * to release ntnode lock, since due to locking order vnode
  924          * lock has to be acquired first.
  925          * ntfs_fget() bumped ntnode usecount, so ntnode won't be recycled
  926          * prematurely.
  927          */
  928         ntfs_ntput(ip);
  929 
  930         if (FTOV(fp)) {
  931                 /* vget() returns error if the vnode has been recycled */
  932                 if (vget(FTOV(fp), lkflags) == 0) {
  933                         *vpp = FTOV(fp);
  934                         return (0);
  935                 }
  936         }
  937 
  938         error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
  939         if(error) {
  940                 ntfs_frele(fp);
  941                 ntfs_ntput(ip);
  942                 return (error);
  943         }
  944         dprintf(("ntfs_vget: vnode: %p for ntnode: %llu\n", vp,
  945             (unsigned long long)ino));
  946 
  947 #ifdef __FreeBSD__
  948         lockinit(&fp->f_lock, PINOD, "fnode", 0, 0);
  949 #endif
  950         fp->f_vp = vp;
  951         vp->v_data = fp;
  952         if (f_type != VBAD)
  953                 vp->v_type = f_type;
  954 
  955         if (ino == NTFS_ROOTINO)
  956                 vp->v_flag |= VROOT;
  957 
  958         if (lkflags & LK_TYPE_MASK) {
  959                 error = vn_lock(vp, lkflags);
  960                 if (error) {
  961                         vput(vp);
  962                         return (error);
  963                 }
  964         }
  965 
  966         genfs_node_init(vp, &ntfs_genfsops);
  967         VREF(ip->i_devvp);
  968         *vpp = vp;
  969         return (0);
  970 }
  971 
  972 static int
  973 ntfs_vget(
  974         struct mount *mp,
  975         ino_t ino,
  976         struct vnode **vpp)
  977 {
  978         return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL,
  979                         LK_EXCLUSIVE | LK_RETRY, 0, vpp);
  980 }
  981 
  982 #if defined(__FreeBSD__)
  983 static struct vfsops ntfs_vfsops = {
  984         ntfs_mount,
  985         ntfs_start,
  986         ntfs_unmount,
  987         ntfs_root,
  988         ntfs_quotactl,
  989         ntfs_statvfs,
  990         ntfs_sync,
  991         ntfs_vget,
  992         ntfs_fhtovp,
  993         ntfs_vptofh,
  994         ntfs_init,
  995         NULL
  996 };
  997 VFS_SET(ntfs_vfsops, ntfs, 0);
  998 #elif defined(__NetBSD__)
  999 extern const struct vnodeopv_desc ntfs_vnodeop_opv_desc;
 1000 
 1001 const struct vnodeopv_desc * const ntfs_vnodeopv_descs[] = {
 1002         &ntfs_vnodeop_opv_desc,
 1003         NULL,
 1004 };
 1005 
 1006 struct vfsops ntfs_vfsops = {
 1007         MOUNT_NTFS,
 1008         ntfs_mount,
 1009         ntfs_start,
 1010         ntfs_unmount,
 1011         ntfs_root,
 1012         ntfs_quotactl,
 1013         ntfs_statvfs,
 1014         ntfs_sync,
 1015         ntfs_vget,
 1016         ntfs_fhtovp,
 1017         ntfs_vptofh,
 1018         ntfs_init,
 1019         ntfs_reinit,
 1020         ntfs_done,
 1021         ntfs_mountroot,
 1022         (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp,
 1023         vfs_stdextattrctl,
 1024         ntfs_vnodeopv_descs,
 1025         0,
 1026         { NULL, NULL },
 1027 };
 1028 VFS_ATTACH(ntfs_vfsops);
 1029 #endif

Cache object: 3af48eb5bd1658224381bb9838171ef1


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