1: /*-
2: * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24: * SUCH DAMAGE.
25: *
26: * $FreeBSD: src/sys/fs/hpfs/hpfs_vfsops.c,v 1.3.2.2 2001/12/25 01:44:45 dillon Exp $
27: * $DragonFly: src/sys/vfs/hpfs/hpfs_vfsops.c,v 1.15 2004/04/24 04:32:04 drhodus Exp $
28: */
29:
30:
31: #include <sys/param.h>
32: #include <sys/systm.h>
33: #include <sys/namei.h>
34: #include <sys/conf.h>
35: #include <sys/proc.h>
36: #include <sys/kernel.h>
37: #include <sys/vnode.h>
38: #include <sys/mount.h>
39: #include <sys/buf.h>
40: #include <sys/fcntl.h>
41: #include <sys/malloc.h>
42:
43: #include <vm/vm.h>
44: #include <vm/vm_param.h>
45: #if defined(__NetBSD__)
46: #include <vm/vm_prot.h>
47: #endif
48: #include <vm/vm_page.h>
49: #include <vm/vm_object.h>
50: #include <vm/vm_extern.h>
51: #include <sys/buf2.h>
52:
53: #if defined(__NetBSD__)
54: #include <miscfs/specfs/specdev.h>
55: #endif
56:
57: #include "hpfs.h"
58: #include "hpfsmount.h"
59: #include "hpfs_subr.h"
60:
61: #if defined(__DragonFly__)
62: MALLOC_DEFINE(M_HPFSMNT, "HPFS mount", "HPFS mount structure");
63: MALLOC_DEFINE(M_HPFSNO, "HPFS node", "HPFS node structure");
64: #endif
65:
66: static int hpfs_root (struct mount *, struct vnode **);
67: static int hpfs_statfs (struct mount *, struct statfs *,
68: struct thread *);
69: static int hpfs_unmount (struct mount *, int, struct thread *);
70: static int hpfs_vget (struct mount *mp, ino_t ino,
71: struct vnode **vpp);
72: static int hpfs_mountfs (struct vnode *, struct mount *,
73: struct hpfs_args *, struct thread *);
74: static int hpfs_vptofh (struct vnode *, struct fid *);
75: static int hpfs_fhtovp (struct mount *, struct fid *,
76: struct vnode **);
77:
78: #if !defined(__DragonFly__)
79: static int hpfs_quotactl (struct mount *, int, uid_t, caddr_t,
80: struct proc *);
81: static int hpfs_start (struct mount *, int, struct proc *);
82: static int hpfs_sync (struct mount *, int, struct ucred *,
83: struct proc *);
84: #endif
85:
86: #if defined(__DragonFly__)
87: struct sockaddr;
88: static int hpfs_mount (struct mount *, char *, caddr_t,
89: struct nameidata *, struct thread *);
90: static int hpfs_init (struct vfsconf *);
91: static int hpfs_checkexp (struct mount *, struct sockaddr *,
92: int *, struct ucred **);
93: #else /* defined(__NetBSD__) */
94: static int hpfs_mount (struct mount *, const char *, void *,
95: struct nameidata *, struct proc *);
96: static void hpfs_init (void);
97: static int hpfs_mountroot (void);
98: static int hpfs_sysctl (int *, u_int, void *, size_t *, void *,
99: size_t, struct proc *);
100: static int hpfs_checkexp (struct mount *, struct mbuf *,
101: int *, struct ucred **);
102: #endif
103:
104: /*ARGSUSED*/
105: static int
106: hpfs_checkexp(struct mount *mp,
107: #if defined(__DragonFly__)
108: struct sockaddr *nam,
109: #else /* defined(__NetBSD__) */
110: struct mbuf *nam,
111: #endif
112: int *exflagsp, struct ucred **credanonp)
113: {
114: struct netcred *np;
115: struct hpfsmount *hpm = VFSTOHPFS(mp);
116:
117: /*
118: * Get the export permission structure for this <mp, client> tuple.
119: */
120: np = vfs_export_lookup(mp, &hpm->hpm_export, nam);
121: if (np == NULL)
122: return (EACCES);
123:
124: *exflagsp = np->netc_exflags;
125: *credanonp = &np->netc_anon;
126: return (0);
127: }
128:
129: #if !defined(__DragonFly__)
130: /*ARGSUSED*/
131: static int
132: hpfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
133: size_t newlen, struct thread *td)
134: {
135: return (EINVAL);
136: }
137:
138: static int
139: hpfs_mountroot(void)
140: {
141: return (EINVAL);
142: }
143: #endif
144:
145: #if defined(__DragonFly__)
146: static int
147: hpfs_init(struct vfsconf *vcp)
148: #else /* defined(__NetBSD__) */
149: static void
150: hpfs_init(void)
151: #endif
152: {
153: dprintf(("hpfs_init():\n"));
154:
155: hpfs_hphashinit();
156: #if defined(__DragonFly__)
157: return 0;
158: #endif
159: }
160:
161: static int
162: hpfs_mount(struct mount *mp,
163: #if defined(__DragonFly__)
164: char *path, caddr_t data,
165: #else /* defined(__NetBSD__) */
166: const char *path, void *data,
167: #endif
168: struct nameidata *ndp, struct thread *td)
169: {
170: u_int size;
171: int err = 0;
172: struct vnode *devvp;
173: struct hpfs_args args;
174: struct hpfsmount *hpmp = 0;
175:
176: dprintf(("hpfs_mount():\n"));
177: /*
178: ***
179: * Mounting non-root file system or updating a file system
180: ***
181: */
182:
183: /* copy in user arguments*/
184: err = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args));
185: if (err)
186: goto error_1; /* can't get arguments*/
187:
188: /*
189: * If updating, check whether changing from read-only to
190: * read/write; if there is no device name, that's all we do.
191: */
192: if (mp->mnt_flag & MNT_UPDATE) {
193: dprintf(("hpfs_mount: MNT_UPDATE: "));
194:
195: hpmp = VFSTOHPFS(mp);
196:
197: if (args.fspec == 0) {
198: dprintf(("export 0x%x\n",args.export.ex_flags));
199: err = vfs_export(mp, &hpmp->hpm_export, &args.export);
200: if (err) {
201: printf("hpfs_mount: vfs_export failed %d\n",
202: err);
203: }
204: goto success;
205: } else {
206: dprintf(("name [FAILED]\n"));
207: err = EINVAL;
208: goto success;
209: }
210: dprintf(("\n"));
211: }
212:
213: /*
214: * Not an update, or updating the name: look up the name
215: * and verify that it refers to a sensible block device.
216: */
217: NDINIT(ndp, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, args.fspec, td);
218: err = namei(ndp);
219: if (err) {
220: /* can't get devvp!*/
221: goto error_1;
222: }
223:
224: devvp = ndp->ni_vp;
225:
226: #if defined(__DragonFly__)
227: if (!vn_isdisk(devvp, &err))
228: goto error_2;
229: #else /* defined(__NetBSD__) */
230: if (devvp->v_type != VBLK) {
231: err = ENOTBLK;
232: goto error_2;
233: }
234: if (major(devvp->v_rdev) >= nblkdev) {
235: err = ENXIO;
236: goto error_2;
237: }
238: #endif
239:
240: /*
241: ********************
242: * NEW MOUNT
243: ********************
244: */
245:
246: /*
247: * Since this is a new mount, we want the names for
248: * the device and the mount point copied in. If an
249: * error occurs, the mountpoint is discarded by the
250: * upper level code.
251: */
252: /* Save "last mounted on" info for mount point (NULL pad)*/
253: copyinstr( path, /* mount point*/
254: mp->mnt_stat.f_mntonname, /* save area*/
255: MNAMELEN - 1, /* max size*/
256: &size); /* real size*/
257: bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
258:
259: /* Save "mounted from" info for mount point (NULL pad)*/
260: copyinstr( args.fspec, /* device name*/
261: mp->mnt_stat.f_mntfromname, /* save area*/
262: MNAMELEN - 1, /* max size*/
263: &size); /* real size*/
264: bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
265:
266: err = hpfs_mountfs(devvp, mp, &args, td);
267: if (err)
268: goto error_2;
269:
270: /*
271: * Initialize FS stat information in mount struct; uses both
272: * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
273: *
274: * This code is common to root and non-root mounts
275: */
276: (void)VFS_STATFS(mp, &mp->mnt_stat, td);
277:
278: goto success;
279:
280:
281: error_2: /* error with devvp held*/
282:
283: /* release devvp before failing*/
284: vrele(devvp);
285:
286: error_1: /* no state to back out*/
287:
288: success:
289: return( err);
290: }
291:
292: /*
293: * Common code for mount and mountroot
294: */
295: int
296: hpfs_mountfs(struct vnode *devvp, struct mount *mp, struct hpfs_args *argsp,
297: struct thread *td)
298: {
299: int error, ncount, ronly;
300: struct sublock *sup;
301: struct spblock *spp;
302: struct hpfsmount *hpmp;
303: struct buf *bp = NULL;
304: struct vnode *vp;
305: dev_t dev = devvp->v_rdev;
306:
307: dprintf(("hpfs_mountfs():\n"));
308: /*
309: * Disallow multiple mounts of the same device.
310: * Disallow mounting of a device that is currently in use
311: * (except for root, which might share swap device for miniroot).
312: * Flush out any old buffers remaining from a previous use.
313: */
314: error = vfs_mountedon(devvp);
315: if (error)
316: return (error);
317: ncount = vcount(devvp);
318: #if defined(__DragonFly__)
319: if (devvp->v_object)
320: ncount -= 1;
321: #endif
322: if (ncount > 1 && devvp != rootvp)
323: return (EBUSY);
324:
325: #if defined(__DragonFly__)
326: VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, td);
327: error = vinvalbuf(devvp, V_SAVE, td, 0, 0);
328: VOP__UNLOCK(devvp, 0, td);
329: #else
330: error = vinvalbuf(devvp, V_SAVE, td, 0, 0);
331: #endif
332: if (error)
333: return (error);
334:
335: ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
336: VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, td);
337: error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td);
338: VOP__UNLOCK(devvp, 0, td);
339: if (error)
340: return (error);
341:
342: /*
343: * Do actual mount
344: */
345: hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK);
346: bzero(hpmp, sizeof(struct hpfsmount));
347:
348: /* Read in SuperBlock */
349: error = bread(devvp, SUBLOCK, SUSIZE, &bp);
350: if (error)
351: goto failed;
352: bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock));
353: brelse(bp); bp = NULL;
354:
355: /* Read in SpareBlock */
356: error = bread(devvp, SPBLOCK, SPSIZE, &bp);
357: if (error)
358: goto failed;
359: bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock));
360: brelse(bp); bp = NULL;
361:
362: sup = &hpmp->hpm_su;
363: spp = &hpmp->hpm_sp;
364:
365: /* Check magic */
366: if (sup->su_magic != SU_MAGIC) {
367: printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n");
368: error = EINVAL;
369: goto failed;
370: }
371: if (spp->sp_magic != SP_MAGIC) {
372: printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n");
373: error = EINVAL;
374: goto failed;
375: }
376:
377: mp->mnt_data = (qaddr_t)hpmp;
378: hpmp->hpm_devvp = devvp;
379: hpmp->hpm_dev = devvp->v_rdev;
380: hpmp->hpm_mp = mp;
381: hpmp->hpm_uid = argsp->uid;
382: hpmp->hpm_gid = argsp->gid;
383: hpmp->hpm_mode = argsp->mode;
384:
385: error = hpfs_bminit(hpmp);
386: if (error)
387: goto failed;
388:
389: error = hpfs_cpinit(hpmp, argsp);
390: if (error) {
391: hpfs_bmdeinit(hpmp);
392: goto failed;
393: }
394:
395: error = hpfs_root(mp, &vp);
396: if (error) {
397: hpfs_cpdeinit(hpmp);
398: hpfs_bmdeinit(hpmp);
399: goto failed;
400: }
401:
402: vput(vp);
403:
404: #if defined(__DragonFly__)
405: mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev);
406: mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
407: #else
408: mp->mnt_stat.f_fsid.val[0] = (long)dev;
409: mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_HPFS);
410: #endif
411: mp->mnt_maxsymlinklen = 0;
412: mp->mnt_flag |= MNT_LOCAL;
413: devvp->v_specmountpoint = mp;
414: return (0);
415:
416: failed:
417: if (bp)
418: brelse (bp);
419: mp->mnt_data = (qaddr_t)NULL;
420: #if defined(__DragonFly__)
421: devvp->v_specmountpoint = NULL;
422: #else
423: devvp->v_specflags &= ~SI_MOUNTEDON;
424: #endif
425: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, td);
426: return (error);
427: }
428:
429: #if !defined(__DragonFly__)
430: static int
431: hpfs_start(struct mount *mp, int flags, struct thread *td)
432: {
433: return (0);
434: }
435: #endif
436:
437: static int
438: hpfs_unmount(struct mount *mp, int mntflags, struct thread *td)
439: {
440: int error, flags, ronly;
441: struct hpfsmount *hpmp = VFSTOHPFS(mp);
442:
443: dprintf(("hpfs_unmount():\n"));
444:
445: ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
446:
447: flags = 0;
448: if(mntflags & MNT_FORCE)
449: flags |= FORCECLOSE;
450:
451: dprintf(("hpfs_unmount: vflushing...\n"));
452:
453: error = vflush(mp, 0, flags);
454: if (error) {
455: printf("hpfs_unmount: vflush failed: %d\n",error);
456: return (error);
457: }
458:
459: #if defined(__DragonFly__)
460: hpmp->hpm_devvp->v_specmountpoint = NULL;
461: #else
462: hpmp->hpm_devvp->v_specflags &= ~SI_MOUNTEDON;
463: #endif
464:
465: vinvalbuf(hpmp->hpm_devvp, V_SAVE, td, 0, 0);
466: error = VOP_CLOSE(hpmp->hpm_devvp, ronly ? FREAD : FREAD|FWRITE, td);
467:
468: vrele(hpmp->hpm_devvp);
469:
470: dprintf(("hpfs_umount: freeing memory...\n"));
471: hpfs_cpdeinit(hpmp);
472: hpfs_bmdeinit(hpmp);
473: mp->mnt_data = (qaddr_t)0;
474: mp->mnt_flag &= ~MNT_LOCAL;
475: FREE(hpmp, M_HPFSMNT);
476:
477: return (0);
478: }
479:
480: static int
481: hpfs_root(struct mount *mp, struct vnode **vpp)
482: {
483: int error = 0;
484: struct hpfsmount *hpmp = VFSTOHPFS(mp);
485:
486: dprintf(("hpfs_root():\n"));
487: error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, vpp);
488: if(error) {
489: printf("hpfs_root: VFS_VGET failed: %d\n",error);
490: return (error);
491: }
492:
493: return (error);
494: }
495:
496: static int
497: hpfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
498: {
499: struct hpfsmount *hpmp = VFSTOHPFS(mp);
500:
501: dprintf(("hpfs_statfs(): HPFS%d.%d\n",
502: hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver));
503:
504: #if defined(__DragonFly__)
505: sbp->f_type = mp->mnt_vfc->vfc_typenum;
506: #else /* defined(__NetBSD__) */
507: sbp->f_type = 0;
508: #endif
509: sbp->f_bsize = DEV_BSIZE;
510: sbp->f_iosize = DEV_BSIZE;
511: sbp->f_blocks = hpmp->hpm_su.su_btotal;
512: sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail;
513: sbp->f_ffree = 0;
514: sbp->f_files = 0;
515: if (sbp != &mp->mnt_stat) {
516: bcopy((caddr_t)mp->mnt_stat.f_mntonname,
517: (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
518: bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
519: (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
520: }
521: sbp->f_flags = mp->mnt_flag;
522:
523: return (0);
524: }
525:
526: #if !defined(__DragonFly__)
527: static int
528: hpfs_sync(struct mount *mp, int waitfor, struct ucred *cred,
529: struct thread *td)
530: {
531: return (0);
532: }
533:
534: static int
535: hpfs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
536: struct thread *td)
537: {
538: printf("hpfs_quotactl():\n");
539: return (EOPNOTSUPP);
540: }
541: #endif
542:
543: /*ARGSUSED*/
544: static int
545: hpfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
546: {
547: struct vnode *nvp;
548: struct hpfid *hpfhp = (struct hpfid *)fhp;
549: int error;
550:
551: if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, &nvp)) != 0) {
552: *vpp = NULLVP;
553: return (error);
554: }
555: /* XXX as unlink/rmdir/mkdir/creat are not currently possible
556: * with HPFS, we don't need to check anything else for now */
557: *vpp = nvp;
558:
559: return (0);
560: }
561:
562: static int
563: hpfs_vptofh(struct vnode *vp, struct fid *fhp)
564: {
565: struct hpfsnode *hpp;
566: struct hpfid *hpfhp;
567:
568: hpp = VTOHP(vp);
569: hpfhp = (struct hpfid *)fhp;
570: hpfhp->hpfid_len = sizeof(struct hpfid);
571: hpfhp->hpfid_ino = hpp->h_no;
572: /* hpfhp->hpfid_gen = hpp->h_gen; */
573: return (0);
574: }
575:
576: static int
577: hpfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
578: {
579: struct hpfsmount *hpmp = VFSTOHPFS(mp);
580: struct vnode *vp;
581: struct hpfsnode *hp;
582: struct buf *bp;
583: struct thread *td = curthread; /* XXX */
584: int error;
585:
586: dprintf(("hpfs_vget(0x%x): ",ino));
587:
588: *vpp = NULL;
589: hp = NULL;
590: vp = NULL;
591:
592: if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, td)) != NULL) {
593: dprintf(("hashed\n"));
594: return (0);
595: }
596:
597: /*
598: * We have to lock node creation for a while,
599: * but then we have to call getnewvnode(),
600: * this may cause hpfs_reclaim() to be called,
601: * this may need to VOP_VGET() parent dir for
602: * update reasons, and if parent is not in
603: * hash, we have to lock node creation...
604: * To solve this, we MALLOC, getnewvnode and init while
605: * not locked (probability of node appearence
606: * at that time is little, and anyway - we'll
607: * check for it).
608: */
609: MALLOC(hp, struct hpfsnode *, sizeof(struct hpfsnode),
610: M_HPFSNO, M_WAITOK);
611:
612: error = getnewvnode(VT_HPFS, hpmp->hpm_mp, hpfs_vnodeop_p, &vp);
613: if (error) {
614: printf("hpfs_vget: can't get new vnode\n");
615: FREE(hp, M_HPFSNO);
616: return (error);
617: }
618:
619: dprintf(("prenew "));
620:
621: vp->v_data = hp;
622:
623: if (ino == (ino_t)hpmp->hpm_su.su_rootfno)
624: vp->v_flag |= VROOT;
625:
626: lwkt_token_init(&hp->h_interlock);
627: lockinit(&hp->h_lock, 0, "hpnode", VLKTIMEOUT, 0);
628:
629: hp->h_flag = H_INVAL;
630: hp->h_vp = vp;
631: hp->h_hpmp = hpmp;
632: hp->h_no = ino;
633: hp->h_dev = hpmp->hpm_dev;
634: hp->h_uid = hpmp->hpm_uid;
635: hp->h_gid = hpmp->hpm_uid;
636: hp->h_mode = hpmp->hpm_mode;
637: hp->h_devvp = hpmp->hpm_devvp;
638: vref(hp->h_devvp);
639:
640: error = VN_LOCK(vp, LK_EXCLUSIVE, td);
641: if (error) {
642: vput(vp);
643: return (error);
644: }
645:
646: do {
647: if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, td)) != NULL) {
648: dprintf(("hashed2\n"));
649: vput(vp);
650: return (0);
651: }
652: } while(LOCKMGR(&hpfs_hphash_lock,LK_EXCLUSIVE|LK_SLEEPFAIL,NULL,NULL));
653:
654: hpfs_hphashins(hp);
655:
656: LOCKMGR(&hpfs_hphash_lock, LK_RELEASE, NULL, NULL);
657:
658: error = bread(hpmp->hpm_devvp, ino, FNODESIZE, &bp);
659: if (error) {
660: printf("hpfs_vget: can't read ino %d\n",ino);
661: vput(vp);
662: return (error);
663: }
664: bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode));
665: brelse(bp);
666:
667: if (hp->h_fn.fn_magic != FN_MAGIC) {
668: printf("hpfs_vget: MAGIC DOESN'T MATCH\n");
669: vput(vp);
670: return (EINVAL);
671: }
672:
673: vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG;
674: hp->h_flag &= ~H_INVAL;
675:
676: *vpp = vp;
677:
678: return (0);
679: }
680:
681: #if defined(__DragonFly__)
682: static struct vfsops hpfs_vfsops = {
683: hpfs_mount,
684: vfs_stdstart,
685: hpfs_unmount,
686: hpfs_root,
687: vfs_stdquotactl,
688: hpfs_statfs,
689: vfs_stdsync,
690: hpfs_vget,
691: hpfs_fhtovp,
692: hpfs_checkexp,
693: hpfs_vptofh,
694: hpfs_init,
695: hpfs_hphash_uninit,
696: vfs_stdextattrctl,
697: };
698: VFS_SET(hpfs_vfsops, hpfs, 0);
699: #else /* defined(__NetBSD__) */
700: extern struct vnodeopv_desc hpfs_vnodeop_opv_desc;
701:
702: struct vnodeopv_desc *hpfs_vnodeopv_descs[] = {
703: &hpfs_vnodeop_opv_desc,
704: NULL,
705: };
706:
707: struct vfsops hpfs_vfsops = {
708: MOUNT_HPFS,
709: hpfs_mount,
710: hpfs_start,
711: hpfs_unmount,
712: hpfs_root,
713: hpfs_quotactl,
714: hpfs_statfs,
715: hpfs_sync,
716: hpfs_vget,
717: hpfs_fhtovp,
718: hpfs_vptofh,
719: hpfs_init,
720: hpfs_sysctl,
721: hpfs_mountroot,
722: hpfs_checkexp,
723: hpfs_vnodeopv_descs,
724: };
725: #endif