1 /* $NetBSD: ntfs_vfsops.c,v 1.23 1999/11/15 19:38:14 jdolecek Exp $ */
4 * Copyright (c) 1998, 1999 Semen Ustimenko
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
28 * $FreeBSD: src/sys/ntfs/ntfs_vfsops.c,v 1.20.2.5 2001/12/25 01:44:45 dillon Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
36 #include <sys/nlookup.h>
37 #include <sys/kernel.h>
38 #include <sys/vnode.h>
39 #include <sys/mount.h>
41 #include <sys/fcntl.h>
42 #include <sys/malloc.h>
43 #if defined(__NetBSD__)
44 #include <sys/device.h>
47 #include <machine/inttypes.h>
50 #include <vm/vm_param.h>
51 #if defined(__NetBSD__)
52 #include <vm/vm_prot.h>
54 #include <vm/vm_page.h>
55 #include <vm/vm_object.h>
56 #include <vm/vm_extern.h>
57 #include <vm/vm_zone.h>
59 #if defined(__NetBSD__)
60 #include <miscfs/specfs/specdev.h>
66 #include "ntfs_inode.h"
67 #include "ntfs_subr.h"
68 #include "ntfs_vfsops.h"
69 #include "ntfs_ihash.h"
70 #include "ntfsmount.h"
72 extern struct vop_ops ntfs_vnode_vops
;
74 #if defined(__DragonFly__)
75 MALLOC_DEFINE(M_NTFSMNT
, "NTFS mount", "NTFS mount structure");
76 MALLOC_DEFINE(M_NTFSNTNODE
,"NTFS ntnode", "NTFS ntnode information");
77 MALLOC_DEFINE(M_NTFSFNODE
,"NTFS fnode", "NTFS fnode information");
78 MALLOC_DEFINE(M_NTFSDIR
,"NTFS dir", "NTFS dir buffer");
81 struct iconv_functions
*ntfs_iconv
= NULL
;
83 static int ntfs_root (struct mount
*, struct vnode
**);
84 static int ntfs_statfs (struct mount
*, struct statfs
*,
86 static int ntfs_statvfs (struct mount
*, struct statvfs
*,
88 static int ntfs_unmount (struct mount
*, int);
89 static int ntfs_vget (struct mount
*mp
, struct vnode
*dvp
,
90 ino_t ino
, struct vnode
**vpp
);
91 static int ntfs_mountfs (struct vnode
*, struct mount
*,
92 struct ntfs_args
*, struct ucred
*);
93 static int ntfs_vptofh (struct vnode
*, struct fid
*);
94 static int ntfs_fhtovp (struct mount
*, struct vnode
*rootvp
,
95 struct fid
*, struct vnode
**);
97 #if !defined (__DragonFly__)
98 static int ntfs_quotactl (struct mount
*, int, uid_t
, caddr_t
,
100 static int ntfs_start (struct mount
*, int, struct thread
*);
101 static int ntfs_sync (struct mount
*, int, struct ucred
*,
105 #if defined(__DragonFly__)
107 static int ntfs_mount (struct mount
*, char *, caddr_t
, struct ucred
*);
108 static int ntfs_init (struct vfsconf
*);
109 static int ntfs_checkexp (struct mount
*, struct sockaddr
*,
110 int *, struct ucred
**);
111 #elif defined(__NetBSD__)
112 static int ntfs_mount (struct mount
*, const char *, void *,
113 struct nameidata
*, struct thread
*);
114 static void ntfs_init (void);
115 static int ntfs_mountroot (void);
116 static int ntfs_sysctl (int *, u_int
, void *, size_t *, void *,
117 size_t, struct thread
*);
118 static int ntfs_checkexp (struct mount
*, struct mbuf
*,
119 int *, struct ucred
**);
123 * Verify a remote client has export rights and return these rights via.
124 * exflagsp and credanonp.
127 ntfs_checkexp(struct mount
*mp
,
128 #if defined(__DragonFly__)
129 struct sockaddr
*nam
,
130 #else /* defined(__NetBSD__) */
133 int *exflagsp
, struct ucred
**credanonp
)
136 struct ntfsmount
*ntm
= VFSTONTFS(mp
);
139 * Get the export permission structure for this <mp, client> tuple.
141 np
= vfs_export_lookup(mp
, &ntm
->ntm_export
, nam
);
145 *exflagsp
= np
->netc_exflags
;
146 *credanonp
= &np
->netc_anon
;
150 #if defined(__NetBSD__)
153 ntfs_sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
,
154 size_t newlen
, struct thread
*td
)
163 struct vnode
*rootvp
;
164 struct thread
*td
= curthread
; /* XXX */
165 struct ntfs_args args
;
168 if (root_device
->dv_class
!= DV_DISK
)
172 * Get vnodes for rootdev.
174 if (bdevvp(rootdev
, &rootvp
))
175 panic("ntfs_mountroot: can't setup rootvp");
177 if ((error
= vfs_rootmountalloc(MOUNT_NTFS
, "root_device", &mp
))) {
187 if ((error
= ntfs_mountfs(rootvp
, mp
, &args
, proc0
.p_ucred
)) != 0) {
188 mp
->mnt_op
->vfs_refcount
--;
194 mountlist_insert(mp
, MNTINS_LAST
);
195 (void)ntfs_statfs(mp
, &mp
->mnt_stat
, proc0
.p_ucred
);
207 #elif defined(__DragonFly__)
210 ntfs_init(struct vfsconf
*vcp
)
220 ntfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
225 struct ntfs_args args
;
226 struct nlookupdata nd
;
227 struct vnode
*rootvp
;
232 * Use NULL path to flag a root mount
237 * Mounting root file system
241 /* Get vnode for root device*/
242 if( bdevvp( rootdev
, &rootvp
))
243 panic("ffs_mountroot: can't setup bdevvp for root");
246 * FS specific handling
248 mp
->mnt_flag
|= MNT_RDONLY
; /* XXX globally applicable?*/
253 if( ( error
= ntfs_mountfs(rootvp
, mp
, &args
, cred
)) != 0) {
254 /* fs specific cleanup (if any)*/
258 goto dostatfs
; /* success*/
265 * Mounting non-root file system or updating a file system
269 /* copy in user arguments*/
270 error
= copyin(data
, (caddr_t
)&args
, sizeof (struct ntfs_args
));
272 goto error_1
; /* can't get arguments*/
275 * If updating, check whether changing from read-only to
276 * read/write; if there is no device name, that's all we do.
278 if (mp
->mnt_flag
& MNT_UPDATE
) {
279 /* if not updating name...*/
280 if (args
.fspec
== NULL
) {
282 * Process export requests. Jumping to "success"
283 * will return the vfs_export() error code.
285 struct ntfsmount
*ntm
= VFSTONTFS(mp
);
286 error
= vfs_export(mp
, &ntm
->ntm_export
, &args
.export
);
290 kprintf("ntfs_mount(): MNT_UPDATE not supported\n");
296 * Not an update, or updating the name: look up the name
297 * and verify that it refers to a sensible block device.
300 error
= nlookup_init(&nd
, args
.fspec
, UIO_USERSPACE
, NLC_FOLLOW
);
302 error
= nlookup(&nd
);
304 error
= cache_vref(&nd
.nl_nch
, nd
.nl_cred
, &devvp
);
309 #if defined(__DragonFly__)
310 if (!vn_isdisk(devvp
, &error
))
313 if (devvp
->v_type
!= VBLK
) {
317 if (devvp
->v_umajor
>= nblkdev
) {
322 if (mp
->mnt_flag
& MNT_UPDATE
) {
330 if (devvp
!= ntmp
->um_devvp
)
331 error
= EINVAL
; /* needs translation */
335 * Update device name only on success
338 /* Save "mounted from" info for mount point (NULL pad)*/
339 copyinstr( args
.fspec
,
340 mp
->mnt_stat
.f_mntfromname
,
343 bzero( mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
353 /* Save "mounted from" info for mount point (NULL pad)*/
354 copyinstr( args
.fspec
, /* device name*/
355 mp
->mnt_stat
.f_mntfromname
, /* save area*/
356 MNAMELEN
- 1, /* max size*/
357 &size
); /* real size*/
358 bzero( mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
360 error
= ntfs_mountfs(devvp
, mp
, &args
, cred
);
370 * Initialize FS stat information in mount struct; uses
371 * mp->mnt_stat.f_mntfromname.
373 * This code is common to root and non-root mounts
375 (void)VFS_STATFS(mp
, &mp
->mnt_stat
, cred
);
380 error_2
: /* error with devvp held*/
382 /* release devvp before failing*/
385 error_1
: /* no state to back out*/
392 * Common code for mount and mountroot
395 ntfs_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct ntfs_args
*argsp
,
399 struct ntfsmount
*ntmp
;
401 int error
, ronly
, ncount
, i
;
403 char cs_local
[ICONV_CSNMAXLEN
];
404 char cs_ntfs
[ICONV_CSNMAXLEN
];
407 * Disallow multiple mounts of the same device.
408 * Disallow mounting of a device that is currently in use
409 * (except for root, which might share swap device for miniroot).
410 * Flush out any old buffers remaining from a previous use.
412 error
= vfs_mountedon(devvp
);
415 ncount
= vcount(devvp
);
416 #if defined(__DragonFly__)
422 #if defined(__DragonFly__)
423 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
424 error
= vinvalbuf(devvp
, V_SAVE
, 0, 0);
425 VOP__UNLOCK(devvp
, 0);
427 error
= vinvalbuf(devvp
, V_SAVE
, 0, 0);
432 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
433 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
434 error
= VOP_OPEN(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, FSCRED
, NULL
);
435 VOP__UNLOCK(devvp
, 0);
442 error
= bread(devvp
, BBLOCK
, BBSIZE
, &bp
);
445 ntmp
= kmalloc(sizeof *ntmp
, M_NTFSMNT
, M_WAITOK
| M_ZERO
);
446 bcopy( bp
->b_data
, &ntmp
->ntm_bootfile
, sizeof(struct bootfile
) );
450 if (strncmp(ntmp
->ntm_bootfile
.bf_sysid
, NTFS_BBID
, NTFS_BBIDLEN
)) {
452 dprintf(("ntfs_mountfs: invalid boot block\n"));
457 int8_t cpr
= ntmp
->ntm_mftrecsz
;
459 ntmp
->ntm_bpmftrec
= ntmp
->ntm_spc
* cpr
;
461 ntmp
->ntm_bpmftrec
= (1 << (-cpr
)) / ntmp
->ntm_bps
;
463 dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
464 ntmp
->ntm_bps
,ntmp
->ntm_spc
,ntmp
->ntm_bootfile
.bf_media
,
465 ntmp
->ntm_mftrecsz
,ntmp
->ntm_bpmftrec
));
466 dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
467 (u_int32_t
)ntmp
->ntm_mftcn
,(u_int32_t
)ntmp
->ntm_mftmirrcn
));
469 ntmp
->ntm_mountp
= mp
;
471 ntmp
->ntm_devvp
= devvp
;
472 ntmp
->ntm_uid
= argsp
->uid
;
473 ntmp
->ntm_gid
= argsp
->gid
;
474 ntmp
->ntm_mode
= argsp
->mode
;
475 ntmp
->ntm_flag
= argsp
->flag
;
477 if (argsp
->flag
& NTFS_MFLAG_KICONV
&& ntfs_iconv
) {
478 bcopy(argsp
->cs_local
, cs_local
, sizeof(cs_local
));
479 bcopy(argsp
->cs_ntfs
, cs_ntfs
, sizeof(cs_ntfs
));
480 ntfs_82u_init(ntmp
, cs_local
, cs_ntfs
);
481 ntfs_u28_init(ntmp
, NULL
, cs_local
, cs_ntfs
);
483 ntfs_82u_init(ntmp
, NULL
, NULL
);
484 ntfs_u28_init(ntmp
, ntmp
->ntm_82u
, NULL
, NULL
);
487 mp
->mnt_data
= (qaddr_t
)ntmp
;
489 dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
490 (ntmp
->ntm_flag
& NTFS_MFLAG_CASEINS
)?"insens.":"sens.",
491 (ntmp
->ntm_flag
& NTFS_MFLAG_ALLNAMES
)?" allnames,":"",
492 ntmp
->ntm_uid
, ntmp
->ntm_gid
, ntmp
->ntm_mode
));
494 vfs_add_vnodeops(mp
, &ntfs_vnode_vops
, &mp
->mnt_vn_norm_ops
);
497 * We read in some system nodes to do not allow
498 * reclaim them and to have everytime access to them.
501 int pi
[3] = { NTFS_MFTINO
, NTFS_ROOTINO
, NTFS_BITMAPINO
};
502 for (i
=0; i
<3; i
++) {
503 error
= VFS_VGET(mp
, NULL
,
504 pi
[i
], &(ntmp
->ntm_sysvn
[pi
[i
]]));
507 vsetflags(ntmp
->ntm_sysvn
[pi
[i
]], VSYSTEM
);
508 vref(ntmp
->ntm_sysvn
[pi
[i
]]);
509 vput(ntmp
->ntm_sysvn
[pi
[i
]]);
513 /* read the Unicode lowercase --> uppercase translation table,
515 if ((error
= ntfs_toupper_use(mp
, ntmp
)))
519 * Scan $BitMap and count free clusters
521 error
= ntfs_calccfree(ntmp
, &ntmp
->ntm_cfree
);
526 * Read and translate to internal format attribute
534 error
= VFS_VGET(mp
, NULL
, NTFS_ATTRDEFINO
, &vp
);
538 /* Count valid entries */
540 error
= ntfs_readattr(ntmp
, VTONT(vp
),
542 num
* sizeof(ad
), sizeof(ad
),
546 if (ad
.ad_name
[0] == 0)
550 /* Alloc memory for attribute definitions */
551 ntmp
->ntm_ad
= kmalloc(num
* sizeof(struct ntvattrdef
),
552 M_NTFSMNT
, M_WAITOK
);
554 ntmp
->ntm_adnum
= num
;
556 /* Read them and translate */
558 error
= ntfs_readattr(ntmp
, VTONT(vp
),
560 i
* sizeof(ad
), sizeof(ad
),
566 ntmp
->ntm_ad
[i
].ad_name
[j
] = ad
.ad_name
[j
];
567 } while(ad
.ad_name
[j
++]);
568 ntmp
->ntm_ad
[i
].ad_namelen
= j
- 1;
569 ntmp
->ntm_ad
[i
].ad_type
= ad
.ad_type
;
575 #if defined(__DragonFly__)
576 mp
->mnt_stat
.f_fsid
.val
[0] = dev2udev(dev
);
577 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
579 mp
->mnt_stat
.f_fsid
.val
[0] = dev
;
580 mp
->mnt_stat
.f_fsid
.val
[1] = makefstype(MOUNT_NTFS
);
582 mp
->mnt_maxsymlinklen
= 0;
583 mp
->mnt_flag
|= MNT_LOCAL
;
584 dev
->si_mountpoint
= mp
;
589 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
590 if(ntmp
->ntm_sysvn
[i
]) vrele(ntmp
->ntm_sysvn
[i
]);
592 if (vflush(mp
, 0, 0))
593 dprintf(("ntfs_mountfs: vflush failed\n"));
596 dev
->si_mountpoint
= NULL
;
600 #if defined __NetBSD__
601 /* lock the device vnode before calling VOP_CLOSE() */
602 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
603 (void)VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
604 VOP__UNLOCK(devvp
, 0);
606 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
607 (void)VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, NULL
);
614 #if !defined(__DragonFly__)
616 ntfs_start(struct mount
*mp
, int flags
, struct thread
*td
)
623 ntfs_unmount(struct mount
*mp
, int mntflags
)
625 struct ntfsmount
*ntmp
;
626 int error
, ronly
, flags
, i
;
628 dprintf(("ntfs_unmount: unmounting...\n"));
629 ntmp
= VFSTONTFS(mp
);
631 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
633 if(mntflags
& MNT_FORCE
)
636 dprintf(("ntfs_unmount: vflushing...\n"));
637 error
= vflush(mp
, 0, flags
| SKIPSYSTEM
);
639 kprintf("ntfs_unmount: vflush failed: %d\n",error
);
643 /* Check if only system vnodes are left */
644 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
645 if((ntmp
->ntm_sysvn
[i
]) &&
646 (VREFCNT(ntmp
->ntm_sysvn
[i
]) > 1)) return (EBUSY
);
648 /* Dereference all system vnodes */
649 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
650 if(ntmp
->ntm_sysvn
[i
]) vrele(ntmp
->ntm_sysvn
[i
]);
652 /* vflush system vnodes */
653 error
= vflush(mp
, 0, flags
);
655 kprintf("ntfs_unmount: vflush failed(sysnodes): %d\n",error
);
657 /* Check if the type of device node isn't VBAD before
658 * touching v_cdevinfo. If the device vnode is revoked, the
659 * field is NULL and touching it causes null pointer derefercence.
661 if (ntmp
->ntm_devvp
->v_type
!= VBAD
)
662 ntmp
->ntm_devvp
->v_rdev
->si_mountpoint
= NULL
;
664 vn_lock(ntmp
->ntm_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
665 vinvalbuf(ntmp
->ntm_devvp
, V_SAVE
, 0, 0);
666 error
= VOP_CLOSE(ntmp
->ntm_devvp
, ronly
? FREAD
: FREAD
|FWRITE
, NULL
);
667 vn_unlock(ntmp
->ntm_devvp
);
669 vrele(ntmp
->ntm_devvp
);
671 /* free the toupper table, if this has been last mounted ntfs volume */
672 ntfs_toupper_unuse();
674 dprintf(("ntfs_umount: freeing memory...\n"));
675 ntfs_u28_uninit(ntmp
);
676 ntfs_82u_uninit(ntmp
);
677 mp
->mnt_data
= (qaddr_t
)0;
678 mp
->mnt_flag
&= ~MNT_LOCAL
;
679 kfree(ntmp
->ntm_ad
, M_NTFSMNT
);
680 kfree(ntmp
, M_NTFSMNT
);
685 ntfs_root(struct mount
*mp
, struct vnode
**vpp
)
690 dprintf(("ntfs_root(): sysvn: %p\n",
691 VFSTONTFS(mp
)->ntm_sysvn
[NTFS_ROOTINO
]));
692 error
= VFS_VGET(mp
, NULL
, (ino_t
)NTFS_ROOTINO
, &nvp
);
694 kprintf("ntfs_root: VFS_VGET failed: %d\n",error
);
702 #if !defined(__DragonFly__)
704 ntfs_quotactl(struct mount
*mp
, int cmds
, uid_t uid
, caddr_t arg
,
707 kprintf("\nntfs_quotactl():\n");
713 ntfs_calccfree(struct ntfsmount
*ntmp
, cn_t
*cfreep
)
721 vp
= ntmp
->ntm_sysvn
[NTFS_BITMAPINO
];
723 bmsize
= VTOF(vp
)->f_size
;
725 tmp
= kmalloc(bmsize
, M_TEMP
, M_WAITOK
);
727 error
= ntfs_readattr(ntmp
, VTONT(vp
), NTFS_A_DATA
, NULL
,
728 0, bmsize
, tmp
, NULL
);
732 for(i
=0;i
<bmsize
;i
++)
734 if(~tmp
[i
] & (1 << j
)) cfree
++;
743 ntfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
745 struct ntfsmount
*ntmp
= VFSTONTFS(mp
);
746 u_int64_t mftallocated
;
748 dprintf(("ntfs_statfs():\n"));
750 mftallocated
= VTOF(ntmp
->ntm_sysvn
[NTFS_MFTINO
])->f_allocated
;
752 #if defined(__DragonFly__)
753 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
754 #elif defined(__NetBSD__)
757 sbp
->f_type
= MOUNT_NTFS
;
759 sbp
->f_bsize
= ntmp
->ntm_bps
;
760 sbp
->f_iosize
= ntmp
->ntm_bps
* ntmp
->ntm_spc
;
761 sbp
->f_blocks
= ntmp
->ntm_bootfile
.bf_spv
;
762 sbp
->f_bfree
= sbp
->f_bavail
= ntfs_cntobn(ntmp
->ntm_cfree
);
763 sbp
->f_ffree
= sbp
->f_bfree
/ ntmp
->ntm_bpmftrec
;
764 sbp
->f_files
= mftallocated
/ ntfs_bntob(ntmp
->ntm_bpmftrec
) +
766 if (sbp
!= &mp
->mnt_stat
) {
767 bcopy((caddr_t
)mp
->mnt_stat
.f_mntfromname
,
768 (caddr_t
)&sbp
->f_mntfromname
[0], MNAMELEN
);
770 sbp
->f_flags
= mp
->mnt_flag
;
772 strncpy(sbp
->f_fstypename
, mp
->mnt_op
->vfs_name
, MFSNAMELEN
);
779 ntfs_statvfs(struct mount
*mp
, struct statvfs
*sbp
, struct ucred
*cred
)
781 struct ntfsmount
*ntmp
= VFSTONTFS(mp
);
782 u_int64_t mftallocated
;
784 dprintf(("ntfs_statvfs():\n"));
786 mftallocated
= VTOF(ntmp
->ntm_sysvn
[NTFS_MFTINO
])->f_allocated
;
788 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
789 sbp
->f_bsize
= ntmp
->ntm_bps
;
790 sbp
->f_blocks
= ntmp
->ntm_bootfile
.bf_spv
;
791 sbp
->f_bfree
= sbp
->f_bavail
= ntmp
->ntm_cfree
* ntmp
->ntm_spc
;
792 sbp
->f_ffree
= sbp
->f_bfree
/ ntmp
->ntm_bpmftrec
;
793 sbp
->f_files
= mftallocated
/ (ntmp
->ntm_bpmftrec
* ntmp
->ntm_bps
) +
799 #if !defined(__DragonFly__)
801 ntfs_sync(struct mount
*mp
, int waitfor
, struct ucred
*cred
, struct thread
*td
)
803 /*dprintf(("ntfs_sync():\n"));*/
810 ntfs_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
811 struct fid
*fhp
, struct vnode
**vpp
)
814 struct ntfid
*ntfhp
= (struct ntfid
*)fhp
;
817 ddprintf(("ntfs_fhtovp(): %d\n", ntfhp
->ntfid_ino
));
819 if ((error
= VFS_VGET(mp
, NULL
, ntfhp
->ntfid_ino
, &nvp
)) != 0) {
823 /* XXX as unlink/rmdir/mkdir/creat are not currently possible
824 * with NTFS, we don't need to check anything else for now */
831 ntfs_vptofh(struct vnode
*vp
, struct fid
*fhp
)
836 ddprintf(("ntfs_fhtovp(): %p\n", vp
));
839 ntfhp
= (struct ntfid
*)fhp
;
840 ntfhp
->ntfid_len
= sizeof(struct ntfid
);
841 ntfhp
->ntfid_ino
= ntp
->i_number
;
842 /* ntfhp->ntfid_gen = ntp->i_gen; */
847 ntfs_vgetex(struct mount
*mp
, ino_t ino
, u_int32_t attrtype
, char *attrname
,
848 u_long lkflags
, u_long flags
, struct thread
*td
,
852 struct ntfsmount
*ntmp
;
858 dprintf(("ntfs_vgetex: ino: %ju, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
859 (uintmax_t) ino
, attrtype
, attrname
?attrname
:"", lkflags
, flags
));
861 ntmp
= VFSTONTFS(mp
);
865 error
= ntfs_ntlookup(ntmp
, ino
, &ip
);
867 kprintf("ntfs_vget: ntfs_ntget failed\n");
871 /* It may be not initialized fully, so force load it */
872 if (!(flags
& VG_DONTLOADIN
) && !(ip
->i_flag
& IN_LOADED
)) {
873 error
= ntfs_loadntnode(ntmp
, ip
);
875 kprintf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %"PRId64
"\n",
882 error
= ntfs_fget(ntmp
, ip
, attrtype
, attrname
, &fp
);
884 kprintf("ntfs_vget: ntfs_fget failed\n");
890 if (!(flags
& VG_DONTVALIDFN
) && !(fp
->f_flag
& FN_VALID
)) {
891 if ((ip
->i_frflag
& NTFS_FRFLAG_DIR
) &&
892 (fp
->f_attrtype
== NTFS_A_DATA
&& fp
->f_attrname
== NULL
)) {
894 } else if (flags
& VG_EXT
) {
896 fp
->f_size
= fp
->f_allocated
= 0;
900 error
= ntfs_filesize(ntmp
, fp
,
901 &fp
->f_size
, &fp
->f_allocated
);
908 fp
->f_flag
|= FN_VALID
;
912 VGET(FTOV(fp
), lkflags
);
918 error
= getnewvnode(VT_NTFS
, ntmp
->ntm_mountp
, &vp
, VLKTIMEOUT
, 0);
924 dprintf(("ntfs_vget: vnode: %p for ntnode: %ju\n", vp
, (uintmax_t)ino
));
930 if (ino
== NTFS_ROOTINO
)
931 vsetflags(vp
, VROOT
);
934 * Normal files use the buffer cache
937 vinitvmio(vp
, fp
->f_size
, PAGE_SIZE
, -1);
941 KKASSERT(lkflags
& LK_TYPE_MASK
);
942 /* XXX leave vnode locked exclusively from getnewvnode */
949 ntfs_vget(struct mount
*mp
, struct vnode
*dvp
, ino_t ino
, struct vnode
**vpp
)
951 return ntfs_vgetex(mp
, ino
, NTFS_A_DATA
, NULL
,
952 LK_EXCLUSIVE
| LK_RETRY
, 0, curthread
, vpp
);
955 #if defined(__DragonFly__)
956 static struct vfsops ntfs_vfsops
= {
957 .vfs_mount
= ntfs_mount
,
958 .vfs_unmount
= ntfs_unmount
,
959 .vfs_root
= ntfs_root
,
960 .vfs_statfs
= ntfs_statfs
,
961 .vfs_statvfs
= ntfs_statvfs
,
962 .vfs_sync
= vfs_stdsync
,
963 .vfs_vget
= ntfs_vget
,
964 .vfs_fhtovp
= ntfs_fhtovp
,
965 .vfs_checkexp
= ntfs_checkexp
,
966 .vfs_vptofh
= ntfs_vptofh
,
967 .vfs_init
= ntfs_init
,
968 .vfs_uninit
= ntfs_nthash_uninit
/* see ntfs_ihash.c */
970 VFS_SET(ntfs_vfsops
, ntfs
, 0);
971 MODULE_VERSION(ntfs
, 1);
972 #elif defined(__NetBSD__)
973 extern struct vnodeopv_desc ntfs_vnodeop_opv_desc
;
975 struct vnodeopv_desc
*ntfs_vnodeopv_descs
[] = {
976 &ntfs_vnodeop_opv_desc
,
980 struct vfsops ntfs_vfsops
= {
998 #else /* !NetBSD && !FreeBSD */
999 static struct vfsops ntfs_vfsops
= {
1012 VFS_SET(ntfs_vfsops
, ntfs
, MOUNT_NTFS
, 0);