hpfs_vfsops.c revision 162647
154371Ssemenu/*- 254371Ssemenu * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) 354371Ssemenu * All rights reserved. 454371Ssemenu * 554371Ssemenu * Redistribution and use in source and binary forms, with or without 654371Ssemenu * modification, are permitted provided that the following conditions 754371Ssemenu * are met: 854371Ssemenu * 1. Redistributions of source code must retain the above copyright 954371Ssemenu * notice, this list of conditions and the following disclaimer. 1054371Ssemenu * 2. Redistributions in binary form must reproduce the above copyright 1154371Ssemenu * notice, this list of conditions and the following disclaimer in the 1254371Ssemenu * documentation and/or other materials provided with the distribution. 1354371Ssemenu * 1454371Ssemenu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1554371Ssemenu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1654371Ssemenu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1754371Ssemenu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1854371Ssemenu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1954371Ssemenu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2054371Ssemenu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2154371Ssemenu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2254371Ssemenu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2354371Ssemenu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2454371Ssemenu * SUCH DAMAGE. 2554371Ssemenu * 2654371Ssemenu * $FreeBSD: head/sys/fs/hpfs/hpfs_vfsops.c 162647 2006-09-26 04:12:49Z tegge $ 2754371Ssemenu */ 2854371Ssemenu 2954371Ssemenu 3054371Ssemenu#include <sys/param.h> 3154371Ssemenu#include <sys/systm.h> 3254371Ssemenu#include <sys/namei.h> 3354371Ssemenu#include <sys/conf.h> 3454371Ssemenu#include <sys/proc.h> 3554371Ssemenu#include <sys/kernel.h> 3654371Ssemenu#include <sys/vnode.h> 3754371Ssemenu#include <sys/mount.h> 3860041Sphk#include <sys/bio.h> 3954371Ssemenu#include <sys/buf.h> 4054371Ssemenu#include <sys/fcntl.h> 4154371Ssemenu#include <sys/malloc.h> 4254371Ssemenu 43137040Sphk#include <geom/geom.h> 44137040Sphk#include <geom/geom_vfs.h> 45137040Sphk 4654371Ssemenu#include <vm/vm.h> 4754371Ssemenu#include <vm/vm_param.h> 4854371Ssemenu#include <vm/vm_page.h> 4954371Ssemenu#include <vm/vm_object.h> 5054371Ssemenu#include <vm/vm_extern.h> 5154371Ssemenu 5254371Ssemenu#include <fs/hpfs/hpfs.h> 5354371Ssemenu#include <fs/hpfs/hpfsmount.h> 5454371Ssemenu#include <fs/hpfs/hpfs_subr.h> 5554371Ssemenu 56151897SrwatsonMALLOC_DEFINE(M_HPFSMNT, "hpfs_mount", "HPFS mount structure"); 57151897SrwatsonMALLOC_DEFINE(M_HPFSNO, "hpfs_node", "HPFS node structure"); 5883384Sjhb 5986927Sjhbstruct sockaddr; 6086927Sjhb 6192727Salfredstatic int hpfs_mountfs(register struct vnode *, struct mount *, 62138487Sphk struct thread *); 6354371Ssemenu 64116271Sphkstatic vfs_fhtovp_t hpfs_fhtovp; 65116271Sphkstatic vfs_vget_t hpfs_vget; 66138487Sphkstatic vfs_cmount_t hpfs_cmount; 67138487Sphkstatic vfs_mount_t hpfs_mount; 68116271Sphkstatic vfs_root_t hpfs_root; 69116271Sphkstatic vfs_statfs_t hpfs_statfs; 70116271Sphkstatic vfs_unmount_t hpfs_unmount; 71116271Sphkstatic vfs_vptofh_t hpfs_vptofh; 72116271Sphk 7354371Ssemenustatic int 74138487Sphkhpfs_cmount ( 75138487Sphk struct mntarg *ma, 76138487Sphk void *data, 77138487Sphk int flags, 78138487Sphk struct thread *td ) 79138487Sphk{ 80138487Sphk struct hpfs_args args; 81138487Sphk int error; 82138487Sphk 83138487Sphk error = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args)); 84138487Sphk if (error) 85138487Sphk return (error); 86138487Sphk 87138487Sphk ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); 88138487Sphk ma = mount_arg(ma, "export", &args.export, sizeof args.export); 89138487Sphk ma = mount_argf(ma, "uid", "%d", args.uid); 90138487Sphk ma = mount_argf(ma, "gid", "%d", args.gid); 91138487Sphk ma = mount_argf(ma, "mode", "%d", args.mode); 92138487Sphk if (args.flags & HPFSMNT_TABLES) { 93138487Sphk ma = mount_arg(ma, "d2u", args.d2u, sizeof args.d2u); 94138487Sphk ma = mount_arg(ma, "u2d", args.u2d, sizeof args.u2d); 95138487Sphk } 96138487Sphk 97138487Sphk error = kernel_mount(ma, flags); 98138487Sphk 99138487Sphk return (error); 100138487Sphk} 101138487Sphk 102138487Sphkstatic const char *hpfs_opts[] = { 103138487Sphk "from", "export", "uid", "gid", "mode", "d2u", "u2d", NULL 104138487Sphk}; 105138487Sphk 106138487Sphkstatic int 107138487Sphkhpfs_mount ( 10854371Ssemenu struct mount *mp, 10986931Sjhb struct thread *td ) 11054371Ssemenu{ 111138487Sphk int err = 0, error; 11254371Ssemenu struct vnode *devvp; 11354371Ssemenu struct hpfsmount *hpmp = 0; 114132902Sphk struct nameidata ndp; 115138487Sphk struct export_args export; 116138487Sphk char *from; 11754371Ssemenu 118132902Sphk dprintf(("hpfs_omount():\n")); 11954371Ssemenu /* 12054371Ssemenu *** 12196755Strhodes * Mounting non-root filesystem or updating a filesystem 12254371Ssemenu *** 12354371Ssemenu */ 124138487Sphk if (vfs_filteropt(mp->mnt_optnew, hpfs_opts)) 125138487Sphk return (EINVAL); 12654371Ssemenu 127138487Sphk from = vfs_getopts(mp->mnt_optnew, "from", &error); 128138487Sphk if (error) 129138487Sphk return (error); 13054371Ssemenu 13154371Ssemenu /* 13254371Ssemenu * If updating, check whether changing from read-only to 13354371Ssemenu * read/write; if there is no device name, that's all we do. 13454371Ssemenu */ 13554371Ssemenu if (mp->mnt_flag & MNT_UPDATE) { 136132902Sphk dprintf(("hpfs_omount: MNT_UPDATE: ")); 13754371Ssemenu 13854371Ssemenu hpmp = VFSTOHPFS(mp); 13954371Ssemenu 140138487Sphk if (from == NULL) { 141138487Sphk error = vfs_copyopt(mp->mnt_optnew, "export", 142138487Sphk &export, sizeof export); 143138487Sphk if (error) 144138487Sphk return (error); 14554371Ssemenu dprintf(("export 0x%x\n",args.export.ex_flags)); 146138487Sphk err = vfs_export(mp, &export); 14754371Ssemenu if (err) { 148132902Sphk printf("hpfs_omount: vfs_export failed %d\n", 14954371Ssemenu err); 15054371Ssemenu } 15154371Ssemenu goto success; 15254371Ssemenu } else { 15354371Ssemenu dprintf(("name [FAILED]\n")); 15454371Ssemenu err = EINVAL; 15554371Ssemenu goto success; 15654371Ssemenu } 15754371Ssemenu dprintf(("\n")); 15854371Ssemenu } 15954371Ssemenu 16054371Ssemenu /* 16154371Ssemenu * Not an update, or updating the name: look up the name 16254371Ssemenu * and verify that it refers to a sensible block device. 16354371Ssemenu */ 164149720Sssouhlal NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td); 165132902Sphk err = namei(&ndp); 16654371Ssemenu if (err) { 16754371Ssemenu /* can't get devvp!*/ 16854371Ssemenu goto error_1; 16954371Ssemenu } 17054371Ssemenu 171132902Sphk devvp = ndp.ni_vp; 17254371Ssemenu 173149720Sssouhlal if (!vn_isdisk(devvp, &err)) { 174149720Sssouhlal vput(devvp); 175149720Sssouhlal return (err); 176149720Sssouhlal } 17754371Ssemenu 17854371Ssemenu /* 17954371Ssemenu ******************** 18054371Ssemenu * NEW MOUNT 18154371Ssemenu ******************** 18254371Ssemenu */ 18354371Ssemenu 18454371Ssemenu /* 18554371Ssemenu * Since this is a new mount, we want the names for 18654371Ssemenu * the device and the mount point copied in. If an 18773286Sadrian * error occurs, the mountpoint is discarded by the 188132902Sphk * upper level code. Note that vfs_omount() handles 18973286Sadrian * copying the mountpoint f_mntonname for us, so we 19073286Sadrian * don't have to do it here unless we want to set it 19173286Sadrian * to something other than "path" for some rason. 19254371Ssemenu */ 19354371Ssemenu /* Save "mounted from" info for mount point (NULL pad)*/ 194138487Sphk vfs_mountedfrom(mp, from); 19554371Ssemenu 196138487Sphk err = hpfs_mountfs(devvp, mp, td); 197149745Sssouhlal if (err) { 198149745Sssouhlal vrele(devvp); 199149745Sssouhlal goto error_1; 200149745Sssouhlal } 20154371Ssemenu 20254371Ssemenu goto success; 20354371Ssemenu 20454371Ssemenuerror_1: /* no state to back out*/ 205132902Sphk /* XXX: Missing NDFREE(&ndp, ...) */ 20654371Ssemenu 20754371Ssemenusuccess: 20854371Ssemenu return( err); 20954371Ssemenu} 21054371Ssemenu 21154371Ssemenu/* 21254371Ssemenu * Common code for mount and mountroot 21354371Ssemenu */ 21454371Ssemenuint 215138487Sphkhpfs_mountfs(devvp, mp, td) 21654371Ssemenu register struct vnode *devvp; 21754371Ssemenu struct mount *mp; 21886931Sjhb struct thread *td; 21954371Ssemenu{ 220138487Sphk int error, ronly, v; 22154371Ssemenu struct sublock *sup; 22254371Ssemenu struct spblock *spp; 22354371Ssemenu struct hpfsmount *hpmp; 22454371Ssemenu struct buf *bp = NULL; 22554371Ssemenu struct vnode *vp; 226130585Sphk struct cdev *dev = devvp->v_rdev; 227137040Sphk struct g_consumer *cp; 228137040Sphk struct bufobj *bo; 22954371Ssemenu 230137478Sphk if (mp->mnt_flag & MNT_ROOTFS) 231137478Sphk return (EOPNOTSUPP); 23254371Ssemenu dprintf(("hpfs_mountfs():\n")); 23354371Ssemenu ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 234137040Sphk /* XXX: use VOP_ACCESS to check FS perms */ 235137040Sphk DROP_GIANT(); 236137040Sphk g_topology_lock(); 237137040Sphk error = g_vfs_open(devvp, &cp, "hpfs", ronly ? 0 : 1); 238137040Sphk g_topology_unlock(); 239137040Sphk PICKUP_GIANT(); 24086931Sjhb VOP_UNLOCK(devvp, 0, td); 24154371Ssemenu if (error) 24254371Ssemenu return (error); 24354371Ssemenu 244137040Sphk bo = &devvp->v_bufobj; 245137040Sphk bo->bo_private = cp; 246137040Sphk bo->bo_ops = g_vfs_bufops; 247137040Sphk 24854371Ssemenu /* 24954371Ssemenu * Do actual mount 25054371Ssemenu */ 251111119Simp hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK | M_ZERO); 25254371Ssemenu 253137040Sphk hpmp->hpm_cp = cp; 254137040Sphk hpmp->hpm_bo = bo; 255137040Sphk 25654371Ssemenu /* Read in SuperBlock */ 25754371Ssemenu error = bread(devvp, SUBLOCK, SUSIZE, NOCRED, &bp); 25854371Ssemenu if (error) 25954371Ssemenu goto failed; 26054371Ssemenu bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock)); 26154371Ssemenu brelse(bp); bp = NULL; 26254371Ssemenu 26354371Ssemenu /* Read in SpareBlock */ 26454371Ssemenu error = bread(devvp, SPBLOCK, SPSIZE, NOCRED, &bp); 26554371Ssemenu if (error) 26654371Ssemenu goto failed; 26754371Ssemenu bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock)); 26854371Ssemenu brelse(bp); bp = NULL; 26954371Ssemenu 27054371Ssemenu sup = &hpmp->hpm_su; 27154371Ssemenu spp = &hpmp->hpm_sp; 27254371Ssemenu 27354371Ssemenu /* Check magic */ 27454371Ssemenu if (sup->su_magic != SU_MAGIC) { 27554371Ssemenu printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n"); 27654371Ssemenu error = EINVAL; 27754371Ssemenu goto failed; 27854371Ssemenu } 27954371Ssemenu if (spp->sp_magic != SP_MAGIC) { 28054371Ssemenu printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n"); 28154371Ssemenu error = EINVAL; 28254371Ssemenu goto failed; 28354371Ssemenu } 28454371Ssemenu 28554371Ssemenu mp->mnt_data = (qaddr_t)hpmp; 28654371Ssemenu hpmp->hpm_devvp = devvp; 28754371Ssemenu hpmp->hpm_dev = devvp->v_rdev; 28854371Ssemenu hpmp->hpm_mp = mp; 289138487Sphk if (1 == vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v)) 290138487Sphk hpmp->hpm_uid = v; 291138487Sphk if (1 == vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v)) 292138487Sphk hpmp->hpm_gid = v; 293138487Sphk if (1 == vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v)) 294138487Sphk hpmp->hpm_mode = v; 29554371Ssemenu 29654371Ssemenu error = hpfs_bminit(hpmp); 29754371Ssemenu if (error) 29854371Ssemenu goto failed; 29954371Ssemenu 300138487Sphk error = hpfs_cpinit(mp, hpmp); 30154371Ssemenu if (error) { 30254371Ssemenu hpfs_bmdeinit(hpmp); 30354371Ssemenu goto failed; 30454371Ssemenu } 30554371Ssemenu 306144058Sjeff error = hpfs_root(mp, LK_EXCLUSIVE, &vp, td); 30754371Ssemenu if (error) { 30854371Ssemenu hpfs_cpdeinit(hpmp); 30954371Ssemenu hpfs_bmdeinit(hpmp); 31054371Ssemenu goto failed; 31154371Ssemenu } 31254371Ssemenu 31354371Ssemenu vput(vp); 31454371Ssemenu 31554371Ssemenu mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev); 31654371Ssemenu mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 31754371Ssemenu mp->mnt_maxsymlinklen = 0; 318162647Stegge MNT_ILOCK(mp); 31954371Ssemenu mp->mnt_flag |= MNT_LOCAL; 320162647Stegge MNT_IUNLOCK(mp); 32154371Ssemenu return (0); 32254371Ssemenu 32354371Ssemenufailed: 32454371Ssemenu if (bp) 32554371Ssemenu brelse (bp); 32654371Ssemenu mp->mnt_data = (qaddr_t)NULL; 327140822Sphk g_vfs_close(cp, td); 32854371Ssemenu return (error); 32954371Ssemenu} 33054371Ssemenu 33154371Ssemenustatic int 33254371Ssemenuhpfs_unmount( 33354371Ssemenu struct mount *mp, 33454371Ssemenu int mntflags, 33586931Sjhb struct thread *td) 33654371Ssemenu{ 33754371Ssemenu int error, flags, ronly; 33854371Ssemenu register struct hpfsmount *hpmp = VFSTOHPFS(mp); 33954371Ssemenu 34054371Ssemenu dprintf(("hpfs_unmount():\n")); 34154371Ssemenu 34254371Ssemenu ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 34354371Ssemenu 34454371Ssemenu flags = 0; 34554371Ssemenu if(mntflags & MNT_FORCE) 34654371Ssemenu flags |= FORCECLOSE; 34754371Ssemenu 34854371Ssemenu dprintf(("hpfs_unmount: vflushing...\n")); 34954371Ssemenu 350132023Salfred error = vflush(mp, 0, flags, td); 35154371Ssemenu if (error) { 35254371Ssemenu printf("hpfs_unmount: vflush failed: %d\n",error); 35354371Ssemenu return (error); 35454371Ssemenu } 35554371Ssemenu 356140220Sphk vinvalbuf(hpmp->hpm_devvp, V_SAVE, td, 0, 0); 357140822Sphk g_vfs_close(hpmp->hpm_cp, td); 35854371Ssemenu vrele(hpmp->hpm_devvp); 35954371Ssemenu 36054371Ssemenu dprintf(("hpfs_umount: freeing memory...\n")); 36154371Ssemenu hpfs_cpdeinit(hpmp); 36254371Ssemenu hpfs_bmdeinit(hpmp); 36354371Ssemenu mp->mnt_data = (qaddr_t)0; 364162647Stegge MNT_ILOCK(mp); 36554371Ssemenu mp->mnt_flag &= ~MNT_LOCAL; 366162647Stegge MNT_IUNLOCK(mp); 36754371Ssemenu FREE(hpmp, M_HPFSMNT); 36854371Ssemenu 36954371Ssemenu return (0); 37054371Ssemenu} 37154371Ssemenu 37254371Ssemenustatic int 37354371Ssemenuhpfs_root( 37454371Ssemenu struct mount *mp, 375144058Sjeff int flags, 376132023Salfred struct vnode **vpp, 377132023Salfred struct thread *td ) 37854371Ssemenu{ 37954371Ssemenu int error = 0; 38054371Ssemenu struct hpfsmount *hpmp = VFSTOHPFS(mp); 38154371Ssemenu 38254371Ssemenu dprintf(("hpfs_root():\n")); 38392462Smckusick error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, LK_EXCLUSIVE, vpp); 38454371Ssemenu if(error) { 38554371Ssemenu printf("hpfs_root: VFS_VGET failed: %d\n",error); 38654371Ssemenu return (error); 38754371Ssemenu } 38854371Ssemenu 38954371Ssemenu return (error); 39054371Ssemenu} 39154371Ssemenu 39254371Ssemenustatic int 39354371Ssemenuhpfs_statfs( 39454371Ssemenu struct mount *mp, 39554371Ssemenu struct statfs *sbp, 39686931Sjhb struct thread *td) 39754371Ssemenu{ 39854371Ssemenu struct hpfsmount *hpmp = VFSTOHPFS(mp); 39954371Ssemenu 40054371Ssemenu dprintf(("hpfs_statfs(): HPFS%d.%d\n", 40154371Ssemenu hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver)); 40254371Ssemenu 40354371Ssemenu sbp->f_type = mp->mnt_vfc->vfc_typenum; 40454371Ssemenu sbp->f_bsize = DEV_BSIZE; 40554371Ssemenu sbp->f_iosize = DEV_BSIZE; 40654371Ssemenu sbp->f_blocks = hpmp->hpm_su.su_btotal; 40754371Ssemenu sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail; 40854371Ssemenu sbp->f_ffree = 0; 40954371Ssemenu sbp->f_files = 0; 41054371Ssemenu sbp->f_flags = mp->mnt_flag; 41154371Ssemenu 41254371Ssemenu return (0); 41354371Ssemenu} 41454371Ssemenu 41554371Ssemenu/*ARGSUSED*/ 41654371Ssemenustatic int 41754371Ssemenuhpfs_fhtovp( 41854371Ssemenu struct mount *mp, 41954371Ssemenu struct fid *fhp, 42054371Ssemenu struct vnode **vpp) 42154371Ssemenu{ 42254371Ssemenu struct vnode *nvp; 42354371Ssemenu struct hpfid *hpfhp = (struct hpfid *)fhp; 42454371Ssemenu int error; 42554371Ssemenu 42692462Smckusick if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, LK_EXCLUSIVE, &nvp)) != 0) { 42754371Ssemenu *vpp = NULLVP; 42854371Ssemenu return (error); 42954371Ssemenu } 43054371Ssemenu /* XXX as unlink/rmdir/mkdir/creat are not currently possible 43154371Ssemenu * with HPFS, we don't need to check anything else for now */ 43254371Ssemenu *vpp = nvp; 43354371Ssemenu 43454371Ssemenu return (0); 43554371Ssemenu} 43654371Ssemenu 43754371Ssemenustatic int 43854371Ssemenuhpfs_vptofh( 43954371Ssemenu struct vnode *vp, 44054371Ssemenu struct fid *fhp) 44154371Ssemenu{ 44254371Ssemenu register struct hpfsnode *hpp; 44354371Ssemenu register struct hpfid *hpfhp; 44454371Ssemenu 44554371Ssemenu hpp = VTOHP(vp); 44654371Ssemenu hpfhp = (struct hpfid *)fhp; 44754371Ssemenu hpfhp->hpfid_len = sizeof(struct hpfid); 44854371Ssemenu hpfhp->hpfid_ino = hpp->h_no; 44954371Ssemenu /* hpfhp->hpfid_gen = hpp->h_gen; */ 45054371Ssemenu return (0); 45154371Ssemenu} 45254371Ssemenu 45354371Ssemenustatic int 45454371Ssemenuhpfs_vget( 45554371Ssemenu struct mount *mp, 45654371Ssemenu ino_t ino, 45792462Smckusick int flags, 45854371Ssemenu struct vnode **vpp) 45954371Ssemenu{ 46054371Ssemenu struct hpfsmount *hpmp = VFSTOHPFS(mp); 46154371Ssemenu struct vnode *vp; 46254371Ssemenu struct hpfsnode *hp; 46354371Ssemenu struct buf *bp; 46454371Ssemenu int error; 46554371Ssemenu 46654371Ssemenu dprintf(("hpfs_vget(0x%x): ",ino)); 46754371Ssemenu 468143692Sphk error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL); 469143619Sphk if (error || *vpp != NULL) 470143588Sphk return (error); 471143588Sphk 47254371Ssemenu *vpp = NULL; 47354371Ssemenu hp = NULL; 47454371Ssemenu vp = NULL; 47554371Ssemenu 47654371Ssemenu /* 47754371Ssemenu * We have to lock node creation for a while, 47854371Ssemenu * but then we have to call getnewvnode(), 47954371Ssemenu * this may cause hpfs_reclaim() to be called, 48054371Ssemenu * this may need to VOP_VGET() parent dir for 48154371Ssemenu * update reasons, and if parent is not in 48254371Ssemenu * hash, we have to lock node creation... 48354371Ssemenu * To solve this, we MALLOC, getnewvnode and init while 48454371Ssemenu * not locked (probability of node appearence 48554371Ssemenu * at that time is little, and anyway - we'll 48654371Ssemenu * check for it). 48754371Ssemenu */ 48854371Ssemenu MALLOC(hp, struct hpfsnode *, sizeof(struct hpfsnode), 489111119Simp M_HPFSNO, M_WAITOK); 49054371Ssemenu 491138290Sphk error = getnewvnode("hpfs", hpmp->hpm_mp, &hpfs_vnodeops, &vp); 49254371Ssemenu if (error) { 49354371Ssemenu printf("hpfs_vget: can't get new vnode\n"); 49454371Ssemenu FREE(hp, M_HPFSNO); 49554371Ssemenu return (error); 49654371Ssemenu } 49754371Ssemenu 49854371Ssemenu dprintf(("prenew ")); 49954371Ssemenu 50054371Ssemenu vp->v_data = hp; 50154371Ssemenu 50254371Ssemenu if (ino == (ino_t)hpmp->hpm_su.su_rootfno) 503101308Sjeff vp->v_vflag |= VV_ROOT; 50454371Ssemenu 50571576Sjasone 50693818Sjhb mtx_init(&hp->h_interlock, "hpfsnode interlock", NULL, MTX_DEF); 50754371Ssemenu 50854371Ssemenu hp->h_flag = H_INVAL; 50954371Ssemenu hp->h_vp = vp; 51054371Ssemenu hp->h_hpmp = hpmp; 51154371Ssemenu hp->h_no = ino; 51254371Ssemenu hp->h_dev = hpmp->hpm_dev; 51354371Ssemenu hp->h_uid = hpmp->hpm_uid; 51454371Ssemenu hp->h_gid = hpmp->hpm_uid; 51554371Ssemenu hp->h_mode = hpmp->hpm_mode; 51654371Ssemenu hp->h_devvp = hpmp->hpm_devvp; 51754371Ssemenu 518143692Sphk error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL); 519143663Sphk if (error || *vpp != NULL) 52054371Ssemenu return (error); 52154371Ssemenu 52254371Ssemenu error = bread(hpmp->hpm_devvp, ino, FNODESIZE, NOCRED, &bp); 52354371Ssemenu if (error) { 52454371Ssemenu printf("hpfs_vget: can't read ino %d\n",ino); 52554371Ssemenu vput(vp); 52654371Ssemenu return (error); 52754371Ssemenu } 52854371Ssemenu bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode)); 52954371Ssemenu brelse(bp); 53054371Ssemenu 53154371Ssemenu if (hp->h_fn.fn_magic != FN_MAGIC) { 53254371Ssemenu printf("hpfs_vget: MAGIC DOESN'T MATCH\n"); 53354371Ssemenu vput(vp); 53454371Ssemenu return (EINVAL); 53554371Ssemenu } 53654371Ssemenu 53754371Ssemenu vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG; 53854371Ssemenu hp->h_flag &= ~H_INVAL; 53954371Ssemenu 54054371Ssemenu *vpp = vp; 54154371Ssemenu 54254371Ssemenu return (0); 54354371Ssemenu} 54454371Ssemenu 54554371Ssemenustatic struct vfsops hpfs_vfsops = { 546116271Sphk .vfs_fhtovp = hpfs_fhtovp, 547138487Sphk .vfs_cmount = hpfs_cmount, 548138487Sphk .vfs_mount = hpfs_mount, 549116271Sphk .vfs_root = hpfs_root, 550116271Sphk .vfs_statfs = hpfs_statfs, 551116271Sphk .vfs_unmount = hpfs_unmount, 552116271Sphk .vfs_vget = hpfs_vget, 553116271Sphk .vfs_vptofh = hpfs_vptofh, 55454371Ssemenu}; 55554371SsemenuVFS_SET(hpfs_vfsops, hpfs, 0); 556