ffs_vfsops.c revision 32286
1/*
2 * Copyright (c) 1989, 1991, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	@(#)ffs_vfsops.c	8.31 (Berkeley) 5/20/95
34 * $Id: ffs_vfsops.c,v 1.63 1997/12/29 00:24:28 dyson Exp $
35 */
36
37#include "opt_quota.h"
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/namei.h>
42#include <sys/proc.h>
43#include <sys/kernel.h>
44#include <sys/vnode.h>
45#include <sys/mount.h>
46#include <sys/buf.h>
47#include <sys/conf.h>
48#include <sys/fcntl.h>
49#include <sys/disklabel.h>
50#include <sys/malloc.h>
51
52#include <miscfs/specfs/specdev.h>
53
54#include <ufs/ufs/quota.h>
55#include <ufs/ufs/ufsmount.h>
56#include <ufs/ufs/inode.h>
57#include <ufs/ufs/ufs_extern.h>
58
59#include <ufs/ffs/fs.h>
60#include <ufs/ffs/ffs_extern.h>
61
62#include <vm/vm.h>
63#include <vm/vm_prot.h>
64#include <vm/vm_page.h>
65#include <vm/vm_extern.h>
66#include <vm/vm_object.h>
67
68static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part");
69
70static int	ffs_sbupdate __P((struct ufsmount *, int));
71static int	ffs_reload __P((struct mount *,struct ucred *,struct proc *));
72static int	ffs_oldfscompat __P((struct fs *));
73static int	ffs_mount __P((struct mount *, char *, caddr_t,
74				struct nameidata *, struct proc *));
75static int	ffs_init __P((struct vfsconf *));
76
77struct vfsops ufs_vfsops = {
78	ffs_mount,
79	ufs_start,
80	ffs_unmount,
81	ufs_root,
82	ufs_quotactl,
83	ffs_statfs,
84	ffs_sync,
85	ffs_vget,
86	ffs_fhtovp,
87	ffs_vptofh,
88	ffs_init,
89};
90
91VFS_SET(ufs_vfsops, ufs, MOUNT_UFS, 0);
92
93/*
94 * ffs_mount
95 *
96 * Called when mounting local physical media
97 *
98 * PARAMETERS:
99 *		mountroot
100 *			mp	mount point structure
101 *			path	NULL (flag for root mount!!!)
102 *			data	<unused>
103 *			ndp	<unused>
104 *			p	process (user credentials check [statfs])
105 *
106 *		mount
107 *			mp	mount point structure
108 *			path	path to mount point
109 *			data	pointer to argument struct in user space
110 *			ndp	mount point namei() return (used for
111 *				credentials on reload), reused to look
112 *				up block device.
113 *			p	process (user credentials check)
114 *
115 * RETURNS:	0	Success
116 *		!0	error number (errno.h)
117 *
118 * LOCK STATE:
119 *
120 *		ENTRY
121 *			mount point is locked
122 *		EXIT
123 *			mount point is locked
124 *
125 * NOTES:
126 *		A NULL path can be used for a flag since the mount
127 *		system call will fail with EFAULT in copyinstr in
128 *		namei() if it is a genuine NULL from the user.
129 */
130static int
131ffs_mount( mp, path, data, ndp, p)
132        struct mount		*mp;	/* mount struct pointer*/
133        char			*path;	/* path to mount point*/
134        caddr_t			data;	/* arguments to FS specific mount*/
135        struct nameidata	*ndp;	/* mount point credentials*/
136        struct proc		*p;	/* process requesting mount*/
137{
138	u_int		size;
139	int		err = 0;
140	struct vnode	*devvp;
141
142	struct ufs_args args;
143	struct ufsmount *ump = 0;
144	register struct fs *fs;
145	int flags;
146
147	/*
148	 * Use NULL path to flag a root mount
149	 */
150	if( path == NULL) {
151		/*
152		 ***
153		 * Mounting root file system
154		 ***
155		 */
156
157		if ((err = bdevvp(rootdev, &rootvp))) {
158			printf("ffs_mountroot: can't find rootvp");
159			return (err);
160		}
161
162		if (bdevsw[major(rootdev)]->d_flags & D_NOCLUSTERR)
163			mp->mnt_flag |= MNT_NOCLUSTERR;
164		if (bdevsw[major(rootdev)]->d_flags & D_NOCLUSTERW)
165			mp->mnt_flag |= MNT_NOCLUSTERW;
166		if( ( err = ffs_mountfs(rootvp, mp, p, M_FFSNODE)) != 0) {
167			/* fs specific cleanup (if any)*/
168			goto error_1;
169		}
170
171		goto dostatfs;		/* success*/
172
173	}
174
175	/*
176	 ***
177	 * Mounting non-root file system or updating a file system
178	 ***
179	 */
180
181	/* copy in user arguments*/
182	err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
183	if (err)
184		goto error_1;		/* can't get arguments*/
185
186	/*
187	 * If updating, check whether changing from read-only to
188	 * read/write; if there is no device name, that's all we do.
189	 * Disallow clearing MNT_NOCLUSTERR and MNT_NOCLUSTERW flags,
190	 * if block device requests.
191	 */
192	if (mp->mnt_flag & MNT_UPDATE) {
193		ump = VFSTOUFS(mp);
194		fs = ump->um_fs;
195		err = 0;
196		if (bdevsw[major(ump->um_dev)]->d_flags & D_NOCLUSTERR)
197			mp->mnt_flag |= MNT_NOCLUSTERR;
198		if (bdevsw[major(ump->um_dev)]->d_flags & D_NOCLUSTERW)
199			mp->mnt_flag |= MNT_NOCLUSTERW;
200		if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
201			flags = WRITECLOSE;
202			if (mp->mnt_flag & MNT_FORCE)
203				flags |= FORCECLOSE;
204			err = ffs_flushfiles(mp, flags, p);
205		}
206		if (!err && (mp->mnt_flag & MNT_RELOAD))
207			err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
208		if (err) {
209			goto error_1;
210		}
211		if (fs->fs_ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
212			if (!fs->fs_clean) {
213				if (mp->mnt_flag & MNT_FORCE) {
214					printf("WARNING: %s was not properly dismounted.\n",fs->fs_fsmnt);
215				} else {
216					printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck.\n",
217					    fs->fs_fsmnt);
218					err = EPERM;
219					goto error_1;
220				}
221			}
222			fs->fs_ronly = 0;
223		}
224		if (fs->fs_ronly == 0) {
225			fs->fs_clean = 0;
226			ffs_sbupdate(ump, MNT_WAIT);
227		}
228		/* if not updating name...*/
229		if (args.fspec == 0) {
230			/*
231			 * Process export requests.  Jumping to "success"
232			 * will return the vfs_export() error code.
233			 */
234			err = vfs_export(mp, &ump->um_export, &args.export);
235			goto success;
236		}
237	}
238
239	/*
240	 * Not an update, or updating the name: look up the name
241	 * and verify that it refers to a sensible block device.
242	 */
243	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
244	err = namei(ndp);
245	if (err) {
246		/* can't get devvp!*/
247		goto error_1;
248	}
249
250	devvp = ndp->ni_vp;
251
252	if (devvp->v_type != VBLK) {
253		err = ENOTBLK;
254		goto error_2;
255	}
256	if (major(devvp->v_rdev) >= nblkdev) {
257		err = ENXIO;
258		goto error_2;
259	}
260	if (mp->mnt_flag & MNT_UPDATE) {
261		/*
262		 ********************
263		 * UPDATE
264		 ********************
265		 */
266
267		if (devvp != ump->um_devvp)
268			err = EINVAL;	/* needs translation */
269		else
270			vrele(devvp);
271		/*
272		 * Update device name only on success
273		 */
274		if( !err) {
275			/* Save "mounted from" info for mount point (NULL pad)*/
276			copyinstr(	args.fspec,
277					mp->mnt_stat.f_mntfromname,
278					MNAMELEN - 1,
279					&size);
280			bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
281		}
282	} else {
283		/*
284		 ********************
285		 * NEW MOUNT
286		 ********************
287		 */
288
289		if (bdevsw[major(devvp->v_rdev)]->d_flags & D_NOCLUSTERR)
290			mp->mnt_flag |= MNT_NOCLUSTERR;
291		if (bdevsw[major(devvp->v_rdev)]->d_flags & D_NOCLUSTERW)
292			mp->mnt_flag |= MNT_NOCLUSTERW;
293
294		/*
295		 * Since this is a new mount, we want the names for
296		 * the device and the mount point copied in.  If an
297		 * error occurs,  the mountpoint is discarded by the
298		 * upper level code.
299		 */
300		/* Save "last mounted on" info for mount point (NULL pad)*/
301		copyinstr(	path,				/* mount point*/
302				mp->mnt_stat.f_mntonname,	/* save area*/
303				MNAMELEN - 1,			/* max size*/
304				&size);				/* real size*/
305		bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
306
307		/* Save "mounted from" info for mount point (NULL pad)*/
308		copyinstr(	args.fspec,			/* device name*/
309				mp->mnt_stat.f_mntfromname,	/* save area*/
310				MNAMELEN - 1,			/* max size*/
311				&size);				/* real size*/
312		bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
313
314		err = ffs_mountfs(devvp, mp, p, M_FFSNODE);
315	}
316	if (err) {
317		goto error_2;
318	}
319
320dostatfs:
321	/*
322	 * Initialize FS stat information in mount struct; uses both
323	 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
324	 *
325	 * This code is common to root and non-root mounts
326	 */
327	(void)VFS_STATFS(mp, &mp->mnt_stat, p);
328
329	goto success;
330
331
332error_2:	/* error with devvp held*/
333
334	/* release devvp before failing*/
335	vrele(devvp);
336
337error_1:	/* no state to back out*/
338
339success:
340	return( err);
341}
342
343/*
344 * Reload all incore data for a filesystem (used after running fsck on
345 * the root filesystem and finding things to fix). The filesystem must
346 * be mounted read-only.
347 *
348 * Things to do to update the mount:
349 *	1) invalidate all cached meta-data.
350 *	2) re-read superblock from disk.
351 *	3) re-read summary information from disk.
352 *	4) invalidate all inactive vnodes.
353 *	5) invalidate all cached file data.
354 *	6) re-read inode data for all active vnodes.
355 */
356static int
357ffs_reload(mp, cred, p)
358	register struct mount *mp;
359	struct ucred *cred;
360	struct proc *p;
361{
362	register struct vnode *vp, *nvp, *devvp;
363	struct inode *ip;
364	struct csum *space;
365	struct buf *bp;
366	struct fs *fs, *newfs;
367	struct partinfo dpart;
368	dev_t dev;
369	int i, blks, size, error;
370	int32_t *lp;
371
372	if ((mp->mnt_flag & MNT_RDONLY) == 0)
373		return (EINVAL);
374	/*
375	 * Step 1: invalidate all cached meta-data.
376	 */
377	devvp = VFSTOUFS(mp)->um_devvp;
378	if (vinvalbuf(devvp, 0, cred, p, 0, 0))
379		panic("ffs_reload: dirty1");
380
381	dev = devvp->v_rdev;
382	/*
383	 * Only VMIO the backing device if the backing device is a real
384	 * block device.  This excludes the original MFS implementation.
385	 * Note that it is optional that the backing device be VMIOed.  This
386	 * increases the opportunity for metadata caching.
387	 */
388	if ((devvp->v_type == VBLK) && (major(dev) < nblkdev)) {
389		vfs_object_create(devvp, p, p->p_ucred, 0);
390	}
391
392	/*
393	 * Step 2: re-read superblock from disk.
394	 */
395	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
396		size = DEV_BSIZE;
397	else
398		size = dpart.disklab->d_secsize;
399	if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp))
400		return (error);
401	newfs = (struct fs *)bp->b_data;
402	if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
403		newfs->fs_bsize < sizeof(struct fs)) {
404			brelse(bp);
405			return (EIO);		/* XXX needs translation */
406	}
407	fs = VFSTOUFS(mp)->um_fs;
408	/*
409	 * Copy pointer fields back into superblock before copying in	XXX
410	 * new superblock. These should really be in the ufsmount.	XXX
411	 * Note that important parameters (eg fs_ncg) are unchanged.
412	 */
413	bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
414	newfs->fs_maxcluster = fs->fs_maxcluster;
415	bcopy(newfs, fs, (u_int)fs->fs_sbsize);
416	if (fs->fs_sbsize < SBSIZE)
417		bp->b_flags |= B_INVAL;
418	brelse(bp);
419	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
420	ffs_oldfscompat(fs);
421
422	/*
423	 * Step 3: re-read summary information from disk.
424	 */
425	blks = howmany(fs->fs_cssize, fs->fs_fsize);
426	space = fs->fs_csp[0];
427	for (i = 0; i < blks; i += fs->fs_frag) {
428		size = fs->fs_bsize;
429		if (i + fs->fs_frag > blks)
430			size = (blks - i) * fs->fs_fsize;
431		error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
432		    NOCRED, &bp);
433		if (error)
434			return (error);
435		bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
436		brelse(bp);
437	}
438	/*
439	 * We no longer know anything about clusters per cylinder group.
440	 */
441	if (fs->fs_contigsumsize > 0) {
442		lp = fs->fs_maxcluster;
443		for (i = 0; i < fs->fs_ncg; i++)
444			*lp++ = fs->fs_contigsumsize;
445	}
446
447loop:
448	simple_lock(&mntvnode_slock);
449	for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
450		if (vp->v_mount != mp) {
451			simple_unlock(&mntvnode_slock);
452			goto loop;
453		}
454		nvp = vp->v_mntvnodes.le_next;
455		/*
456		 * Step 4: invalidate all inactive vnodes.
457		 */
458		if (vrecycle(vp, &mntvnode_slock, p))
459			goto loop;
460		/*
461		 * Step 5: invalidate all cached file data.
462		 */
463		simple_lock(&vp->v_interlock);
464		simple_unlock(&mntvnode_slock);
465		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
466			goto loop;
467		}
468		if (vinvalbuf(vp, 0, cred, p, 0, 0))
469			panic("ffs_reload: dirty2");
470		/*
471		 * Step 6: re-read inode data for all active vnodes.
472		 */
473		ip = VTOI(vp);
474		error =
475		    bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
476		    (int)fs->fs_bsize, NOCRED, &bp);
477		if (error) {
478			vput(vp);
479			return (error);
480		}
481		ip->i_din = *((struct dinode *)bp->b_data +
482		    ino_to_fsbo(fs, ip->i_number));
483		brelse(bp);
484		vput(vp);
485		simple_lock(&mntvnode_slock);
486	}
487	simple_unlock(&mntvnode_slock);
488	return (0);
489}
490
491/*
492 * Common code for mount and mountroot
493 */
494int
495ffs_mountfs(devvp, mp, p, malloctype)
496	register struct vnode *devvp;
497	struct mount *mp;
498	struct proc *p;
499	struct malloc_type *malloctype;
500{
501	register struct ufsmount *ump;
502	struct buf *bp;
503	register struct fs *fs;
504	dev_t dev;
505	struct partinfo dpart;
506	caddr_t base, space;
507	int error, i, blks, size, ronly;
508	int32_t *lp;
509	struct ucred *cred;
510	u_int64_t maxfilesize;					/* XXX */
511	u_int strsize;
512	int ncount;
513
514	dev = devvp->v_rdev;
515	cred = p ? p->p_ucred : NOCRED;
516	/*
517	 * Disallow multiple mounts of the same device.
518	 * Disallow mounting of a device that is currently in use
519	 * (except for root, which might share swap device for miniroot).
520	 * Flush out any old buffers remaining from a previous use.
521	 */
522	error = vfs_mountedon(devvp);
523	if (error)
524		return (error);
525	ncount = vcount(devvp);
526/*
527	if (devvp->v_object)
528		ncount -= 1;
529*/
530	if (ncount > 1 && devvp != rootvp)
531		return (EBUSY);
532	if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
533		return (error);
534
535	/*
536	 * Only VMIO the backing device if the backing device is a real
537	 * block device.  This excludes the original MFS implementation.
538	 * Note that it is optional that the backing device be VMIOed.  This
539	 * increases the opportunity for metadata caching.
540	 */
541	if ((devvp->v_type == VBLK) && (major(dev) < nblkdev)) {
542		vfs_object_create(devvp, p, p->p_ucred, 0);
543	}
544
545
546	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
547	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
548	if (error)
549		return (error);
550
551	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
552		size = DEV_BSIZE;
553	else
554		size = dpart.disklab->d_secsize;
555
556	bp = NULL;
557	ump = NULL;
558	if (error = bread(devvp, SBLOCK, SBSIZE, cred, &bp))
559		goto out;
560	fs = (struct fs *)bp->b_data;
561	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
562	    fs->fs_bsize < sizeof(struct fs)) {
563		error = EINVAL;		/* XXX needs translation */
564		goto out;
565	}
566	fs->fs_fmod = 0;
567	if (!fs->fs_clean) {
568		if (ronly || (mp->mnt_flag & MNT_FORCE)) {
569			printf("WARNING: %s was not properly dismounted.\n",fs->fs_fsmnt);
570		} else {
571			printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck.\n",fs->fs_fsmnt);
572			error = EPERM;
573			goto out;
574		}
575	}
576	/* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
577	if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
578		error = EROFS;          /* needs translation */
579		goto out;
580	}
581	ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
582	bzero((caddr_t)ump, sizeof *ump);
583	ump->um_malloctype = malloctype;
584	ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
585	    M_WAITOK);
586	ump->um_blkatoff = ffs_blkatoff;
587	ump->um_truncate = ffs_truncate;
588	ump->um_update = ffs_update;
589	ump->um_valloc = ffs_valloc;
590	ump->um_vfree = ffs_vfree;
591	bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
592	if (fs->fs_sbsize < SBSIZE)
593		bp->b_flags |= B_INVAL;
594	brelse(bp);
595	bp = NULL;
596	fs = ump->um_fs;
597	fs->fs_ronly = ronly;
598	if (ronly == 0) {
599		fs->fs_fmod = 1;
600		fs->fs_clean = 0;
601	}
602	size = fs->fs_cssize;
603	blks = howmany(size, fs->fs_fsize);
604	if (fs->fs_contigsumsize > 0)
605		size += fs->fs_ncg * sizeof(int32_t);
606	base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
607	for (i = 0; i < blks; i += fs->fs_frag) {
608		size = fs->fs_bsize;
609		if (i + fs->fs_frag > blks)
610			size = (blks - i) * fs->fs_fsize;
611		if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
612		    cred, &bp)) {
613			free(base, M_UFSMNT);
614			goto out;
615		}
616		bcopy(bp->b_data, space, (u_int)size);
617		fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
618		space += size;
619		brelse(bp);
620		bp = NULL;
621	}
622	if (fs->fs_contigsumsize > 0) {
623		fs->fs_maxcluster = lp = (int32_t *)space;
624		for (i = 0; i < fs->fs_ncg; i++)
625			*lp++ = fs->fs_contigsumsize;
626	}
627	mp->mnt_data = (qaddr_t)ump;
628	mp->mnt_stat.f_fsid.val[0] = (long)dev;
629	if (fs->fs_id[0] != 0 && fs->fs_id[1] != 0)
630		mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
631	else
632		mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
633	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
634	mp->mnt_flag |= MNT_LOCAL;
635	ump->um_mountp = mp;
636	ump->um_dev = dev;
637	ump->um_devvp = devvp;
638	ump->um_nindir = fs->fs_nindir;
639	ump->um_bptrtodb = fs->fs_fsbtodb;
640	ump->um_seqinc = fs->fs_frag;
641	for (i = 0; i < MAXQUOTAS; i++)
642		ump->um_quotas[i] = NULLVP;
643	devvp->v_specflags |= SI_MOUNTEDON;
644	ffs_oldfscompat(fs);
645
646	/*
647	 * Set FS local "last mounted on" information (NULL pad)
648	 */
649	copystr(	mp->mnt_stat.f_mntonname,	/* mount point*/
650			fs->fs_fsmnt,			/* copy area*/
651			sizeof(fs->fs_fsmnt) - 1,	/* max size*/
652			&strsize);			/* real size*/
653	bzero( fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize);
654
655	if( mp->mnt_flag & MNT_ROOTFS) {
656		/*
657		 * Root mount; update timestamp in mount structure.
658		 * this will be used by the common root mount code
659		 * to update the system clock.
660		 */
661		mp->mnt_time = fs->fs_time;
662	}
663
664	ump->um_savedmaxfilesize = fs->fs_maxfilesize;		/* XXX */
665	maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1;	/* XXX */
666	if (fs->fs_maxfilesize > maxfilesize)			/* XXX */
667		fs->fs_maxfilesize = maxfilesize;		/* XXX */
668	if (ronly == 0) {
669		fs->fs_clean = 0;
670		(void) ffs_sbupdate(ump, MNT_WAIT);
671	}
672	return (0);
673out:
674	if (bp)
675		brelse(bp);
676	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
677	if (ump) {
678		free(ump->um_fs, M_UFSMNT);
679		free(ump, M_UFSMNT);
680		mp->mnt_data = (qaddr_t)0;
681	}
682	return (error);
683}
684
685/*
686 * Sanity checks for old file systems.
687 *
688 * XXX - goes away some day.
689 */
690static int
691ffs_oldfscompat(fs)
692	struct fs *fs;
693{
694
695	fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);	/* XXX */
696	fs->fs_interleave = max(fs->fs_interleave, 1);		/* XXX */
697	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
698		fs->fs_nrpos = 8;				/* XXX */
699	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
700#if 0
701		int i;						/* XXX */
702		u_int64_t sizepb = fs->fs_bsize;		/* XXX */
703								/* XXX */
704		fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;	/* XXX */
705		for (i = 0; i < NIADDR; i++) {			/* XXX */
706			sizepb *= NINDIR(fs);			/* XXX */
707			fs->fs_maxfilesize += sizepb;		/* XXX */
708		}						/* XXX */
709#endif
710		fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
711		fs->fs_qbmask = ~fs->fs_bmask;			/* XXX */
712		fs->fs_qfmask = ~fs->fs_fmask;			/* XXX */
713	}							/* XXX */
714	return (0);
715}
716
717/*
718 * unmount system call
719 */
720int
721ffs_unmount(mp, mntflags, p)
722	struct mount *mp;
723	int mntflags;
724	struct proc *p;
725{
726	register struct ufsmount *ump;
727	register struct fs *fs;
728	int error, flags;
729
730	flags = 0;
731	if (mntflags & MNT_FORCE) {
732		flags |= FORCECLOSE;
733	}
734	error = ffs_flushfiles(mp, flags, p);
735	if (error)
736		return (error);
737	ump = VFSTOUFS(mp);
738	fs = ump->um_fs;
739	if (fs->fs_ronly == 0) {
740		fs->fs_clean = 1;
741		error = ffs_sbupdate(ump, MNT_WAIT);
742		if (error) {
743			fs->fs_clean = 0;
744			return (error);
745		}
746	}
747	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
748
749	vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
750	if (ump->um_devvp->v_object)
751		vm_object_terminate(ump->um_devvp->v_object);
752
753	error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
754		NOCRED, p);
755
756	vrele(ump->um_devvp);
757
758	free(fs->fs_csp[0], M_UFSMNT);
759	free(fs, M_UFSMNT);
760	free(ump, M_UFSMNT);
761	mp->mnt_data = (qaddr_t)0;
762	mp->mnt_flag &= ~MNT_LOCAL;
763	return (error);
764}
765
766/*
767 * Flush out all the files in a filesystem.
768 */
769int
770ffs_flushfiles(mp, flags, p)
771	register struct mount *mp;
772	int flags;
773	struct proc *p;
774{
775	register struct ufsmount *ump;
776	int error;
777
778	ump = VFSTOUFS(mp);
779#ifdef QUOTA
780	if (mp->mnt_flag & MNT_QUOTA) {
781		int i;
782		error = vflush(mp, NULLVP, SKIPSYSTEM|flags);
783		if (error)
784			return (error);
785		for (i = 0; i < MAXQUOTAS; i++) {
786			if (ump->um_quotas[i] == NULLVP)
787				continue;
788			quotaoff(p, mp, i);
789		}
790		/*
791		 * Here we fall through to vflush again to ensure
792		 * that we have gotten rid of all the system vnodes.
793		 */
794	}
795#endif
796	error = vflush(mp, NULLVP, flags);
797	return (error);
798}
799
800/*
801 * Get file system statistics.
802 */
803int
804ffs_statfs(mp, sbp, p)
805	struct mount *mp;
806	register struct statfs *sbp;
807	struct proc *p;
808{
809	register struct ufsmount *ump;
810	register struct fs *fs;
811
812	ump = VFSTOUFS(mp);
813	fs = ump->um_fs;
814	if (fs->fs_magic != FS_MAGIC)
815		panic("ffs_statfs");
816	sbp->f_bsize = fs->fs_fsize;
817	sbp->f_iosize = fs->fs_bsize;
818	sbp->f_blocks = fs->fs_dsize;
819	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
820		fs->fs_cstotal.cs_nffree;
821	sbp->f_bavail = freespace(fs, fs->fs_minfree);
822	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
823	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
824	if (sbp != &mp->mnt_stat) {
825		sbp->f_type = mp->mnt_vfc->vfc_typenum;
826		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
827			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
828		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
829			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
830	}
831	return (0);
832}
833
834/*
835 * Go through the disk queues to initiate sandbagged IO;
836 * go through the inodes to write those that have been modified;
837 * initiate the writing of the super block if it has been modified.
838 *
839 * Note: we are always called with the filesystem marked `MPBUSY'.
840 */
841int
842ffs_sync(mp, waitfor, cred, p)
843	struct mount *mp;
844	int waitfor;
845	struct ucred *cred;
846	struct proc *p;
847{
848	struct vnode *nvp, *vp;
849	struct inode *ip;
850	struct ufsmount *ump = VFSTOUFS(mp);
851	struct fs *fs;
852	struct timeval tv;
853	int error, allerror = 0;
854
855	fs = ump->um_fs;
856	if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {		/* XXX */
857		printf("fs = %s\n", fs->fs_fsmnt);
858		panic("ffs_sync: rofs mod");
859	}
860	/*
861	 * Write back each (modified) inode.
862	 */
863	simple_lock(&mntvnode_slock);
864loop:
865	for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
866		/*
867		 * If the vnode that we are about to sync is no longer
868		 * associated with this mount point, start over.
869		 */
870		if (vp->v_mount != mp)
871			goto loop;
872		simple_lock(&vp->v_interlock);
873		nvp = vp->v_mntvnodes.le_next;
874		ip = VTOI(vp);
875		if (((ip->i_flag &
876		     (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) &&
877		    vp->v_dirtyblkhd.lh_first == NULL) {
878			simple_unlock(&vp->v_interlock);
879			continue;
880		}
881		if (vp->v_type != VCHR) {
882			simple_unlock(&mntvnode_slock);
883			error =
884			  vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
885			if (error) {
886				simple_lock(&mntvnode_slock);
887				if (error == ENOENT)
888					goto loop;
889				continue;
890			}
891			if (error = VOP_FSYNC(vp, cred, waitfor, p))
892				allerror = error;
893			VOP_UNLOCK(vp, 0, p);
894			vrele(vp);
895			simple_lock(&mntvnode_slock);
896		} else {
897			simple_unlock(&mntvnode_slock);
898			simple_unlock(&vp->v_interlock);
899			gettime(&tv);
900			/* UFS_UPDATE(vp, &tv, &tv, waitfor == MNT_WAIT); */
901			UFS_UPDATE(vp, &tv, &tv, 0);
902			simple_lock(&mntvnode_slock);
903		}
904	}
905	simple_unlock(&mntvnode_slock);
906	/*
907	 * Force stale file system control information to be flushed.
908	 */
909	error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p);
910	if (error)
911		allerror = error;
912#ifdef QUOTA
913	qsync(mp);
914#endif
915	/*
916	 * Write back modified superblock.
917	 */
918	if (fs->fs_fmod != 0) {
919		fs->fs_fmod = 0;
920		fs->fs_time = time.tv_sec;
921		if (error = ffs_sbupdate(ump, waitfor))
922			allerror = error;
923	}
924	return (allerror);
925}
926
927/*
928 * Look up a FFS dinode number to find its incore vnode, otherwise read it
929 * in from disk.  If it is in core, wait for the lock bit to clear, then
930 * return the inode locked.  Detection and handling of mount points must be
931 * done by the calling routine.
932 */
933static int ffs_inode_hash_lock;
934
935int
936ffs_vget(mp, ino, vpp)
937	struct mount *mp;
938	ino_t ino;
939	struct vnode **vpp;
940{
941	struct fs *fs;
942	struct inode *ip;
943	struct ufsmount *ump;
944	struct buf *bp;
945	struct vnode *vp;
946	dev_t dev;
947	int error;
948
949	ump = VFSTOUFS(mp);
950	dev = ump->um_dev;
951restart:
952	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
953		return (0);
954
955	/*
956	 * Lock out the creation of new entries in the FFS hash table in
957	 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
958	 * may occur!
959	 */
960	if (ffs_inode_hash_lock) {
961		while (ffs_inode_hash_lock) {
962			ffs_inode_hash_lock = -1;
963			tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0);
964		}
965		goto restart;
966	}
967	ffs_inode_hash_lock = 1;
968
969	/*
970	 * If this MALLOC() is performed after the getnewvnode()
971	 * it might block, leaving a vnode with a NULL v_data to be
972	 * found by ffs_sync() if a sync happens to fire right then,
973	 * which will cause a panic because ffs_sync() blindly
974	 * dereferences vp->v_data (as well it should).
975	 */
976	MALLOC(ip, struct inode *, sizeof(struct inode),
977	    ump->um_malloctype, M_WAITOK);
978
979	/* Allocate a new vnode/inode. */
980	error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp);
981	if (error) {
982		if (ffs_inode_hash_lock < 0)
983			wakeup(&ffs_inode_hash_lock);
984		ffs_inode_hash_lock = 0;
985		*vpp = NULL;
986		FREE(ip, ump->um_malloctype);
987		return (error);
988	}
989	bzero((caddr_t)ip, sizeof(struct inode));
990	lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
991	vp->v_data = ip;
992	ip->i_vnode = vp;
993	ip->i_fs = fs = ump->um_fs;
994	ip->i_dev = dev;
995	ip->i_number = ino;
996#ifdef QUOTA
997	{
998		int i;
999		for (i = 0; i < MAXQUOTAS; i++)
1000			ip->i_dquot[i] = NODQUOT;
1001	}
1002#endif
1003	/*
1004	 * Put it onto its hash chain and lock it so that other requests for
1005	 * this inode will block if they arrive while we are sleeping waiting
1006	 * for old data structures to be purged or for the contents of the
1007	 * disk portion of this inode to be read.
1008	 */
1009	ufs_ihashins(ip);
1010
1011	if (ffs_inode_hash_lock < 0)
1012		wakeup(&ffs_inode_hash_lock);
1013	ffs_inode_hash_lock = 0;
1014
1015	/* Read in the disk contents for the inode, copy into the inode. */
1016	error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1017	    (int)fs->fs_bsize, NOCRED, &bp);
1018	if (error) {
1019		/*
1020		 * The inode does not contain anything useful, so it would
1021		 * be misleading to leave it on its hash chain. With mode
1022		 * still zero, it will be unlinked and returned to the free
1023		 * list by vput().
1024		 */
1025		brelse(bp);
1026		vput(vp);
1027		*vpp = NULL;
1028		return (error);
1029	}
1030	ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1031	bqrelse(bp);
1032
1033	/*
1034	 * Initialize the vnode from the inode, check for aliases.
1035	 * Note that the underlying vnode may have changed.
1036	 */
1037	error = ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
1038	if (error) {
1039		vput(vp);
1040		*vpp = NULL;
1041		return (error);
1042	}
1043	/*
1044	 * Finish inode initialization now that aliasing has been resolved.
1045	 */
1046	ip->i_devvp = ump->um_devvp;
1047	VREF(ip->i_devvp);
1048	/*
1049	 * Set up a generation number for this inode if it does not
1050	 * already have one. This should only happen on old filesystems.
1051	 */
1052	if (ip->i_gen == 0) {
1053		ip->i_gen = random() / 2 + 1;
1054		if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1055			ip->i_flag |= IN_MODIFIED;
1056	}
1057	/*
1058	 * Ensure that uid and gid are correct. This is a temporary
1059	 * fix until fsck has been changed to do the update.
1060	 */
1061	if (fs->fs_inodefmt < FS_44INODEFMT) {		/* XXX */
1062		ip->i_uid = ip->i_din.di_ouid;		/* XXX */
1063		ip->i_gid = ip->i_din.di_ogid;		/* XXX */
1064	}						/* XXX */
1065
1066	*vpp = vp;
1067	return (0);
1068}
1069
1070/*
1071 * File handle to vnode
1072 *
1073 * Have to be really careful about stale file handles:
1074 * - check that the inode number is valid
1075 * - call ffs_vget() to get the locked inode
1076 * - check for an unallocated inode (i_mode == 0)
1077 * - check that the given client host has export rights and return
1078 *   those rights via. exflagsp and credanonp
1079 */
1080int
1081ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
1082	register struct mount *mp;
1083	struct fid *fhp;
1084	struct sockaddr *nam;
1085	struct vnode **vpp;
1086	int *exflagsp;
1087	struct ucred **credanonp;
1088{
1089	register struct ufid *ufhp;
1090	struct fs *fs;
1091
1092	ufhp = (struct ufid *)fhp;
1093	fs = VFSTOUFS(mp)->um_fs;
1094	if (ufhp->ufid_ino < ROOTINO ||
1095	    ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1096		return (ESTALE);
1097	return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
1098}
1099
1100/*
1101 * Vnode pointer to File handle
1102 */
1103/* ARGSUSED */
1104int
1105ffs_vptofh(vp, fhp)
1106	struct vnode *vp;
1107	struct fid *fhp;
1108{
1109	register struct inode *ip;
1110	register struct ufid *ufhp;
1111
1112	ip = VTOI(vp);
1113	ufhp = (struct ufid *)fhp;
1114	ufhp->ufid_len = sizeof(struct ufid);
1115	ufhp->ufid_ino = ip->i_number;
1116	ufhp->ufid_gen = ip->i_gen;
1117	return (0);
1118}
1119
1120/*
1121 * Initialize the filesystem; just use ufs_init.
1122 */
1123static int
1124ffs_init(vfsp)
1125	struct vfsconf *vfsp;
1126{
1127
1128	return (ufs_init(vfsp));
1129}
1130
1131/*
1132 * Write a superblock and associated information back to disk.
1133 */
1134static int
1135ffs_sbupdate(mp, waitfor)
1136	struct ufsmount *mp;
1137	int waitfor;
1138{
1139	register struct fs *dfs, *fs = mp->um_fs;
1140	register struct buf *bp;
1141	int blks;
1142	caddr_t space;
1143	int i, size, error, allerror = 0;
1144
1145	/*
1146	 * First write back the summary information.
1147	 */
1148	blks = howmany(fs->fs_cssize, fs->fs_fsize);
1149	space = (caddr_t)fs->fs_csp[0];
1150	for (i = 0; i < blks; i += fs->fs_frag) {
1151		size = fs->fs_bsize;
1152		if (i + fs->fs_frag > blks)
1153			size = (blks - i) * fs->fs_fsize;
1154		bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1155		    size, 0, 0);
1156		bcopy(space, bp->b_data, (u_int)size);
1157		space += size;
1158		if (waitfor != MNT_WAIT)
1159			bawrite(bp);
1160		else if (error = bwrite(bp))
1161			allerror = error;
1162	}
1163	/*
1164	 * Now write back the superblock itself. If any errors occurred
1165	 * up to this point, then fail so that the superblock avoids
1166	 * being written out as clean.
1167	 */
1168	if (allerror)
1169		return (allerror);
1170	bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
1171	bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
1172	/* Restore compatibility to old file systems.		   XXX */
1173	dfs = (struct fs *)bp->b_data;				/* XXX */
1174	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
1175		dfs->fs_nrpos = -1;				/* XXX */
1176	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
1177		int32_t *lp, tmp;				/* XXX */
1178								/* XXX */
1179		lp = (int32_t *)&dfs->fs_qbmask;		/* XXX */
1180		tmp = lp[4];					/* XXX */
1181		for (i = 4; i > 0; i--)				/* XXX */
1182			lp[i] = lp[i-1];			/* XXX */
1183		lp[0] = tmp;					/* XXX */
1184	}							/* XXX */
1185	dfs->fs_maxfilesize = mp->um_savedmaxfilesize;		/* XXX */
1186	if (waitfor != MNT_WAIT)
1187		bawrite(bp);
1188	else if (error = bwrite(bp))
1189		allerror = error;
1190	return (allerror);
1191}
1192