hpfs_vfsops.c revision 137478
1219820Sjeff/*- 2219820Sjeff * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) 3219820Sjeff * All rights reserved. 4219820Sjeff * 5219820Sjeff * Redistribution and use in source and binary forms, with or without 6219820Sjeff * modification, are permitted provided that the following conditions 7219820Sjeff * are met: 8219820Sjeff * 1. Redistributions of source code must retain the above copyright 9219820Sjeff * notice, this list of conditions and the following disclaimer. 10219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright 11219820Sjeff * notice, this list of conditions and the following disclaimer in the 12219820Sjeff * documentation and/or other materials provided with the distribution. 13219820Sjeff * 14219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15219820Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17219820Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18219820Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19219820Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20219820Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22219820Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23219820Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24219820Sjeff * SUCH DAMAGE. 25219820Sjeff * 26219820Sjeff * $FreeBSD: head/sys/fs/hpfs/hpfs_vfsops.c 137478 2004-11-09 22:14:57Z phk $ 27219820Sjeff */ 28219820Sjeff 29219820Sjeff 30219820Sjeff#include <sys/param.h> 31219820Sjeff#include <sys/systm.h> 32219820Sjeff#include <sys/namei.h> 33219820Sjeff#include <sys/conf.h> 34219820Sjeff#include <sys/proc.h> 35219820Sjeff#include <sys/kernel.h> 36219820Sjeff#include <sys/vnode.h> 37255932Salfred#include <sys/mount.h> 38219820Sjeff#include <sys/bio.h> 39219820Sjeff#include <sys/buf.h> 40255932Salfred#include <sys/fcntl.h> 41255932Salfred#include <sys/malloc.h> 42255932Salfred 43255932Salfred#include <geom/geom.h> 44219820Sjeff#include <geom/geom_vfs.h> 45255932Salfred 46219820Sjeff#include <vm/vm.h> 47219820Sjeff#include <vm/vm_param.h> 48219820Sjeff#include <vm/vm_page.h> 49219820Sjeff#include <vm/vm_object.h> 50219820Sjeff#include <vm/vm_extern.h> 51255932Salfred 52255932Salfred#include <fs/hpfs/hpfs.h> 53255932Salfred#include <fs/hpfs/hpfsmount.h> 54255932Salfred#include <fs/hpfs/hpfs_subr.h> 55255932Salfred 56255932SalfredMALLOC_DEFINE(M_HPFSMNT, "HPFS mount", "HPFS mount structure"); 57219820SjeffMALLOC_DEFINE(M_HPFSNO, "HPFS node", "HPFS node structure"); 58219820Sjeff 59219820Sjeffstruct sockaddr; 60219820Sjeff 61219820Sjeffstatic int hpfs_mountfs(register struct vnode *, struct mount *, 62219820Sjeff struct hpfs_args *, struct thread *); 63219820Sjeff 64219820Sjeffstatic vfs_init_t hpfs_init; 65219820Sjeffstatic vfs_uninit_t hpfs_uninit; 66219820Sjeffstatic vfs_fhtovp_t hpfs_fhtovp; 67219820Sjeffstatic vfs_vget_t hpfs_vget; 68219820Sjeffstatic vfs_omount_t hpfs_omount; 69219820Sjeffstatic vfs_root_t hpfs_root; 70219820Sjeffstatic vfs_statfs_t hpfs_statfs; 71219820Sjeffstatic vfs_unmount_t hpfs_unmount; 72219820Sjeffstatic vfs_vptofh_t hpfs_vptofh; 73219820Sjeff 74219820Sjeffstatic int 75219820Sjeffhpfs_init ( 76219820Sjeff struct vfsconf *vcp ) 77219820Sjeff{ 78219820Sjeff dprintf(("hpfs_init():\n")); 79255932Salfred 80219820Sjeff hpfs_hphashinit(); 81219820Sjeff return 0; 82219820Sjeff} 83255932Salfred 84255932Salfredstatic int 85255932Salfredhpfs_uninit (vfsp) 86255932Salfred struct vfsconf *vfsp; 87255932Salfred{ 88255932Salfred hpfs_hphashdestroy(); 89255932Salfred return 0;; 90255932Salfred} 91255932Salfred 92255932Salfredstatic int 93255932Salfredhpfs_omount ( 94255932Salfred struct mount *mp, 95255932Salfred char *path, 96255932Salfred caddr_t data, 97255932Salfred struct thread *td ) 98255932Salfred{ 99255932Salfred size_t size; 100255932Salfred int err = 0; 101255932Salfred struct vnode *devvp; 102255932Salfred struct hpfs_args args; 103255932Salfred struct hpfsmount *hpmp = 0; 104255932Salfred struct nameidata ndp; 105255932Salfred 106255932Salfred dprintf(("hpfs_omount():\n")); 107255932Salfred /* 108255932Salfred *** 109219820Sjeff * Mounting non-root filesystem or updating a filesystem 110219820Sjeff *** 111219820Sjeff */ 112219820Sjeff 113219820Sjeff /* copy in user arguments*/ 114219820Sjeff err = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args)); 115219820Sjeff if (err) 116219820Sjeff goto error_1; /* can't get arguments*/ 117219820Sjeff 118219820Sjeff /* 119219820Sjeff * If updating, check whether changing from read-only to 120219820Sjeff * read/write; if there is no device name, that's all we do. 121219820Sjeff */ 122219820Sjeff if (mp->mnt_flag & MNT_UPDATE) { 123255932Salfred dprintf(("hpfs_omount: MNT_UPDATE: ")); 124219820Sjeff 125255932Salfred hpmp = VFSTOHPFS(mp); 126219820Sjeff 127219820Sjeff if (args.fspec == 0) { 128219820Sjeff dprintf(("export 0x%x\n",args.export.ex_flags)); 129219820Sjeff err = vfs_export(mp, &args.export); 130219820Sjeff if (err) { 131255932Salfred printf("hpfs_omount: vfs_export failed %d\n", 132219820Sjeff err); 133255932Salfred } 134255932Salfred goto success; 135219820Sjeff } else { 136219820Sjeff dprintf(("name [FAILED]\n")); 137219820Sjeff err = EINVAL; 138255932Salfred goto success; 139255932Salfred } 140255932Salfred dprintf(("\n")); 141219820Sjeff } 142255932Salfred 143255932Salfred /* 144219820Sjeff * Not an update, or updating the name: look up the name 145219820Sjeff * and verify that it refers to a sensible block device. 146219820Sjeff */ 147219820Sjeff NDINIT(&ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, td); 148219820Sjeff err = namei(&ndp); 149255932Salfred if (err) { 150255932Salfred /* can't get devvp!*/ 151219820Sjeff goto error_1; 152219820Sjeff } 153219820Sjeff 154219820Sjeff devvp = ndp.ni_vp; 155219820Sjeff 156219820Sjeff if (!vn_isdisk(devvp, &err)) 157219820Sjeff goto error_2; 158219820Sjeff 159219820Sjeff /* 160219820Sjeff ******************** 161219820Sjeff * NEW MOUNT 162219820Sjeff ******************** 163219820Sjeff */ 164219820Sjeff 165219820Sjeff /* 166219820Sjeff * Since this is a new mount, we want the names for 167219820Sjeff * the device and the mount point copied in. If an 168219820Sjeff * error occurs, the mountpoint is discarded by the 169255932Salfred * upper level code. Note that vfs_omount() handles 170255932Salfred * copying the mountpoint f_mntonname for us, so we 171219820Sjeff * don't have to do it here unless we want to set it 172219820Sjeff * to something other than "path" for some rason. 173219820Sjeff */ 174255932Salfred /* Save "mounted from" info for mount point (NULL pad)*/ 175219820Sjeff copyinstr( args.fspec, /* device name*/ 176255932Salfred mp->mnt_stat.f_mntfromname, /* save area*/ 177219820Sjeff MNAMELEN - 1, /* max size*/ 178219820Sjeff &size); /* real size*/ 179219820Sjeff bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 180219820Sjeff 181219820Sjeff err = hpfs_mountfs(devvp, mp, &args, td); 182255932Salfred if (err) 183255932Salfred goto error_2; 184255932Salfred 185255932Salfred /* 186255932Salfred * Initialize FS stat information in mount struct; uses both 187255932Salfred * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname 188255932Salfred * 189255932Salfred * This code is common to root and non-root mounts 190255932Salfred */ 191255932Salfred (void)VFS_STATFS(mp, &mp->mnt_stat, td); 192255932Salfred 193255932Salfred goto success; 194255932Salfred 195255932Salfred 196255932Salfrederror_2: /* error with devvp held*/ 197255932Salfred 198255932Salfred /* release devvp before failing*/ 199255932Salfred vrele(devvp); 200255932Salfred 201219820Sjefferror_1: /* no state to back out*/ 202219820Sjeff /* XXX: Missing NDFREE(&ndp, ...) */ 203255932Salfred 204219820Sjeffsuccess: 205255932Salfred return( err); 206255932Salfred} 207255932Salfred 208255932Salfred/* 209219820Sjeff * Common code for mount and mountroot 210255932Salfred */ 211255932Salfredint 212255932Salfredhpfs_mountfs(devvp, mp, argsp, td) 213255932Salfred register struct vnode *devvp; 214255932Salfred struct mount *mp; 215255932Salfred struct hpfs_args *argsp; 216255932Salfred struct thread *td; 217255932Salfred{ 218255932Salfred int error, ronly; 219255932Salfred struct sublock *sup; 220255932Salfred struct spblock *spp; 221255932Salfred struct hpfsmount *hpmp; 222219820Sjeff struct buf *bp = NULL; 223255932Salfred struct vnode *vp; 224255932Salfred struct cdev *dev = devvp->v_rdev; 225255932Salfred struct g_consumer *cp; 226255932Salfred struct bufobj *bo; 227219820Sjeff 228255932Salfred if (mp->mnt_flag & MNT_ROOTFS) 229219820Sjeff return (EOPNOTSUPP); 230255932Salfred dprintf(("hpfs_mountfs():\n")); 231255932Salfred ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 232219820Sjeff vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); 233219820Sjeff /* XXX: use VOP_ACCESS to check FS perms */ 234255932Salfred DROP_GIANT(); 235219820Sjeff g_topology_lock(); 236219820Sjeff error = g_vfs_open(devvp, &cp, "hpfs", ronly ? 0 : 1); 237219820Sjeff g_topology_unlock(); 238219820Sjeff PICKUP_GIANT(); 239219820Sjeff VOP_UNLOCK(devvp, 0, td); 240219820Sjeff if (error) 241255932Salfred return (error); 242255932Salfred 243255932Salfred bo = &devvp->v_bufobj; 244255932Salfred bo->bo_private = cp; 245255932Salfred bo->bo_ops = g_vfs_bufops; 246255932Salfred 247255932Salfred /* 248255932Salfred * Do actual mount 249255932Salfred */ 250255932Salfred hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK | M_ZERO); 251255932Salfred 252255932Salfred hpmp->hpm_cp = cp; 253255932Salfred hpmp->hpm_bo = bo; 254255932Salfred 255255932Salfred /* Read in SuperBlock */ 256255932Salfred error = bread(devvp, SUBLOCK, SUSIZE, NOCRED, &bp); 257219820Sjeff if (error) 258219820Sjeff goto failed; 259255932Salfred bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock)); 260255932Salfred brelse(bp); bp = NULL; 261255932Salfred 262255932Salfred /* Read in SpareBlock */ 263255932Salfred error = bread(devvp, SPBLOCK, SPSIZE, NOCRED, &bp); 264255932Salfred if (error) 265255932Salfred goto failed; 266255932Salfred bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock)); 267255932Salfred brelse(bp); bp = NULL; 268255932Salfred 269255932Salfred sup = &hpmp->hpm_su; 270255932Salfred spp = &hpmp->hpm_sp; 271255932Salfred 272255932Salfred /* Check magic */ 273255932Salfred if (sup->su_magic != SU_MAGIC) { 274255932Salfred printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n"); 275255932Salfred error = EINVAL; 276255932Salfred goto failed; 277255932Salfred } 278255932Salfred if (spp->sp_magic != SP_MAGIC) { 279255932Salfred printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n"); 280255932Salfred error = EINVAL; 281255932Salfred goto failed; 282255932Salfred } 283255932Salfred 284255932Salfred mp->mnt_data = (qaddr_t)hpmp; 285255932Salfred hpmp->hpm_devvp = devvp; 286255932Salfred hpmp->hpm_dev = devvp->v_rdev; 287219820Sjeff hpmp->hpm_mp = mp; 288219820Sjeff hpmp->hpm_uid = argsp->uid; 289219820Sjeff hpmp->hpm_gid = argsp->gid; 290219820Sjeff hpmp->hpm_mode = argsp->mode; 291219820Sjeff 292219820Sjeff error = hpfs_bminit(hpmp); 293219820Sjeff if (error) 294219820Sjeff goto failed; 295219820Sjeff 296219820Sjeff error = hpfs_cpinit(hpmp, argsp); 297219820Sjeff if (error) { 298219820Sjeff hpfs_bmdeinit(hpmp); 299219820Sjeff goto failed; 300219820Sjeff } 301255932Salfred 302219820Sjeff error = hpfs_root(mp, &vp, td); 303219820Sjeff if (error) { 304219820Sjeff hpfs_cpdeinit(hpmp); 305219820Sjeff hpfs_bmdeinit(hpmp); 306219820Sjeff goto failed; 307219820Sjeff } 308219820Sjeff 309219820Sjeff vput(vp); 310219820Sjeff 311219820Sjeff mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev); 312219820Sjeff mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 313219820Sjeff mp->mnt_maxsymlinklen = 0; 314219820Sjeff mp->mnt_flag |= MNT_LOCAL; 315219820Sjeff return (0); 316219820Sjeff 317255932Salfredfailed: 318219820Sjeff if (bp) 319219820Sjeff brelse (bp); 320219820Sjeff mp->mnt_data = (qaddr_t)NULL; 321219820Sjeff g_wither_geom_close(cp->geom, ENXIO); 322219820Sjeff return (error); 323219820Sjeff} 324219820Sjeff 325219820Sjeffstatic int 326219820Sjeffhpfs_unmount( 327255932Salfred struct mount *mp, 328255932Salfred int mntflags, 329219820Sjeff struct thread *td) 330219820Sjeff{ 331219820Sjeff int error, flags, ronly; 332219820Sjeff register struct hpfsmount *hpmp = VFSTOHPFS(mp); 333219820Sjeff 334219820Sjeff dprintf(("hpfs_unmount():\n")); 335255932Salfred 336255932Salfred ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 337255932Salfred 338255932Salfred flags = 0; 339255932Salfred if(mntflags & MNT_FORCE) 340255932Salfred flags |= FORCECLOSE; 341255932Salfred 342219820Sjeff dprintf(("hpfs_unmount: vflushing...\n")); 343219820Sjeff 344219820Sjeff error = vflush(mp, 0, flags, td); 345219820Sjeff if (error) { 346219820Sjeff printf("hpfs_unmount: vflush failed: %d\n",error); 347219820Sjeff return (error); 348219820Sjeff } 349219820Sjeff 350219820Sjeff vinvalbuf(hpmp->hpm_devvp, V_SAVE, NOCRED, td, 0, 0); 351255932Salfred g_wither_geom_close(hpmp->hpm_cp->geom, ENXIO); 352219820Sjeff vrele(hpmp->hpm_devvp); 353219820Sjeff 354219820Sjeff dprintf(("hpfs_umount: freeing memory...\n")); 355219820Sjeff hpfs_cpdeinit(hpmp); 356219820Sjeff hpfs_bmdeinit(hpmp); 357219820Sjeff mp->mnt_data = (qaddr_t)0; 358219820Sjeff mp->mnt_flag &= ~MNT_LOCAL; 359219820Sjeff FREE(hpmp, M_HPFSMNT); 360219820Sjeff 361219820Sjeff return (0); 362219820Sjeff} 363255932Salfred 364219820Sjeffstatic int 365219820Sjeffhpfs_root( 366219820Sjeff struct mount *mp, 367219820Sjeff struct vnode **vpp, 368219820Sjeff struct thread *td ) 369219820Sjeff{ 370219820Sjeff int error = 0; 371219820Sjeff struct hpfsmount *hpmp = VFSTOHPFS(mp); 372219820Sjeff 373219820Sjeff dprintf(("hpfs_root():\n")); 374219820Sjeff error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, LK_EXCLUSIVE, vpp); 375219820Sjeff if(error) { 376219820Sjeff printf("hpfs_root: VFS_VGET failed: %d\n",error); 377219820Sjeff return (error); 378219820Sjeff } 379219820Sjeff 380219820Sjeff return (error); 381255932Salfred} 382255932Salfred 383255932Salfredstatic int 384255932Salfredhpfs_statfs( 385255932Salfred struct mount *mp, 386255932Salfred struct statfs *sbp, 387255932Salfred struct thread *td) 388255932Salfred{ 389255932Salfred struct hpfsmount *hpmp = VFSTOHPFS(mp); 390255932Salfred 391255932Salfred dprintf(("hpfs_statfs(): HPFS%d.%d\n", 392255932Salfred hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver)); 393255932Salfred 394255932Salfred sbp->f_type = mp->mnt_vfc->vfc_typenum; 395255932Salfred sbp->f_bsize = DEV_BSIZE; 396255932Salfred sbp->f_iosize = DEV_BSIZE; 397255932Salfred sbp->f_blocks = hpmp->hpm_su.su_btotal; 398255932Salfred sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail; 399255932Salfred sbp->f_ffree = 0; 400255932Salfred sbp->f_files = 0; 401255932Salfred if (sbp != &mp->mnt_stat) { 402219820Sjeff bcopy((caddr_t)mp->mnt_stat.f_mntonname, 403219820Sjeff (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 404255932Salfred bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 405219820Sjeff (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 406219820Sjeff } 407255932Salfred sbp->f_flags = mp->mnt_flag; 408219820Sjeff 409255932Salfred return (0); 410255932Salfred} 411255932Salfred 412255932Salfred/*ARGSUSED*/ 413255932Salfredstatic int 414255932Salfredhpfs_fhtovp( 415219820Sjeff struct mount *mp, 416219820Sjeff struct fid *fhp, 417255932Salfred struct vnode **vpp) 418219820Sjeff{ 419219820Sjeff struct vnode *nvp; 420219820Sjeff struct hpfid *hpfhp = (struct hpfid *)fhp; 421255932Salfred int error; 422255932Salfred 423255932Salfred if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, LK_EXCLUSIVE, &nvp)) != 0) { 424219820Sjeff *vpp = NULLVP; 425219820Sjeff return (error); 426219820Sjeff } 427219820Sjeff /* XXX as unlink/rmdir/mkdir/creat are not currently possible 428219820Sjeff * with HPFS, we don't need to check anything else for now */ 429219820Sjeff *vpp = nvp; 430219820Sjeff 431219820Sjeff return (0); 432255932Salfred} 433255932Salfred 434255932Salfredstatic int 435255932Salfredhpfs_vptofh( 436255932Salfred struct vnode *vp, 437255932Salfred struct fid *fhp) 438255932Salfred{ 439255932Salfred register struct hpfsnode *hpp; 440255932Salfred register struct hpfid *hpfhp; 441255932Salfred 442255932Salfred hpp = VTOHP(vp); 443255932Salfred hpfhp = (struct hpfid *)fhp; 444255932Salfred hpfhp->hpfid_len = sizeof(struct hpfid); 445255932Salfred hpfhp->hpfid_ino = hpp->h_no; 446255932Salfred /* hpfhp->hpfid_gen = hpp->h_gen; */ 447219820Sjeff return (0); 448219820Sjeff} 449219820Sjeff 450219820Sjeffstatic int 451219820Sjeffhpfs_vget( 452219820Sjeff struct mount *mp, 453219820Sjeff ino_t ino, 454219820Sjeff int flags, 455219820Sjeff struct vnode **vpp) 456219820Sjeff{ 457219820Sjeff struct hpfsmount *hpmp = VFSTOHPFS(mp); 458219820Sjeff struct vnode *vp; 459219820Sjeff struct hpfsnode *hp; 460219820Sjeff struct buf *bp; 461219820Sjeff struct thread *td = curthread; /* XXX */ 462219820Sjeff int error; 463219820Sjeff 464219820Sjeff dprintf(("hpfs_vget(0x%x): ",ino)); 465219820Sjeff 466219820Sjeff *vpp = NULL; 467219820Sjeff hp = NULL; 468219820Sjeff vp = NULL; 469219820Sjeff 470219820Sjeff if ((error = hpfs_hphashvget(hpmp->hpm_dev, ino, flags, vpp, td)) != 0) 471219820Sjeff return (error); 472219820Sjeff if (*vpp != NULL) { 473219820Sjeff dprintf(("hashed\n")); 474219820Sjeff return (0); 475219820Sjeff } 476219820Sjeff 477255932Salfred /* 478255932Salfred * We have to lock node creation for a while, 479219820Sjeff * but then we have to call getnewvnode(), 480219820Sjeff * this may cause hpfs_reclaim() to be called, 481219820Sjeff * this may need to VOP_VGET() parent dir for 482219820Sjeff * update reasons, and if parent is not in 483219820Sjeff * hash, we have to lock node creation... 484219820Sjeff * To solve this, we MALLOC, getnewvnode and init while 485255932Salfred * not locked (probability of node appearence 486219820Sjeff * at that time is little, and anyway - we'll 487255932Salfred * check for it). 488219820Sjeff */ 489255932Salfred MALLOC(hp, struct hpfsnode *, sizeof(struct hpfsnode), 490255932Salfred M_HPFSNO, M_WAITOK); 491255932Salfred 492255932Salfred error = getnewvnode("hpfs", hpmp->hpm_mp, hpfs_vnodeop_p, &vp); 493255932Salfred if (error) { 494255932Salfred printf("hpfs_vget: can't get new vnode\n"); 495255932Salfred FREE(hp, M_HPFSNO); 496255932Salfred return (error); 497255932Salfred } 498255932Salfred 499255932Salfred dprintf(("prenew ")); 500255932Salfred 501255932Salfred vp->v_data = hp; 502255932Salfred 503255932Salfred if (ino == (ino_t)hpmp->hpm_su.su_rootfno) 504255932Salfred vp->v_vflag |= VV_ROOT; 505255932Salfred 506255932Salfred 507255932Salfred mtx_init(&hp->h_interlock, "hpfsnode interlock", NULL, MTX_DEF); 508255932Salfred 509255932Salfred hp->h_flag = H_INVAL; 510255932Salfred hp->h_vp = vp; 511255932Salfred hp->h_hpmp = hpmp; 512255932Salfred hp->h_no = ino; 513255932Salfred hp->h_dev = hpmp->hpm_dev; 514255932Salfred hp->h_uid = hpmp->hpm_uid; 515255932Salfred hp->h_gid = hpmp->hpm_uid; 516255932Salfred hp->h_mode = hpmp->hpm_mode; 517255932Salfred hp->h_devvp = hpmp->hpm_devvp; 518255932Salfred VREF(hp->h_devvp); 519255932Salfred 520255932Salfred error = vn_lock(vp, LK_EXCLUSIVE, td); 521255932Salfred if (error) { 522255932Salfred vput(vp); 523255932Salfred return (error); 524255932Salfred } 525255932Salfred 526255932Salfred do { 527255932Salfred if ((error = 528255932Salfred hpfs_hphashvget(hpmp->hpm_dev, ino, flags, vpp, td))) { 529255932Salfred vput(vp); 530219820Sjeff return (error); 531255932Salfred } 532255932Salfred if (*vpp != NULL) { 533255932Salfred dprintf(("hashed2\n")); 534255932Salfred vput(vp); 535255932Salfred return (0); 536219820Sjeff } 537255932Salfred } while(lockmgr(&hpfs_hphash_lock,LK_EXCLUSIVE|LK_SLEEPFAIL,NULL,NULL)); 538255932Salfred 539255932Salfred hpfs_hphashins(hp); 540255932Salfred 541255932Salfred lockmgr(&hpfs_hphash_lock, LK_RELEASE, NULL, NULL); 542255932Salfred 543255932Salfred error = bread(hpmp->hpm_devvp, ino, FNODESIZE, NOCRED, &bp); 544255932Salfred if (error) { 545255932Salfred printf("hpfs_vget: can't read ino %d\n",ino); 546255932Salfred vput(vp); 547255932Salfred return (error); 548255932Salfred } 549255932Salfred bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode)); 550255932Salfred brelse(bp); 551255932Salfred 552255932Salfred if (hp->h_fn.fn_magic != FN_MAGIC) { 553255932Salfred printf("hpfs_vget: MAGIC DOESN'T MATCH\n"); 554255932Salfred vput(vp); 555255932Salfred return (EINVAL); 556255932Salfred } 557255932Salfred 558255932Salfred vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG; 559255932Salfred hp->h_flag &= ~H_INVAL; 560255932Salfred 561255932Salfred *vpp = vp; 562255932Salfred 563255932Salfred return (0); 564255932Salfred} 565255932Salfred 566255932Salfredstatic struct vfsops hpfs_vfsops = { 567255932Salfred .vfs_fhtovp = hpfs_fhtovp, 568255932Salfred .vfs_init = hpfs_init, 569255932Salfred .vfs_omount = hpfs_omount, 570255932Salfred .vfs_root = hpfs_root, 571255932Salfred .vfs_statfs = hpfs_statfs, 572255932Salfred .vfs_uninit = hpfs_uninit, 573255932Salfred .vfs_unmount = hpfs_unmount, 574255932Salfred .vfs_vget = hpfs_vget, 575255932Salfred .vfs_vptofh = hpfs_vptofh, 576255932Salfred}; 577255932SalfredVFS_SET(hpfs_vfsops, hpfs, 0); 578255932Salfred