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