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.7 2003/08/07 21:17:41 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 52 #if defined(__NetBSD__) 53 #include <miscfs/specfs/specdev.h> 54 #endif 55 56 #include "hpfs.h" 57 #include "hpfsmount.h" 58 #include "hpfs_subr.h" 59 60 #if defined(__FreeBSD__) 61 MALLOC_DEFINE(M_HPFSMNT, "HPFS mount", "HPFS mount structure"); 62 MALLOC_DEFINE(M_HPFSNO, "HPFS node", "HPFS node structure"); 63 #endif 64 65 static int hpfs_root __P((struct mount *, struct vnode **)); 66 static int hpfs_statfs __P((struct mount *, struct statfs *, 67 struct proc *)); 68 static int hpfs_unmount __P((struct mount *, int, struct proc *)); 69 static int hpfs_vget __P((struct mount *mp, ino_t ino, 70 struct vnode **vpp)); 71 static int hpfs_mountfs __P((struct vnode *, struct mount *, 72 struct hpfs_args *, struct proc *)); 73 static int hpfs_vptofh __P((struct vnode *, struct fid *)); 74 static int hpfs_fhtovp __P((struct mount *, struct fid *, 75 struct vnode **)); 76 77 #if !defined(__FreeBSD__) 78 static int hpfs_quotactl __P((struct mount *, int, uid_t, caddr_t, 79 struct proc *)); 80 static int hpfs_start __P((struct mount *, int, struct proc *)); 81 static int hpfs_sync __P((struct mount *, int, struct ucred *, 82 struct proc *)); 83 #endif 84 85 #if defined(__FreeBSD__) 86 struct sockaddr; 87 static int hpfs_mount __P((struct mount *, char *, caddr_t, 88 struct nameidata *, struct proc *)); 89 static int hpfs_init __P((struct vfsconf *)); 90 static int hpfs_checkexp __P((struct mount *, struct sockaddr *, 91 int *, struct ucred **)); 92 #else /* defined(__NetBSD__) */ 93 static int hpfs_mount __P((struct mount *, const char *, void *, 94 struct nameidata *, struct proc *)); 95 static void hpfs_init __P((void)); 96 static int hpfs_mountroot __P((void)); 97 static int hpfs_sysctl __P((int *, u_int, void *, size_t *, void *, 98 size_t, struct proc *)); 99 static int hpfs_checkexp __P((struct mount *, struct mbuf *, 100 int *, struct ucred **)); 101 #endif 102 103 /*ARGSUSED*/ 104 static int 105 hpfs_checkexp(mp, nam, exflagsp, credanonp) 106 #if defined(__FreeBSD__) 107 struct mount *mp; 108 struct sockaddr *nam; 109 int *exflagsp; 110 struct ucred **credanonp; 111 #else /* defined(__NetBSD__) */ 112 struct mount *mp; 113 struct mbuf *nam; 114 int *exflagsp; 115 struct ucred **credanonp; 116 #endif 117 { 118 struct netcred *np; 119 struct hpfsmount *hpm = VFSTOHPFS(mp); 120 121 /* 122 * Get the export permission structure for this <mp, client> tuple. 123 */ 124 np = vfs_export_lookup(mp, &hpm->hpm_export, nam); 125 if (np == NULL) 126 return (EACCES); 127 128 *exflagsp = np->netc_exflags; 129 *credanonp = &np->netc_anon; 130 return (0); 131 } 132 133 #if !defined(__FreeBSD__) 134 /*ARGSUSED*/ 135 static int 136 hpfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 137 int *name; 138 u_int namelen; 139 void *oldp; 140 size_t *oldlenp; 141 void *newp; 142 size_t newlen; 143 struct proc *p; 144 { 145 return (EINVAL); 146 } 147 148 static int 149 hpfs_mountroot() 150 { 151 return (EINVAL); 152 } 153 #endif 154 155 #if defined(__FreeBSD__) 156 static int 157 hpfs_init ( 158 struct vfsconf *vcp ) 159 #else /* defined(__NetBSD__) */ 160 static void 161 hpfs_init () 162 #endif 163 { 164 dprintf(("hpfs_init():\n")); 165 166 hpfs_hphashinit(); 167 #if defined(__FreeBSD__) 168 return 0; 169 #endif 170 } 171 172 static int 173 hpfs_mount ( 174 struct mount *mp, 175 #if defined(__FreeBSD__) 176 char *path, 177 caddr_t data, 178 #else /* defined(__NetBSD__) */ 179 const char *path, 180 void *data, 181 #endif 182 struct nameidata *ndp, 183 struct proc *p ) 184 { 185 u_int size; 186 int err = 0; 187 struct vnode *devvp; 188 struct hpfs_args args; 189 struct hpfsmount *hpmp = 0; 190 191 dprintf(("hpfs_mount():\n")); 192 /* 193 *** 194 * Mounting non-root file system or updating a file system 195 *** 196 */ 197 198 /* copy in user arguments*/ 199 err = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args)); 200 if (err) 201 goto error_1; /* can't get arguments*/ 202 203 /* 204 * If updating, check whether changing from read-only to 205 * read/write; if there is no device name, that's all we do. 206 */ 207 if (mp->mnt_flag & MNT_UPDATE) { 208 dprintf(("hpfs_mount: MNT_UPDATE: ")); 209 210 hpmp = VFSTOHPFS(mp); 211 212 if (args.fspec == 0) { 213 dprintf(("export 0x%x\n",args.export.ex_flags)); 214 err = vfs_export(mp, &hpmp->hpm_export, &args.export); 215 if (err) { 216 printf("hpfs_mount: vfs_export failed %d\n", 217 err); 218 } 219 goto success; 220 } else { 221 dprintf(("name [FAILED]\n")); 222 err = EINVAL; 223 goto success; 224 } 225 dprintf(("\n")); 226 } 227 228 /* 229 * Not an update, or updating the name: look up the name 230 * and verify that it refers to a sensible block device. 231 */ 232 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 233 err = namei(ndp); 234 if (err) { 235 /* can't get devvp!*/ 236 goto error_1; 237 } 238 239 devvp = ndp->ni_vp; 240 241 #if defined(__FreeBSD__) 242 if (!vn_isdisk(devvp, &err)) 243 goto error_2; 244 #else /* defined(__NetBSD__) */ 245 if (devvp->v_type != VBLK) { 246 err = ENOTBLK; 247 goto error_2; 248 } 249 if (major(devvp->v_rdev) >= nblkdev) { 250 err = ENXIO; 251 goto error_2; 252 } 253 #endif 254 255 /* 256 ******************** 257 * NEW MOUNT 258 ******************** 259 */ 260 261 /* 262 * Since this is a new mount, we want the names for 263 * the device and the mount point copied in. If an 264 * error occurs, the mountpoint is discarded by the 265 * upper level code. 266 */ 267 /* Save "last mounted on" info for mount point (NULL pad)*/ 268 copyinstr( path, /* mount point*/ 269 mp->mnt_stat.f_mntonname, /* save area*/ 270 MNAMELEN - 1, /* max size*/ 271 &size); /* real size*/ 272 bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 273 274 /* Save "mounted from" info for mount point (NULL pad)*/ 275 copyinstr( args.fspec, /* device name*/ 276 mp->mnt_stat.f_mntfromname, /* save area*/ 277 MNAMELEN - 1, /* max size*/ 278 &size); /* real size*/ 279 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 280 281 err = hpfs_mountfs(devvp, mp, &args, p); 282 if (err) 283 goto error_2; 284 285 /* 286 * Initialize FS stat information in mount struct; uses both 287 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname 288 * 289 * This code is common to root and non-root mounts 290 */ 291 (void)VFS_STATFS(mp, &mp->mnt_stat, p); 292 293 goto success; 294 295 296 error_2: /* error with devvp held*/ 297 298 /* release devvp before failing*/ 299 vrele(devvp); 300 301 error_1: /* no state to back out*/ 302 303 success: 304 return( err); 305 } 306 307 /* 308 * Common code for mount and mountroot 309 */ 310 int 311 hpfs_mountfs(devvp, mp, argsp, p) 312 struct vnode *devvp; 313 struct mount *mp; 314 struct hpfs_args *argsp; 315 struct proc *p; 316 { 317 int error, ncount, ronly; 318 struct sublock *sup; 319 struct spblock *spp; 320 struct hpfsmount *hpmp; 321 struct buf *bp = NULL; 322 struct vnode *vp; 323 dev_t dev = devvp->v_rdev; 324 325 dprintf(("hpfs_mountfs():\n")); 326 /* 327 * Disallow multiple mounts of the same device. 328 * Disallow mounting of a device that is currently in use 329 * (except for root, which might share swap device for miniroot). 330 * Flush out any old buffers remaining from a previous use. 331 */ 332 error = vfs_mountedon(devvp); 333 if (error) 334 return (error); 335 ncount = vcount(devvp); 336 #if defined(__FreeBSD__) 337 if (devvp->v_object) 338 ncount -= 1; 339 #endif 340 if (ncount > 1 && devvp != rootvp) 341 return (EBUSY); 342 343 #if defined(__FreeBSD__) 344 VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p); 345 error = vinvalbuf(devvp, V_SAVE, p, 0, 0); 346 VOP__UNLOCK(devvp, 0, p); 347 #else 348 error = vinvalbuf(devvp, V_SAVE, p, 0, 0); 349 #endif 350 if (error) 351 return (error); 352 353 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 354 VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p); 355 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 356 VOP__UNLOCK(devvp, 0, p); 357 if (error) 358 return (error); 359 360 /* 361 * Do actual mount 362 */ 363 hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK); 364 bzero(hpmp, sizeof(struct hpfsmount)); 365 366 /* Read in SuperBlock */ 367 error = bread(devvp, SUBLOCK, SUSIZE, NOCRED, &bp); 368 if (error) 369 goto failed; 370 bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock)); 371 brelse(bp); bp = NULL; 372 373 /* Read in SpareBlock */ 374 error = bread(devvp, SPBLOCK, SPSIZE, NOCRED, &bp); 375 if (error) 376 goto failed; 377 bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock)); 378 brelse(bp); bp = NULL; 379 380 sup = &hpmp->hpm_su; 381 spp = &hpmp->hpm_sp; 382 383 /* Check magic */ 384 if (sup->su_magic != SU_MAGIC) { 385 printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n"); 386 error = EINVAL; 387 goto failed; 388 } 389 if (spp->sp_magic != SP_MAGIC) { 390 printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n"); 391 error = EINVAL; 392 goto failed; 393 } 394 395 mp->mnt_data = (qaddr_t)hpmp; 396 hpmp->hpm_devvp = devvp; 397 hpmp->hpm_dev = devvp->v_rdev; 398 hpmp->hpm_mp = mp; 399 hpmp->hpm_uid = argsp->uid; 400 hpmp->hpm_gid = argsp->gid; 401 hpmp->hpm_mode = argsp->mode; 402 403 error = hpfs_bminit(hpmp); 404 if (error) 405 goto failed; 406 407 error = hpfs_cpinit(hpmp, argsp); 408 if (error) { 409 hpfs_bmdeinit(hpmp); 410 goto failed; 411 } 412 413 error = hpfs_root(mp, &vp); 414 if (error) { 415 hpfs_cpdeinit(hpmp); 416 hpfs_bmdeinit(hpmp); 417 goto failed; 418 } 419 420 vput(vp); 421 422 #if defined(__FreeBSD__) 423 mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev); 424 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 425 #else 426 mp->mnt_stat.f_fsid.val[0] = (long)dev; 427 mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_HPFS); 428 #endif 429 mp->mnt_maxsymlinklen = 0; 430 mp->mnt_flag |= MNT_LOCAL; 431 devvp->v_specmountpoint = mp; 432 return (0); 433 434 failed: 435 if (bp) 436 brelse (bp); 437 mp->mnt_data = (qaddr_t)NULL; 438 #if defined(__FreeBSD__) 439 devvp->v_specmountpoint = NULL; 440 #else 441 devvp->v_specflags &= ~SI_MOUNTEDON; 442 #endif 443 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 444 return (error); 445 } 446 447 #if !defined(__FreeBSD__) 448 static int 449 hpfs_start ( 450 struct mount *mp, 451 int flags, 452 struct proc *p ) 453 { 454 return (0); 455 } 456 #endif 457 458 static int 459 hpfs_unmount( 460 struct mount *mp, 461 int mntflags, 462 struct proc *p) 463 { 464 int error, flags, ronly; 465 struct hpfsmount *hpmp = VFSTOHPFS(mp); 466 467 dprintf(("hpfs_unmount():\n")); 468 469 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 470 471 flags = 0; 472 if(mntflags & MNT_FORCE) 473 flags |= FORCECLOSE; 474 475 dprintf(("hpfs_unmount: vflushing...\n")); 476 477 error = vflush(mp, 0, flags); 478 if (error) { 479 printf("hpfs_unmount: vflush failed: %d\n",error); 480 return (error); 481 } 482 483 #if defined(__FreeBSD__) 484 hpmp->hpm_devvp->v_specmountpoint = NULL; 485 #else 486 hpmp->hpm_devvp->v_specflags &= ~SI_MOUNTEDON; 487 #endif 488 489 vinvalbuf(hpmp->hpm_devvp, V_SAVE, p, 0, 0); 490 error = VOP_CLOSE(hpmp->hpm_devvp, ronly ? FREAD : FREAD|FWRITE, 491 NOCRED, p); 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 proc *p) 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 proc *p) 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 proc *p) 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 proc *p = curproc; /* 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, p)) != 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, p); 686 if (error) { 687 vput(vp); 688 return (error); 689 } 690 691 do { 692 if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, p)) != 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, NOCRED, &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