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