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.10 2003/09/23 05:03:52 dillon 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(__FreeBSD__) 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(__FreeBSD__) 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(__FreeBSD__) 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(mp, nam, exflagsp, credanonp) 107 #if defined(__FreeBSD__) 108 struct mount *mp; 109 struct sockaddr *nam; 110 int *exflagsp; 111 struct ucred **credanonp; 112 #else /* defined(__NetBSD__) */ 113 struct mount *mp; 114 struct mbuf *nam; 115 int *exflagsp; 116 struct ucred **credanonp; 117 #endif 118 { 119 struct netcred *np; 120 struct hpfsmount *hpm = VFSTOHPFS(mp); 121 122 /* 123 * Get the export permission structure for this <mp, client> tuple. 124 */ 125 np = vfs_export_lookup(mp, &hpm->hpm_export, nam); 126 if (np == NULL) 127 return (EACCES); 128 129 *exflagsp = np->netc_exflags; 130 *credanonp = &np->netc_anon; 131 return (0); 132 } 133 134 #if !defined(__FreeBSD__) 135 /*ARGSUSED*/ 136 static int 137 hpfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, td) 138 int *name; 139 u_int namelen; 140 void *oldp; 141 size_t *oldlenp; 142 void *newp; 143 size_t newlen; 144 struct thread *td; 145 { 146 return (EINVAL); 147 } 148 149 static int 150 hpfs_mountroot() 151 { 152 return (EINVAL); 153 } 154 #endif 155 156 #if defined(__FreeBSD__) 157 static int 158 hpfs_init ( 159 struct vfsconf *vcp ) 160 #else /* defined(__NetBSD__) */ 161 static void 162 hpfs_init () 163 #endif 164 { 165 dprintf(("hpfs_init():\n")); 166 167 hpfs_hphashinit(); 168 #if defined(__FreeBSD__) 169 return 0; 170 #endif 171 } 172 173 static int 174 hpfs_mount ( 175 struct mount *mp, 176 #if defined(__FreeBSD__) 177 char *path, 178 caddr_t data, 179 #else /* defined(__NetBSD__) */ 180 const char *path, 181 void *data, 182 #endif 183 struct nameidata *ndp, 184 struct thread *td ) 185 { 186 u_int size; 187 int err = 0; 188 struct vnode *devvp; 189 struct hpfs_args args; 190 struct hpfsmount *hpmp = 0; 191 192 dprintf(("hpfs_mount():\n")); 193 /* 194 *** 195 * Mounting non-root file system or updating a file system 196 *** 197 */ 198 199 /* copy in user arguments*/ 200 err = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args)); 201 if (err) 202 goto error_1; /* can't get arguments*/ 203 204 /* 205 * If updating, check whether changing from read-only to 206 * read/write; if there is no device name, that's all we do. 207 */ 208 if (mp->mnt_flag & MNT_UPDATE) { 209 dprintf(("hpfs_mount: MNT_UPDATE: ")); 210 211 hpmp = VFSTOHPFS(mp); 212 213 if (args.fspec == 0) { 214 dprintf(("export 0x%x\n",args.export.ex_flags)); 215 err = vfs_export(mp, &hpmp->hpm_export, &args.export); 216 if (err) { 217 printf("hpfs_mount: vfs_export failed %d\n", 218 err); 219 } 220 goto success; 221 } else { 222 dprintf(("name [FAILED]\n")); 223 err = EINVAL; 224 goto success; 225 } 226 dprintf(("\n")); 227 } 228 229 /* 230 * Not an update, or updating the name: look up the name 231 * and verify that it refers to a sensible block device. 232 */ 233 NDINIT(ndp, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, args.fspec, td); 234 err = namei(ndp); 235 if (err) { 236 /* can't get devvp!*/ 237 goto error_1; 238 } 239 240 devvp = ndp->ni_vp; 241 242 #if defined(__FreeBSD__) 243 if (!vn_isdisk(devvp, &err)) 244 goto error_2; 245 #else /* defined(__NetBSD__) */ 246 if (devvp->v_type != VBLK) { 247 err = ENOTBLK; 248 goto error_2; 249 } 250 if (major(devvp->v_rdev) >= nblkdev) { 251 err = ENXIO; 252 goto error_2; 253 } 254 #endif 255 256 /* 257 ******************** 258 * NEW MOUNT 259 ******************** 260 */ 261 262 /* 263 * Since this is a new mount, we want the names for 264 * the device and the mount point copied in. If an 265 * error occurs, the mountpoint is discarded by the 266 * upper level code. 267 */ 268 /* Save "last mounted on" info for mount point (NULL pad)*/ 269 copyinstr( path, /* mount point*/ 270 mp->mnt_stat.f_mntonname, /* save area*/ 271 MNAMELEN - 1, /* max size*/ 272 &size); /* real size*/ 273 bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 274 275 /* Save "mounted from" info for mount point (NULL pad)*/ 276 copyinstr( args.fspec, /* device name*/ 277 mp->mnt_stat.f_mntfromname, /* save area*/ 278 MNAMELEN - 1, /* max size*/ 279 &size); /* real size*/ 280 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 281 282 err = hpfs_mountfs(devvp, mp, &args, td); 283 if (err) 284 goto error_2; 285 286 /* 287 * Initialize FS stat information in mount struct; uses both 288 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname 289 * 290 * This code is common to root and non-root mounts 291 */ 292 (void)VFS_STATFS(mp, &mp->mnt_stat, td); 293 294 goto success; 295 296 297 error_2: /* error with devvp held*/ 298 299 /* release devvp before failing*/ 300 vrele(devvp); 301 302 error_1: /* no state to back out*/ 303 304 success: 305 return( err); 306 } 307 308 /* 309 * Common code for mount and mountroot 310 */ 311 int 312 hpfs_mountfs(devvp, mp, argsp, td) 313 struct vnode *devvp; 314 struct mount *mp; 315 struct hpfs_args *argsp; 316 struct thread *td; 317 { 318 int error, ncount, ronly; 319 struct sublock *sup; 320 struct spblock *spp; 321 struct hpfsmount *hpmp; 322 struct buf *bp = NULL; 323 struct vnode *vp; 324 dev_t dev = devvp->v_rdev; 325 326 dprintf(("hpfs_mountfs():\n")); 327 /* 328 * Disallow multiple mounts of the same device. 329 * Disallow mounting of a device that is currently in use 330 * (except for root, which might share swap device for miniroot). 331 * Flush out any old buffers remaining from a previous use. 332 */ 333 error = vfs_mountedon(devvp); 334 if (error) 335 return (error); 336 ncount = vcount(devvp); 337 #if defined(__FreeBSD__) 338 if (devvp->v_object) 339 ncount -= 1; 340 #endif 341 if (ncount > 1 && devvp != rootvp) 342 return (EBUSY); 343 344 #if defined(__FreeBSD__) 345 VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, td); 346 error = vinvalbuf(devvp, V_SAVE, td, 0, 0); 347 VOP__UNLOCK(devvp, 0, td); 348 #else 349 error = vinvalbuf(devvp, V_SAVE, td, 0, 0); 350 #endif 351 if (error) 352 return (error); 353 354 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 355 VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, td); 356 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td); 357 VOP__UNLOCK(devvp, 0, td); 358 if (error) 359 return (error); 360 361 /* 362 * Do actual mount 363 */ 364 hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK); 365 bzero(hpmp, sizeof(struct hpfsmount)); 366 367 /* Read in SuperBlock */ 368 error = bread(devvp, SUBLOCK, SUSIZE, &bp); 369 if (error) 370 goto failed; 371 bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock)); 372 brelse(bp); bp = NULL; 373 374 /* Read in SpareBlock */ 375 error = bread(devvp, SPBLOCK, SPSIZE, &bp); 376 if (error) 377 goto failed; 378 bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock)); 379 brelse(bp); bp = NULL; 380 381 sup = &hpmp->hpm_su; 382 spp = &hpmp->hpm_sp; 383 384 /* Check magic */ 385 if (sup->su_magic != SU_MAGIC) { 386 printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n"); 387 error = EINVAL; 388 goto failed; 389 } 390 if (spp->sp_magic != SP_MAGIC) { 391 printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n"); 392 error = EINVAL; 393 goto failed; 394 } 395 396 mp->mnt_data = (qaddr_t)hpmp; 397 hpmp->hpm_devvp = devvp; 398 hpmp->hpm_dev = devvp->v_rdev; 399 hpmp->hpm_mp = mp; 400 hpmp->hpm_uid = argsp->uid; 401 hpmp->hpm_gid = argsp->gid; 402 hpmp->hpm_mode = argsp->mode; 403 404 error = hpfs_bminit(hpmp); 405 if (error) 406 goto failed; 407 408 error = hpfs_cpinit(hpmp, argsp); 409 if (error) { 410 hpfs_bmdeinit(hpmp); 411 goto failed; 412 } 413 414 error = hpfs_root(mp, &vp); 415 if (error) { 416 hpfs_cpdeinit(hpmp); 417 hpfs_bmdeinit(hpmp); 418 goto failed; 419 } 420 421 vput(vp); 422 423 #if defined(__FreeBSD__) 424 mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev); 425 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 426 #else 427 mp->mnt_stat.f_fsid.val[0] = (long)dev; 428 mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_HPFS); 429 #endif 430 mp->mnt_maxsymlinklen = 0; 431 mp->mnt_flag |= MNT_LOCAL; 432 devvp->v_specmountpoint = mp; 433 return (0); 434 435 failed: 436 if (bp) 437 brelse (bp); 438 mp->mnt_data = (qaddr_t)NULL; 439 #if defined(__FreeBSD__) 440 devvp->v_specmountpoint = NULL; 441 #else 442 devvp->v_specflags &= ~SI_MOUNTEDON; 443 #endif 444 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, td); 445 return (error); 446 } 447 448 #if !defined(__FreeBSD__) 449 static int 450 hpfs_start ( 451 struct mount *mp, 452 int flags, 453 struct thread *td ) 454 { 455 return (0); 456 } 457 #endif 458 459 static int 460 hpfs_unmount( 461 struct mount *mp, 462 int mntflags, 463 struct thread *td) 464 { 465 int error, flags, ronly; 466 struct hpfsmount *hpmp = VFSTOHPFS(mp); 467 468 dprintf(("hpfs_unmount():\n")); 469 470 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 471 472 flags = 0; 473 if(mntflags & MNT_FORCE) 474 flags |= FORCECLOSE; 475 476 dprintf(("hpfs_unmount: vflushing...\n")); 477 478 error = vflush(mp, 0, flags); 479 if (error) { 480 printf("hpfs_unmount: vflush failed: %d\n",error); 481 return (error); 482 } 483 484 #if defined(__FreeBSD__) 485 hpmp->hpm_devvp->v_specmountpoint = NULL; 486 #else 487 hpmp->hpm_devvp->v_specflags &= ~SI_MOUNTEDON; 488 #endif 489 490 vinvalbuf(hpmp->hpm_devvp, V_SAVE, td, 0, 0); 491 error = VOP_CLOSE(hpmp->hpm_devvp, ronly ? FREAD : FREAD|FWRITE, td); 492 493 vrele(hpmp->hpm_devvp); 494 495 dprintf(("hpfs_umount: freeing memory...\n")); 496 hpfs_cpdeinit(hpmp); 497 hpfs_bmdeinit(hpmp); 498 mp->mnt_data = (qaddr_t)0; 499 mp->mnt_flag &= ~MNT_LOCAL; 500 FREE(hpmp, M_HPFSMNT); 501 502 return (0); 503 } 504 505 static int 506 hpfs_root( 507 struct mount *mp, 508 struct vnode **vpp ) 509 { 510 int error = 0; 511 struct hpfsmount *hpmp = VFSTOHPFS(mp); 512 513 dprintf(("hpfs_root():\n")); 514 error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, vpp); 515 if(error) { 516 printf("hpfs_root: VFS_VGET failed: %d\n",error); 517 return (error); 518 } 519 520 return (error); 521 } 522 523 static int 524 hpfs_statfs( 525 struct mount *mp, 526 struct statfs *sbp, 527 struct thread *td) 528 { 529 struct hpfsmount *hpmp = VFSTOHPFS(mp); 530 531 dprintf(("hpfs_statfs(): HPFS%d.%d\n", 532 hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver)); 533 534 #if defined(__FreeBSD__) 535 sbp->f_type = mp->mnt_vfc->vfc_typenum; 536 #else /* defined(__NetBSD__) */ 537 sbp->f_type = 0; 538 #endif 539 sbp->f_bsize = DEV_BSIZE; 540 sbp->f_iosize = DEV_BSIZE; 541 sbp->f_blocks = hpmp->hpm_su.su_btotal; 542 sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail; 543 sbp->f_ffree = 0; 544 sbp->f_files = 0; 545 if (sbp != &mp->mnt_stat) { 546 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 547 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 548 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 549 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 550 } 551 sbp->f_flags = mp->mnt_flag; 552 553 return (0); 554 } 555 556 #if !defined(__FreeBSD__) 557 static int 558 hpfs_sync ( 559 struct mount *mp, 560 int waitfor, 561 struct ucred *cred, 562 struct thread *td) 563 { 564 return (0); 565 } 566 567 static int 568 hpfs_quotactl ( 569 struct mount *mp, 570 int cmds, 571 uid_t uid, 572 caddr_t arg, 573 struct thread *td) 574 { 575 printf("hpfs_quotactl():\n"); 576 return (EOPNOTSUPP); 577 } 578 #endif 579 580 /*ARGSUSED*/ 581 static int 582 hpfs_fhtovp( 583 struct mount *mp, 584 struct fid *fhp, 585 struct vnode **vpp) 586 { 587 struct vnode *nvp; 588 struct hpfid *hpfhp = (struct hpfid *)fhp; 589 int error; 590 591 if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, &nvp)) != 0) { 592 *vpp = NULLVP; 593 return (error); 594 } 595 /* XXX as unlink/rmdir/mkdir/creat are not currently possible 596 * with HPFS, we don't need to check anything else for now */ 597 *vpp = nvp; 598 599 return (0); 600 } 601 602 static int 603 hpfs_vptofh( 604 struct vnode *vp, 605 struct fid *fhp) 606 { 607 struct hpfsnode *hpp; 608 struct hpfid *hpfhp; 609 610 hpp = VTOHP(vp); 611 hpfhp = (struct hpfid *)fhp; 612 hpfhp->hpfid_len = sizeof(struct hpfid); 613 hpfhp->hpfid_ino = hpp->h_no; 614 /* hpfhp->hpfid_gen = hpp->h_gen; */ 615 return (0); 616 } 617 618 static int 619 hpfs_vget( 620 struct mount *mp, 621 ino_t ino, 622 struct vnode **vpp) 623 { 624 struct hpfsmount *hpmp = VFSTOHPFS(mp); 625 struct vnode *vp; 626 struct hpfsnode *hp; 627 struct buf *bp; 628 struct thread *td = curthread; /* XXX */ 629 int error; 630 631 dprintf(("hpfs_vget(0x%x): ",ino)); 632 633 *vpp = NULL; 634 hp = NULL; 635 vp = NULL; 636 637 if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, td)) != NULL) { 638 dprintf(("hashed\n")); 639 return (0); 640 } 641 642 /* 643 * We have to lock node creation for a while, 644 * but then we have to call getnewvnode(), 645 * this may cause hpfs_reclaim() to be called, 646 * this may need to VOP_VGET() parent dir for 647 * update reasons, and if parent is not in 648 * hash, we have to lock node creation... 649 * To solve this, we MALLOC, getnewvnode and init while 650 * not locked (probability of node appearence 651 * at that time is little, and anyway - we'll 652 * check for it). 653 */ 654 MALLOC(hp, struct hpfsnode *, sizeof(struct hpfsnode), 655 M_HPFSNO, M_WAITOK); 656 657 error = getnewvnode(VT_HPFS, hpmp->hpm_mp, hpfs_vnodeop_p, &vp); 658 if (error) { 659 printf("hpfs_vget: can't get new vnode\n"); 660 FREE(hp, M_HPFSNO); 661 return (error); 662 } 663 664 dprintf(("prenew ")); 665 666 vp->v_data = hp; 667 668 if (ino == (ino_t)hpmp->hpm_su.su_rootfno) 669 vp->v_flag |= VROOT; 670 671 lwkt_inittoken(&hp->h_interlock); 672 lockinit(&hp->h_lock, 0, "hpnode", VLKTIMEOUT, 0); 673 674 hp->h_flag = H_INVAL; 675 hp->h_vp = vp; 676 hp->h_hpmp = hpmp; 677 hp->h_no = ino; 678 hp->h_dev = hpmp->hpm_dev; 679 hp->h_uid = hpmp->hpm_uid; 680 hp->h_gid = hpmp->hpm_uid; 681 hp->h_mode = hpmp->hpm_mode; 682 hp->h_devvp = hpmp->hpm_devvp; 683 VREF(hp->h_devvp); 684 685 error = VN_LOCK(vp, LK_EXCLUSIVE, td); 686 if (error) { 687 vput(vp); 688 return (error); 689 } 690 691 do { 692 if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, td)) != NULL) { 693 dprintf(("hashed2\n")); 694 vput(vp); 695 return (0); 696 } 697 } while(LOCKMGR(&hpfs_hphash_lock,LK_EXCLUSIVE|LK_SLEEPFAIL,NULL,NULL)); 698 699 hpfs_hphashins(hp); 700 701 LOCKMGR(&hpfs_hphash_lock, LK_RELEASE, NULL, NULL); 702 703 error = bread(hpmp->hpm_devvp, ino, FNODESIZE, &bp); 704 if (error) { 705 printf("hpfs_vget: can't read ino %d\n",ino); 706 vput(vp); 707 return (error); 708 } 709 bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode)); 710 brelse(bp); 711 712 if (hp->h_fn.fn_magic != FN_MAGIC) { 713 printf("hpfs_vget: MAGIC DOESN'T MATCH\n"); 714 vput(vp); 715 return (EINVAL); 716 } 717 718 vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG; 719 hp->h_flag &= ~H_INVAL; 720 721 *vpp = vp; 722 723 return (0); 724 } 725 726 #if defined(__FreeBSD__) 727 static struct vfsops hpfs_vfsops = { 728 hpfs_mount, 729 vfs_stdstart, 730 hpfs_unmount, 731 hpfs_root, 732 vfs_stdquotactl, 733 hpfs_statfs, 734 vfs_stdsync, 735 hpfs_vget, 736 hpfs_fhtovp, 737 hpfs_checkexp, 738 hpfs_vptofh, 739 hpfs_init, 740 vfs_stduninit, 741 vfs_stdextattrctl, 742 }; 743 VFS_SET(hpfs_vfsops, hpfs, 0); 744 #else /* defined(__NetBSD__) */ 745 extern struct vnodeopv_desc hpfs_vnodeop_opv_desc; 746 747 struct vnodeopv_desc *hpfs_vnodeopv_descs[] = { 748 &hpfs_vnodeop_opv_desc, 749 NULL, 750 }; 751 752 struct vfsops hpfs_vfsops = { 753 MOUNT_HPFS, 754 hpfs_mount, 755 hpfs_start, 756 hpfs_unmount, 757 hpfs_root, 758 hpfs_quotactl, 759 hpfs_statfs, 760 hpfs_sync, 761 hpfs_vget, 762 hpfs_fhtovp, 763 hpfs_vptofh, 764 hpfs_init, 765 hpfs_sysctl, 766 hpfs_mountroot, 767 hpfs_checkexp, 768 hpfs_vnodeopv_descs, 769 }; 770 #endif 771