1 /* $NetBSD: ntfs_vfsops.c,v 1.23 1999/11/15 19:38:14 jdolecek Exp $ */
2
3 /*-
4 * Copyright (c) 1998, 1999 Semen Ustimenko
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
15 *
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
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: releng/5.0/sys/fs/ntfs/ntfs_vfsops.c 105077 2002-10-14 03:20:36Z mckusick $
29 */
30
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/namei.h>
35 #include <sys/conf.h>
36 #include <sys/proc.h>
37 #include <sys/kernel.h>
38 #include <sys/vnode.h>
39 #include <sys/mount.h>
40 #include <sys/bio.h>
41 #include <sys/buf.h>
42 #include <sys/fcntl.h>
43 #include <sys/malloc.h>
44 #include <sys/systm.h>
45
46 #include <vm/vm.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
52 /*#define NTFS_DEBUG 1*/
53 #include <fs/ntfs/ntfs.h>
54 #include <fs/ntfs/ntfs_inode.h>
55 #include <fs/ntfs/ntfs_subr.h>
56 #include <fs/ntfs/ntfs_vfsops.h>
57 #include <fs/ntfs/ntfs_ihash.h>
58 #include <fs/ntfs/ntfsmount.h>
59
60 MALLOC_DEFINE(M_NTFSMNT, "NTFS mount", "NTFS mount structure");
61 MALLOC_DEFINE(M_NTFSNTNODE,"NTFS ntnode", "NTFS ntnode information");
62 MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode", "NTFS fnode information");
63 MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer");
64
65 struct sockaddr;
66
67 static int ntfs_root(struct mount *, struct vnode **);
68 static int ntfs_statfs(struct mount *, struct statfs *, struct thread *);
69 static int ntfs_unmount(struct mount *, int, struct thread *);
70 static int ntfs_vget(struct mount *mp, ino_t ino, int lkflags,
71 struct vnode **vpp);
72 static int ntfs_mountfs(register struct vnode *, struct mount *,
73 struct ntfs_args *, struct thread *);
74 static int ntfs_vptofh(struct vnode *, struct fid *);
75 static int ntfs_fhtovp(struct mount *, struct fid *, struct vnode **);
76 static int ntfs_mount(struct mount *, char *, caddr_t,
77 struct nameidata *, struct thread *);
78 static int ntfs_init(struct vfsconf *);
79
80 static int
81 ntfs_init (
82 struct vfsconf *vcp )
83 {
84 ntfs_nthashinit();
85 ntfs_toupper_init();
86 return 0;
87 }
88
89 static int
90 ntfs_uninit (
91 struct vfsconf *vcp )
92 {
93 ntfs_toupper_destroy();
94 ntfs_nthashdestroy();
95 return 0;
96 }
97
98 static int
99 ntfs_mount (
100 struct mount *mp,
101 char *path,
102 caddr_t data,
103 struct nameidata *ndp,
104 struct thread *td )
105 {
106 size_t size;
107 int err = 0;
108 struct vnode *devvp;
109 struct ntfs_args args;
110
111 /*
112 * Use NULL path to flag a root mount
113 */
114 if( path == NULL) {
115 /*
116 ***
117 * Mounting root filesystem
118 ***
119 */
120
121 /* Get vnode for root device*/
122 if( bdevvp( rootdev, &rootvp))
123 panic("ntfs_mountroot: can't setup bdevvp for root");
124
125 /*
126 * FS specific handling
127 */
128 mp->mnt_flag |= MNT_RDONLY; /* XXX globally applicable?*/
129
130 /*
131 * Attempt mount
132 */
133 if( ( err = ntfs_mountfs(rootvp, mp, &args, td)) != 0) {
134 /* fs specific cleanup (if any)*/
135 goto error_1;
136 }
137
138 goto dostatfs; /* success*/
139
140 }
141
142 /*
143 ***
144 * Mounting non-root filesystem or updating a filesystem
145 ***
146 */
147
148 /* copy in user arguments*/
149 err = copyin(data, (caddr_t)&args, sizeof (struct ntfs_args));
150 if (err)
151 goto error_1; /* can't get arguments*/
152
153 /*
154 * If updating, check whether changing from read-only to
155 * read/write; if there is no device name, that's all we do.
156 */
157 if (mp->mnt_flag & MNT_UPDATE) {
158 /* if not updating name...*/
159 if (args.fspec == 0) {
160 /*
161 * Process export requests. Jumping to "success"
162 * will return the vfs_export() error code.
163 */
164 err = vfs_export(mp, &args.export);
165 goto success;
166 }
167
168 printf("ntfs_mount(): MNT_UPDATE not supported\n");
169 err = EINVAL;
170 goto error_1;
171 }
172
173 /*
174 * Not an update, or updating the name: look up the name
175 * and verify that it refers to a sensible block device.
176 */
177 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, td);
178 err = namei(ndp);
179 if (err) {
180 /* can't get devvp!*/
181 goto error_1;
182 }
183 NDFREE(ndp, NDF_ONLY_PNBUF);
184 devvp = ndp->ni_vp;
185
186 if (!vn_isdisk(devvp, &err))
187 goto error_2;
188 if (mp->mnt_flag & MNT_UPDATE) {
189 #if 0
190 /*
191 ********************
192 * UPDATE
193 ********************
194 */
195
196 if (devvp != ntmp->um_devvp)
197 err = EINVAL; /* needs translation */
198 else
199 vrele(devvp);
200 /*
201 * Update device name only on success
202 */
203 if( !err) {
204 /* Save "mounted from" info for mount point (NULL pad)*/
205 copyinstr( args.fspec,
206 mp->mnt_stat.f_mntfromname,
207 MNAMELEN - 1,
208 &size);
209 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
210 }
211 #endif
212 } else {
213 /*
214 ********************
215 * NEW MOUNT
216 ********************
217 */
218
219 /*
220 * Since this is a new mount, we want the names for
221 * the device and the mount point copied in. If an
222 * error occurs, the mountpoint is discarded by the
223 * upper level code. Note that vfs_mount() handles
224 * copying the mountpoint f_mntonname for us, so we
225 * don't have to do it here unless we want to set it
226 * to something other than "path" for some rason.
227 */
228 /* Save "mounted from" info for mount point (NULL pad)*/
229 copyinstr( args.fspec, /* device name*/
230 mp->mnt_stat.f_mntfromname, /* save area*/
231 MNAMELEN - 1, /* max size*/
232 &size); /* real size*/
233 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
234
235 err = ntfs_mountfs(devvp, mp, &args, td);
236 }
237 if (err) {
238 goto error_2;
239 }
240
241 dostatfs:
242 /*
243 * Initialize FS stat information in mount struct; uses both
244 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
245 *
246 * This code is common to root and non-root mounts
247 */
248 (void)VFS_STATFS(mp, &mp->mnt_stat, td);
249
250 goto success;
251
252
253 error_2: /* error with devvp held*/
254
255 /* release devvp before failing*/
256 vrele(devvp);
257
258 error_1: /* no state to back out*/
259
260 success:
261 return(err);
262 }
263
264 /*
265 * Common code for mount and mountroot
266 */
267 int
268 ntfs_mountfs(devvp, mp, argsp, td)
269 register struct vnode *devvp;
270 struct mount *mp;
271 struct ntfs_args *argsp;
272 struct thread *td;
273 {
274 struct buf *bp;
275 struct ntfsmount *ntmp;
276 dev_t dev = devvp->v_rdev;
277 int error, ronly, ncount, i;
278 struct vnode *vp;
279
280 /*
281 * Disallow multiple mounts of the same device.
282 * Disallow mounting of a device that is currently in use
283 * (except for root, which might share swap device for miniroot).
284 * Flush out any old buffers remaining from a previous use.
285 */
286 error = vfs_mountedon(devvp);
287 if (error)
288 return (error);
289 ncount = vcount(devvp);
290 if (devvp->v_object)
291 ncount -= 1;
292 if (ncount > 1 && devvp != rootvp)
293 return (EBUSY);
294 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
295 error = vinvalbuf(devvp, V_SAVE, td->td_ucred, td, 0, 0);
296 VOP_UNLOCK(devvp, 0, td);
297 if (error)
298 return (error);
299
300 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
301 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
302 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td);
303 VOP_UNLOCK(devvp, 0, td);
304 if (error)
305 return (error);
306
307 bp = NULL;
308
309 error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp);
310 if (error)
311 goto out;
312 ntmp = malloc( sizeof *ntmp, M_NTFSMNT, M_WAITOK | M_ZERO);
313 bcopy( bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile) );
314 brelse( bp );
315 bp = NULL;
316
317 if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
318 error = EINVAL;
319 dprintf(("ntfs_mountfs: invalid boot block\n"));
320 goto out;
321 }
322
323 {
324 int8_t cpr = ntmp->ntm_mftrecsz;
325 if( cpr > 0 )
326 ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
327 else
328 ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
329 }
330 dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
331 ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media,
332 ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec));
333 dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
334 (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn));
335
336 ntmp->ntm_mountp = mp;
337 ntmp->ntm_dev = dev;
338 ntmp->ntm_devvp = devvp;
339 ntmp->ntm_uid = argsp->uid;
340 ntmp->ntm_gid = argsp->gid;
341 ntmp->ntm_mode = argsp->mode;
342 ntmp->ntm_flag = argsp->flag;
343
344 /* Copy in the 8-bit to Unicode conversion table */
345 if (argsp->flag & NTFSMNT_U2WTABLE) {
346 ntfs_82u_init(ntmp, argsp->u2w);
347 } else {
348 ntfs_82u_init(ntmp, NULL);
349 }
350
351 /* Initialize Unicode to 8-bit table from 8toU table */
352 ntfs_u28_init(ntmp, ntmp->ntm_82u);
353
354 mp->mnt_data = (qaddr_t)ntmp;
355
356 dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
357 (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
358 (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
359 ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
360
361 /*
362 * We read in some system nodes to do not allow
363 * reclaim them and to have everytime access to them.
364 */
365 {
366 int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
367 for (i=0; i<3; i++) {
368 error = VFS_VGET(mp, pi[i], LK_EXCLUSIVE,
369 &(ntmp->ntm_sysvn[pi[i]]));
370 if(error)
371 goto out1;
372 ntmp->ntm_sysvn[pi[i]]->v_vflag |= VV_SYSTEM;
373 VREF(ntmp->ntm_sysvn[pi[i]]);
374 vput(ntmp->ntm_sysvn[pi[i]]);
375 }
376 }
377
378 /* read the Unicode lowercase --> uppercase translation table,
379 * if necessary */
380 if ((error = ntfs_toupper_use(mp, ntmp)))
381 goto out1;
382
383 /*
384 * Scan $BitMap and count free clusters
385 */
386 error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
387 if(error)
388 goto out1;
389
390 /*
391 * Read and translate to internal format attribute
392 * definition file.
393 */
394 {
395 int num,j;
396 struct attrdef ad;
397
398 /* Open $AttrDef */
399 error = VFS_VGET(mp, NTFS_ATTRDEFINO, LK_EXCLUSIVE, &vp );
400 if(error)
401 goto out1;
402
403 /* Count valid entries */
404 for(num=0;;num++) {
405 error = ntfs_readattr(ntmp, VTONT(vp),
406 NTFS_A_DATA, NULL,
407 num * sizeof(ad), sizeof(ad),
408 &ad, NULL);
409 if (error)
410 goto out1;
411 if (ad.ad_name[0] == 0)
412 break;
413 }
414
415 /* Alloc memory for attribute definitions */
416 MALLOC(ntmp->ntm_ad, struct ntvattrdef *,
417 num * sizeof(struct ntvattrdef),
418 M_NTFSMNT, M_WAITOK);
419
420 ntmp->ntm_adnum = num;
421
422 /* Read them and translate */
423 for(i=0;i<num;i++){
424 error = ntfs_readattr(ntmp, VTONT(vp),
425 NTFS_A_DATA, NULL,
426 i * sizeof(ad), sizeof(ad),
427 &ad, NULL);
428 if (error)
429 goto out1;
430 j = 0;
431 do {
432 ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
433 } while(ad.ad_name[j++]);
434 ntmp->ntm_ad[i].ad_namelen = j - 1;
435 ntmp->ntm_ad[i].ad_type = ad.ad_type;
436 }
437
438 vput(vp);
439 }
440
441 mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
442 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
443 mp->mnt_maxsymlinklen = 0;
444 mp->mnt_flag |= MNT_LOCAL;
445 devvp->v_rdev->si_mountpoint = mp;
446 return (0);
447
448 out1:
449 for(i=0;i<NTFS_SYSNODESNUM;i++)
450 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
451
452 if (vflush(mp, 0, 0))
453 dprintf(("ntfs_mountfs: vflush failed\n"));
454
455 out:
456 devvp->v_rdev->si_mountpoint = NULL;
457 if (bp)
458 brelse(bp);
459
460 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, td);
461
462 return (error);
463 }
464
465 static int
466 ntfs_unmount(
467 struct mount *mp,
468 int mntflags,
469 struct thread *td)
470 {
471 struct ntfsmount *ntmp;
472 int error, ronly, flags, i;
473
474 dprintf(("ntfs_unmount: unmounting...\n"));
475 ntmp = VFSTONTFS(mp);
476
477 flags = 0;
478 if(mntflags & MNT_FORCE)
479 flags |= FORCECLOSE;
480
481 dprintf(("ntfs_unmount: vflushing...\n"));
482 error = vflush(mp, 0, flags | SKIPSYSTEM);
483 if (error) {
484 printf("ntfs_unmount: vflush failed: %d\n",error);
485 return (error);
486 }
487
488 /* Check if only system vnodes are rest */
489 for(i=0;i<NTFS_SYSNODESNUM;i++)
490 if((ntmp->ntm_sysvn[i]) &&
491 (vrefcnt(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY);
492
493 /* Dereference all system vnodes */
494 for(i=0;i<NTFS_SYSNODESNUM;i++)
495 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
496
497 /* vflush system vnodes */
498 error = vflush(mp, 0, flags);
499 if (error)
500 printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
501
502 /* Check if the type of device node isn't VBAD before
503 * touching v_cdev. If the device vnode is revoked, the
504 * field is NULL and touching it causes null pointer derefercence.
505 */
506 if (ntmp->ntm_devvp->v_type != VBAD)
507 ntmp->ntm_devvp->v_rdev->si_mountpoint = NULL;
508
509 vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, td, 0, 0);
510
511 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
512 error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE,
513 NOCRED, td);
514
515 vrele(ntmp->ntm_devvp);
516
517 /* free the toupper table, if this has been last mounted ntfs volume */
518 ntfs_toupper_unuse();
519
520 dprintf(("ntfs_umount: freeing memory...\n"));
521 ntfs_u28_uninit(ntmp);
522 ntfs_82u_uninit(ntmp);
523 mp->mnt_data = (qaddr_t)0;
524 mp->mnt_flag &= ~MNT_LOCAL;
525 FREE(ntmp->ntm_ad, M_NTFSMNT);
526 FREE(ntmp, M_NTFSMNT);
527 return (error);
528 }
529
530 static int
531 ntfs_root(
532 struct mount *mp,
533 struct vnode **vpp )
534 {
535 struct vnode *nvp;
536 int error = 0;
537
538 dprintf(("ntfs_root(): sysvn: %p\n",
539 VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]));
540 error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, LK_EXCLUSIVE, &nvp);
541 if(error) {
542 printf("ntfs_root: VFS_VGET failed: %d\n",error);
543 return (error);
544 }
545
546 *vpp = nvp;
547 return (0);
548 }
549
550 int
551 ntfs_calccfree(
552 struct ntfsmount *ntmp,
553 cn_t *cfreep)
554 {
555 struct vnode *vp;
556 u_int8_t *tmp;
557 int j, error;
558 long cfree = 0;
559 size_t bmsize, i;
560
561 vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
562
563 bmsize = VTOF(vp)->f_size;
564
565 MALLOC(tmp, u_int8_t *, bmsize, M_TEMP, M_WAITOK);
566
567 error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
568 0, bmsize, tmp, NULL);
569 if (error)
570 goto out;
571
572 for(i=0;i<bmsize;i++)
573 for(j=0;j<8;j++)
574 if(~tmp[i] & (1 << j)) cfree++;
575 *cfreep = cfree;
576
577 out:
578 FREE(tmp, M_TEMP);
579 return(error);
580 }
581
582 static int
583 ntfs_statfs(
584 struct mount *mp,
585 struct statfs *sbp,
586 struct thread *td)
587 {
588 struct ntfsmount *ntmp = VFSTONTFS(mp);
589 u_int64_t mftsize,mftallocated;
590
591 dprintf(("ntfs_statfs():\n"));
592
593 mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size;
594 mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
595
596 sbp->f_type = mp->mnt_vfc->vfc_typenum;
597 sbp->f_bsize = ntmp->ntm_bps;
598 sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
599 sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
600 sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
601 sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
602 sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
603 sbp->f_ffree;
604 if (sbp != &mp->mnt_stat) {
605 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
606 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
607 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
608 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
609 }
610 sbp->f_flags = mp->mnt_flag;
611
612 return (0);
613 }
614
615 /*ARGSUSED*/
616 static int
617 ntfs_fhtovp(
618 struct mount *mp,
619 struct fid *fhp,
620 struct vnode **vpp)
621 {
622 struct vnode *nvp;
623 struct ntfid *ntfhp = (struct ntfid *)fhp;
624 int error;
625
626 ddprintf(("ntfs_fhtovp(): %d\n", ntfhp->ntfid_ino));
627
628 if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
629 *vpp = NULLVP;
630 return (error);
631 }
632 /* XXX as unlink/rmdir/mkdir/creat are not currently possible
633 * with NTFS, we don't need to check anything else for now */
634 *vpp = nvp;
635
636 return (0);
637 }
638
639 static int
640 ntfs_vptofh(
641 struct vnode *vp,
642 struct fid *fhp)
643 {
644 register struct ntnode *ntp;
645 register struct ntfid *ntfhp;
646
647 ddprintf(("ntfs_fhtovp(): %p\n", vp));
648
649 ntp = VTONT(vp);
650 ntfhp = (struct ntfid *)fhp;
651 ntfhp->ntfid_len = sizeof(struct ntfid);
652 ntfhp->ntfid_ino = ntp->i_number;
653 /* ntfhp->ntfid_gen = ntp->i_gen; */
654 return (0);
655 }
656
657 int
658 ntfs_vgetex(
659 struct mount *mp,
660 ino_t ino,
661 u_int32_t attrtype,
662 char *attrname,
663 u_long lkflags,
664 u_long flags,
665 struct thread *td,
666 struct vnode **vpp)
667 {
668 int error;
669 register struct ntfsmount *ntmp;
670 struct ntnode *ip;
671 struct fnode *fp;
672 struct vnode *vp;
673 enum vtype f_type;
674
675 dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
676 ino, attrtype, attrname?attrname:"", (u_long)lkflags,
677 (u_long)flags ));
678
679 ntmp = VFSTONTFS(mp);
680 *vpp = NULL;
681
682 /* Get ntnode */
683 error = ntfs_ntlookup(ntmp, ino, &ip);
684 if (error) {
685 printf("ntfs_vget: ntfs_ntget failed\n");
686 return (error);
687 }
688
689 /* It may be not initialized fully, so force load it */
690 if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
691 error = ntfs_loadntnode(ntmp, ip);
692 if(error) {
693 printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
694 ip->i_number);
695 ntfs_ntput(ip);
696 return (error);
697 }
698 }
699
700 error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
701 if (error) {
702 printf("ntfs_vget: ntfs_fget failed\n");
703 ntfs_ntput(ip);
704 return (error);
705 }
706
707 f_type = VNON;
708 if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
709 if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
710 (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
711 f_type = VDIR;
712 } else if (flags & VG_EXT) {
713 f_type = VNON;
714 fp->f_size = fp->f_allocated = 0;
715 } else {
716 f_type = VREG;
717
718 error = ntfs_filesize(ntmp, fp,
719 &fp->f_size, &fp->f_allocated);
720 if (error) {
721 ntfs_ntput(ip);
722 return (error);
723 }
724 }
725
726 fp->f_flag |= FN_VALID;
727 }
728
729 if (FTOV(fp)) {
730 vget(FTOV(fp), lkflags, td);
731 *vpp = FTOV(fp);
732 ntfs_ntput(ip);
733 return (0);
734 }
735
736 error = getnewvnode("ntfs", ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
737 if(error) {
738 ntfs_frele(fp);
739 ntfs_ntput(ip);
740 return (error);
741 }
742 dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
743
744 fp->f_vp = vp;
745 vp->v_data = fp;
746 vp->v_type = f_type;
747
748 if (ino == NTFS_ROOTINO)
749 vp->v_vflag |= VV_ROOT;
750
751 ntfs_ntput(ip);
752
753 if (lkflags & LK_TYPE_MASK) {
754 error = vn_lock(vp, lkflags, td);
755 if (error) {
756 vput(vp);
757 return (error);
758 }
759 }
760
761 *vpp = vp;
762 return (0);
763
764 }
765
766 static int
767 ntfs_vget(
768 struct mount *mp,
769 ino_t ino,
770 int lkflags,
771 struct vnode **vpp)
772 {
773 return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, lkflags, 0,
774 curthread, vpp);
775 }
776
777 static struct vfsops ntfs_vfsops = {
778 ntfs_mount,
779 vfs_stdstart,
780 ntfs_unmount,
781 ntfs_root,
782 vfs_stdquotactl,
783 ntfs_statfs,
784 vfs_stdsync,
785 ntfs_vget,
786 ntfs_fhtovp,
787 vfs_stdcheckexp,
788 ntfs_vptofh,
789 ntfs_init,
790 ntfs_uninit,
791 vfs_stdextattrctl,
792 };
793 VFS_SET(ntfs_vfsops, ntfs, 0);
Cache object: 6cde6c88da5656de49ac8da6336f4ef7
|