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

Cache object: dee2355db351907f8d2c374df32361bc


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