hpfs_vfsops.c revision 175294
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 175294 2008-01-13 14:44:15Z attilio $ 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; 71116271Sphk 7254371Ssemenustatic int 73138487Sphkhpfs_cmount ( 74138487Sphk struct mntarg *ma, 75138487Sphk void *data, 76138487Sphk int flags, 77138487Sphk struct thread *td ) 78138487Sphk{ 79138487Sphk struct hpfs_args args; 80138487Sphk int error; 81138487Sphk 82138487Sphk error = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args)); 83138487Sphk if (error) 84138487Sphk return (error); 85138487Sphk 86138487Sphk ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); 87138487Sphk ma = mount_arg(ma, "export", &args.export, sizeof args.export); 88138487Sphk ma = mount_argf(ma, "uid", "%d", args.uid); 89138487Sphk ma = mount_argf(ma, "gid", "%d", args.gid); 90138487Sphk ma = mount_argf(ma, "mode", "%d", args.mode); 91138487Sphk if (args.flags & HPFSMNT_TABLES) { 92138487Sphk ma = mount_arg(ma, "d2u", args.d2u, sizeof args.d2u); 93138487Sphk ma = mount_arg(ma, "u2d", args.u2d, sizeof args.u2d); 94138487Sphk } 95138487Sphk 96138487Sphk error = kernel_mount(ma, flags); 97138487Sphk 98138487Sphk return (error); 99138487Sphk} 100138487Sphk 101138487Sphkstatic const char *hpfs_opts[] = { 102138487Sphk "from", "export", "uid", "gid", "mode", "d2u", "u2d", NULL 103138487Sphk}; 104138487Sphk 105138487Sphkstatic int 106138487Sphkhpfs_mount ( 10754371Ssemenu struct mount *mp, 10886931Sjhb struct thread *td ) 10954371Ssemenu{ 110138487Sphk int err = 0, error; 11154371Ssemenu struct vnode *devvp; 11254371Ssemenu struct hpfsmount *hpmp = 0; 113132902Sphk struct nameidata ndp; 114138487Sphk struct export_args export; 115138487Sphk char *from; 11654371Ssemenu 117132902Sphk dprintf(("hpfs_omount():\n")); 11854371Ssemenu /* 11954371Ssemenu *** 12096755Strhodes * Mounting non-root filesystem or updating a filesystem 12154371Ssemenu *** 12254371Ssemenu */ 123138487Sphk if (vfs_filteropt(mp->mnt_optnew, hpfs_opts)) 124138487Sphk return (EINVAL); 12554371Ssemenu 126138487Sphk from = vfs_getopts(mp->mnt_optnew, "from", &error); 127138487Sphk if (error) 128138487Sphk return (error); 12954371Ssemenu 13054371Ssemenu /* 13154371Ssemenu * If updating, check whether changing from read-only to 13254371Ssemenu * read/write; if there is no device name, that's all we do. 13354371Ssemenu */ 13454371Ssemenu if (mp->mnt_flag & MNT_UPDATE) { 135132902Sphk dprintf(("hpfs_omount: MNT_UPDATE: ")); 13654371Ssemenu 13754371Ssemenu hpmp = VFSTOHPFS(mp); 13854371Ssemenu 139138487Sphk if (from == NULL) { 140138487Sphk error = vfs_copyopt(mp->mnt_optnew, "export", 141138487Sphk &export, sizeof export); 142138487Sphk if (error) 143138487Sphk return (error); 14454371Ssemenu dprintf(("export 0x%x\n",args.export.ex_flags)); 145138487Sphk err = vfs_export(mp, &export); 14654371Ssemenu if (err) { 147132902Sphk printf("hpfs_omount: vfs_export failed %d\n", 14854371Ssemenu err); 14954371Ssemenu } 15054371Ssemenu goto success; 15154371Ssemenu } else { 15254371Ssemenu dprintf(("name [FAILED]\n")); 15354371Ssemenu err = EINVAL; 15454371Ssemenu goto success; 15554371Ssemenu } 15654371Ssemenu dprintf(("\n")); 15754371Ssemenu } 15854371Ssemenu 15954371Ssemenu /* 16054371Ssemenu * Not an update, or updating the name: look up the name 16154371Ssemenu * and verify that it refers to a sensible block device. 16254371Ssemenu */ 163149720Sssouhlal NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td); 164132902Sphk err = namei(&ndp); 16554371Ssemenu if (err) { 16654371Ssemenu /* can't get devvp!*/ 16754371Ssemenu goto error_1; 16854371Ssemenu } 16954371Ssemenu 170132902Sphk devvp = ndp.ni_vp; 17154371Ssemenu 172149720Sssouhlal if (!vn_isdisk(devvp, &err)) { 173149720Sssouhlal vput(devvp); 174149720Sssouhlal return (err); 175149720Sssouhlal } 17654371Ssemenu 17754371Ssemenu /* 17854371Ssemenu ******************** 17954371Ssemenu * NEW MOUNT 18054371Ssemenu ******************** 18154371Ssemenu */ 18254371Ssemenu 18354371Ssemenu /* 18454371Ssemenu * Since this is a new mount, we want the names for 18554371Ssemenu * the device and the mount point copied in. If an 18673286Sadrian * error occurs, the mountpoint is discarded by the 187132902Sphk * upper level code. Note that vfs_omount() handles 18873286Sadrian * copying the mountpoint f_mntonname for us, so we 18973286Sadrian * don't have to do it here unless we want to set it 19073286Sadrian * to something other than "path" for some rason. 19154371Ssemenu */ 19254371Ssemenu /* Save "mounted from" info for mount point (NULL pad)*/ 193138487Sphk vfs_mountedfrom(mp, from); 19454371Ssemenu 195138487Sphk err = hpfs_mountfs(devvp, mp, td); 196149745Sssouhlal if (err) { 197149745Sssouhlal vrele(devvp); 198149745Sssouhlal goto error_1; 199149745Sssouhlal } 20054371Ssemenu 20154371Ssemenu goto success; 20254371Ssemenu 20354371Ssemenuerror_1: /* no state to back out*/ 204132902Sphk /* XXX: Missing NDFREE(&ndp, ...) */ 20554371Ssemenu 20654371Ssemenusuccess: 20754371Ssemenu return( err); 20854371Ssemenu} 20954371Ssemenu 21054371Ssemenu/* 21154371Ssemenu * Common code for mount and mountroot 21254371Ssemenu */ 21354371Ssemenuint 214138487Sphkhpfs_mountfs(devvp, mp, td) 21554371Ssemenu register struct vnode *devvp; 21654371Ssemenu struct mount *mp; 21786931Sjhb struct thread *td; 21854371Ssemenu{ 219138487Sphk int error, ronly, v; 22054371Ssemenu struct sublock *sup; 22154371Ssemenu struct spblock *spp; 22254371Ssemenu struct hpfsmount *hpmp; 22354371Ssemenu struct buf *bp = NULL; 22454371Ssemenu struct vnode *vp; 225130585Sphk struct cdev *dev = devvp->v_rdev; 226137040Sphk struct g_consumer *cp; 227137040Sphk struct bufobj *bo; 22854371Ssemenu 229137478Sphk if (mp->mnt_flag & MNT_ROOTFS) 230137478Sphk return (EOPNOTSUPP); 23154371Ssemenu dprintf(("hpfs_mountfs():\n")); 23254371Ssemenu ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 233137040Sphk /* XXX: use VOP_ACCESS to check FS perms */ 234137040Sphk DROP_GIANT(); 235137040Sphk g_topology_lock(); 236137040Sphk error = g_vfs_open(devvp, &cp, "hpfs", ronly ? 0 : 1); 237137040Sphk g_topology_unlock(); 238137040Sphk PICKUP_GIANT(); 239175294Sattilio VOP_UNLOCK(devvp, 0); 24054371Ssemenu if (error) 24154371Ssemenu return (error); 24254371Ssemenu 243137040Sphk bo = &devvp->v_bufobj; 244137040Sphk bo->bo_private = cp; 245137040Sphk bo->bo_ops = g_vfs_bufops; 246137040Sphk 24754371Ssemenu /* 24854371Ssemenu * Do actual mount 24954371Ssemenu */ 250111119Simp hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK | M_ZERO); 25154371Ssemenu 252137040Sphk hpmp->hpm_cp = cp; 253137040Sphk hpmp->hpm_bo = bo; 254137040Sphk 25554371Ssemenu /* Read in SuperBlock */ 25654371Ssemenu error = bread(devvp, SUBLOCK, SUSIZE, NOCRED, &bp); 25754371Ssemenu if (error) 25854371Ssemenu goto failed; 25954371Ssemenu bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock)); 26054371Ssemenu brelse(bp); bp = NULL; 26154371Ssemenu 26254371Ssemenu /* Read in SpareBlock */ 26354371Ssemenu error = bread(devvp, SPBLOCK, SPSIZE, NOCRED, &bp); 26454371Ssemenu if (error) 26554371Ssemenu goto failed; 26654371Ssemenu bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock)); 26754371Ssemenu brelse(bp); bp = NULL; 26854371Ssemenu 26954371Ssemenu sup = &hpmp->hpm_su; 27054371Ssemenu spp = &hpmp->hpm_sp; 27154371Ssemenu 27254371Ssemenu /* Check magic */ 27354371Ssemenu if (sup->su_magic != SU_MAGIC) { 27454371Ssemenu printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n"); 27554371Ssemenu error = EINVAL; 27654371Ssemenu goto failed; 27754371Ssemenu } 27854371Ssemenu if (spp->sp_magic != SP_MAGIC) { 27954371Ssemenu printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n"); 28054371Ssemenu error = EINVAL; 28154371Ssemenu goto failed; 28254371Ssemenu } 28354371Ssemenu 284172697Salfred mp->mnt_data = hpmp; 28554371Ssemenu hpmp->hpm_devvp = devvp; 28654371Ssemenu hpmp->hpm_dev = devvp->v_rdev; 28754371Ssemenu hpmp->hpm_mp = mp; 288138487Sphk if (1 == vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v)) 289138487Sphk hpmp->hpm_uid = v; 290138487Sphk if (1 == vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v)) 291138487Sphk hpmp->hpm_gid = v; 292138487Sphk if (1 == vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v)) 293138487Sphk hpmp->hpm_mode = v; 29454371Ssemenu 29554371Ssemenu error = hpfs_bminit(hpmp); 29654371Ssemenu if (error) 29754371Ssemenu goto failed; 29854371Ssemenu 299138487Sphk error = hpfs_cpinit(mp, hpmp); 30054371Ssemenu if (error) { 30154371Ssemenu hpfs_bmdeinit(hpmp); 30254371Ssemenu goto failed; 30354371Ssemenu } 30454371Ssemenu 305144058Sjeff error = hpfs_root(mp, LK_EXCLUSIVE, &vp, td); 30654371Ssemenu if (error) { 30754371Ssemenu hpfs_cpdeinit(hpmp); 30854371Ssemenu hpfs_bmdeinit(hpmp); 30954371Ssemenu goto failed; 31054371Ssemenu } 31154371Ssemenu 31254371Ssemenu vput(vp); 31354371Ssemenu 31454371Ssemenu mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev); 31554371Ssemenu mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 31654371Ssemenu mp->mnt_maxsymlinklen = 0; 317162647Stegge MNT_ILOCK(mp); 31854371Ssemenu mp->mnt_flag |= MNT_LOCAL; 319162647Stegge MNT_IUNLOCK(mp); 32054371Ssemenu return (0); 32154371Ssemenu 32254371Ssemenufailed: 32354371Ssemenu if (bp) 32454371Ssemenu brelse (bp); 325172697Salfred mp->mnt_data = NULL; 326175137Sattilio DROP_GIANT(); 327175137Sattilio g_topology_lock(); 328140822Sphk g_vfs_close(cp, td); 329175137Sattilio g_topology_unlock(); 330175137Sattilio PICKUP_GIANT(); 33154371Ssemenu return (error); 33254371Ssemenu} 33354371Ssemenu 33454371Ssemenustatic int 33554371Ssemenuhpfs_unmount( 33654371Ssemenu struct mount *mp, 33754371Ssemenu int mntflags, 33886931Sjhb struct thread *td) 33954371Ssemenu{ 34054371Ssemenu int error, flags, ronly; 34154371Ssemenu register struct hpfsmount *hpmp = VFSTOHPFS(mp); 34254371Ssemenu 34354371Ssemenu dprintf(("hpfs_unmount():\n")); 34454371Ssemenu 34554371Ssemenu ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 34654371Ssemenu 34754371Ssemenu flags = 0; 34854371Ssemenu if(mntflags & MNT_FORCE) 34954371Ssemenu flags |= FORCECLOSE; 35054371Ssemenu 35154371Ssemenu dprintf(("hpfs_unmount: vflushing...\n")); 35254371Ssemenu 353132023Salfred error = vflush(mp, 0, flags, td); 35454371Ssemenu if (error) { 35554371Ssemenu printf("hpfs_unmount: vflush failed: %d\n",error); 35654371Ssemenu return (error); 35754371Ssemenu } 35854371Ssemenu 359140220Sphk vinvalbuf(hpmp->hpm_devvp, V_SAVE, td, 0, 0); 360175137Sattilio DROP_GIANT(); 361175137Sattilio g_topology_lock(); 362140822Sphk g_vfs_close(hpmp->hpm_cp, td); 363175137Sattilio g_topology_unlock(); 364175137Sattilio PICKUP_GIANT(); 36554371Ssemenu vrele(hpmp->hpm_devvp); 36654371Ssemenu 36754371Ssemenu dprintf(("hpfs_umount: freeing memory...\n")); 36854371Ssemenu hpfs_cpdeinit(hpmp); 36954371Ssemenu hpfs_bmdeinit(hpmp); 370172697Salfred mp->mnt_data = NULL; 371162647Stegge MNT_ILOCK(mp); 37254371Ssemenu mp->mnt_flag &= ~MNT_LOCAL; 373162647Stegge MNT_IUNLOCK(mp); 37454371Ssemenu FREE(hpmp, M_HPFSMNT); 37554371Ssemenu 37654371Ssemenu return (0); 37754371Ssemenu} 37854371Ssemenu 37954371Ssemenustatic int 38054371Ssemenuhpfs_root( 38154371Ssemenu struct mount *mp, 382144058Sjeff int flags, 383132023Salfred struct vnode **vpp, 384132023Salfred struct thread *td ) 38554371Ssemenu{ 38654371Ssemenu int error = 0; 38754371Ssemenu struct hpfsmount *hpmp = VFSTOHPFS(mp); 38854371Ssemenu 38954371Ssemenu dprintf(("hpfs_root():\n")); 39092462Smckusick error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, LK_EXCLUSIVE, vpp); 39154371Ssemenu if(error) { 39254371Ssemenu printf("hpfs_root: VFS_VGET failed: %d\n",error); 39354371Ssemenu return (error); 39454371Ssemenu } 39554371Ssemenu 39654371Ssemenu return (error); 39754371Ssemenu} 39854371Ssemenu 39954371Ssemenustatic int 40054371Ssemenuhpfs_statfs( 40154371Ssemenu struct mount *mp, 40254371Ssemenu struct statfs *sbp, 40386931Sjhb struct thread *td) 40454371Ssemenu{ 40554371Ssemenu struct hpfsmount *hpmp = VFSTOHPFS(mp); 40654371Ssemenu 40754371Ssemenu dprintf(("hpfs_statfs(): HPFS%d.%d\n", 40854371Ssemenu hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver)); 40954371Ssemenu 41054371Ssemenu sbp->f_type = mp->mnt_vfc->vfc_typenum; 41154371Ssemenu sbp->f_bsize = DEV_BSIZE; 41254371Ssemenu sbp->f_iosize = DEV_BSIZE; 41354371Ssemenu sbp->f_blocks = hpmp->hpm_su.su_btotal; 41454371Ssemenu sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail; 41554371Ssemenu sbp->f_ffree = 0; 41654371Ssemenu sbp->f_files = 0; 41754371Ssemenu sbp->f_flags = mp->mnt_flag; 41854371Ssemenu 41954371Ssemenu return (0); 42054371Ssemenu} 42154371Ssemenu 42254371Ssemenu/*ARGSUSED*/ 42354371Ssemenustatic int 42454371Ssemenuhpfs_fhtovp( 42554371Ssemenu struct mount *mp, 42654371Ssemenu struct fid *fhp, 42754371Ssemenu struct vnode **vpp) 42854371Ssemenu{ 42954371Ssemenu struct vnode *nvp; 43054371Ssemenu struct hpfid *hpfhp = (struct hpfid *)fhp; 43154371Ssemenu int error; 43254371Ssemenu 43392462Smckusick if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, LK_EXCLUSIVE, &nvp)) != 0) { 43454371Ssemenu *vpp = NULLVP; 43554371Ssemenu return (error); 43654371Ssemenu } 43754371Ssemenu /* XXX as unlink/rmdir/mkdir/creat are not currently possible 43854371Ssemenu * with HPFS, we don't need to check anything else for now */ 43954371Ssemenu *vpp = nvp; 44054371Ssemenu 44154371Ssemenu return (0); 44254371Ssemenu} 44354371Ssemenu 44454371Ssemenustatic int 44554371Ssemenuhpfs_vget( 44654371Ssemenu struct mount *mp, 44754371Ssemenu ino_t ino, 44892462Smckusick int flags, 44954371Ssemenu struct vnode **vpp) 45054371Ssemenu{ 45154371Ssemenu struct hpfsmount *hpmp = VFSTOHPFS(mp); 45254371Ssemenu struct vnode *vp; 45354371Ssemenu struct hpfsnode *hp; 45454371Ssemenu struct buf *bp; 45554371Ssemenu int error; 456167497Stegge struct thread *td; 45754371Ssemenu 45854371Ssemenu dprintf(("hpfs_vget(0x%x): ",ino)); 45954371Ssemenu 460143692Sphk error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL); 461143619Sphk if (error || *vpp != NULL) 462143588Sphk return (error); 463143588Sphk 46454371Ssemenu *vpp = NULL; 46554371Ssemenu hp = NULL; 46654371Ssemenu vp = NULL; 46754371Ssemenu 46854371Ssemenu /* 46954371Ssemenu * We have to lock node creation for a while, 47054371Ssemenu * but then we have to call getnewvnode(), 47154371Ssemenu * this may cause hpfs_reclaim() to be called, 47254371Ssemenu * this may need to VOP_VGET() parent dir for 47354371Ssemenu * update reasons, and if parent is not in 47454371Ssemenu * hash, we have to lock node creation... 47554371Ssemenu * To solve this, we MALLOC, getnewvnode and init while 47654371Ssemenu * not locked (probability of node appearence 47754371Ssemenu * at that time is little, and anyway - we'll 47854371Ssemenu * check for it). 47954371Ssemenu */ 48054371Ssemenu MALLOC(hp, struct hpfsnode *, sizeof(struct hpfsnode), 481111119Simp M_HPFSNO, M_WAITOK); 48254371Ssemenu 483167497Stegge error = getnewvnode("hpfs", mp, &hpfs_vnodeops, &vp); 48454371Ssemenu if (error) { 48554371Ssemenu printf("hpfs_vget: can't get new vnode\n"); 48654371Ssemenu FREE(hp, M_HPFSNO); 48754371Ssemenu return (error); 48854371Ssemenu } 48954371Ssemenu 49054371Ssemenu dprintf(("prenew ")); 49154371Ssemenu 49254371Ssemenu vp->v_data = hp; 49354371Ssemenu 49454371Ssemenu if (ino == (ino_t)hpmp->hpm_su.su_rootfno) 495101308Sjeff vp->v_vflag |= VV_ROOT; 49654371Ssemenu 49771576Sjasone 49893818Sjhb mtx_init(&hp->h_interlock, "hpfsnode interlock", NULL, MTX_DEF); 49954371Ssemenu 50054371Ssemenu hp->h_flag = H_INVAL; 50154371Ssemenu hp->h_vp = vp; 50254371Ssemenu hp->h_hpmp = hpmp; 50354371Ssemenu hp->h_no = ino; 50454371Ssemenu hp->h_dev = hpmp->hpm_dev; 50554371Ssemenu hp->h_uid = hpmp->hpm_uid; 50654371Ssemenu hp->h_gid = hpmp->hpm_uid; 50754371Ssemenu hp->h_mode = hpmp->hpm_mode; 50854371Ssemenu hp->h_devvp = hpmp->hpm_devvp; 50954371Ssemenu 510167497Stegge td = curthread; 511167497Stegge lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL, td); 512167497Stegge error = insmntque(vp, mp); 513167497Stegge if (error != 0) { 514167497Stegge free(hp, M_HPFSNO); 515167497Stegge return (error); 516167497Stegge } 517167497Stegge error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL); 518143663Sphk if (error || *vpp != NULL) 51954371Ssemenu return (error); 52054371Ssemenu 52154371Ssemenu error = bread(hpmp->hpm_devvp, ino, FNODESIZE, NOCRED, &bp); 52254371Ssemenu if (error) { 52354371Ssemenu printf("hpfs_vget: can't read ino %d\n",ino); 52454371Ssemenu vput(vp); 52554371Ssemenu return (error); 52654371Ssemenu } 52754371Ssemenu bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode)); 52854371Ssemenu brelse(bp); 52954371Ssemenu 53054371Ssemenu if (hp->h_fn.fn_magic != FN_MAGIC) { 53154371Ssemenu printf("hpfs_vget: MAGIC DOESN'T MATCH\n"); 53254371Ssemenu vput(vp); 53354371Ssemenu return (EINVAL); 53454371Ssemenu } 53554371Ssemenu 53654371Ssemenu vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG; 53754371Ssemenu hp->h_flag &= ~H_INVAL; 53854371Ssemenu 53954371Ssemenu *vpp = vp; 54054371Ssemenu 54154371Ssemenu return (0); 54254371Ssemenu} 54354371Ssemenu 54454371Ssemenustatic struct vfsops hpfs_vfsops = { 545116271Sphk .vfs_fhtovp = hpfs_fhtovp, 546138487Sphk .vfs_cmount = hpfs_cmount, 547138487Sphk .vfs_mount = hpfs_mount, 548116271Sphk .vfs_root = hpfs_root, 549116271Sphk .vfs_statfs = hpfs_statfs, 550116271Sphk .vfs_unmount = hpfs_unmount, 551116271Sphk .vfs_vget = hpfs_vget, 55254371Ssemenu}; 55354371SsemenuVFS_SET(hpfs_vfsops, hpfs, 0); 554