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