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 $
29 * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.47 2008/01/05 14:02:41 swildner Exp $
33 #include <sys/param.h>
34 #include <sys/systm.h>
37 #include <sys/nlookup.h>
38 #include <sys/kernel.h>
39 #include <sys/vnode.h>
40 #include <sys/mount.h>
42 #include <sys/fcntl.h>
43 #include <sys/malloc.h>
44 #include <sys/systm.h>
45 #if defined(__NetBSD__)
46 #include <sys/device.h>
49 #include <machine/inttypes.h>
52 #include <vm/vm_param.h>
53 #if defined(__NetBSD__)
54 #include <vm/vm_prot.h>
56 #include <vm/vm_page.h>
57 #include <vm/vm_object.h>
58 #include <vm/vm_extern.h>
59 #include <vm/vm_zone.h>
61 #if defined(__NetBSD__)
62 #include <miscfs/specfs/specdev.h>
65 /*#define NTFS_DEBUG 1*/
67 #include "ntfs_inode.h"
68 #include "ntfs_subr.h"
69 #include "ntfs_vfsops.h"
70 #include "ntfs_ihash.h"
71 #include "ntfsmount.h"
73 extern struct vop_ops ntfs_vnode_vops
;
75 #if defined(__DragonFly__)
76 MALLOC_DEFINE(M_NTFSMNT
, "NTFS mount", "NTFS mount structure");
77 MALLOC_DEFINE(M_NTFSNTNODE
,"NTFS ntnode", "NTFS ntnode information");
78 MALLOC_DEFINE(M_NTFSFNODE
,"NTFS fnode", "NTFS fnode information");
79 MALLOC_DEFINE(M_NTFSDIR
,"NTFS dir", "NTFS dir buffer");
82 static int ntfs_root (struct mount
*, struct vnode
**);
83 static int ntfs_statfs (struct mount
*, struct statfs
*, struct ucred
*cred
);
84 static int ntfs_unmount (struct mount
*, int);
85 static int ntfs_vget (struct mount
*mp
, ino_t ino
, struct vnode
**vpp
);
86 static int ntfs_mountfs (struct vnode
*, struct mount
*,
87 struct ntfs_args
*, struct ucred
*);
88 static int ntfs_vptofh (struct vnode
*, struct fid
*);
89 static int ntfs_fhtovp (struct mount
*, struct fid
*,
92 #if !defined (__DragonFly__)
93 static int ntfs_quotactl (struct mount
*, int, uid_t
, caddr_t
,
95 static int ntfs_start (struct mount
*, int, struct thread
*);
96 static int ntfs_sync (struct mount
*, int, struct ucred
*,
100 #if defined(__DragonFly__)
102 static int ntfs_mount (struct mount
*, char *, caddr_t
, struct ucred
*);
103 static int ntfs_init (struct vfsconf
*);
104 static int ntfs_checkexp (struct mount
*, struct sockaddr
*,
105 int *, struct ucred
**);
106 #elif defined(__NetBSD__)
107 static int ntfs_mount (struct mount
*, const char *, void *,
108 struct nameidata
*, struct thread
*);
109 static void ntfs_init (void);
110 static int ntfs_mountroot (void);
111 static int ntfs_sysctl (int *, u_int
, void *, size_t *, void *,
112 size_t, struct thread
*);
113 static int ntfs_checkexp (struct mount
*, struct mbuf
*,
114 int *, struct ucred
**);
118 * Verify a remote client has export rights and return these rights via.
119 * exflagsp and credanonp.
122 ntfs_checkexp(struct mount
*mp
,
123 #if defined(__DragonFly__)
124 struct sockaddr
*nam
,
125 #else /* defined(__NetBSD__) */
128 int *exflagsp
, struct ucred
**credanonp
)
131 struct ntfsmount
*ntm
= VFSTONTFS(mp
);
134 * Get the export permission structure for this <mp, client> tuple.
136 np
= vfs_export_lookup(mp
, &ntm
->ntm_export
, nam
);
140 *exflagsp
= np
->netc_exflags
;
141 *credanonp
= &np
->netc_anon
;
145 #if defined(__NetBSD__)
148 ntfs_sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
,
149 size_t newlen
, struct thread
*td
)
158 struct vnode
*rootvp
;
159 struct thread
*td
= curthread
; /* XXX */
160 struct ntfs_args args
;
164 if (root_device
->dv_class
!= DV_DISK
)
168 * Get vnodes for rootdev.
170 if (bdevvp(rootdev
, &rootvp
))
171 panic("ntfs_mountroot: can't setup rootvp");
173 if ((error
= vfs_rootmountalloc(MOUNT_NTFS
, "root_device", &mp
))) {
183 if ((error
= ntfs_mountfs(rootvp
, mp
, &args
, proc0
.p_ucred
)) != 0) {
184 mp
->mnt_op
->vfs_refcount
--;
190 mountlist_insert(mp
, MNTINS_LAST
);
191 (void)ntfs_statfs(mp
, &mp
->mnt_stat
, proc0
.p_ucred
);
203 #elif defined(__DragonFly__)
206 ntfs_init(struct vfsconf
*vcp
)
216 ntfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
221 struct ntfs_args args
;
222 struct nlookupdata nd
;
223 struct vnode
*rootvp
;
228 * Use NULL path to flag a root mount
233 * Mounting root file system
237 /* Get vnode for root device*/
238 if( bdevvp( rootdev
, &rootvp
))
239 panic("ffs_mountroot: can't setup bdevvp for root");
242 * FS specific handling
244 mp
->mnt_flag
|= MNT_RDONLY
; /* XXX globally applicable?*/
249 if( ( error
= ntfs_mountfs(rootvp
, mp
, &args
, cred
)) != 0) {
250 /* fs specific cleanup (if any)*/
254 goto dostatfs
; /* success*/
261 * Mounting non-root file system or updating a file system
265 /* copy in user arguments*/
266 error
= copyin(data
, (caddr_t
)&args
, sizeof (struct ntfs_args
));
268 goto error_1
; /* can't get arguments*/
271 * If updating, check whether changing from read-only to
272 * read/write; if there is no device name, that's all we do.
274 if (mp
->mnt_flag
& MNT_UPDATE
) {
275 /* if not updating name...*/
276 if (args
.fspec
== 0) {
278 * Process export requests. Jumping to "success"
279 * will return the vfs_export() error code.
281 struct ntfsmount
*ntm
= VFSTONTFS(mp
);
282 error
= vfs_export(mp
, &ntm
->ntm_export
, &args
.export
);
286 kprintf("ntfs_mount(): MNT_UPDATE not supported\n");
292 * Not an update, or updating the name: look up the name
293 * and verify that it refers to a sensible block device.
296 error
= nlookup_init(&nd
, args
.fspec
, UIO_USERSPACE
, NLC_FOLLOW
);
298 error
= nlookup(&nd
);
300 error
= cache_vref(&nd
.nl_nch
, nd
.nl_cred
, &devvp
);
305 #if defined(__DragonFly__)
306 if (!vn_isdisk(devvp
, &error
))
309 if (devvp
->v_type
!= VBLK
) {
313 if (devvp
->v_umajor
>= nblkdev
) {
318 if (mp
->mnt_flag
& MNT_UPDATE
) {
326 if (devvp
!= ntmp
->um_devvp
)
327 error
= EINVAL
; /* needs translation */
331 * Update device name only on success
334 /* Save "mounted from" info for mount point (NULL pad)*/
335 copyinstr( args
.fspec
,
336 mp
->mnt_stat
.f_mntfromname
,
339 bzero( mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
349 /* Save "mounted from" info for mount point (NULL pad)*/
350 copyinstr( args
.fspec
, /* device name*/
351 mp
->mnt_stat
.f_mntfromname
, /* save area*/
352 MNAMELEN
- 1, /* max size*/
353 &size
); /* real size*/
354 bzero( mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
356 error
= ntfs_mountfs(devvp
, mp
, &args
, cred
);
366 * Initialize FS stat information in mount struct; uses
367 * mp->mnt_stat.f_mntfromname.
369 * This code is common to root and non-root mounts
371 (void)VFS_STATFS(mp
, &mp
->mnt_stat
, cred
);
376 error_2
: /* error with devvp held*/
378 /* release devvp before failing*/
381 error_1
: /* no state to back out*/
388 * Common code for mount and mountroot
391 ntfs_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct ntfs_args
*argsp
,
395 struct ntfsmount
*ntmp
;
397 int error
, ronly
, ncount
, i
;
401 * Disallow multiple mounts of the same device.
402 * Disallow mounting of a device that is currently in use
403 * (except for root, which might share swap device for miniroot).
404 * Flush out any old buffers remaining from a previous use.
406 error
= vfs_mountedon(devvp
);
409 ncount
= count_udev(devvp
->v_umajor
, devvp
->v_uminor
);
410 #if defined(__DragonFly__)
416 #if defined(__DragonFly__)
417 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
418 error
= vinvalbuf(devvp
, V_SAVE
, 0, 0);
419 VOP__UNLOCK(devvp
, 0);
421 error
= vinvalbuf(devvp
, V_SAVE
, 0, 0);
426 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
427 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
428 error
= VOP_OPEN(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, FSCRED
, NULL
);
429 VOP__UNLOCK(devvp
, 0);
436 error
= bread(devvp
, ntfs_bntodoff(BBLOCK
), BBSIZE
, &bp
);
439 ntmp
= kmalloc(sizeof *ntmp
, M_NTFSMNT
, M_WAITOK
| M_ZERO
);
440 bcopy( bp
->b_data
, &ntmp
->ntm_bootfile
, sizeof(struct bootfile
) );
444 if (strncmp(ntmp
->ntm_bootfile
.bf_sysid
, NTFS_BBID
, NTFS_BBIDLEN
)) {
446 dprintf(("ntfs_mountfs: invalid boot block\n"));
451 int8_t cpr
= ntmp
->ntm_mftrecsz
;
453 ntmp
->ntm_bpmftrec
= ntmp
->ntm_spc
* cpr
;
455 ntmp
->ntm_bpmftrec
= (1 << (-cpr
)) / ntmp
->ntm_bps
;
457 dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
458 ntmp
->ntm_bps
,ntmp
->ntm_spc
,ntmp
->ntm_bootfile
.bf_media
,
459 ntmp
->ntm_mftrecsz
,ntmp
->ntm_bpmftrec
));
460 dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
461 (u_int32_t
)ntmp
->ntm_mftcn
,(u_int32_t
)ntmp
->ntm_mftmirrcn
));
463 ntmp
->ntm_mountp
= mp
;
465 ntmp
->ntm_devvp
= devvp
;
466 ntmp
->ntm_uid
= argsp
->uid
;
467 ntmp
->ntm_gid
= argsp
->gid
;
468 ntmp
->ntm_mode
= argsp
->mode
;
469 ntmp
->ntm_flag
= argsp
->flag
;
471 /* Copy in the 8-bit to Unicode conversion table */
472 if (argsp
->flag
& NTFSMNT_U2WTABLE
) {
473 ntfs_82u_init(ntmp
, argsp
->u2w
);
475 ntfs_82u_init(ntmp
, NULL
);
478 /* Initialize Unicode to 8-bit table from 8toU table */
479 ntfs_u28_init(ntmp
, ntmp
->ntm_82u
);
481 mp
->mnt_data
= (qaddr_t
)ntmp
;
483 dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
484 (ntmp
->ntm_flag
& NTFS_MFLAG_CASEINS
)?"insens.":"sens.",
485 (ntmp
->ntm_flag
& NTFS_MFLAG_ALLNAMES
)?" allnames,":"",
486 ntmp
->ntm_uid
, ntmp
->ntm_gid
, ntmp
->ntm_mode
));
488 vfs_add_vnodeops(mp
, &ntfs_vnode_vops
, &mp
->mnt_vn_norm_ops
);
491 * We read in some system nodes to do not allow
492 * reclaim them and to have everytime access to them.
495 int pi
[3] = { NTFS_MFTINO
, NTFS_ROOTINO
, NTFS_BITMAPINO
};
496 for (i
=0; i
<3; i
++) {
497 error
= VFS_VGET(mp
, pi
[i
], &(ntmp
->ntm_sysvn
[pi
[i
]]));
500 ntmp
->ntm_sysvn
[pi
[i
]]->v_flag
|= VSYSTEM
;
501 vref(ntmp
->ntm_sysvn
[pi
[i
]]);
502 vput(ntmp
->ntm_sysvn
[pi
[i
]]);
506 /* read the Unicode lowercase --> uppercase translation table,
508 if ((error
= ntfs_toupper_use(mp
, ntmp
)))
512 * Scan $BitMap and count free clusters
514 error
= ntfs_calccfree(ntmp
, &ntmp
->ntm_cfree
);
519 * Read and translate to internal format attribute
527 error
= VFS_VGET(mp
, NTFS_ATTRDEFINO
, &vp
);
531 /* Count valid entries */
533 error
= ntfs_readattr(ntmp
, VTONT(vp
),
535 num
* sizeof(ad
), sizeof(ad
),
539 if (ad
.ad_name
[0] == 0)
543 /* Alloc memory for attribute definitions */
544 MALLOC(ntmp
->ntm_ad
, struct ntvattrdef
*,
545 num
* sizeof(struct ntvattrdef
),
546 M_NTFSMNT
, M_WAITOK
);
548 ntmp
->ntm_adnum
= num
;
550 /* Read them and translate */
552 error
= ntfs_readattr(ntmp
, VTONT(vp
),
554 i
* sizeof(ad
), sizeof(ad
),
560 ntmp
->ntm_ad
[i
].ad_name
[j
] = ad
.ad_name
[j
];
561 } while(ad
.ad_name
[j
++]);
562 ntmp
->ntm_ad
[i
].ad_namelen
= j
- 1;
563 ntmp
->ntm_ad
[i
].ad_type
= ad
.ad_type
;
569 #if defined(__DragonFly__)
570 mp
->mnt_stat
.f_fsid
.val
[0] = dev2udev(dev
);
571 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
573 mp
->mnt_stat
.f_fsid
.val
[0] = dev
;
574 mp
->mnt_stat
.f_fsid
.val
[1] = makefstype(MOUNT_NTFS
);
576 mp
->mnt_maxsymlinklen
= 0;
577 mp
->mnt_flag
|= MNT_LOCAL
;
578 dev
->si_mountpoint
= mp
;
583 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
584 if(ntmp
->ntm_sysvn
[i
]) vrele(ntmp
->ntm_sysvn
[i
]);
586 if (vflush(mp
, 0, 0))
587 dprintf(("ntfs_mountfs: vflush failed\n"));
590 dev
->si_mountpoint
= NULL
;
594 #if defined __NetBSD__
595 /* lock the device vnode before calling VOP_CLOSE() */
596 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
597 (void)VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
598 VOP__UNLOCK(devvp
, 0);
600 (void)VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
606 #if !defined(__DragonFly__)
608 ntfs_start(struct mount
*mp
, int flags
, struct thread
*td
)
615 ntfs_unmount(struct mount
*mp
, int mntflags
)
617 struct ntfsmount
*ntmp
;
618 int error
, ronly
, flags
, i
;
620 dprintf(("ntfs_unmount: unmounting...\n"));
621 ntmp
= VFSTONTFS(mp
);
623 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
625 if(mntflags
& MNT_FORCE
)
628 dprintf(("ntfs_unmount: vflushing...\n"));
629 error
= vflush(mp
, 0, flags
| SKIPSYSTEM
);
631 kprintf("ntfs_unmount: vflush failed: %d\n",error
);
635 /* Check if only system vnodes are rest */
636 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
637 if((ntmp
->ntm_sysvn
[i
]) &&
638 (ntmp
->ntm_sysvn
[i
]->v_sysref
.refcnt
> 1)) return (EBUSY
);
640 /* Dereference all system vnodes */
641 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
642 if(ntmp
->ntm_sysvn
[i
]) vrele(ntmp
->ntm_sysvn
[i
]);
644 /* vflush system vnodes */
645 error
= vflush(mp
, 0, flags
);
647 kprintf("ntfs_unmount: vflush failed(sysnodes): %d\n",error
);
649 /* Check if the type of device node isn't VBAD before
650 * touching v_cdevinfo. If the device vnode is revoked, the
651 * field is NULL and touching it causes null pointer derefercence.
653 if (ntmp
->ntm_devvp
->v_type
!= VBAD
)
654 ntmp
->ntm_devvp
->v_rdev
->si_mountpoint
= NULL
;
656 vinvalbuf(ntmp
->ntm_devvp
, V_SAVE
, 0, 0);
658 error
= VOP_CLOSE(ntmp
->ntm_devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
660 vrele(ntmp
->ntm_devvp
);
662 /* free the toupper table, if this has been last mounted ntfs volume */
663 ntfs_toupper_unuse();
665 dprintf(("ntfs_umount: freeing memory...\n"));
666 ntfs_u28_uninit(ntmp
);
667 ntfs_82u_uninit(ntmp
);
668 mp
->mnt_data
= (qaddr_t
)0;
669 mp
->mnt_flag
&= ~MNT_LOCAL
;
670 FREE(ntmp
->ntm_ad
, M_NTFSMNT
);
671 FREE(ntmp
, M_NTFSMNT
);
676 ntfs_root(struct mount
*mp
, struct vnode
**vpp
)
681 dprintf(("ntfs_root(): sysvn: %p\n",
682 VFSTONTFS(mp
)->ntm_sysvn
[NTFS_ROOTINO
]));
683 error
= VFS_VGET(mp
, (ino_t
)NTFS_ROOTINO
, &nvp
);
685 kprintf("ntfs_root: VFS_VGET failed: %d\n",error
);
693 #if !defined(__DragonFly__)
695 ntfs_quotactl(struct mount
*mp
, int cmds
, uid_t uid
, caddr_t arg
,
698 kprintf("\nntfs_quotactl():\n");
704 ntfs_calccfree(struct ntfsmount
*ntmp
, cn_t
*cfreep
)
712 vp
= ntmp
->ntm_sysvn
[NTFS_BITMAPINO
];
714 bmsize
= VTOF(vp
)->f_size
;
716 MALLOC(tmp
, u_int8_t
*, bmsize
, M_TEMP
, M_WAITOK
);
718 error
= ntfs_readattr(ntmp
, VTONT(vp
), NTFS_A_DATA
, NULL
,
719 0, bmsize
, tmp
, NULL
);
723 for(i
=0;i
<bmsize
;i
++)
725 if(~tmp
[i
] & (1 << j
)) cfree
++;
734 ntfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
736 struct ntfsmount
*ntmp
= VFSTONTFS(mp
);
737 u_int64_t mftsize
,mftallocated
;
739 dprintf(("ntfs_statfs():\n"));
741 mftsize
= VTOF(ntmp
->ntm_sysvn
[NTFS_MFTINO
])->f_size
;
742 mftallocated
= VTOF(ntmp
->ntm_sysvn
[NTFS_MFTINO
])->f_allocated
;
744 #if defined(__DragonFly__)
745 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
746 #elif defined(__NetBSD__)
749 sbp
->f_type
= MOUNT_NTFS
;
751 sbp
->f_bsize
= ntmp
->ntm_bps
;
752 sbp
->f_iosize
= ntmp
->ntm_bps
* ntmp
->ntm_spc
;
753 sbp
->f_blocks
= ntmp
->ntm_bootfile
.bf_spv
;
754 sbp
->f_bfree
= sbp
->f_bavail
= ntfs_cntobn(ntmp
->ntm_cfree
);
755 sbp
->f_ffree
= sbp
->f_bfree
/ ntmp
->ntm_bpmftrec
;
756 sbp
->f_files
= mftallocated
/ ntfs_bntob(ntmp
->ntm_bpmftrec
) +
758 if (sbp
!= &mp
->mnt_stat
) {
759 bcopy((caddr_t
)mp
->mnt_stat
.f_mntfromname
,
760 (caddr_t
)&sbp
->f_mntfromname
[0], MNAMELEN
);
762 sbp
->f_flags
= mp
->mnt_flag
;
764 strncpy(sbp
->f_fstypename
, mp
->mnt_op
->vfs_name
, MFSNAMELEN
);
770 #if !defined(__DragonFly__)
772 ntfs_sync(struct mount
*mp
, int waitfor
, struct ucred
*cred
, struct thread
*td
)
774 /*dprintf(("ntfs_sync():\n"));*/
781 ntfs_fhtovp(struct mount
*mp
, struct fid
*fhp
, struct vnode
**vpp
)
784 struct ntfid
*ntfhp
= (struct ntfid
*)fhp
;
787 ddprintf(("ntfs_fhtovp(): %d\n", ntfhp
->ntfid_ino
));
789 if ((error
= VFS_VGET(mp
, ntfhp
->ntfid_ino
, &nvp
)) != 0) {
793 /* XXX as unlink/rmdir/mkdir/creat are not currently possible
794 * with NTFS, we don't need to check anything else for now */
801 ntfs_vptofh(struct vnode
*vp
, struct fid
*fhp
)
806 ddprintf(("ntfs_fhtovp(): %p\n", vp
));
809 ntfhp
= (struct ntfid
*)fhp
;
810 ntfhp
->ntfid_len
= sizeof(struct ntfid
);
811 ntfhp
->ntfid_ino
= ntp
->i_number
;
812 /* ntfhp->ntfid_gen = ntp->i_gen; */
817 ntfs_vgetex(struct mount
*mp
, ino_t ino
, u_int32_t attrtype
, char *attrname
,
818 u_long lkflags
, u_long flags
, struct thread
*td
,
822 struct ntfsmount
*ntmp
;
828 dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
829 ino
, attrtype
, attrname
?attrname
:"", (u_long
)lkflags
,
832 ntmp
= VFSTONTFS(mp
);
836 error
= ntfs_ntlookup(ntmp
, ino
, &ip
);
838 kprintf("ntfs_vget: ntfs_ntget failed\n");
842 /* It may be not initialized fully, so force load it */
843 if (!(flags
& VG_DONTLOADIN
) && !(ip
->i_flag
& IN_LOADED
)) {
844 error
= ntfs_loadntnode(ntmp
, ip
);
846 kprintf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %"PRId64
"\n",
853 error
= ntfs_fget(ntmp
, ip
, attrtype
, attrname
, &fp
);
855 kprintf("ntfs_vget: ntfs_fget failed\n");
861 if (!(flags
& VG_DONTVALIDFN
) && !(fp
->f_flag
& FN_VALID
)) {
862 if ((ip
->i_frflag
& NTFS_FRFLAG_DIR
) &&
863 (fp
->f_attrtype
== NTFS_A_DATA
&& fp
->f_attrname
== NULL
)) {
865 } else if (flags
& VG_EXT
) {
867 fp
->f_size
= fp
->f_allocated
= 0;
871 error
= ntfs_filesize(ntmp
, fp
,
872 &fp
->f_size
, &fp
->f_allocated
);
879 fp
->f_flag
|= FN_VALID
;
883 VGET(FTOV(fp
), lkflags
);
889 error
= getnewvnode(VT_NTFS
, ntmp
->ntm_mountp
, &vp
, VLKTIMEOUT
, 0);
895 dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp
,ino
));
901 if (ino
== NTFS_ROOTINO
)
905 * Normal files use the buffer cache
908 vinitvmio(vp
, fp
->f_size
);
912 KKASSERT(lkflags
& LK_TYPE_MASK
);
913 /* XXX leave vnode locked exclusively from getnewvnode */
920 ntfs_vget(struct mount
*mp
, ino_t ino
, struct vnode
**vpp
)
922 return ntfs_vgetex(mp
, ino
, NTFS_A_DATA
, NULL
,
923 LK_EXCLUSIVE
| LK_RETRY
, 0, curthread
, vpp
);
926 #if defined(__DragonFly__)
927 static struct vfsops ntfs_vfsops
= {
928 .vfs_mount
= ntfs_mount
,
929 .vfs_unmount
= ntfs_unmount
,
930 .vfs_root
= ntfs_root
,
931 .vfs_statfs
= ntfs_statfs
,
932 .vfs_sync
= vfs_stdsync
,
933 .vfs_vget
= ntfs_vget
,
934 .vfs_fhtovp
= ntfs_fhtovp
,
935 .vfs_checkexp
= ntfs_checkexp
,
936 .vfs_vptofh
= ntfs_vptofh
,
937 .vfs_init
= ntfs_init
,
938 .vfs_uninit
= ntfs_nthash_uninit
/* see ntfs_ihash.c */
940 VFS_SET(ntfs_vfsops
, ntfs
, 0);
941 #elif defined(__NetBSD__)
942 extern struct vnodeopv_desc ntfs_vnodeop_opv_desc
;
944 struct vnodeopv_desc
*ntfs_vnodeopv_descs
[] = {
945 &ntfs_vnodeop_opv_desc
,
949 struct vfsops ntfs_vfsops
= {
967 #else /* !NetBSD && !FreeBSD */
968 static struct vfsops ntfs_vfsops
= {
981 VFS_SET(ntfs_vfsops
, ntfs
, MOUNT_NTFS
, 0);