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

Cache object: c91d2a8c326f3d2fe982065208a829c7


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