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 #include <sys/systm.h>
44 #if defined(__NetBSD__)
45 #include <sys/device.h>
48 #include <machine/inttypes.h>
51 #include <vm/vm_param.h>
52 #if defined(__NetBSD__)
53 #include <vm/vm_prot.h>
55 #include <vm/vm_page.h>
56 #include <vm/vm_object.h>
57 #include <vm/vm_extern.h>
58 #include <vm/vm_zone.h>
60 #if defined(__NetBSD__)
61 #include <miscfs/specfs/specdev.h>
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 struct iconv_functions
*ntfs_iconv
= NULL
;
84 static int ntfs_root (struct mount
*, struct vnode
**);
85 static int ntfs_statfs (struct mount
*, struct statfs
*, struct ucred
*cred
);
86 static int ntfs_unmount (struct mount
*, int);
87 static int ntfs_vget (struct mount
*mp
, struct vnode
*dvp
,
88 ino_t ino
, struct vnode
**vpp
);
89 static int ntfs_mountfs (struct vnode
*, struct mount
*,
90 struct ntfs_args
*, struct ucred
*);
91 static int ntfs_vptofh (struct vnode
*, struct fid
*);
92 static int ntfs_fhtovp (struct mount
*, struct vnode
*rootvp
,
93 struct fid
*, struct vnode
**);
95 #if !defined (__DragonFly__)
96 static int ntfs_quotactl (struct mount
*, int, uid_t
, caddr_t
,
98 static int ntfs_start (struct mount
*, int, struct thread
*);
99 static int ntfs_sync (struct mount
*, int, struct ucred
*,
103 #if defined(__DragonFly__)
105 static int ntfs_mount (struct mount
*, char *, caddr_t
, struct ucred
*);
106 static int ntfs_init (struct vfsconf
*);
107 static int ntfs_checkexp (struct mount
*, struct sockaddr
*,
108 int *, struct ucred
**);
109 #elif defined(__NetBSD__)
110 static int ntfs_mount (struct mount
*, const char *, void *,
111 struct nameidata
*, struct thread
*);
112 static void ntfs_init (void);
113 static int ntfs_mountroot (void);
114 static int ntfs_sysctl (int *, u_int
, void *, size_t *, void *,
115 size_t, struct thread
*);
116 static int ntfs_checkexp (struct mount
*, struct mbuf
*,
117 int *, struct ucred
**);
121 * Verify a remote client has export rights and return these rights via.
122 * exflagsp and credanonp.
125 ntfs_checkexp(struct mount
*mp
,
126 #if defined(__DragonFly__)
127 struct sockaddr
*nam
,
128 #else /* defined(__NetBSD__) */
131 int *exflagsp
, struct ucred
**credanonp
)
134 struct ntfsmount
*ntm
= VFSTONTFS(mp
);
137 * Get the export permission structure for this <mp, client> tuple.
139 np
= vfs_export_lookup(mp
, &ntm
->ntm_export
, nam
);
143 *exflagsp
= np
->netc_exflags
;
144 *credanonp
= &np
->netc_anon
;
148 #if defined(__NetBSD__)
151 ntfs_sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
,
152 size_t newlen
, struct thread
*td
)
161 struct vnode
*rootvp
;
162 struct thread
*td
= curthread
; /* XXX */
163 struct ntfs_args args
;
166 if (root_device
->dv_class
!= DV_DISK
)
170 * Get vnodes for rootdev.
172 if (bdevvp(rootdev
, &rootvp
))
173 panic("ntfs_mountroot: can't setup rootvp");
175 if ((error
= vfs_rootmountalloc(MOUNT_NTFS
, "root_device", &mp
))) {
185 if ((error
= ntfs_mountfs(rootvp
, mp
, &args
, proc0
.p_ucred
)) != 0) {
186 mp
->mnt_op
->vfs_refcount
--;
192 mountlist_insert(mp
, MNTINS_LAST
);
193 (void)ntfs_statfs(mp
, &mp
->mnt_stat
, proc0
.p_ucred
);
205 #elif defined(__DragonFly__)
208 ntfs_init(struct vfsconf
*vcp
)
218 ntfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
223 struct ntfs_args args
;
224 struct nlookupdata nd
;
225 struct vnode
*rootvp
;
230 * Use NULL path to flag a root mount
235 * Mounting root file system
239 /* Get vnode for root device*/
240 if( bdevvp( rootdev
, &rootvp
))
241 panic("ffs_mountroot: can't setup bdevvp for root");
244 * FS specific handling
246 mp
->mnt_flag
|= MNT_RDONLY
; /* XXX globally applicable?*/
251 if( ( error
= ntfs_mountfs(rootvp
, mp
, &args
, cred
)) != 0) {
252 /* fs specific cleanup (if any)*/
256 goto dostatfs
; /* success*/
263 * Mounting non-root file system or updating a file system
267 /* copy in user arguments*/
268 error
= copyin(data
, (caddr_t
)&args
, sizeof (struct ntfs_args
));
270 goto error_1
; /* can't get arguments*/
273 * If updating, check whether changing from read-only to
274 * read/write; if there is no device name, that's all we do.
276 if (mp
->mnt_flag
& MNT_UPDATE
) {
277 /* if not updating name...*/
278 if (args
.fspec
== 0) {
280 * Process export requests. Jumping to "success"
281 * will return the vfs_export() error code.
283 struct ntfsmount
*ntm
= VFSTONTFS(mp
);
284 error
= vfs_export(mp
, &ntm
->ntm_export
, &args
.export
);
288 kprintf("ntfs_mount(): MNT_UPDATE not supported\n");
294 * Not an update, or updating the name: look up the name
295 * and verify that it refers to a sensible block device.
298 error
= nlookup_init(&nd
, args
.fspec
, UIO_USERSPACE
, NLC_FOLLOW
);
300 error
= nlookup(&nd
);
302 error
= cache_vref(&nd
.nl_nch
, nd
.nl_cred
, &devvp
);
307 #if defined(__DragonFly__)
308 if (!vn_isdisk(devvp
, &error
))
311 if (devvp
->v_type
!= VBLK
) {
315 if (devvp
->v_umajor
>= nblkdev
) {
320 if (mp
->mnt_flag
& MNT_UPDATE
) {
328 if (devvp
!= ntmp
->um_devvp
)
329 error
= EINVAL
; /* needs translation */
333 * Update device name only on success
336 /* Save "mounted from" info for mount point (NULL pad)*/
337 copyinstr( args
.fspec
,
338 mp
->mnt_stat
.f_mntfromname
,
341 bzero( mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
351 /* Save "mounted from" info for mount point (NULL pad)*/
352 copyinstr( args
.fspec
, /* device name*/
353 mp
->mnt_stat
.f_mntfromname
, /* save area*/
354 MNAMELEN
- 1, /* max size*/
355 &size
); /* real size*/
356 bzero( mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
358 error
= ntfs_mountfs(devvp
, mp
, &args
, cred
);
368 * Initialize FS stat information in mount struct; uses
369 * mp->mnt_stat.f_mntfromname.
371 * This code is common to root and non-root mounts
373 (void)VFS_STATFS(mp
, &mp
->mnt_stat
, cred
);
378 error_2
: /* error with devvp held*/
380 /* release devvp before failing*/
383 error_1
: /* no state to back out*/
390 * Common code for mount and mountroot
393 ntfs_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct ntfs_args
*argsp
,
397 struct ntfsmount
*ntmp
;
399 int error
, ronly
, ncount
, i
;
401 char cs_local
[ICONV_CSNMAXLEN
];
402 char cs_ntfs
[ICONV_CSNMAXLEN
];
405 * Disallow multiple mounts of the same device.
406 * Disallow mounting of a device that is currently in use
407 * (except for root, which might share swap device for miniroot).
408 * Flush out any old buffers remaining from a previous use.
410 error
= vfs_mountedon(devvp
);
413 ncount
= vcount(devvp
);
414 #if defined(__DragonFly__)
420 #if defined(__DragonFly__)
421 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
422 error
= vinvalbuf(devvp
, V_SAVE
, 0, 0);
423 VOP__UNLOCK(devvp
, 0);
425 error
= vinvalbuf(devvp
, V_SAVE
, 0, 0);
430 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
431 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
432 error
= VOP_OPEN(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, FSCRED
, NULL
);
433 VOP__UNLOCK(devvp
, 0);
440 error
= bread(devvp
, BBLOCK
, BBSIZE
, &bp
);
443 ntmp
= kmalloc(sizeof *ntmp
, M_NTFSMNT
, M_WAITOK
| M_ZERO
);
444 bcopy( bp
->b_data
, &ntmp
->ntm_bootfile
, sizeof(struct bootfile
) );
448 if (strncmp(ntmp
->ntm_bootfile
.bf_sysid
, NTFS_BBID
, NTFS_BBIDLEN
)) {
450 dprintf(("ntfs_mountfs: invalid boot block\n"));
455 int8_t cpr
= ntmp
->ntm_mftrecsz
;
457 ntmp
->ntm_bpmftrec
= ntmp
->ntm_spc
* cpr
;
459 ntmp
->ntm_bpmftrec
= (1 << (-cpr
)) / ntmp
->ntm_bps
;
461 dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
462 ntmp
->ntm_bps
,ntmp
->ntm_spc
,ntmp
->ntm_bootfile
.bf_media
,
463 ntmp
->ntm_mftrecsz
,ntmp
->ntm_bpmftrec
));
464 dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
465 (u_int32_t
)ntmp
->ntm_mftcn
,(u_int32_t
)ntmp
->ntm_mftmirrcn
));
467 ntmp
->ntm_mountp
= mp
;
469 ntmp
->ntm_devvp
= devvp
;
470 ntmp
->ntm_uid
= argsp
->uid
;
471 ntmp
->ntm_gid
= argsp
->gid
;
472 ntmp
->ntm_mode
= argsp
->mode
;
473 ntmp
->ntm_flag
= argsp
->flag
;
475 if (argsp
->flag
& NTFS_MFLAG_KICONV
&& ntfs_iconv
) {
476 bcopy(argsp
->cs_local
, cs_local
, sizeof(cs_local
));
477 bcopy(argsp
->cs_ntfs
, cs_ntfs
, sizeof(cs_ntfs
));
478 ntfs_82u_init(ntmp
, cs_local
, cs_ntfs
);
479 ntfs_u28_init(ntmp
, NULL
, cs_local
, cs_ntfs
);
481 ntfs_82u_init(ntmp
, NULL
, NULL
);
482 ntfs_u28_init(ntmp
, ntmp
->ntm_82u
, NULL
, NULL
);
485 mp
->mnt_data
= (qaddr_t
)ntmp
;
487 dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
488 (ntmp
->ntm_flag
& NTFS_MFLAG_CASEINS
)?"insens.":"sens.",
489 (ntmp
->ntm_flag
& NTFS_MFLAG_ALLNAMES
)?" allnames,":"",
490 ntmp
->ntm_uid
, ntmp
->ntm_gid
, ntmp
->ntm_mode
));
492 vfs_add_vnodeops(mp
, &ntfs_vnode_vops
, &mp
->mnt_vn_norm_ops
);
495 * We read in some system nodes to do not allow
496 * reclaim them and to have everytime access to them.
499 int pi
[3] = { NTFS_MFTINO
, NTFS_ROOTINO
, NTFS_BITMAPINO
};
500 for (i
=0; i
<3; i
++) {
501 error
= VFS_VGET(mp
, NULL
,
502 pi
[i
], &(ntmp
->ntm_sysvn
[pi
[i
]]));
505 vsetflags(ntmp
->ntm_sysvn
[pi
[i
]], VSYSTEM
);
506 vref(ntmp
->ntm_sysvn
[pi
[i
]]);
507 vput(ntmp
->ntm_sysvn
[pi
[i
]]);
511 /* read the Unicode lowercase --> uppercase translation table,
513 if ((error
= ntfs_toupper_use(mp
, ntmp
)))
517 * Scan $BitMap and count free clusters
519 error
= ntfs_calccfree(ntmp
, &ntmp
->ntm_cfree
);
524 * Read and translate to internal format attribute
532 error
= VFS_VGET(mp
, NULL
, NTFS_ATTRDEFINO
, &vp
);
536 /* Count valid entries */
538 error
= ntfs_readattr(ntmp
, VTONT(vp
),
540 num
* sizeof(ad
), sizeof(ad
),
544 if (ad
.ad_name
[0] == 0)
548 /* Alloc memory for attribute definitions */
549 ntmp
->ntm_ad
= kmalloc(num
* sizeof(struct ntvattrdef
),
550 M_NTFSMNT
, M_WAITOK
);
552 ntmp
->ntm_adnum
= num
;
554 /* Read them and translate */
556 error
= ntfs_readattr(ntmp
, VTONT(vp
),
558 i
* sizeof(ad
), sizeof(ad
),
564 ntmp
->ntm_ad
[i
].ad_name
[j
] = ad
.ad_name
[j
];
565 } while(ad
.ad_name
[j
++]);
566 ntmp
->ntm_ad
[i
].ad_namelen
= j
- 1;
567 ntmp
->ntm_ad
[i
].ad_type
= ad
.ad_type
;
573 #if defined(__DragonFly__)
574 mp
->mnt_stat
.f_fsid
.val
[0] = dev2udev(dev
);
575 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
577 mp
->mnt_stat
.f_fsid
.val
[0] = dev
;
578 mp
->mnt_stat
.f_fsid
.val
[1] = makefstype(MOUNT_NTFS
);
580 mp
->mnt_maxsymlinklen
= 0;
581 mp
->mnt_flag
|= MNT_LOCAL
;
582 dev
->si_mountpoint
= mp
;
587 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
588 if(ntmp
->ntm_sysvn
[i
]) vrele(ntmp
->ntm_sysvn
[i
]);
590 if (vflush(mp
, 0, 0))
591 dprintf(("ntfs_mountfs: vflush failed\n"));
594 dev
->si_mountpoint
= NULL
;
598 #if defined __NetBSD__
599 /* lock the device vnode before calling VOP_CLOSE() */
600 VN_LOCK(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
601 (void)VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
602 VOP__UNLOCK(devvp
, 0);
604 (void)VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
610 #if !defined(__DragonFly__)
612 ntfs_start(struct mount
*mp
, int flags
, struct thread
*td
)
619 ntfs_unmount(struct mount
*mp
, int mntflags
)
621 struct ntfsmount
*ntmp
;
622 int error
, ronly
, flags
, i
;
624 dprintf(("ntfs_unmount: unmounting...\n"));
625 ntmp
= VFSTONTFS(mp
);
627 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
629 if(mntflags
& MNT_FORCE
)
632 dprintf(("ntfs_unmount: vflushing...\n"));
633 error
= vflush(mp
, 0, flags
| SKIPSYSTEM
);
635 kprintf("ntfs_unmount: vflush failed: %d\n",error
);
639 /* Check if only system vnodes are left */
640 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
641 if((ntmp
->ntm_sysvn
[i
]) &&
642 (ntmp
->ntm_sysvn
[i
]->v_sysref
.refcnt
> 1)) return (EBUSY
);
644 /* Dereference all system vnodes */
645 for(i
=0;i
<NTFS_SYSNODESNUM
;i
++)
646 if(ntmp
->ntm_sysvn
[i
]) vrele(ntmp
->ntm_sysvn
[i
]);
648 /* vflush system vnodes */
649 error
= vflush(mp
, 0, flags
);
651 kprintf("ntfs_unmount: vflush failed(sysnodes): %d\n",error
);
653 /* Check if the type of device node isn't VBAD before
654 * touching v_cdevinfo. If the device vnode is revoked, the
655 * field is NULL and touching it causes null pointer derefercence.
657 if (ntmp
->ntm_devvp
->v_type
!= VBAD
)
658 ntmp
->ntm_devvp
->v_rdev
->si_mountpoint
= NULL
;
660 vinvalbuf(ntmp
->ntm_devvp
, V_SAVE
, 0, 0);
662 error
= VOP_CLOSE(ntmp
->ntm_devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
664 vrele(ntmp
->ntm_devvp
);
666 /* free the toupper table, if this has been last mounted ntfs volume */
667 ntfs_toupper_unuse();
669 dprintf(("ntfs_umount: freeing memory...\n"));
670 ntfs_u28_uninit(ntmp
);
671 ntfs_82u_uninit(ntmp
);
672 mp
->mnt_data
= (qaddr_t
)0;
673 mp
->mnt_flag
&= ~MNT_LOCAL
;
674 kfree(ntmp
->ntm_ad
, M_NTFSMNT
);
675 kfree(ntmp
, M_NTFSMNT
);
680 ntfs_root(struct mount
*mp
, struct vnode
**vpp
)
685 dprintf(("ntfs_root(): sysvn: %p\n",
686 VFSTONTFS(mp
)->ntm_sysvn
[NTFS_ROOTINO
]));
687 error
= VFS_VGET(mp
, NULL
, (ino_t
)NTFS_ROOTINO
, &nvp
);
689 kprintf("ntfs_root: VFS_VGET failed: %d\n",error
);
697 #if !defined(__DragonFly__)
699 ntfs_quotactl(struct mount
*mp
, int cmds
, uid_t uid
, caddr_t arg
,
702 kprintf("\nntfs_quotactl():\n");
708 ntfs_calccfree(struct ntfsmount
*ntmp
, cn_t
*cfreep
)
716 vp
= ntmp
->ntm_sysvn
[NTFS_BITMAPINO
];
718 bmsize
= VTOF(vp
)->f_size
;
720 tmp
= kmalloc(bmsize
, M_TEMP
, M_WAITOK
);
722 error
= ntfs_readattr(ntmp
, VTONT(vp
), NTFS_A_DATA
, NULL
,
723 0, bmsize
, tmp
, NULL
);
727 for(i
=0;i
<bmsize
;i
++)
729 if(~tmp
[i
] & (1 << j
)) cfree
++;
738 ntfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
740 struct ntfsmount
*ntmp
= VFSTONTFS(mp
);
741 u_int64_t mftsize
,mftallocated
;
743 dprintf(("ntfs_statfs():\n"));
745 mftsize
= VTOF(ntmp
->ntm_sysvn
[NTFS_MFTINO
])->f_size
;
746 mftallocated
= VTOF(ntmp
->ntm_sysvn
[NTFS_MFTINO
])->f_allocated
;
748 #if defined(__DragonFly__)
749 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
750 #elif defined(__NetBSD__)
753 sbp
->f_type
= MOUNT_NTFS
;
755 sbp
->f_bsize
= ntmp
->ntm_bps
;
756 sbp
->f_iosize
= ntmp
->ntm_bps
* ntmp
->ntm_spc
;
757 sbp
->f_blocks
= ntmp
->ntm_bootfile
.bf_spv
;
758 sbp
->f_bfree
= sbp
->f_bavail
= ntfs_cntobn(ntmp
->ntm_cfree
);
759 sbp
->f_ffree
= sbp
->f_bfree
/ ntmp
->ntm_bpmftrec
;
760 sbp
->f_files
= mftallocated
/ ntfs_bntob(ntmp
->ntm_bpmftrec
) +
762 if (sbp
!= &mp
->mnt_stat
) {
763 bcopy((caddr_t
)mp
->mnt_stat
.f_mntfromname
,
764 (caddr_t
)&sbp
->f_mntfromname
[0], MNAMELEN
);
766 sbp
->f_flags
= mp
->mnt_flag
;
768 strncpy(sbp
->f_fstypename
, mp
->mnt_op
->vfs_name
, MFSNAMELEN
);
774 #if !defined(__DragonFly__)
776 ntfs_sync(struct mount
*mp
, int waitfor
, struct ucred
*cred
, struct thread
*td
)
778 /*dprintf(("ntfs_sync():\n"));*/
785 ntfs_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
786 struct fid
*fhp
, struct vnode
**vpp
)
789 struct ntfid
*ntfhp
= (struct ntfid
*)fhp
;
792 ddprintf(("ntfs_fhtovp(): %d\n", ntfhp
->ntfid_ino
));
794 if ((error
= VFS_VGET(mp
, NULL
, ntfhp
->ntfid_ino
, &nvp
)) != 0) {
798 /* XXX as unlink/rmdir/mkdir/creat are not currently possible
799 * with NTFS, we don't need to check anything else for now */
806 ntfs_vptofh(struct vnode
*vp
, struct fid
*fhp
)
811 ddprintf(("ntfs_fhtovp(): %p\n", vp
));
814 ntfhp
= (struct ntfid
*)fhp
;
815 ntfhp
->ntfid_len
= sizeof(struct ntfid
);
816 ntfhp
->ntfid_ino
= ntp
->i_number
;
817 /* ntfhp->ntfid_gen = ntp->i_gen; */
822 ntfs_vgetex(struct mount
*mp
, ino_t ino
, u_int32_t attrtype
, char *attrname
,
823 u_long lkflags
, u_long flags
, struct thread
*td
,
827 struct ntfsmount
*ntmp
;
833 dprintf(("ntfs_vgetex: ino: %ju, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
834 (uintmax_t) ino
, attrtype
, attrname
?attrname
:"", lkflags
, flags
));
836 ntmp
= VFSTONTFS(mp
);
840 error
= ntfs_ntlookup(ntmp
, ino
, &ip
);
842 kprintf("ntfs_vget: ntfs_ntget failed\n");
846 /* It may be not initialized fully, so force load it */
847 if (!(flags
& VG_DONTLOADIN
) && !(ip
->i_flag
& IN_LOADED
)) {
848 error
= ntfs_loadntnode(ntmp
, ip
);
850 kprintf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %"PRId64
"\n",
857 error
= ntfs_fget(ntmp
, ip
, attrtype
, attrname
, &fp
);
859 kprintf("ntfs_vget: ntfs_fget failed\n");
865 if (!(flags
& VG_DONTVALIDFN
) && !(fp
->f_flag
& FN_VALID
)) {
866 if ((ip
->i_frflag
& NTFS_FRFLAG_DIR
) &&
867 (fp
->f_attrtype
== NTFS_A_DATA
&& fp
->f_attrname
== NULL
)) {
869 } else if (flags
& VG_EXT
) {
871 fp
->f_size
= fp
->f_allocated
= 0;
875 error
= ntfs_filesize(ntmp
, fp
,
876 &fp
->f_size
, &fp
->f_allocated
);
883 fp
->f_flag
|= FN_VALID
;
887 VGET(FTOV(fp
), lkflags
);
893 error
= getnewvnode(VT_NTFS
, ntmp
->ntm_mountp
, &vp
, VLKTIMEOUT
, 0);
899 dprintf(("ntfs_vget: vnode: %p for ntnode: %ju\n", vp
, (uintmax_t)ino
));
905 if (ino
== NTFS_ROOTINO
)
906 vsetflags(vp
, VROOT
);
909 * Normal files use the buffer cache
912 vinitvmio(vp
, fp
->f_size
, PAGE_SIZE
, -1);
916 KKASSERT(lkflags
& LK_TYPE_MASK
);
917 /* XXX leave vnode locked exclusively from getnewvnode */
924 ntfs_vget(struct mount
*mp
, struct vnode
*dvp
, ino_t ino
, struct vnode
**vpp
)
926 return ntfs_vgetex(mp
, ino
, NTFS_A_DATA
, NULL
,
927 LK_EXCLUSIVE
| LK_RETRY
, 0, curthread
, vpp
);
930 #if defined(__DragonFly__)
931 static struct vfsops ntfs_vfsops
= {
932 .vfs_mount
= ntfs_mount
,
933 .vfs_unmount
= ntfs_unmount
,
934 .vfs_root
= ntfs_root
,
935 .vfs_statfs
= ntfs_statfs
,
936 .vfs_sync
= vfs_stdsync
,
937 .vfs_vget
= ntfs_vget
,
938 .vfs_fhtovp
= ntfs_fhtovp
,
939 .vfs_checkexp
= ntfs_checkexp
,
940 .vfs_vptofh
= ntfs_vptofh
,
941 .vfs_init
= ntfs_init
,
942 .vfs_uninit
= ntfs_nthash_uninit
/* see ntfs_ihash.c */
944 VFS_SET(ntfs_vfsops
, ntfs
, 0);
945 MODULE_VERSION(ntfs
, 1);
946 #elif defined(__NetBSD__)
947 extern struct vnodeopv_desc ntfs_vnodeop_opv_desc
;
949 struct vnodeopv_desc
*ntfs_vnodeopv_descs
[] = {
950 &ntfs_vnodeop_opv_desc
,
954 struct vfsops ntfs_vfsops
= {
972 #else /* !NetBSD && !FreeBSD */
973 static struct vfsops ntfs_vfsops
= {
986 VFS_SET(ntfs_vfsops
, ntfs
, MOUNT_NTFS
, 0);