root/ntfs/ntfs_vfsops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ntfs_checkexp
  2. ntfs_sysctl
  3. ntfs_mountroot
  4. ntfs_init
  5. ntfs_reinit
  6. ntfs_done
  7. ntfs_init
  8. ntfs_mount
  9. ntfs_mountfs
  10. ntfs_start
  11. ntfs_unmount
  12. ntfs_root
  13. ntfs_quotactl
  14. ntfs_calccfree
  15. ntfs_statfs
  16. ntfs_sync
  17. ntfs_fhtovp
  18. ntfs_vptofh
  19. ntfs_vgetex
  20. ntfs_vget

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

/* [<][>][^][v][top][bottom][index][help] */