Annotation of sys/ntfs/ntfs_vfsops.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ntfs_vfsops.c,v 1.11 2006/04/19 11:55:55 pedro Exp $ */
2: /* $NetBSD: ntfs_vfsops.c,v 1.7 2003/04/24 07:50:19 christos Exp $ */
3:
4: /*-
5: * Copyright (c) 1998, 1999 Semen Ustimenko
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: *
29: * Id: ntfs_vfsops.c,v 1.7 1999/05/31 11:28:30 phk Exp
30: */
31:
32: #include <sys/cdefs.h>
33: #ifdef __KERNEL_RCSID
34: __KERNEL_RCSID(0, "$NetBSD: ntfs_vfsops.c,v 1.7 2003/04/24 07:50:19 christos Exp $");
35: #endif
36:
37: #include <sys/param.h>
38: #include <sys/systm.h>
39: #include <sys/namei.h>
40: #include <sys/proc.h>
41: #include <sys/kernel.h>
42: #include <sys/vnode.h>
43: #include <sys/mount.h>
44: #include <sys/buf.h>
45: #include <sys/fcntl.h>
46: #include <sys/malloc.h>
47: #include <sys/systm.h>
48: #include <sys/device.h>
49: #include <sys/conf.h>
50:
51: #if defined(__NetBSD__) || defined(__OpenBSD__)
52: #include <uvm/uvm_extern.h>
53: #else
54: #include <vm/vm.h>
55: #endif
56:
57: #include <miscfs/specfs/specdev.h>
58:
59: /*#define NTFS_DEBUG 1*/
60: #if defined(__FreeBSD__) || defined(__NetBSD__)
61: #include <fs/ntfs/ntfs.h>
62: #include <fs/ntfs/ntfs_inode.h>
63: #include <fs/ntfs/ntfs_subr.h>
64: #include <fs/ntfs/ntfs_vfsops.h>
65: #include <fs/ntfs/ntfs_ihash.h>
66: #include <fs/ntfs/ntfsmount.h>
67: #else
68: #include <ntfs/ntfs.h>
69: #include <ntfs/ntfs_inode.h>
70: #include <ntfs/ntfs_subr.h>
71: #include <ntfs/ntfs_vfsops.h>
72: #include <ntfs/ntfs_ihash.h>
73: #include <ntfs/ntfsmount.h>
74: #endif
75:
76: #ifdef MALLOC_DEFINE
77: MALLOC_DEFINE(M_NTFSMNT, "NTFS mount", "NTFS mount structure");
78: MALLOC_DEFINE(M_NTFSNTNODE,"NTFS ntnode", "NTFS ntnode information");
79: MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode", "NTFS fnode information");
80: MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer");
81: #endif
82:
83: #if defined(__FreeBSD__)
84: static int ntfs_mount(struct mount *, char *, caddr_t,
85: struct nameidata *, struct proc *);
86: #else
87: static int ntfs_mount(struct mount *, const char *, void *,
88: struct nameidata *, struct proc *);
89: #endif
90: static int ntfs_quotactl(struct mount *, int, uid_t, caddr_t,
91: struct proc *);
92: static int ntfs_root(struct mount *, struct vnode **);
93: static int ntfs_start(struct mount *, int, struct proc *);
94: static int ntfs_statfs(struct mount *, struct statfs *,
95: struct proc *);
96: static int ntfs_sync(struct mount *, int, struct ucred *,
97: struct proc *);
98: static int ntfs_unmount(struct mount *, int, struct proc *);
99: static int ntfs_vget(struct mount *mp, ino_t ino,
100: struct vnode **vpp);
101: static int ntfs_mountfs(struct vnode *, struct mount *,
102: struct ntfs_args *, struct proc *);
103: static int ntfs_vptofh(struct vnode *, struct fid *);
104:
105: #if defined(__FreeBSD__)
106: static int ntfs_init(struct vfsconf *);
107: static int ntfs_fhtovp(struct mount *, struct fid *,
108: struct sockaddr *, struct vnode **,
109: int *, struct ucred **);
110: #elif defined(__NetBSD__)
111: static void ntfs_init(void);
112: static void ntfs_reinit(void);
113: static void ntfs_done(void);
114: static int ntfs_fhtovp(struct mount *, struct fid *,
115: struct vnode **);
116: static int ntfs_checkexp(struct mount *, struct mbuf *,
117: int *, struct ucred **);
118: static int ntfs_mountroot(void);
119: static int ntfs_sysctl(int *, u_int, void *, size_t *, void *,
120: size_t, struct proc *);
121: #elif defined(__OpenBSD__)
122: static int ntfs_init(struct vfsconf *);
123: static int ntfs_fhtovp(struct mount *, struct fid *,
124: struct vnode **);
125: static int ntfs_checkexp(struct mount *, struct mbuf *,
126: int *, struct ucred **);
127: static int ntfs_sysctl(int *, u_int, void *, size_t *, void *,
128: size_t, struct proc *);
129: #else
130: static int ntfs_init(void);
131: static int ntfs_fhtovp(struct mount *, struct fid *,
132: struct mbuf *, struct vnode **,
133: int *, struct ucred **);
134: #endif
135:
136: #if defined(__FreeBSD__) || defined(__NetBSD__)
137: struct genfs_ops ntfs_genfsops = {
138: NULL,
139: NULL,
140: genfs_compat_gop_write,
141: };
142: #endif
143:
144: #if defined(__NetBSD__) || defined(__OpenBSD__)
145: /*
146: * Verify a remote client has export rights and return these rights via.
147: * exflagsp and credanonp.
148: */
149: static int
150: ntfs_checkexp(mp, nam, exflagsp, credanonp)
151: struct mount *mp;
152: struct mbuf *nam;
153: int *exflagsp;
154: struct ucred **credanonp;
155: {
156: struct netcred *np;
157: struct ntfsmount *ntm = VFSTONTFS(mp);
158:
159: /*
160: * Get the export permission structure for this <mp, client> tuple.
161: */
162: np = vfs_export_lookup(mp, &ntm->ntm_export, nam);
163: if (np == NULL)
164: return (EACCES);
165:
166: *exflagsp = np->netc_exflags;
167: *credanonp = &np->netc_anon;
168: return (0);
169: }
170:
171: /*ARGSUSED*/
172: static int
173: ntfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
174: int *name;
175: u_int namelen;
176: void *oldp;
177: size_t *oldlenp;
178: void *newp;
179: size_t newlen;
180: struct proc *p;
181: {
182: return (EINVAL);
183: }
184:
185: #endif
186:
187: #ifdef __NetBSD__
188: static int
189: ntfs_mountroot()
190: {
191: struct mount *mp;
192: struct proc *p = curproc; /* XXX */
193: int error;
194: struct ntfs_args args;
195:
196: if (root_device->dv_class != DV_DISK)
197: return (ENODEV);
198:
199: /*
200: * Get vnodes for rootdev.
201: */
202: if (bdevvp(rootdev, &rootvp))
203: panic("ntfs_mountroot: can't setup rootvp");
204:
205: if ((error = vfs_rootmountalloc(MOUNT_NTFS, "root_device", &mp))) {
206: vrele(rootvp);
207: return (error);
208: }
209:
210: args.flag = 0;
211: args.uid = 0;
212: args.gid = 0;
213: args.mode = 0777;
214:
215: if ((error = ntfs_mountfs(rootvp, mp, &args, p)) != 0) {
216: mp->mnt_op->vfs_refcount--;
217: vfs_unbusy(mp);
218: free(mp, M_MOUNT);
219: vrele(rootvp);
220: return (error);
221: }
222:
223: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
224: (void)ntfs_statfs(mp, &mp->mnt_stat, p);
225: vfs_unbusy(mp);
226:
227: return (0);
228: }
229:
230: static void
231: ntfs_init()
232: {
233: #ifdef _LKM
234: malloc_type_attach(M_NTFSMNT);
235: malloc_type_attach(M_NTFSNTNODE);
236: malloc_type_attach(M_NTFSFNODE);
237: malloc_type_attach(M_NTFSDIR);
238: malloc_type_attach(M_NTFSNTHASH);
239: malloc_type_attach(M_NTFSNTVATTR);
240: malloc_type_attach(M_NTFSRDATA);
241: malloc_type_attach(M_NTFSDECOMP);
242: malloc_type_attach(M_NTFSRUN);
243: #endif
244: ntfs_nthashinit();
245: ntfs_toupper_init();
246: }
247:
248: static void
249: ntfs_reinit()
250: {
251: ntfs_nthashreinit();
252: }
253:
254: static void
255: ntfs_done()
256: {
257: ntfs_nthashdone();
258: #ifdef _LKM
259: malloc_type_detach(M_NTFSMNT);
260: malloc_type_detach(M_NTFSNTNODE);
261: malloc_type_detach(M_NTFSFNODE);
262: malloc_type_detach(M_NTFSDIR);
263: malloc_type_detach(M_NTFSNTHASH);
264: malloc_type_detach(M_NTFSNTVATTR);
265: malloc_type_detach(M_NTFSRDATA);
266: malloc_type_detach(M_NTFSDECOMP);
267: malloc_type_detach(M_NTFSRUN);
268: #endif
269: }
270:
271: #elif defined(__FreeBSD__) || defined(__OpenBSD__)
272:
273: static int
274: ntfs_init (
275: struct vfsconf *vcp )
276: {
277: ntfs_nthashinit();
278: ntfs_toupper_init();
279: return 0;
280: }
281:
282: #endif /* NetBSD */
283:
284: static int
285: ntfs_mount(
286: struct mount *mp,
287: #if defined(__FreeBSD__)
288: char *path,
289: caddr_t data,
290: #else
291: const char *path,
292: void *data,
293: #endif
294: struct nameidata *ndp,
295: struct proc *p )
296: {
297: int err = 0;
298: struct vnode *devvp;
299: struct ntfs_args args;
300: size_t size;
301: mode_t amode;
302:
303: #ifdef __FreeBSD__
304: /*
305: * Use NULL path to flag a root mount
306: */
307: if( path == NULL) {
308: /*
309: ***
310: * Mounting root file system
311: ***
312: */
313:
314: /* Get vnode for root device*/
315: if( bdevvp( rootdev, &rootvp))
316: panic("ffs_mountroot: can't setup bdevvp for root");
317:
318: /*
319: * FS specific handling
320: */
321: mp->mnt_flag |= MNT_RDONLY; /* XXX globally applicable?*/
322:
323: /*
324: * Attempt mount
325: */
326: if( ( err = ntfs_mountfs(rootvp, mp, &args, p)) != 0) {
327: /* fs specific cleanup (if any)*/
328: goto error_1;
329: }
330:
331: goto dostatfs; /* success*/
332:
333: }
334: #endif /* FreeBSD */
335:
336: #ifdef __NetBSD__
337: if (mp->mnt_flag & MNT_GETARGS) {
338: struct ntfsmount *ntmp = VFSTONTFS(mp);
339: if (ntmp == NULL)
340: return EIO;
341: args.fspec = NULL;
342: args.uid = ntmp->ntm_uid;
343: args.gid = ntmp->ntm_gid;
344: args.mode = ntmp->ntm_mode;
345: args.flag = ntmp->ntm_flag;
346: vfs_showexport(mp, &args.export, &ntmp->ntm_export);
347: return copyout(&args, data, sizeof(args));
348: }
349: #endif
350:
351: /*
352: ***
353: * Mounting non-root file system or updating a file system
354: ***
355: */
356:
357: /* copy in user arguments*/
358: err = copyin(data, (caddr_t)&args, sizeof (struct ntfs_args));
359: if (err)
360: goto error_1; /* can't get arguments*/
361:
362: /*
363: * If updating, check whether changing from read-only to
364: * read/write; if there is no device name, that's all we do.
365: */
366: if (mp->mnt_flag & MNT_UPDATE) {
367: /* if not updating name...*/
368: if (args.fspec == 0) {
369: /*
370: * Process export requests. Jumping to "success"
371: * will return the vfs_export() error code.
372: */
373: struct ntfsmount *ntm = VFSTONTFS(mp);
374: err = vfs_export(mp, &ntm->ntm_export, &args.export_info);
375: goto success;
376: }
377:
378: printf("ntfs_mount(): MNT_UPDATE not supported\n");
379: err = EINVAL;
380: goto error_1;
381: }
382:
383: /*
384: * Not an update, or updating the name: look up the name
385: * and verify that it refers to a sensible block device.
386: */
387: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
388: err = namei(ndp);
389: if (err) {
390: /* can't get devvp!*/
391: goto error_1;
392: }
393:
394: devvp = ndp->ni_vp;
395:
396: if (devvp->v_type != VBLK) {
397: err = ENOTBLK;
398: goto error_2;
399: }
400:
401: #ifdef __FreeBSD__
402: if (bdevsw(devvp->v_rdev) == NULL) {
403: #elif defined(__NetBSD__)
404: if (bdevsw_lookup(devvp->v_rdev) == NULL) {
405: #else
406: if (major(devvp->v_rdev) >= nblkdev) {
407: #endif
408: err = ENXIO;
409: goto error_2;
410: }
411:
412: /*
413: * If we are not root, make sure we have permission to access the
414: * requested device.
415: */
416: if (p->p_ucred->cr_uid) {
417: amode = (mp->mnt_flag & MNT_RDONLY) ? VREAD : (VREAD | VWRITE);
418: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
419: err = VOP_ACCESS(devvp, amode, p->p_ucred, p);
420: VOP_UNLOCK(devvp, 0, p);
421: if (err)
422: goto error_2;
423: }
424:
425: if (mp->mnt_flag & MNT_UPDATE) {
426: #if 0
427: /*
428: ********************
429: * UPDATE
430: ********************
431: */
432:
433: if (devvp != ntmp->um_devvp)
434: err = EINVAL; /* needs translation */
435: else
436: vrele(devvp);
437: /*
438: * Update device name only on success
439: */
440: if( !err) {
441: err = set_statfs_info(NULL, UIO_USERSPACE, args.fspec,
442: UIO_USERSPACE, mp, p);
443: }
444: #endif
445: } else {
446: /*
447: ********************
448: * NEW MOUNT
449: ********************
450: */
451:
452: /*
453: * Since this is a new mount, we want the names for
454: * the device and the mount point copied in. If an
455: * error occurs, the mountpoint is discarded by the
456: * upper level code.
457: */
458: /* Save "last mounted on" info for mount point (NULL pad)*/
459: #if defined(__FreeBSD__) || defined(__NetBSD__)
460: err = set_statfs_info(path, UIO_USERSPACE, args.fspec,
461: UIO_USERSPACE, mp, p);
462: #else
463: (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1,
464: &size);
465: bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
466: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname,
467: MNAMELEN - 1, &size);
468: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
469: bcopy(&args, &mp->mnt_stat.mount_info.ntfs_args, sizeof(args));
470: #endif
471: if ( !err) {
472: err = ntfs_mountfs(devvp, mp, &args, p);
473: }
474: }
475: if (err) {
476: goto error_2;
477: }
478:
479: #ifdef __FreeBSD__
480: dostatfs:
481: #endif
482: /*
483: * Initialize FS stat information in mount struct; uses both
484: * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
485: *
486: * This code is common to root and non-root mounts
487: */
488: (void)VFS_STATFS(mp, &mp->mnt_stat, p);
489:
490: goto success;
491:
492:
493: error_2: /* error with devvp held*/
494:
495: /* release devvp before failing*/
496: vrele(devvp);
497:
498: error_1: /* no state to back out*/
499:
500: success:
501: return(err);
502: }
503:
504: /*
505: * Common code for mount and mountroot
506: */
507: int
508: ntfs_mountfs(devvp, mp, argsp, p)
509: struct vnode *devvp;
510: struct mount *mp;
511: struct ntfs_args *argsp;
512: struct proc *p;
513: {
514: struct buf *bp;
515: struct ntfsmount *ntmp = NULL;
516: dev_t dev = devvp->v_rdev;
517: int error, ronly, ncount, i;
518: struct vnode *vp;
519:
520: /*
521: * Disallow multiple mounts of the same device.
522: * Disallow mounting of a device that is currently in use
523: * (except for root, which might share swap device for miniroot).
524: * Flush out any old buffers remaining from a previous use.
525: */
526: error = vfs_mountedon(devvp);
527: if (error)
528: return (error);
529: ncount = vcount(devvp);
530: if (ncount > 1 && devvp != rootvp)
531: return (EBUSY);
532: error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
533: if (error)
534: return (error);
535:
536: ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
537: error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
538: if (error)
539: return (error);
540:
541: bp = NULL;
542:
543: error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp);
544: if (error)
545: goto out;
546: ntmp = malloc(sizeof *ntmp, M_NTFSMNT, M_WAITOK);
547: bzero(ntmp, sizeof *ntmp);
548: bcopy(bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile));
549: brelse(bp);
550: bp = NULL;
551:
552: if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
553: error = EINVAL;
554: dprintf(("ntfs_mountfs: invalid boot block\n"));
555: goto out;
556: }
557:
558: {
559: int8_t cpr = ntmp->ntm_mftrecsz;
560: if( cpr > 0 )
561: ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
562: else
563: ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
564: }
565: dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
566: ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media,
567: ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec));
568: dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
569: (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn));
570:
571: ntmp->ntm_mountp = mp;
572: ntmp->ntm_dev = dev;
573: ntmp->ntm_devvp = devvp;
574: ntmp->ntm_uid = argsp->uid;
575: ntmp->ntm_gid = argsp->gid;
576: ntmp->ntm_mode = argsp->mode;
577: ntmp->ntm_flag = argsp->flag;
578: #ifdef __OpenBSD__
579: mp->mnt_data = (qaddr_t) ntmp;
580: #else
581: mp->mnt_data = ntmp;
582: #endif
583:
584: /* set file name encode/decode hooks XXX utf-8 only for now */
585: ntmp->ntm_wget = ntfs_utf8_wget;
586: ntmp->ntm_wput = ntfs_utf8_wput;
587: ntmp->ntm_wcmp = ntfs_utf8_wcmp;
588:
589: dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
590: (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
591: (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
592: ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
593:
594: /*
595: * We read in some system nodes to do not allow
596: * reclaim them and to have everytime access to them.
597: */
598: {
599: int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
600: for (i=0; i<3; i++) {
601: error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]]));
602: if(error)
603: goto out1;
604: ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM;
605: VREF(ntmp->ntm_sysvn[pi[i]]);
606: vput(ntmp->ntm_sysvn[pi[i]]);
607: }
608: }
609:
610: /* read the Unicode lowercase --> uppercase translation table,
611: * if necessary */
612: #ifndef __OpenBSD__
613: if ((error = ntfs_toupper_use(mp, ntmp)))
614: #else
615: if ((error = ntfs_toupper_use(mp, ntmp, p)))
616: #endif
617: goto out1;
618:
619: /*
620: * Scan $BitMap and count free clusters
621: */
622: error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
623: if(error)
624: goto out1;
625:
626: /*
627: * Read and translate to internal format attribute
628: * definition file.
629: */
630: {
631: int num,j;
632: struct attrdef ad;
633:
634: /* Open $AttrDef */
635: error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp );
636: if(error)
637: goto out1;
638:
639: /* Count valid entries */
640: for(num=0;;num++) {
641: error = ntfs_readattr(ntmp, VTONT(vp),
642: NTFS_A_DATA, NULL,
643: num * sizeof(ad), sizeof(ad),
644: &ad, NULL);
645: if (error)
646: goto out1;
647: if (ad.ad_name[0] == 0)
648: break;
649: }
650:
651: /* Alloc memory for attribute definitions */
652: ntmp->ntm_ad = (struct ntvattrdef *) malloc(
653: num * sizeof(struct ntvattrdef),
654: M_NTFSMNT, M_WAITOK);
655:
656: ntmp->ntm_adnum = num;
657:
658: /* Read them and translate */
659: for(i=0;i<num;i++){
660: error = ntfs_readattr(ntmp, VTONT(vp),
661: NTFS_A_DATA, NULL,
662: i * sizeof(ad), sizeof(ad),
663: &ad, NULL);
664: if (error)
665: goto out1;
666: j = 0;
667: do {
668: ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
669: } while(ad.ad_name[j++]);
670: ntmp->ntm_ad[i].ad_namelen = j - 1;
671: ntmp->ntm_ad[i].ad_type = ad.ad_type;
672: }
673:
674: vput(vp);
675: }
676:
677: #if defined(__FreeBSD__)
678: mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
679: mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
680: #else
681: mp->mnt_stat.f_fsid.val[0] = dev;
682: mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_NTFS);
683: #endif
684: mp->mnt_maxsymlinklen = 0;
685: mp->mnt_flag |= MNT_LOCAL;
686: devvp->v_specmountpoint = mp;
687: return (0);
688:
689: out1:
690: for (i = 0; i < NTFS_SYSNODESNUM; i++)
691: if (ntmp->ntm_sysvn[i])
692: vrele(ntmp->ntm_sysvn[i]);
693:
694: if (vflush(mp,NULLVP,0))
695: dprintf(("ntfs_mountfs: vflush failed\n"));
696:
697: out:
698: devvp->v_specmountpoint = NULL;
699: if (bp)
700: brelse(bp);
701:
702: if (ntmp != NULL) {
703: if (ntmp->ntm_ad != NULL)
704: free(ntmp->ntm_ad, M_NTFSMNT);
705: free(ntmp, M_NTFSMNT);
706: mp->mnt_data = NULL;
707: }
708:
709: /* lock the device vnode before calling VOP_CLOSE() */
710: VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p);
711: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
712: VOP__UNLOCK(devvp, 0, p);
713:
714: return (error);
715: }
716:
717: static int
718: ntfs_start (
719: struct mount *mp,
720: int flags,
721: struct proc *p )
722: {
723: return (0);
724: }
725:
726: static int
727: ntfs_unmount(
728: struct mount *mp,
729: int mntflags,
730: struct proc *p)
731: {
732: struct ntfsmount *ntmp;
733: int error, ronly = 0, flags, i;
734:
735: dprintf(("ntfs_unmount: unmounting...\n"));
736: ntmp = VFSTONTFS(mp);
737:
738: flags = 0;
739: if(mntflags & MNT_FORCE)
740: flags |= FORCECLOSE;
741:
742: dprintf(("ntfs_unmount: vflushing...\n"));
743: error = vflush(mp,NULLVP,flags | SKIPSYSTEM);
744: if (error) {
745: dprintf(("ntfs_unmount: vflush failed: %d\n",error));
746: return (error);
747: }
748:
749: /* Check if only system vnodes are rest */
750: for(i=0;i<NTFS_SYSNODESNUM;i++)
751: if((ntmp->ntm_sysvn[i]) &&
752: (ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY);
753:
754: /* Dereference all system vnodes */
755: for(i=0;i<NTFS_SYSNODESNUM;i++)
756: if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
757:
758: /* vflush system vnodes */
759: error = vflush(mp,NULLVP,flags);
760: if (error) {
761: /* XXX should this be panic() ? */
762: printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
763: }
764:
765: /* Check if the type of device node isn't VBAD before
766: * touching v_specinfo. If the device vnode is revoked, the
767: * field is NULL and touching it causes null pointer derefercence.
768: */
769: if (ntmp->ntm_devvp->v_type != VBAD)
770: ntmp->ntm_devvp->v_specmountpoint = NULL;
771:
772: vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, p, 0, 0);
773:
774: /* lock the device vnode before calling VOP_CLOSE() */
775: #ifndef __OpenBSD__
776: VOP_LOCK(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY);
777: #else
778: VOP_LOCK(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY, p);
779: #endif
780: error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE,
781: NOCRED, p);
782: VOP__UNLOCK(ntmp->ntm_devvp, 0, p);
783:
784: vrele(ntmp->ntm_devvp);
785:
786: /* free the toupper table, if this has been last mounted ntfs volume */
787: #ifndef __OpenBSD__
788: ntfs_toupper_unuse();
789: #else
790: ntfs_toupper_unuse(p);
791: #endif
792:
793: dprintf(("ntfs_umount: freeing memory...\n"));
794: mp->mnt_data = NULL;
795: mp->mnt_flag &= ~MNT_LOCAL;
796: free(ntmp->ntm_ad, M_NTFSMNT);
797: free(ntmp, M_NTFSMNT);
798: return (error);
799: }
800:
801: static int
802: ntfs_root(
803: struct mount *mp,
804: struct vnode **vpp )
805: {
806: struct vnode *nvp;
807: int error = 0;
808:
809: dprintf(("ntfs_root(): sysvn: %p\n",
810: VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]));
811: error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp);
812: if(error) {
813: printf("ntfs_root: VFS_VGET failed: %d\n",error);
814: return (error);
815: }
816:
817: *vpp = nvp;
818: return (0);
819: }
820:
821: /*
822: * Do operations associated with quotas, not supported
823: */
824: /* ARGSUSED */
825: static int
826: ntfs_quotactl (
827: struct mount *mp,
828: int cmds,
829: uid_t uid,
830: caddr_t arg,
831: struct proc *p)
832: {
833:
834: return EOPNOTSUPP;
835: }
836:
837: int
838: ntfs_calccfree(
839: struct ntfsmount *ntmp,
840: cn_t *cfreep)
841: {
842: struct vnode *vp;
843: u_int8_t *tmp;
844: int j, error;
845: cn_t cfree = 0;
846: size_t bmsize, i;
847:
848: vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
849:
850: bmsize = VTOF(vp)->f_size;
851:
852: tmp = (u_int8_t *) malloc(bmsize, M_TEMP, M_WAITOK);
853:
854: error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
855: 0, bmsize, tmp, NULL);
856: if (error)
857: goto out;
858:
859: for(i=0;i<bmsize;i++)
860: for(j=0;j<8;j++)
861: if(~tmp[i] & (1 << j)) cfree++;
862: *cfreep = cfree;
863:
864: out:
865: free(tmp, M_TEMP);
866: return(error);
867: }
868:
869: static int
870: ntfs_statfs(
871: struct mount *mp,
872: struct statfs *sbp,
873: struct proc *p)
874: {
875: struct ntfsmount *ntmp = VFSTONTFS(mp);
876: u_int64_t mftallocated;
877:
878: dprintf(("ntfs_statfs():\n"));
879:
880: mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
881:
882: #if defined(__FreeBSD__)
883: sbp->f_type = mp->mnt_vfc->vfc_typenum;
884: #elif defined(__NetBSD__)
885: sbp->f_type = 0;
886: #elif !defined(__OpenBSD__)
887: sbp->f_type = MOUNT_NTFS;
888: #endif
889: sbp->f_bsize = ntmp->ntm_bps;
890: sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
891: sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
892: sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
893: sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
894: sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
895: sbp->f_ffree;
896: sbp->f_flags = mp->mnt_flag;
897: #if !defined(__OpenBSD__)
898: copy_statfs_info(sbp, mp);
899: #else
900: if (sbp != &mp->mnt_stat) {
901: bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
902: bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
903: bcopy(&mp->mnt_stat.mount_info.msdosfs_args,
904: &sbp->mount_info.msdosfs_args, sizeof(struct msdosfs_args));
905: }
906: strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
907: #endif
908: return (0);
909: }
910:
911: static int
912: ntfs_sync (
913: struct mount *mp,
914: int waitfor,
915: struct ucred *cred,
916: struct proc *p)
917: {
918: /*dprintf(("ntfs_sync():\n"));*/
919: return (0);
920: }
921:
922: /*ARGSUSED*/
923: static int
924: ntfs_fhtovp(
925: #if defined(__FreeBSD__)
926: struct mount *mp,
927: struct fid *fhp,
928: struct sockaddr *nam,
929: struct vnode **vpp,
930: int *exflagsp,
931: struct ucred **credanonp)
932: #elif defined(__NetBSD__) || defined(__OpenBSD__)
933: struct mount *mp,
934: struct fid *fhp,
935: struct vnode **vpp)
936: #else
937: struct mount *mp,
938: struct fid *fhp,
939: struct mbuf *nam,
940: struct vnode **vpp,
941: int *exflagsp,
942: struct ucred **credanonp)
943: #endif
944: {
945: struct ntfid *ntfhp = (struct ntfid *)fhp;
946: int error;
947:
948: ddprintf(("ntfs_fhtovp(): %s: %d\n", mp->mnt_stat.f_mntonname,
949: ntfhp->ntfid_ino));
950:
951: error = ntfs_vgetex(mp, ntfhp->ntfid_ino, ntfhp->ntfid_attr, NULL,
952: LK_EXCLUSIVE | LK_RETRY, 0, curproc, vpp); /* XXX */
953: if (error != 0) {
954: *vpp = NULLVP;
955: return (error);
956: }
957:
958: /* XXX as unlink/rmdir/mkdir/creat are not currently possible
959: * with NTFS, we don't need to check anything else for now */
960: return (0);
961: }
962:
963: static int
964: ntfs_vptofh(
965: struct vnode *vp,
966: struct fid *fhp)
967: {
968: struct ntnode *ntp;
969: struct ntfid *ntfhp;
970: struct fnode *fn;
971:
972: ddprintf(("ntfs_fhtovp(): %s: %p\n", vp->v_mount->mnt_stat.f_mntonname,
973: vp));
974:
975: fn = VTOF(vp);
976: ntp = VTONT(vp);
977: ntfhp = (struct ntfid *)fhp;
978: ntfhp->ntfid_len = sizeof(struct ntfid);
979: ntfhp->ntfid_ino = ntp->i_number;
980: ntfhp->ntfid_attr = fn->f_attrtype;
981: #ifdef notyet
982: ntfhp->ntfid_gen = ntp->i_gen;
983: #endif
984: return (0);
985: }
986:
987: int
988: ntfs_vgetex(
989: struct mount *mp,
990: ino_t ino,
991: u_int32_t attrtype,
992: char *attrname,
993: u_long lkflags,
994: u_long flags,
995: struct proc *p,
996: struct vnode **vpp)
997: {
998: int error;
999: struct ntfsmount *ntmp;
1000: struct ntnode *ip;
1001: struct fnode *fp;
1002: struct vnode *vp;
1003: enum vtype f_type;
1004:
1005: dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
1006: ino, attrtype, attrname?attrname:"", (u_long)lkflags,
1007: (u_long)flags ));
1008:
1009: ntmp = VFSTONTFS(mp);
1010: *vpp = NULL;
1011:
1012: /* Get ntnode */
1013: #ifndef __OpenBSD__
1014: error = ntfs_ntlookup(ntmp, ino, &ip);
1015: #else
1016: error = ntfs_ntlookup(ntmp, ino, &ip, p);
1017: #endif
1018: if (error) {
1019: printf("ntfs_vget: ntfs_ntget failed\n");
1020: return (error);
1021: }
1022:
1023: /* It may be not initialized fully, so force load it */
1024: if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
1025: error = ntfs_loadntnode(ntmp, ip);
1026: if(error) {
1027: printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
1028: ip->i_number);
1029: #ifndef __OpenBSD__
1030: ntfs_ntput(ip);
1031: #else
1032: ntfs_ntput(ip, p);
1033: #endif
1034: return (error);
1035: }
1036: }
1037:
1038: error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
1039: if (error) {
1040: printf("ntfs_vget: ntfs_fget failed\n");
1041: #ifndef __OpenBSD__
1042: ntfs_ntput(ip);
1043: #else
1044: ntfs_ntput(ip, p);
1045: #endif
1046: return (error);
1047: }
1048:
1049: if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
1050: if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
1051: (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
1052: f_type = VDIR;
1053: } else if (flags & VG_EXT) {
1054: f_type = VNON;
1055: fp->f_size = fp->f_allocated = 0;
1056: } else {
1057: f_type = VREG;
1058:
1059: error = ntfs_filesize(ntmp, fp,
1060: &fp->f_size, &fp->f_allocated);
1061: if (error) {
1062: #ifndef __OpenBSD__
1063: ntfs_ntput(ip);
1064: #else
1065: ntfs_ntput(ip, p);
1066: #endif
1067: return (error);
1068: }
1069: }
1070:
1071: fp->f_flag |= FN_VALID;
1072: }
1073:
1074: /*
1075: * We may be calling vget() now. To avoid potential deadlock, we need
1076: * to release ntnode lock, since due to locking order vnode
1077: * lock has to be acquired first.
1078: * ntfs_fget() bumped ntnode usecount, so ntnode won't be recycled
1079: * prematurely.
1080: */
1081: #ifndef __OpenBSD__
1082: ntfs_ntput(ip);
1083: #else
1084: ntfs_ntput(ip, p);
1085: #endif
1086:
1087: if (FTOV(fp)) {
1088: /* vget() returns error if the vnode has been recycled */
1089: if (VGET(FTOV(fp), lkflags, p) == 0) {
1090: *vpp = FTOV(fp);
1091: return (0);
1092: }
1093: }
1094:
1095: error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
1096: if(error) {
1097: ntfs_frele(fp);
1098: #ifndef __OpenBSD__
1099: ntfs_ntput(ip);
1100: #else
1101: ntfs_ntput(ip, p);
1102: #endif
1103: return (error);
1104: }
1105: dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
1106:
1107: #ifdef __FreeBSD__
1108: lockinit(&fp->f_lock, PINOD, "fnode", 0, 0);
1109: #endif
1110: fp->f_vp = vp;
1111: vp->v_data = fp;
1112: vp->v_type = f_type;
1113:
1114: if (ino == NTFS_ROOTINO)
1115: vp->v_flag |= VROOT;
1116:
1117: if (lkflags & LK_TYPE_MASK) {
1118: error = VN_LOCK(vp, lkflags, p);
1119: if (error) {
1120: vput(vp);
1121: return (error);
1122: }
1123: }
1124:
1125: #if defined(__FreeBSD__) || defined(__NetBSD__)
1126: genfs_node_init(vp, &ntfs_genfsops);
1127: #endif
1128: *vpp = vp;
1129: return (0);
1130: }
1131:
1132: static int
1133: ntfs_vget(
1134: struct mount *mp,
1135: ino_t ino,
1136: struct vnode **vpp)
1137: {
1138: return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL,
1139: LK_EXCLUSIVE | LK_RETRY, 0, curproc, vpp); /* XXX */
1140: }
1141:
1142: #if defined(__FreeBSD__)
1143: static struct vfsops ntfs_vfsops = {
1144: ntfs_mount,
1145: ntfs_start,
1146: ntfs_unmount,
1147: ntfs_root,
1148: ntfs_quotactl,
1149: ntfs_statfs,
1150: ntfs_sync,
1151: ntfs_vget,
1152: ntfs_fhtovp,
1153: ntfs_vptofh,
1154: ntfs_init,
1155: NULL
1156: };
1157: VFS_SET(ntfs_vfsops, ntfs, 0);
1158: #elif defined(__NetBSD__)
1159: extern const struct vnodeopv_desc ntfs_vnodeop_opv_desc;
1160:
1161: const struct vnodeopv_desc * const ntfs_vnodeopv_descs[] = {
1162: &ntfs_vnodeop_opv_desc,
1163: NULL,
1164: };
1165:
1166: struct vfsops ntfs_vfsops = {
1167: MOUNT_NTFS,
1168: ntfs_mount,
1169: ntfs_start,
1170: ntfs_unmount,
1171: ntfs_root,
1172: ntfs_quotactl,
1173: ntfs_statfs,
1174: ntfs_sync,
1175: ntfs_vget,
1176: ntfs_fhtovp,
1177: ntfs_vptofh,
1178: ntfs_init,
1179: ntfs_reinit,
1180: ntfs_done,
1181: ntfs_sysctl,
1182: ntfs_mountroot,
1183: ntfs_checkexp,
1184: ntfs_vnodeopv_descs,
1185: };
1186: #elif defined(__OpenBSD__)
1187: extern const struct vnodeopv_desc ntfs_vnodeop_opv_desc;
1188:
1189: const struct vnodeopv_desc * const ntfs_vnodeopv_descs[] = {
1190: &ntfs_vnodeop_opv_desc,
1191: NULL,
1192: };
1193:
1194: const struct vfsops ntfs_vfsops = {
1195: ntfs_mount,
1196: ntfs_start,
1197: ntfs_unmount,
1198: ntfs_root,
1199: ntfs_quotactl,
1200: ntfs_statfs,
1201: ntfs_sync,
1202: ntfs_vget,
1203: ntfs_fhtovp,
1204: ntfs_vptofh,
1205: ntfs_init,
1206: ntfs_sysctl,
1207: ntfs_checkexp,
1208: };
1209:
1210: #endif
CVSweb