hpfs_vfsops.c revision 83384
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 83384 2001-09-12 23:39:36Z jhb $ 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 4354371Ssemenu#include <vm/vm.h> 4454371Ssemenu#include <vm/vm_param.h> 4554371Ssemenu#if defined(__NetBSD__) 4654371Ssemenu#include <vm/vm_prot.h> 4754371Ssemenu#endif 4854371Ssemenu#include <vm/vm_page.h> 4954371Ssemenu#include <vm/vm_object.h> 5054371Ssemenu#include <vm/vm_extern.h> 5154371Ssemenu 5254371Ssemenu#if defined(__NetBSD__) 5354371Ssemenu#include <miscfs/specfs/specdev.h> 5454371Ssemenu#endif 5554371Ssemenu 5654371Ssemenu#include <fs/hpfs/hpfs.h> 5754371Ssemenu#include <fs/hpfs/hpfsmount.h> 5854371Ssemenu#include <fs/hpfs/hpfs_subr.h> 5954371Ssemenu 6054371Ssemenu#if defined(__FreeBSD__) 6154371SsemenuMALLOC_DEFINE(M_HPFSMNT, "HPFS mount", "HPFS mount structure"); 6254371SsemenuMALLOC_DEFINE(M_HPFSNO, "HPFS node", "HPFS node structure"); 6383384Sjhb 6483384Sjhb#define a_p a_td 6583384Sjhb#define cn_proc cn_thread 6683384Sjhb#define proc thread 6754371Ssemenu#endif 6854371Ssemenu 6954371Ssemenustatic int hpfs_root __P((struct mount *, struct vnode **)); 7054371Ssemenustatic int hpfs_statfs __P((struct mount *, struct statfs *, 7183384Sjhb struct proc *)); 7283384Sjhbstatic int hpfs_unmount __P((struct mount *, int, struct proc *)); 7354371Ssemenustatic int hpfs_vget __P((struct mount *mp, ino_t ino, 7454371Ssemenu struct vnode **vpp)); 7554371Ssemenustatic int hpfs_mountfs __P((register struct vnode *, struct mount *, 7683384Sjhb struct hpfs_args *, struct proc *)); 7754371Ssemenustatic int hpfs_vptofh __P((struct vnode *, struct fid *)); 7854371Ssemenustatic int hpfs_fhtovp __P((struct mount *, struct fid *, 7954371Ssemenu struct vnode **)); 8054371Ssemenu 8154371Ssemenu#if !defined(__FreeBSD__) 8254371Ssemenustatic int hpfs_quotactl __P((struct mount *, int, uid_t, caddr_t, 8383384Sjhb struct proc *)); 8483384Sjhbstatic int hpfs_start __P((struct mount *, int, struct proc *)); 8554371Ssemenustatic int hpfs_sync __P((struct mount *, int, struct ucred *, 8683384Sjhb struct proc *)); 8754371Ssemenu#endif 8854371Ssemenu 8954371Ssemenu#if defined(__FreeBSD__) 9054371Ssemenustruct sockaddr; 9154371Ssemenustatic int hpfs_mount __P((struct mount *, char *, caddr_t, 9283366Sjulian struct nameidata *, struct thread *)); 9354371Ssemenustatic int hpfs_init __P((struct vfsconf *)); 9466615Sjasonestatic int hpfs_uninit __P((struct vfsconf *)); 9554371Ssemenu#else /* defined(__NetBSD__) */ 9654371Ssemenustatic int hpfs_mount __P((struct mount *, const char *, void *, 9783384Sjhb struct nameidata *, struct proc *)); 9854371Ssemenustatic void hpfs_init __P((void)); 9954371Ssemenustatic int hpfs_mountroot __P((void)); 10054371Ssemenustatic int hpfs_sysctl __P((int *, u_int, void *, size_t *, void *, 10183384Sjhb size_t, struct proc *)); 10254371Ssemenustatic int hpfs_checkexp __P((struct mount *, struct mbuf *, 10354371Ssemenu int *, struct ucred **)); 10454371Ssemenu#endif 10554371Ssemenu 10675934Sphk#if !defined(__FreeBSD__) 10754371Ssemenu/*ARGSUSED*/ 10854371Ssemenustatic int 10954371Ssemenuhpfs_checkexp(mp, nam, exflagsp, credanonp) 11054371Ssemenu register struct mount *mp; 11154371Ssemenu struct mbuf *nam; 11254371Ssemenu int *exflagsp; 11354371Ssemenu struct ucred **credanonp; 11454371Ssemenu{ 11554371Ssemenu register struct netcred *np; 11654371Ssemenu register struct hpfsmount *hpm = VFSTOHPFS(mp); 11754371Ssemenu 11854371Ssemenu /* 11954371Ssemenu * Get the export permission structure for this <mp, client> tuple. 12054371Ssemenu */ 12154371Ssemenu np = vfs_export_lookup(mp, &hpm->hpm_export, nam); 12254371Ssemenu if (np == NULL) 12354371Ssemenu return (EACCES); 12454371Ssemenu 12554371Ssemenu *exflagsp = np->netc_exflags; 12654371Ssemenu *credanonp = &np->netc_anon; 12754371Ssemenu return (0); 12854371Ssemenu} 12975934Sphk#endif 13054371Ssemenu 13154371Ssemenu#if !defined(__FreeBSD__) 13254371Ssemenu/*ARGSUSED*/ 13354371Ssemenustatic int 13483384Sjhbhpfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 13554371Ssemenu int *name; 13654371Ssemenu u_int namelen; 13754371Ssemenu void *oldp; 13854371Ssemenu size_t *oldlenp; 13954371Ssemenu void *newp; 14054371Ssemenu size_t newlen; 14183384Sjhb struct proc *p; 14254371Ssemenu{ 14354371Ssemenu return (EINVAL); 14454371Ssemenu} 14554371Ssemenu 14654371Ssemenustatic int 14754371Ssemenuhpfs_mountroot() 14854371Ssemenu{ 14954371Ssemenu return (EINVAL); 15054371Ssemenu} 15154371Ssemenu#endif 15254371Ssemenu 15354371Ssemenu#if defined(__FreeBSD__) 15454371Ssemenustatic int 15554371Ssemenuhpfs_init ( 15654371Ssemenu struct vfsconf *vcp ) 15754371Ssemenu#else /* defined(__NetBSD__) */ 15854371Ssemenustatic void 15954371Ssemenuhpfs_init () 16054371Ssemenu#endif 16154371Ssemenu{ 16254371Ssemenu dprintf(("hpfs_init():\n")); 16354371Ssemenu 16454371Ssemenu hpfs_hphashinit(); 16554371Ssemenu#if defined(__FreeBSD__) 16654371Ssemenu return 0; 16754371Ssemenu#endif 16854371Ssemenu} 16954371Ssemenu 17066615Sjasone#if defined(__FreeBSD__) 17154371Ssemenustatic int 17266615Sjasonehpfs_uninit (vfsp) 17366615Sjasone struct vfsconf *vfsp; 17466615Sjasone{ 17566615Sjasone hpfs_hphashdestroy(); 17666615Sjasone return 0;; 17766615Sjasone} 17866615Sjasone#endif 17966615Sjasone 18066615Sjasonestatic int 18154371Ssemenuhpfs_mount ( 18254371Ssemenu struct mount *mp, 18354371Ssemenu#if defined(__FreeBSD__) 18454371Ssemenu char *path, 18554371Ssemenu caddr_t data, 18654371Ssemenu#else /* defined(__NetBSD__) */ 18754371Ssemenu const char *path, 18854371Ssemenu void *data, 18983384Sjhb#endif 19083366Sjulian struct nameidata *ndp, 19183384Sjhb struct proc *p ) 19254371Ssemenu{ 19354371Ssemenu u_int size; 19454371Ssemenu int err = 0; 19554371Ssemenu struct vnode *devvp; 19654371Ssemenu struct hpfs_args args; 19754371Ssemenu struct hpfsmount *hpmp = 0; 19854371Ssemenu 19954371Ssemenu dprintf(("hpfs_mount():\n")); 20054371Ssemenu /* 20154371Ssemenu *** 20254371Ssemenu * Mounting non-root file system or updating a file system 20354371Ssemenu *** 20454371Ssemenu */ 20554371Ssemenu 20654371Ssemenu /* copy in user arguments*/ 20754371Ssemenu err = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args)); 20854371Ssemenu if (err) 20954371Ssemenu goto error_1; /* can't get arguments*/ 21054371Ssemenu 21154371Ssemenu /* 21254371Ssemenu * If updating, check whether changing from read-only to 21354371Ssemenu * read/write; if there is no device name, that's all we do. 21454371Ssemenu */ 21554371Ssemenu if (mp->mnt_flag & MNT_UPDATE) { 21654371Ssemenu dprintf(("hpfs_mount: MNT_UPDATE: ")); 21754371Ssemenu 21854371Ssemenu hpmp = VFSTOHPFS(mp); 21954371Ssemenu 22054371Ssemenu if (args.fspec == 0) { 22154371Ssemenu dprintf(("export 0x%x\n",args.export.ex_flags)); 22275934Sphk#if defined(__FreeBSD__) 22375934Sphk err = vfs_export(mp, &args.export); 22475934Sphk#else /* defined(__NetBSD__) */ 22554371Ssemenu err = vfs_export(mp, &hpmp->hpm_export, &args.export); 22675934Sphk#endif 22754371Ssemenu if (err) { 22854371Ssemenu printf("hpfs_mount: vfs_export failed %d\n", 22954371Ssemenu err); 23054371Ssemenu } 23154371Ssemenu goto success; 23254371Ssemenu } else { 23354371Ssemenu dprintf(("name [FAILED]\n")); 23454371Ssemenu err = EINVAL; 23554371Ssemenu goto success; 23654371Ssemenu } 23754371Ssemenu dprintf(("\n")); 23854371Ssemenu } 23954371Ssemenu 24054371Ssemenu /* 24154371Ssemenu * Not an update, or updating the name: look up the name 24254371Ssemenu * and verify that it refers to a sensible block device. 24354371Ssemenu */ 24483384Sjhb NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 24554371Ssemenu err = namei(ndp); 24654371Ssemenu if (err) { 24754371Ssemenu /* can't get devvp!*/ 24854371Ssemenu goto error_1; 24954371Ssemenu } 25054371Ssemenu 25154371Ssemenu devvp = ndp->ni_vp; 25254371Ssemenu 25354371Ssemenu#if defined(__FreeBSD__) 25455756Sphk if (!vn_isdisk(devvp, &err)) 25554371Ssemenu goto error_2; 25654371Ssemenu#else /* defined(__NetBSD__) */ 25754371Ssemenu if (devvp->v_type != VBLK) { 25854371Ssemenu err = ENOTBLK; 25954371Ssemenu goto error_2; 26054371Ssemenu } 26154371Ssemenu if (major(devvp->v_rdev) >= nblkdev) { 26254371Ssemenu err = ENXIO; 26354371Ssemenu goto error_2; 26454371Ssemenu } 26554371Ssemenu#endif 26654371Ssemenu 26754371Ssemenu /* 26854371Ssemenu ******************** 26954371Ssemenu * NEW MOUNT 27054371Ssemenu ******************** 27154371Ssemenu */ 27254371Ssemenu 27354371Ssemenu /* 27454371Ssemenu * Since this is a new mount, we want the names for 27554371Ssemenu * the device and the mount point copied in. If an 27673286Sadrian * error occurs, the mountpoint is discarded by the 27773286Sadrian * upper level code. Note that vfs_mount() handles 27873286Sadrian * copying the mountpoint f_mntonname for us, so we 27973286Sadrian * don't have to do it here unless we want to set it 28073286Sadrian * to something other than "path" for some rason. 28154371Ssemenu */ 28254371Ssemenu /* Save "mounted from" info for mount point (NULL pad)*/ 28354371Ssemenu copyinstr( args.fspec, /* device name*/ 28454371Ssemenu mp->mnt_stat.f_mntfromname, /* save area*/ 28554371Ssemenu MNAMELEN - 1, /* max size*/ 28654371Ssemenu &size); /* real size*/ 28754371Ssemenu bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 28854371Ssemenu 28983384Sjhb err = hpfs_mountfs(devvp, mp, &args, p); 29054371Ssemenu if (err) 29154371Ssemenu goto error_2; 29254371Ssemenu 29354371Ssemenu /* 29454371Ssemenu * Initialize FS stat information in mount struct; uses both 29554371Ssemenu * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname 29654371Ssemenu * 29754371Ssemenu * This code is common to root and non-root mounts 29854371Ssemenu */ 29983384Sjhb (void)VFS_STATFS(mp, &mp->mnt_stat, p); 30054371Ssemenu 30154371Ssemenu goto success; 30254371Ssemenu 30354371Ssemenu 30454371Ssemenuerror_2: /* error with devvp held*/ 30554371Ssemenu 30654371Ssemenu /* release devvp before failing*/ 30754371Ssemenu vrele(devvp); 30854371Ssemenu 30954371Ssemenuerror_1: /* no state to back out*/ 31054371Ssemenu 31154371Ssemenusuccess: 31254371Ssemenu return( err); 31354371Ssemenu} 31454371Ssemenu 31554371Ssemenu/* 31654371Ssemenu * Common code for mount and mountroot 31754371Ssemenu */ 31854371Ssemenuint 31983384Sjhbhpfs_mountfs(devvp, mp, argsp, p) 32054371Ssemenu register struct vnode *devvp; 32154371Ssemenu struct mount *mp; 32254371Ssemenu struct hpfs_args *argsp; 32383384Sjhb struct proc *p; 32454371Ssemenu{ 32554371Ssemenu int error, ncount, ronly; 32654371Ssemenu struct sublock *sup; 32754371Ssemenu struct spblock *spp; 32854371Ssemenu struct hpfsmount *hpmp; 32954371Ssemenu struct buf *bp = NULL; 33054371Ssemenu struct vnode *vp; 33154371Ssemenu dev_t dev = devvp->v_rdev; 33254371Ssemenu 33354371Ssemenu dprintf(("hpfs_mountfs():\n")); 33454371Ssemenu /* 33554371Ssemenu * Disallow multiple mounts of the same device. 33654371Ssemenu * Disallow mounting of a device that is currently in use 33754371Ssemenu * (except for root, which might share swap device for miniroot). 33854371Ssemenu * Flush out any old buffers remaining from a previous use. 33954371Ssemenu */ 34054371Ssemenu error = vfs_mountedon(devvp); 34154371Ssemenu if (error) 34254371Ssemenu return (error); 34354371Ssemenu ncount = vcount(devvp); 34454371Ssemenu#if defined(__FreeBSD__) 34554371Ssemenu if (devvp->v_object) 34654371Ssemenu ncount -= 1; 34754371Ssemenu#endif 34854371Ssemenu if (ncount > 1 && devvp != rootvp) 34954371Ssemenu return (EBUSY); 35054371Ssemenu 35154371Ssemenu#if defined(__FreeBSD__) 35283384Sjhb VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p); 35383384Sjhb error = vinvalbuf(devvp, V_SAVE, p->td_proc->p_ucred, p, 0, 0); 35483384Sjhb VOP__UNLOCK(devvp, 0, p); 35554371Ssemenu#else 35683384Sjhb error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0); 35754371Ssemenu#endif 35854371Ssemenu if (error) 35954371Ssemenu return (error); 36054371Ssemenu 36154371Ssemenu ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 36283384Sjhb VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p); 36383384Sjhb error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 36483384Sjhb VOP__UNLOCK(devvp, 0, p); 36554371Ssemenu if (error) 36654371Ssemenu return (error); 36754371Ssemenu 36854371Ssemenu /* 36954371Ssemenu * Do actual mount 37054371Ssemenu */ 37169781Sdwmalone hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK | M_ZERO); 37254371Ssemenu 37354371Ssemenu /* Read in SuperBlock */ 37454371Ssemenu error = bread(devvp, SUBLOCK, SUSIZE, NOCRED, &bp); 37554371Ssemenu if (error) 37654371Ssemenu goto failed; 37754371Ssemenu bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock)); 37854371Ssemenu brelse(bp); bp = NULL; 37954371Ssemenu 38054371Ssemenu /* Read in SpareBlock */ 38154371Ssemenu error = bread(devvp, SPBLOCK, SPSIZE, NOCRED, &bp); 38254371Ssemenu if (error) 38354371Ssemenu goto failed; 38454371Ssemenu bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock)); 38554371Ssemenu brelse(bp); bp = NULL; 38654371Ssemenu 38754371Ssemenu sup = &hpmp->hpm_su; 38854371Ssemenu spp = &hpmp->hpm_sp; 38954371Ssemenu 39054371Ssemenu /* Check magic */ 39154371Ssemenu if (sup->su_magic != SU_MAGIC) { 39254371Ssemenu printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n"); 39354371Ssemenu error = EINVAL; 39454371Ssemenu goto failed; 39554371Ssemenu } 39654371Ssemenu if (spp->sp_magic != SP_MAGIC) { 39754371Ssemenu printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n"); 39854371Ssemenu error = EINVAL; 39954371Ssemenu goto failed; 40054371Ssemenu } 40154371Ssemenu 40254371Ssemenu mp->mnt_data = (qaddr_t)hpmp; 40354371Ssemenu hpmp->hpm_devvp = devvp; 40454371Ssemenu hpmp->hpm_dev = devvp->v_rdev; 40554371Ssemenu hpmp->hpm_mp = mp; 40654371Ssemenu hpmp->hpm_uid = argsp->uid; 40754371Ssemenu hpmp->hpm_gid = argsp->gid; 40854371Ssemenu hpmp->hpm_mode = argsp->mode; 40954371Ssemenu 41054371Ssemenu error = hpfs_bminit(hpmp); 41154371Ssemenu if (error) 41254371Ssemenu goto failed; 41354371Ssemenu 41454371Ssemenu error = hpfs_cpinit(hpmp, argsp); 41554371Ssemenu if (error) { 41654371Ssemenu hpfs_bmdeinit(hpmp); 41754371Ssemenu goto failed; 41854371Ssemenu } 41954371Ssemenu 42054371Ssemenu error = hpfs_root(mp, &vp); 42154371Ssemenu if (error) { 42254371Ssemenu hpfs_cpdeinit(hpmp); 42354371Ssemenu hpfs_bmdeinit(hpmp); 42454371Ssemenu goto failed; 42554371Ssemenu } 42654371Ssemenu 42754371Ssemenu vput(vp); 42854371Ssemenu 42954371Ssemenu#if defined(__FreeBSD__) 43054371Ssemenu mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev); 43154371Ssemenu mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 43254371Ssemenu#else 43354371Ssemenu mp->mnt_stat.f_fsid.val[0] = (long)dev; 43454371Ssemenu mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_HPFS); 43554371Ssemenu#endif 43654371Ssemenu mp->mnt_maxsymlinklen = 0; 43754371Ssemenu mp->mnt_flag |= MNT_LOCAL; 43866886Seivind devvp->v_rdev->si_mountpoint = mp; 43954371Ssemenu return (0); 44054371Ssemenu 44154371Ssemenufailed: 44254371Ssemenu if (bp) 44354371Ssemenu brelse (bp); 44454371Ssemenu mp->mnt_data = (qaddr_t)NULL; 44554371Ssemenu#if defined(__FreeBSD__) 44666886Seivind devvp->v_rdev->si_mountpoint = NULL; 44754371Ssemenu#else 44854371Ssemenu devvp->v_specflags &= ~SI_MOUNTEDON; 44954371Ssemenu#endif 45083384Sjhb (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 45154371Ssemenu return (error); 45254371Ssemenu} 45354371Ssemenu 45454371Ssemenu#if !defined(__FreeBSD__) 45554371Ssemenustatic int 45654371Ssemenuhpfs_start ( 45754371Ssemenu struct mount *mp, 45854371Ssemenu int flags, 45983384Sjhb struct proc *p ) 46054371Ssemenu{ 46154371Ssemenu return (0); 46254371Ssemenu} 46354371Ssemenu#endif 46454371Ssemenu 46554371Ssemenustatic int 46654371Ssemenuhpfs_unmount( 46754371Ssemenu struct mount *mp, 46854371Ssemenu int mntflags, 46983384Sjhb struct proc *p) 47054371Ssemenu{ 47154371Ssemenu int error, flags, ronly; 47254371Ssemenu register struct hpfsmount *hpmp = VFSTOHPFS(mp); 47354371Ssemenu 47454371Ssemenu dprintf(("hpfs_unmount():\n")); 47554371Ssemenu 47654371Ssemenu ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 47754371Ssemenu 47854371Ssemenu flags = 0; 47954371Ssemenu if(mntflags & MNT_FORCE) 48054371Ssemenu flags |= FORCECLOSE; 48154371Ssemenu 48254371Ssemenu dprintf(("hpfs_unmount: vflushing...\n")); 48354371Ssemenu 48476688Siedowse error = vflush(mp, 0, flags); 48554371Ssemenu if (error) { 48654371Ssemenu printf("hpfs_unmount: vflush failed: %d\n",error); 48754371Ssemenu return (error); 48854371Ssemenu } 48954371Ssemenu 49054371Ssemenu#if defined(__FreeBSD__) 49166886Seivind hpmp->hpm_devvp->v_rdev->si_mountpoint = NULL; 49254371Ssemenu#else 49354371Ssemenu hpmp->hpm_devvp->v_specflags &= ~SI_MOUNTEDON; 49454371Ssemenu#endif 49554371Ssemenu 49683384Sjhb vinvalbuf(hpmp->hpm_devvp, V_SAVE, NOCRED, p, 0, 0); 49754371Ssemenu error = VOP_CLOSE(hpmp->hpm_devvp, ronly ? FREAD : FREAD|FWRITE, 49883384Sjhb NOCRED, p); 49954371Ssemenu 50054371Ssemenu vrele(hpmp->hpm_devvp); 50154371Ssemenu 50254371Ssemenu dprintf(("hpfs_umount: freeing memory...\n")); 50354371Ssemenu hpfs_cpdeinit(hpmp); 50454371Ssemenu hpfs_bmdeinit(hpmp); 50554371Ssemenu mp->mnt_data = (qaddr_t)0; 50654371Ssemenu mp->mnt_flag &= ~MNT_LOCAL; 50754371Ssemenu FREE(hpmp, M_HPFSMNT); 50854371Ssemenu 50954371Ssemenu return (0); 51054371Ssemenu} 51154371Ssemenu 51254371Ssemenustatic int 51354371Ssemenuhpfs_root( 51454371Ssemenu struct mount *mp, 51554371Ssemenu struct vnode **vpp ) 51654371Ssemenu{ 51754371Ssemenu int error = 0; 51854371Ssemenu struct hpfsmount *hpmp = VFSTOHPFS(mp); 51954371Ssemenu 52054371Ssemenu dprintf(("hpfs_root():\n")); 52154371Ssemenu error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, vpp); 52254371Ssemenu if(error) { 52354371Ssemenu printf("hpfs_root: VFS_VGET failed: %d\n",error); 52454371Ssemenu return (error); 52554371Ssemenu } 52654371Ssemenu 52754371Ssemenu return (error); 52854371Ssemenu} 52954371Ssemenu 53054371Ssemenustatic int 53154371Ssemenuhpfs_statfs( 53254371Ssemenu struct mount *mp, 53354371Ssemenu struct statfs *sbp, 53483384Sjhb struct proc *p) 53554371Ssemenu{ 53654371Ssemenu struct hpfsmount *hpmp = VFSTOHPFS(mp); 53754371Ssemenu 53854371Ssemenu dprintf(("hpfs_statfs(): HPFS%d.%d\n", 53954371Ssemenu hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver)); 54054371Ssemenu 54154371Ssemenu#if defined(__FreeBSD__) 54254371Ssemenu sbp->f_type = mp->mnt_vfc->vfc_typenum; 54354371Ssemenu#else /* defined(__NetBSD__) */ 54454371Ssemenu sbp->f_type = 0; 54554371Ssemenu#endif 54654371Ssemenu sbp->f_bsize = DEV_BSIZE; 54754371Ssemenu sbp->f_iosize = DEV_BSIZE; 54854371Ssemenu sbp->f_blocks = hpmp->hpm_su.su_btotal; 54954371Ssemenu sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail; 55054371Ssemenu sbp->f_ffree = 0; 55154371Ssemenu sbp->f_files = 0; 55254371Ssemenu if (sbp != &mp->mnt_stat) { 55354371Ssemenu bcopy((caddr_t)mp->mnt_stat.f_mntonname, 55454371Ssemenu (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 55554371Ssemenu bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 55654371Ssemenu (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 55754371Ssemenu } 55854371Ssemenu sbp->f_flags = mp->mnt_flag; 55954371Ssemenu 56054371Ssemenu return (0); 56154371Ssemenu} 56254371Ssemenu 56354371Ssemenu#if !defined(__FreeBSD__) 56454371Ssemenustatic int 56554371Ssemenuhpfs_sync ( 56654371Ssemenu struct mount *mp, 56754371Ssemenu int waitfor, 56854371Ssemenu struct ucred *cred, 56983384Sjhb struct proc *p) 57054371Ssemenu{ 57154371Ssemenu return (0); 57254371Ssemenu} 57354371Ssemenu 57454371Ssemenustatic int 57554371Ssemenuhpfs_quotactl ( 57654371Ssemenu struct mount *mp, 57754371Ssemenu int cmds, 57854371Ssemenu uid_t uid, 57954371Ssemenu caddr_t arg, 58083384Sjhb struct proc *p) 58154371Ssemenu{ 58254371Ssemenu printf("hpfs_quotactl():\n"); 58354371Ssemenu return (EOPNOTSUPP); 58454371Ssemenu} 58554371Ssemenu#endif 58654371Ssemenu 58754371Ssemenu/*ARGSUSED*/ 58854371Ssemenustatic int 58954371Ssemenuhpfs_fhtovp( 59054371Ssemenu struct mount *mp, 59154371Ssemenu struct fid *fhp, 59254371Ssemenu struct vnode **vpp) 59354371Ssemenu{ 59454371Ssemenu struct vnode *nvp; 59554371Ssemenu struct hpfid *hpfhp = (struct hpfid *)fhp; 59654371Ssemenu int error; 59754371Ssemenu 59854371Ssemenu if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, &nvp)) != 0) { 59954371Ssemenu *vpp = NULLVP; 60054371Ssemenu return (error); 60154371Ssemenu } 60254371Ssemenu /* XXX as unlink/rmdir/mkdir/creat are not currently possible 60354371Ssemenu * with HPFS, we don't need to check anything else for now */ 60454371Ssemenu *vpp = nvp; 60554371Ssemenu 60654371Ssemenu return (0); 60754371Ssemenu} 60854371Ssemenu 60954371Ssemenustatic int 61054371Ssemenuhpfs_vptofh( 61154371Ssemenu struct vnode *vp, 61254371Ssemenu struct fid *fhp) 61354371Ssemenu{ 61454371Ssemenu register struct hpfsnode *hpp; 61554371Ssemenu register struct hpfid *hpfhp; 61654371Ssemenu 61754371Ssemenu hpp = VTOHP(vp); 61854371Ssemenu hpfhp = (struct hpfid *)fhp; 61954371Ssemenu hpfhp->hpfid_len = sizeof(struct hpfid); 62054371Ssemenu hpfhp->hpfid_ino = hpp->h_no; 62154371Ssemenu /* hpfhp->hpfid_gen = hpp->h_gen; */ 62254371Ssemenu return (0); 62354371Ssemenu} 62454371Ssemenu 62554371Ssemenustatic int 62654371Ssemenuhpfs_vget( 62754371Ssemenu struct mount *mp, 62854371Ssemenu ino_t ino, 62954371Ssemenu struct vnode **vpp) 63054371Ssemenu{ 63154371Ssemenu struct hpfsmount *hpmp = VFSTOHPFS(mp); 63254371Ssemenu struct vnode *vp; 63354371Ssemenu struct hpfsnode *hp; 63454371Ssemenu struct buf *bp; 63583384Sjhb#if defined(__FreeBSD__) 63683384Sjhb struct thread *p = curthread; /* XXX */ 63783384Sjhb#else 63883384Sjhb struct proc *p = curproc; /* XXX */ 63983384Sjhb#endif 64054371Ssemenu int error; 64154371Ssemenu 64254371Ssemenu dprintf(("hpfs_vget(0x%x): ",ino)); 64354371Ssemenu 64454371Ssemenu *vpp = NULL; 64554371Ssemenu hp = NULL; 64654371Ssemenu vp = NULL; 64754371Ssemenu 64883384Sjhb if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, p)) != NULL) { 64954371Ssemenu dprintf(("hashed\n")); 65054371Ssemenu return (0); 65154371Ssemenu } 65254371Ssemenu 65354371Ssemenu /* 65454371Ssemenu * We have to lock node creation for a while, 65554371Ssemenu * but then we have to call getnewvnode(), 65654371Ssemenu * this may cause hpfs_reclaim() to be called, 65754371Ssemenu * this may need to VOP_VGET() parent dir for 65854371Ssemenu * update reasons, and if parent is not in 65954371Ssemenu * hash, we have to lock node creation... 66054371Ssemenu * To solve this, we MALLOC, getnewvnode and init while 66154371Ssemenu * not locked (probability of node appearence 66254371Ssemenu * at that time is little, and anyway - we'll 66354371Ssemenu * check for it). 66454371Ssemenu */ 66554371Ssemenu MALLOC(hp, struct hpfsnode *, sizeof(struct hpfsnode), 66654371Ssemenu M_HPFSNO, M_WAITOK); 66754371Ssemenu 66854371Ssemenu error = getnewvnode(VT_HPFS, hpmp->hpm_mp, hpfs_vnodeop_p, &vp); 66954371Ssemenu if (error) { 67054371Ssemenu printf("hpfs_vget: can't get new vnode\n"); 67154371Ssemenu FREE(hp, M_HPFSNO); 67254371Ssemenu return (error); 67354371Ssemenu } 67454371Ssemenu 67554371Ssemenu dprintf(("prenew ")); 67654371Ssemenu 67754371Ssemenu vp->v_data = hp; 67854371Ssemenu 67954371Ssemenu if (ino == (ino_t)hpmp->hpm_su.su_rootfno) 68054371Ssemenu vp->v_flag |= VROOT; 68154371Ssemenu 68271576Sjasone 68371576Sjasone mtx_init(&hp->h_interlock, "hpfsnode interlock", MTX_DEF); 68454371Ssemenu lockinit(&hp->h_lock, PINOD, "hpnode", 0, 0); 68554371Ssemenu 68654371Ssemenu hp->h_flag = H_INVAL; 68754371Ssemenu hp->h_vp = vp; 68854371Ssemenu hp->h_hpmp = hpmp; 68954371Ssemenu hp->h_no = ino; 69054371Ssemenu hp->h_dev = hpmp->hpm_dev; 69154371Ssemenu hp->h_uid = hpmp->hpm_uid; 69254371Ssemenu hp->h_gid = hpmp->hpm_uid; 69354371Ssemenu hp->h_mode = hpmp->hpm_mode; 69454371Ssemenu hp->h_devvp = hpmp->hpm_devvp; 69554371Ssemenu VREF(hp->h_devvp); 69654371Ssemenu 69783384Sjhb error = VN_LOCK(vp, LK_EXCLUSIVE, p); 69854371Ssemenu if (error) { 69954371Ssemenu vput(vp); 70054371Ssemenu return (error); 70154371Ssemenu } 70254371Ssemenu 70354371Ssemenu do { 70483384Sjhb if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, p)) != NULL) { 70554371Ssemenu dprintf(("hashed2\n")); 70654371Ssemenu vput(vp); 70754371Ssemenu return (0); 70854371Ssemenu } 70954371Ssemenu } while(LOCKMGR(&hpfs_hphash_lock,LK_EXCLUSIVE|LK_SLEEPFAIL,NULL,NULL)); 71054371Ssemenu 71154371Ssemenu hpfs_hphashins(hp); 71254371Ssemenu 71354371Ssemenu LOCKMGR(&hpfs_hphash_lock, LK_RELEASE, NULL, NULL); 71454371Ssemenu 71554371Ssemenu error = bread(hpmp->hpm_devvp, ino, FNODESIZE, NOCRED, &bp); 71654371Ssemenu if (error) { 71754371Ssemenu printf("hpfs_vget: can't read ino %d\n",ino); 71854371Ssemenu vput(vp); 71954371Ssemenu return (error); 72054371Ssemenu } 72154371Ssemenu bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode)); 72254371Ssemenu brelse(bp); 72354371Ssemenu 72454371Ssemenu if (hp->h_fn.fn_magic != FN_MAGIC) { 72554371Ssemenu printf("hpfs_vget: MAGIC DOESN'T MATCH\n"); 72654371Ssemenu vput(vp); 72754371Ssemenu return (EINVAL); 72854371Ssemenu } 72954371Ssemenu 73054371Ssemenu vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG; 73154371Ssemenu hp->h_flag &= ~H_INVAL; 73254371Ssemenu 73354371Ssemenu *vpp = vp; 73454371Ssemenu 73554371Ssemenu return (0); 73654371Ssemenu} 73754371Ssemenu 73854371Ssemenu#if defined(__FreeBSD__) 73954371Ssemenustatic struct vfsops hpfs_vfsops = { 74054371Ssemenu hpfs_mount, 74154371Ssemenu vfs_stdstart, 74254371Ssemenu hpfs_unmount, 74354371Ssemenu hpfs_root, 74454371Ssemenu vfs_stdquotactl, 74554371Ssemenu hpfs_statfs, 74654371Ssemenu vfs_stdsync, 74754371Ssemenu hpfs_vget, 74854371Ssemenu hpfs_fhtovp, 74975934Sphk vfs_stdcheckexp, 75054371Ssemenu hpfs_vptofh, 75154371Ssemenu hpfs_init, 75266615Sjasone hpfs_uninit, 75354803Srwatson vfs_stdextattrctl, 75454371Ssemenu}; 75554371SsemenuVFS_SET(hpfs_vfsops, hpfs, 0); 75654371Ssemenu#else /* defined(__NetBSD__) */ 75754371Ssemenuextern struct vnodeopv_desc hpfs_vnodeop_opv_desc; 75854371Ssemenu 75954371Ssemenustruct vnodeopv_desc *hpfs_vnodeopv_descs[] = { 76054371Ssemenu &hpfs_vnodeop_opv_desc, 76154371Ssemenu NULL, 76254371Ssemenu}; 76354371Ssemenu 76454371Ssemenustruct vfsops hpfs_vfsops = { 76554371Ssemenu MOUNT_HPFS, 76654371Ssemenu hpfs_mount, 76754371Ssemenu hpfs_start, 76854371Ssemenu hpfs_unmount, 76954371Ssemenu hpfs_root, 77054371Ssemenu hpfs_quotactl, 77154371Ssemenu hpfs_statfs, 77254371Ssemenu hpfs_sync, 77354371Ssemenu hpfs_vget, 77454371Ssemenu hpfs_fhtovp, 77554371Ssemenu hpfs_vptofh, 77654371Ssemenu hpfs_init, 77754371Ssemenu hpfs_sysctl, 77854371Ssemenu hpfs_mountroot, 77954371Ssemenu hpfs_checkexp, 78054371Ssemenu hpfs_vnodeopv_descs, 78154371Ssemenu}; 78254371Ssemenu#endif 783