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.2/sys/fs/ntfs/ntfs_vfsops.c 120492 2003-09-26 20:26:25Z fjoe $
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_mountfs(register struct vnode *, struct mount *,
68 struct ntfs_args *, struct thread *);
69
70 static vfs_init_t ntfs_init;
71 static vfs_uninit_t ntfs_uninit;
72 static vfs_vget_t ntfs_vget;
73 static vfs_fhtovp_t ntfs_fhtovp;
74 static vfs_mount_t ntfs_mount;
75 static vfs_root_t ntfs_root;
76 static vfs_statfs_t ntfs_statfs;
77 static vfs_unmount_t ntfs_unmount;
78 static vfs_vptofh_t ntfs_vptofh;
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, -1);
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 /*
315 * We must not cache the boot block if its size is not exactly
316 * one cluster in order to avoid confusing the buffer cache when
317 * the boot file is read later by ntfs_readntvattr_plain(), which
318 * reads a cluster at a time.
319 */
320 if (ntfs_cntob(1) != BBSIZE)
321 bp->b_flags |= B_NOCACHE;
322 brelse( bp );
323 bp = NULL;
324
325 if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
326 error = EINVAL;
327 dprintf(("ntfs_mountfs: invalid boot block\n"));
328 goto out;
329 }
330
331 {
332 int8_t cpr = ntmp->ntm_mftrecsz;
333 if( cpr > 0 )
334 ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
335 else
336 ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
337 }
338 dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
339 ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media,
340 ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec));
341 dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
342 (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn));
343
344 ntmp->ntm_mountp = mp;
345 ntmp->ntm_dev = dev;
346 ntmp->ntm_devvp = devvp;
347 ntmp->ntm_uid = argsp->uid;
348 ntmp->ntm_gid = argsp->gid;
349 ntmp->ntm_mode = argsp->mode;
350 ntmp->ntm_flag = argsp->flag;
351
352 /* Copy in the 8-bit to Unicode conversion table */
353 /* Initialize Unicode to 8-bit table from 8toU table */
354 if (argsp->flag & NTFS_MFLAG_KICONV) {
355 ntfs_82u_init(ntmp, argsp->cs_local, argsp->cs_ntfs);
356 ntfs_u28_init(ntmp, NULL, argsp->cs_local, argsp->cs_ntfs);
357 } else {
358 ntfs_82u_init(ntmp, NULL, NULL);
359 ntfs_u28_init(ntmp, ntmp->ntm_82u, NULL, NULL);
360 }
361
362 mp->mnt_data = (qaddr_t)ntmp;
363
364 dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
365 (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
366 (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
367 ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
368
369 /*
370 * We read in some system nodes to do not allow
371 * reclaim them and to have everytime access to them.
372 */
373 {
374 int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
375 for (i=0; i<3; i++) {
376 error = VFS_VGET(mp, pi[i], LK_EXCLUSIVE,
377 &(ntmp->ntm_sysvn[pi[i]]));
378 if(error)
379 goto out1;
380 ntmp->ntm_sysvn[pi[i]]->v_vflag |= VV_SYSTEM;
381 VREF(ntmp->ntm_sysvn[pi[i]]);
382 vput(ntmp->ntm_sysvn[pi[i]]);
383 }
384 }
385
386 /* read the Unicode lowercase --> uppercase translation table,
387 * if necessary */
388 if ((error = ntfs_toupper_use(mp, ntmp)))
389 goto out1;
390
391 /*
392 * Scan $BitMap and count free clusters
393 */
394 error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
395 if(error)
396 goto out1;
397
398 /*
399 * Read and translate to internal format attribute
400 * definition file.
401 */
402 {
403 int num,j;
404 struct attrdef ad;
405
406 /* Open $AttrDef */
407 error = VFS_VGET(mp, NTFS_ATTRDEFINO, LK_EXCLUSIVE, &vp );
408 if(error)
409 goto out1;
410
411 /* Count valid entries */
412 for(num=0;;num++) {
413 error = ntfs_readattr(ntmp, VTONT(vp),
414 NTFS_A_DATA, NULL,
415 num * sizeof(ad), sizeof(ad),
416 &ad, NULL);
417 if (error)
418 goto out1;
419 if (ad.ad_name[0] == 0)
420 break;
421 }
422
423 /* Alloc memory for attribute definitions */
424 MALLOC(ntmp->ntm_ad, struct ntvattrdef *,
425 num * sizeof(struct ntvattrdef),
426 M_NTFSMNT, M_WAITOK);
427
428 ntmp->ntm_adnum = num;
429
430 /* Read them and translate */
431 for(i=0;i<num;i++){
432 error = ntfs_readattr(ntmp, VTONT(vp),
433 NTFS_A_DATA, NULL,
434 i * sizeof(ad), sizeof(ad),
435 &ad, NULL);
436 if (error)
437 goto out1;
438 j = 0;
439 do {
440 ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
441 } while(ad.ad_name[j++]);
442 ntmp->ntm_ad[i].ad_namelen = j - 1;
443 ntmp->ntm_ad[i].ad_type = ad.ad_type;
444 }
445
446 vput(vp);
447 }
448
449 mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
450 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
451 mp->mnt_maxsymlinklen = 0;
452 mp->mnt_flag |= MNT_LOCAL;
453 devvp->v_rdev->si_mountpoint = mp;
454 return (0);
455
456 out1:
457 for(i=0;i<NTFS_SYSNODESNUM;i++)
458 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
459
460 if (vflush(mp, 0, 0))
461 dprintf(("ntfs_mountfs: vflush failed\n"));
462
463 out:
464 devvp->v_rdev->si_mountpoint = NULL;
465 if (bp)
466 brelse(bp);
467
468 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, td);
469
470 return (error);
471 }
472
473 static int
474 ntfs_unmount(
475 struct mount *mp,
476 int mntflags,
477 struct thread *td)
478 {
479 struct ntfsmount *ntmp;
480 int error, ronly, flags, i;
481
482 dprintf(("ntfs_unmount: unmounting...\n"));
483 ntmp = VFSTONTFS(mp);
484
485 flags = 0;
486 if(mntflags & MNT_FORCE)
487 flags |= FORCECLOSE;
488
489 dprintf(("ntfs_unmount: vflushing...\n"));
490 error = vflush(mp, 0, flags | SKIPSYSTEM);
491 if (error) {
492 printf("ntfs_unmount: vflush failed: %d\n",error);
493 return (error);
494 }
495
496 /* Check if only system vnodes are rest */
497 for(i=0;i<NTFS_SYSNODESNUM;i++)
498 if((ntmp->ntm_sysvn[i]) &&
499 (vrefcnt(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY);
500
501 /* Dereference all system vnodes */
502 for(i=0;i<NTFS_SYSNODESNUM;i++)
503 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
504
505 /* vflush system vnodes */
506 error = vflush(mp, 0, flags);
507 if (error)
508 printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
509
510 /* Check if the type of device node isn't VBAD before
511 * touching v_cdev. If the device vnode is revoked, the
512 * field is NULL and touching it causes null pointer derefercence.
513 */
514 if (ntmp->ntm_devvp->v_type != VBAD)
515 ntmp->ntm_devvp->v_rdev->si_mountpoint = NULL;
516
517 vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, td, 0, 0);
518
519 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
520 error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE,
521 NOCRED, td);
522
523 vrele(ntmp->ntm_devvp);
524
525 /* free the toupper table, if this has been last mounted ntfs volume */
526 ntfs_toupper_unuse();
527
528 dprintf(("ntfs_umount: freeing memory...\n"));
529 ntfs_u28_uninit(ntmp);
530 ntfs_82u_uninit(ntmp);
531 mp->mnt_data = (qaddr_t)0;
532 mp->mnt_flag &= ~MNT_LOCAL;
533 FREE(ntmp->ntm_ad, M_NTFSMNT);
534 FREE(ntmp, M_NTFSMNT);
535 return (error);
536 }
537
538 static int
539 ntfs_root(
540 struct mount *mp,
541 struct vnode **vpp )
542 {
543 struct vnode *nvp;
544 int error = 0;
545
546 dprintf(("ntfs_root(): sysvn: %p\n",
547 VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]));
548 error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, LK_EXCLUSIVE, &nvp);
549 if(error) {
550 printf("ntfs_root: VFS_VGET failed: %d\n",error);
551 return (error);
552 }
553
554 *vpp = nvp;
555 return (0);
556 }
557
558 int
559 ntfs_calccfree(
560 struct ntfsmount *ntmp,
561 cn_t *cfreep)
562 {
563 struct vnode *vp;
564 u_int8_t *tmp;
565 int j, error;
566 long cfree = 0;
567 size_t bmsize, i;
568
569 vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
570
571 bmsize = VTOF(vp)->f_size;
572
573 MALLOC(tmp, u_int8_t *, bmsize, M_TEMP, M_WAITOK);
574
575 error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
576 0, bmsize, tmp, NULL);
577 if (error)
578 goto out;
579
580 for(i=0;i<bmsize;i++)
581 for(j=0;j<8;j++)
582 if(~tmp[i] & (1 << j)) cfree++;
583 *cfreep = cfree;
584
585 out:
586 FREE(tmp, M_TEMP);
587 return(error);
588 }
589
590 static int
591 ntfs_statfs(
592 struct mount *mp,
593 struct statfs *sbp,
594 struct thread *td)
595 {
596 struct ntfsmount *ntmp = VFSTONTFS(mp);
597 u_int64_t mftsize,mftallocated;
598
599 dprintf(("ntfs_statfs():\n"));
600
601 mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size;
602 mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
603
604 sbp->f_type = mp->mnt_vfc->vfc_typenum;
605 sbp->f_bsize = ntmp->ntm_bps;
606 sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
607 sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
608 sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
609 sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
610 sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
611 sbp->f_ffree;
612 if (sbp != &mp->mnt_stat) {
613 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
614 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
615 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
616 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
617 }
618 sbp->f_flags = mp->mnt_flag;
619
620 return (0);
621 }
622
623 /*ARGSUSED*/
624 static int
625 ntfs_fhtovp(
626 struct mount *mp,
627 struct fid *fhp,
628 struct vnode **vpp)
629 {
630 struct vnode *nvp;
631 struct ntfid *ntfhp = (struct ntfid *)fhp;
632 int error;
633
634 ddprintf(("ntfs_fhtovp(): %d\n", ntfhp->ntfid_ino));
635
636 if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
637 *vpp = NULLVP;
638 return (error);
639 }
640 /* XXX as unlink/rmdir/mkdir/creat are not currently possible
641 * with NTFS, we don't need to check anything else for now */
642 *vpp = nvp;
643
644 return (0);
645 }
646
647 static int
648 ntfs_vptofh(
649 struct vnode *vp,
650 struct fid *fhp)
651 {
652 register struct ntnode *ntp;
653 register struct ntfid *ntfhp;
654
655 ddprintf(("ntfs_fhtovp(): %p\n", vp));
656
657 ntp = VTONT(vp);
658 ntfhp = (struct ntfid *)fhp;
659 ntfhp->ntfid_len = sizeof(struct ntfid);
660 ntfhp->ntfid_ino = ntp->i_number;
661 /* ntfhp->ntfid_gen = ntp->i_gen; */
662 return (0);
663 }
664
665 int
666 ntfs_vgetex(
667 struct mount *mp,
668 ino_t ino,
669 u_int32_t attrtype,
670 char *attrname,
671 u_long lkflags,
672 u_long flags,
673 struct thread *td,
674 struct vnode **vpp)
675 {
676 int error;
677 register struct ntfsmount *ntmp;
678 struct ntnode *ip;
679 struct fnode *fp;
680 struct vnode *vp;
681 enum vtype f_type;
682
683 dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
684 ino, attrtype, attrname?attrname:"", (u_long)lkflags,
685 (u_long)flags ));
686
687 ntmp = VFSTONTFS(mp);
688 *vpp = NULL;
689
690 /* Get ntnode */
691 error = ntfs_ntlookup(ntmp, ino, &ip);
692 if (error) {
693 printf("ntfs_vget: ntfs_ntget failed\n");
694 return (error);
695 }
696
697 /* It may be not initialized fully, so force load it */
698 if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
699 error = ntfs_loadntnode(ntmp, ip);
700 if(error) {
701 printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
702 ip->i_number);
703 ntfs_ntput(ip);
704 return (error);
705 }
706 }
707
708 error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
709 if (error) {
710 printf("ntfs_vget: ntfs_fget failed\n");
711 ntfs_ntput(ip);
712 return (error);
713 }
714
715 f_type = VNON;
716 if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
717 if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
718 (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
719 f_type = VDIR;
720 } else if (flags & VG_EXT) {
721 f_type = VNON;
722 fp->f_size = fp->f_allocated = 0;
723 } else {
724 f_type = VREG;
725
726 error = ntfs_filesize(ntmp, fp,
727 &fp->f_size, &fp->f_allocated);
728 if (error) {
729 ntfs_ntput(ip);
730 return (error);
731 }
732 }
733
734 fp->f_flag |= FN_VALID;
735 }
736
737 if (FTOV(fp)) {
738 vget(FTOV(fp), lkflags, td);
739 *vpp = FTOV(fp);
740 ntfs_ntput(ip);
741 return (0);
742 }
743
744 error = getnewvnode("ntfs", ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
745 if(error) {
746 ntfs_frele(fp);
747 ntfs_ntput(ip);
748 return (error);
749 }
750 dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
751
752 fp->f_vp = vp;
753 vp->v_data = fp;
754 vp->v_type = f_type;
755
756 if (ino == NTFS_ROOTINO)
757 vp->v_vflag |= VV_ROOT;
758
759 ntfs_ntput(ip);
760
761 if (lkflags & LK_TYPE_MASK) {
762 error = vn_lock(vp, lkflags, td);
763 if (error) {
764 vput(vp);
765 return (error);
766 }
767 }
768
769 *vpp = vp;
770 return (0);
771
772 }
773
774 static int
775 ntfs_vget(
776 struct mount *mp,
777 ino_t ino,
778 int lkflags,
779 struct vnode **vpp)
780 {
781 return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, lkflags, 0,
782 curthread, vpp);
783 }
784
785 static struct vfsops ntfs_vfsops = {
786 .vfs_fhtovp = ntfs_fhtovp,
787 .vfs_init = ntfs_init,
788 .vfs_mount = ntfs_mount,
789 .vfs_root = ntfs_root,
790 .vfs_statfs = ntfs_statfs,
791 .vfs_uninit = ntfs_uninit,
792 .vfs_unmount = ntfs_unmount,
793 .vfs_vget = ntfs_vget,
794 .vfs_vptofh = ntfs_vptofh,
795 };
796 VFS_SET(ntfs_vfsops, ntfs, 0);
797 MODULE_VERSION(ntfs, 1);
Cache object: 7e6d20ecc8b779d9c85a1717ba48e1f0
|