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