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_subr.c,v 1.7.2.4 2001/10/12 22:08:49 semenu 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>
44 #include <machine/inttypes.h>
47 #include <vm/vm_param.h>
48 #include <vm/vm_page.h>
49 #include <vm/vm_object.h>
50 #include <vm/vm_extern.h>
51 #include <vm/vm_zone.h>
56 #include "ntfs_inode.h"
57 #include "ntfs_subr.h"
58 #include "ntfs_vfsops.h"
59 #include "ntfs_ihash.h"
60 #include "ntfsmount.h"
62 extern struct vop_ops ntfs_vnode_vops
;
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");
69 struct iconv_functions
*ntfs_iconv
= NULL
;
71 static int ntfs_root (struct mount
*, struct vnode
**);
72 static int ntfs_statfs (struct mount
*, struct statfs
*,
74 static int ntfs_statvfs (struct mount
*, struct statvfs
*,
76 static int ntfs_unmount (struct mount
*, int);
77 static int ntfs_vget (struct mount
*mp
, struct vnode
*dvp
,
78 ino_t ino
, struct vnode
**vpp
);
79 static int ntfs_mountfs (struct vnode
*, struct mount
*,
80 struct ntfs_args
*, struct ucred
*);
81 static int ntfs_vptofh (struct vnode
*, struct fid
*);
82 static int ntfs_fhtovp (struct mount
*, struct vnode
*rootvp
,
83 struct fid
*, struct vnode
**);
86 static int ntfs_mount (struct mount
*, char *, caddr_t
, struct ucred
*);
87 static int ntfs_init (struct vfsconf
*);
88 static int ntfs_checkexp (struct mount
*, struct sockaddr
*,
89 int *, struct ucred
**);
91 * Verify a remote client has export rights and return these rights via.
92 * exflagsp and credanonp.
95 ntfs_checkexp(struct mount
*mp
, struct sockaddr
*nam
,
96 int *exflagsp
, struct ucred
**credanonp
)
99 struct ntfsmount
*ntm
= VFSTONTFS(mp
);
102 * Get the export permission structure for this <mp, client> tuple.
104 np
= vfs_export_lookup(mp
, &ntm
->ntm_export
, nam
);
108 *exflagsp
= np
->netc_exflags
;
109 *credanonp
= &np
->netc_anon
;
114 ntfs_init(struct vfsconf
*vcp
)
122 ntfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
127 struct ntfs_args args
;
128 struct nlookupdata nd
;
129 struct vnode
*rootvp
;
133 * Use NULL path to flag a root mount
138 * Mounting root file system
142 /* Get vnode for root device*/
143 if( bdevvp( rootdev
, &rootvp
))
144 panic("ffs_mountroot: can't setup bdevvp for root");
147 * FS specific handling
149 mp
->mnt_flag
|= MNT_RDONLY
; /* XXX globally applicable?*/
154 if( ( error
= ntfs_mountfs(rootvp
, mp
, &args
, cred
)) != 0) {
155 /* fs specific cleanup (if any)*/
159 goto dostatfs
; /* success*/
165 * Mounting non-root file system or updating a file system
169 /* copy in user arguments*/
170 error
= copyin(data
, (caddr_t
)&args
, sizeof (struct ntfs_args
));
172 goto error_1
; /* can't get arguments*/
175 * If updating, check whether changing from read-only to
176 * read/write; if there is no device name, that's all we do.
178 if (mp
->mnt_flag
& MNT_UPDATE
) {
179 /* if not updating name...*/
180 if (args
.fspec
== NULL
) {
182 * Process export requests. Jumping to "success"
183 * will return the vfs_export() error code.
185 struct ntfsmount
*ntm
= VFSTONTFS(mp
);
186 error
= vfs_export(mp
, &ntm
->ntm_export
, &args
.export
);
190 kprintf("ntfs_mount(): MNT_UPDATE not supported\n");
196 * Not an update, or updating the name: look up the name
197 * and verify that it refers to a sensible block device.
200 error
= nlookup_init(&nd
, args
.fspec
, UIO_USERSPACE
, NLC_FOLLOW
);
202 error
= nlookup(&nd
);
204 error
= cache_vref(&nd
.nl_nch
, nd
.nl_cred
, &devvp
);
209 if (!vn_isdisk(devvp
, &error
))
212 if (mp
->mnt_flag
& MNT_UPDATE
) {
220 if (devvp
!= ntmp
->um_devvp
)
221 error
= EINVAL
; /* needs translation */
225 * Update device name only on success
228 /* Save "mounted from" info for mount point (NULL pad)*/
229 copyinstr( args
.fspec
,
230 mp
->mnt_stat
.f_mntfromname
,
233 bzero( mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
243 /* Save "mounted from" info for mount point (NULL pad)*/
244 copyinstr( args
.fspec
, /* device name*/
245 mp
->mnt_stat
.f_mntfromname
, /* save area*/
246 MNAMELEN
- 1, /* max size*/
247 &size
); /* real size*/
248 bzero( mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
250 error
= ntfs_mountfs(devvp
, mp
, &args
, cred
);
258 * Initialize FS stat information in mount struct; uses
259 * mp->mnt_stat.f_mntfromname.
261 * This code is common to root and non-root mounts
263 (void)VFS_STATFS(mp
, &mp
->mnt_stat
, cred
);
268 error_2
: /* error with devvp held*/
270 /* release devvp before failing*/
273 error_1
: /* no state to back out*/
280 * Common code for mount and mountroot
283 ntfs_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct ntfs_args
*argsp
,
287 struct ntfsmount
*ntmp
;
289 int error
, ronly
, ncount
, i
;
291 char cs_local
[ICONV_CSNMAXLEN
];
292 char cs_ntfs
[ICONV_CSNMAXLEN
];
295 * Disallow multiple mounts of the same device.
296 * Disallow mounting of a device that is currently in use
297 * (except for root, which might share swap device for miniroot).
298 * Flush out any old buffers remaining from a previous use.
300 error
= vfs_mountedon(devvp
);
303 ncount
= vcount(devvp
);
311 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
312 error
= vinvalbuf(devvp
, V_SAVE
, 0, 0);
313 VOP__UNLOCK(devvp
, 0);
317 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
318 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
319 error
= VOP_OPEN(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, FSCRED
, NULL
);
320 VOP__UNLOCK(devvp
, 0);
327 error
= bread(devvp
, BBLOCK
, BBSIZE
, &bp
);
330 ntmp
= kmalloc(sizeof *ntmp
, M_NTFSMNT
, M_WAITOK
| M_ZERO
);
331 bcopy( bp
->b_data
, &ntmp
->ntm_bootfile
, sizeof(struct bootfile
) );
333 * We must not cache the boot block if its size is not exactly
334 * one cluster in order to avoid confusing the buffer cache when
335 * the boot file is read later by ntfs_readntvattr_plain(), which
336 * reads a cluster at a time.
338 if (ntfs_cntob(1) != BBSIZE
)
339 bp
->b_flags
|= B_NOCACHE
;
343 if (strncmp(ntmp
->ntm_bootfile
.bf_sysid
, NTFS_BBID
, NTFS_BBIDLEN
)) {
345 dprintf(("ntfs_mountfs: invalid boot block\n"));
350 int8_t cpr
= ntmp
->ntm_mftrecsz
;
352 ntmp
->ntm_bpmftrec
= ntmp
->ntm_spc
* cpr
;
354 ntmp
->ntm_bpmftrec
= (1 << (-cpr
)) / ntmp
->ntm_bps
;
356 dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
357 ntmp
->ntm_bps
,ntmp
->ntm_spc
,ntmp
->ntm_bootfile
.bf_media
,
358 ntmp
->ntm_mftrecsz
,ntmp
->ntm_bpmftrec
));
359 dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
360 (u_int32_t
)ntmp
->ntm_mftcn
,(u_int32_t
)ntmp
->ntm_mftmirrcn
));
362 ntmp
->ntm_mountp
= mp
;
364 ntmp
->ntm_devvp
= devvp
;
365 ntmp
->ntm_uid
= argsp
->uid
;
366 ntmp
->ntm_gid
= argsp
->gid
;
367 ntmp
->ntm_mode
= argsp
->mode
;
368 ntmp
->ntm_flag
= argsp
->flag
;
370 if (argsp
->flag
& NTFS_MFLAG_KICONV
&& ntfs_iconv
) {
371 bcopy(argsp
->cs_local
, cs_local
, sizeof(cs_local
));
372 bcopy(argsp
->cs_ntfs
, cs_ntfs
, sizeof(cs_ntfs
));
373 ntfs_82u_init(ntmp
, cs_local
, cs_ntfs
);
374 ntfs_u28_init(ntmp
, NULL
, cs_local
, cs_ntfs
);
376 ntfs_82u_init(ntmp
, NULL
, NULL
);
377 ntfs_u28_init(ntmp
, ntmp
->ntm_82u
, NULL
, NULL
);
380 mp
->mnt_data
= (qaddr_t
)ntmp
;
382 dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
383 (ntmp
->ntm_flag
& NTFS_MFLAG_CASEINS
)?"insens.":"sens.",
384 (ntmp
->ntm_flag
& NTFS_MFLAG_ALLNAMES
)?" allnames,":"",
385 ntmp
->ntm_uid
, ntmp
->ntm_gid
, ntmp
->ntm_mode
));
387 vfs_add_vnodeops(mp
, &ntfs_vnode_vops
, &mp
->mnt_vn_norm_ops
);
390 * We read in some system nodes to do not allow
391 * reclaim them and to have everytime access to them.
394 int pi
[3] = { NTFS_MFTINO
, NTFS_ROOTINO
, NTFS_BITMAPINO
};
395 for (i
=0; i
<3; i
++) {
396 error
= VFS_VGET(mp
, NULL
,
397 pi
[i
], &(ntmp
->ntm_sysvn
[pi
[i
]]));
400 vsetflags(ntmp
->ntm_sysvn
[pi
[i
]], VSYSTEM
);
401 vref(ntmp
->ntm_sysvn
[pi
[i
]]);
402 vput(ntmp
->ntm_sysvn
[pi
[i
]]);
406 /* read the Unicode lowercase --> uppercase translation table,
408 if ((error
= ntfs_toupper_use(mp
, ntmp
)))
412 * Scan $BitMap and count free clusters
414 error
= ntfs_calccfree(ntmp
, &ntmp
->ntm_cfree
);
419 * Read and translate to internal format attribute
427 error
= VFS_VGET(mp
, NULL
, NTFS_ATTRDEFINO
, &vp
);
431 /* Count valid entries */
433 error
= ntfs_readattr(ntmp
, VTONT(vp
),
435 num
* sizeof(ad
), sizeof(ad
),
439 if (ad
.ad_name
[0] == 0)
443 /* Alloc memory for attribute definitions */
444 ntmp
->ntm_ad
= kmalloc(num
* sizeof(struct ntvattrdef
),
445 M_NTFSMNT
, M_WAITOK
);
447 ntmp
->ntm_adnum
= num
;
449 /* Read them and translate */
451 error
= ntfs_readattr(ntmp
, VTONT(vp
),
453 i
* sizeof(ad
), sizeof(ad
),
459 ntmp
->ntm_ad
[i
].ad_name
[j
] = ad
.ad_name
[j
];
460 } while(ad
.ad_name
[j
++]);
461 ntmp
->ntm_ad
[i
].ad_namelen
= j
- 1;
462 ntmp
->ntm_ad
[i
].ad_type
= ad
.ad_type
;
468 mp
->mnt_stat
.f_fsid
.val
[0] = dev2udev(dev
);
469 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
470 mp
->mnt_maxsymlinklen
= 0;
471 mp
->mnt_flag
|= MNT_LOCAL
;
472 dev
->si_mountpoint
= mp
;
477 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
478 if(ntmp
->ntm_sysvn
[i
]) vrele(ntmp
->ntm_sysvn
[i
]);
480 if (vflush(mp
, 0, 0))
481 dprintf(("ntfs_mountfs: vflush failed\n"));
484 dev
->si_mountpoint
= NULL
;
488 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
489 (void)VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, NULL
);
496 ntfs_unmount(struct mount
*mp
, int mntflags
)
498 struct ntfsmount
*ntmp
;
499 int error
, ronly
, flags
, i
;
501 dprintf(("ntfs_unmount: unmounting...\n"));
502 ntmp
= VFSTONTFS(mp
);
504 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
506 if(mntflags
& MNT_FORCE
)
509 dprintf(("ntfs_unmount: vflushing...\n"));
510 error
= vflush(mp
, 0, flags
| SKIPSYSTEM
);
512 kprintf("ntfs_unmount: vflush failed: %d\n",error
);
516 /* Check if only system vnodes are left */
517 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
518 if((ntmp
->ntm_sysvn
[i
]) &&
519 (VREFCNT(ntmp
->ntm_sysvn
[i
]) > 1)) return (EBUSY
);
521 /* Dereference all system vnodes */
522 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
523 if(ntmp
->ntm_sysvn
[i
]) vrele(ntmp
->ntm_sysvn
[i
]);
525 /* vflush system vnodes */
526 error
= vflush(mp
, 0, flags
);
528 kprintf("ntfs_unmount: vflush failed(sysnodes): %d\n",error
);
530 /* Check if the type of device node isn't VBAD before
531 * touching v_cdevinfo. If the device vnode is revoked, the
532 * field is NULL and touching it causes null pointer derefercence.
534 if (ntmp
->ntm_devvp
->v_type
!= VBAD
)
535 ntmp
->ntm_devvp
->v_rdev
->si_mountpoint
= NULL
;
537 vn_lock(ntmp
->ntm_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
538 vinvalbuf(ntmp
->ntm_devvp
, V_SAVE
, 0, 0);
539 error
= VOP_CLOSE(ntmp
->ntm_devvp
, ronly
? FREAD
: FREAD
|FWRITE
, NULL
);
540 vn_unlock(ntmp
->ntm_devvp
);
542 vrele(ntmp
->ntm_devvp
);
544 /* free the toupper table, if this has been last mounted ntfs volume */
545 ntfs_toupper_unuse();
547 dprintf(("ntfs_umount: freeing memory...\n"));
548 ntfs_u28_uninit(ntmp
);
549 ntfs_82u_uninit(ntmp
);
550 mp
->mnt_data
= (qaddr_t
)0;
551 mp
->mnt_flag
&= ~MNT_LOCAL
;
552 kfree(ntmp
->ntm_ad
, M_NTFSMNT
);
553 kfree(ntmp
, M_NTFSMNT
);
558 ntfs_root(struct mount
*mp
, struct vnode
**vpp
)
563 dprintf(("ntfs_root(): sysvn: %p\n",
564 VFSTONTFS(mp
)->ntm_sysvn
[NTFS_ROOTINO
]));
565 error
= VFS_VGET(mp
, NULL
, (ino_t
)NTFS_ROOTINO
, &nvp
);
567 kprintf("ntfs_root: VFS_VGET failed: %d\n",error
);
576 ntfs_calccfree(struct ntfsmount
*ntmp
, cn_t
*cfreep
)
584 vp
= ntmp
->ntm_sysvn
[NTFS_BITMAPINO
];
586 bmsize
= VTOF(vp
)->f_size
;
588 tmp
= kmalloc(bmsize
, M_TEMP
, M_WAITOK
);
590 error
= ntfs_readattr(ntmp
, VTONT(vp
), NTFS_A_DATA
, NULL
,
591 0, bmsize
, tmp
, NULL
);
595 for(i
=0;i
<bmsize
;i
++)
597 if(~tmp
[i
] & (1 << j
)) cfree
++;
606 ntfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
608 struct ntfsmount
*ntmp
= VFSTONTFS(mp
);
609 u_int64_t mftallocated
;
611 dprintf(("ntfs_statfs():\n"));
613 mftallocated
= VTOF(ntmp
->ntm_sysvn
[NTFS_MFTINO
])->f_allocated
;
615 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
616 sbp
->f_bsize
= ntmp
->ntm_bps
;
617 sbp
->f_iosize
= ntmp
->ntm_bps
* ntmp
->ntm_spc
;
618 sbp
->f_blocks
= ntmp
->ntm_bootfile
.bf_spv
;
619 sbp
->f_bfree
= sbp
->f_bavail
= ntfs_cntobn(ntmp
->ntm_cfree
);
620 sbp
->f_ffree
= sbp
->f_bfree
/ ntmp
->ntm_bpmftrec
;
621 sbp
->f_files
= mftallocated
/ ntfs_bntob(ntmp
->ntm_bpmftrec
) +
623 if (sbp
!= &mp
->mnt_stat
) {
624 bcopy((caddr_t
)mp
->mnt_stat
.f_mntfromname
,
625 (caddr_t
)&sbp
->f_mntfromname
[0], MNAMELEN
);
627 sbp
->f_flags
= mp
->mnt_flag
;
633 ntfs_statvfs(struct mount
*mp
, struct statvfs
*sbp
, struct ucred
*cred
)
635 struct ntfsmount
*ntmp
= VFSTONTFS(mp
);
636 u_int64_t mftallocated
;
638 dprintf(("ntfs_statvfs():\n"));
640 mftallocated
= VTOF(ntmp
->ntm_sysvn
[NTFS_MFTINO
])->f_allocated
;
642 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
643 sbp
->f_bsize
= ntmp
->ntm_bps
;
644 sbp
->f_blocks
= ntmp
->ntm_bootfile
.bf_spv
;
645 sbp
->f_bfree
= sbp
->f_bavail
= ntmp
->ntm_cfree
* ntmp
->ntm_spc
;
646 sbp
->f_ffree
= sbp
->f_bfree
/ ntmp
->ntm_bpmftrec
;
647 sbp
->f_files
= mftallocated
/ (ntmp
->ntm_bpmftrec
* ntmp
->ntm_bps
) +
655 ntfs_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
656 struct fid
*fhp
, struct vnode
**vpp
)
659 struct ntfid
*ntfhp
= (struct ntfid
*)fhp
;
662 ddprintf(("ntfs_fhtovp(): %ju\n", ntfhp
->ntfid_ino
));
664 if ((error
= VFS_VGET(mp
, NULL
, ntfhp
->ntfid_ino
, &nvp
)) != 0) {
668 /* XXX as unlink/rmdir/mkdir/creat are not currently possible
669 * with NTFS, we don't need to check anything else for now */
676 ntfs_vptofh(struct vnode
*vp
, struct fid
*fhp
)
681 ddprintf(("ntfs_fhtovp(): %p\n", vp
));
684 ntfhp
= (struct ntfid
*)fhp
;
685 ntfhp
->ntfid_len
= sizeof(struct ntfid
);
686 ntfhp
->ntfid_ino
= ntp
->i_number
;
687 /* ntfhp->ntfid_gen = ntp->i_gen; */
692 ntfs_vgetex(struct mount
*mp
, ino_t ino
, u_int32_t attrtype
, char *attrname
,
693 u_long lkflags
, u_long flags
, struct thread
*td
,
697 struct ntfsmount
*ntmp
;
703 dprintf(("ntfs_vgetex: ino: %ju, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
704 (uintmax_t) ino
, attrtype
, attrname
?attrname
:"", lkflags
, flags
));
706 ntmp
= VFSTONTFS(mp
);
710 error
= ntfs_ntlookup(ntmp
, ino
, &ip
);
712 kprintf("ntfs_vget: ntfs_ntget failed\n");
716 /* It may be not initialized fully, so force load it */
717 if (!(flags
& VG_DONTLOADIN
) && !(ip
->i_flag
& IN_LOADED
)) {
718 error
= ntfs_loadntnode(ntmp
, ip
);
720 kprintf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %"PRId64
"\n",
727 error
= ntfs_fget(ntmp
, ip
, attrtype
, attrname
, &fp
);
729 kprintf("ntfs_vget: ntfs_fget failed\n");
735 if (!(flags
& VG_DONTVALIDFN
) && !(fp
->f_flag
& FN_VALID
)) {
736 if ((ip
->i_frflag
& NTFS_FRFLAG_DIR
) &&
737 (fp
->f_attrtype
== NTFS_A_DATA
&& fp
->f_attrname
== NULL
)) {
739 } else if (flags
& VG_EXT
) {
741 fp
->f_size
= fp
->f_allocated
= 0;
745 error
= ntfs_filesize(ntmp
, fp
,
746 &fp
->f_size
, &fp
->f_allocated
);
753 fp
->f_flag
|= FN_VALID
;
757 VGET(FTOV(fp
), lkflags
);
763 error
= getnewvnode(VT_NTFS
, ntmp
->ntm_mountp
, &vp
, VLKTIMEOUT
, 0);
769 dprintf(("ntfs_vget: vnode: %p for ntnode: %ju\n", vp
, (uintmax_t)ino
));
775 if (ino
== NTFS_ROOTINO
)
776 vsetflags(vp
, VROOT
);
779 * Normal files use the buffer cache
782 vinitvmio(vp
, fp
->f_size
, PAGE_SIZE
, -1);
786 KKASSERT(lkflags
& LK_TYPE_MASK
);
787 /* XXX leave vnode locked exclusively from getnewvnode */
793 ntfs_vget(struct mount
*mp
, struct vnode
*dvp
, ino_t ino
, struct vnode
**vpp
)
795 return ntfs_vgetex(mp
, ino
, NTFS_A_DATA
, NULL
,
796 LK_EXCLUSIVE
| LK_RETRY
, 0, curthread
, vpp
);
799 static struct vfsops ntfs_vfsops
= {
800 .vfs_mount
= ntfs_mount
,
801 .vfs_unmount
= ntfs_unmount
,
802 .vfs_root
= ntfs_root
,
803 .vfs_statfs
= ntfs_statfs
,
804 .vfs_statvfs
= ntfs_statvfs
,
805 .vfs_vget
= ntfs_vget
,
806 .vfs_fhtovp
= ntfs_fhtovp
,
807 .vfs_checkexp
= ntfs_checkexp
,
808 .vfs_vptofh
= ntfs_vptofh
,
809 .vfs_init
= ntfs_init
,
810 .vfs_uninit
= ntfs_nthash_uninit
/* see ntfs_ihash.c */
812 VFS_SET(ntfs_vfsops
, ntfs
, 0);
813 MODULE_VERSION(ntfs
, 1);