ffs_vfsops.c revision 32585
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.64 1998/01/06 05:23:41 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	error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
751		NOCRED, p);
752
753	vrele(ump->um_devvp);
754
755	free(fs->fs_csp[0], M_UFSMNT);
756	free(fs, M_UFSMNT);
757	free(ump, M_UFSMNT);
758	mp->mnt_data = (qaddr_t)0;
759	mp->mnt_flag &= ~MNT_LOCAL;
760	return (error);
761}
762
763/*
764 * Flush out all the files in a filesystem.
765 */
766int
767ffs_flushfiles(mp, flags, p)
768	register struct mount *mp;
769	int flags;
770	struct proc *p;
771{
772	register struct ufsmount *ump;
773	int error;
774
775	ump = VFSTOUFS(mp);
776#ifdef QUOTA
777	if (mp->mnt_flag & MNT_QUOTA) {
778		int i;
779		error = vflush(mp, NULLVP, SKIPSYSTEM|flags);
780		if (error)
781			return (error);
782		for (i = 0; i < MAXQUOTAS; i++) {
783			if (ump->um_quotas[i] == NULLVP)
784				continue;
785			quotaoff(p, mp, i);
786		}
787		/*
788		 * Here we fall through to vflush again to ensure
789		 * that we have gotten rid of all the system vnodes.
790		 */
791	}
792#endif
793	error = vflush(mp, NULLVP, flags);
794	return (error);
795}
796
797/*
798 * Get file system statistics.
799 */
800int
801ffs_statfs(mp, sbp, p)
802	struct mount *mp;
803	register struct statfs *sbp;
804	struct proc *p;
805{
806	register struct ufsmount *ump;
807	register struct fs *fs;
808
809	ump = VFSTOUFS(mp);
810	fs = ump->um_fs;
811	if (fs->fs_magic != FS_MAGIC)
812		panic("ffs_statfs");
813	sbp->f_bsize = fs->fs_fsize;
814	sbp->f_iosize = fs->fs_bsize;
815	sbp->f_blocks = fs->fs_dsize;
816	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
817		fs->fs_cstotal.cs_nffree;
818	sbp->f_bavail = freespace(fs, fs->fs_minfree);
819	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
820	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
821	if (sbp != &mp->mnt_stat) {
822		sbp->f_type = mp->mnt_vfc->vfc_typenum;
823		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
824			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
825		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
826			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
827	}
828	return (0);
829}
830
831/*
832 * Go through the disk queues to initiate sandbagged IO;
833 * go through the inodes to write those that have been modified;
834 * initiate the writing of the super block if it has been modified.
835 *
836 * Note: we are always called with the filesystem marked `MPBUSY'.
837 */
838int
839ffs_sync(mp, waitfor, cred, p)
840	struct mount *mp;
841	int waitfor;
842	struct ucred *cred;
843	struct proc *p;
844{
845	struct vnode *nvp, *vp;
846	struct inode *ip;
847	struct ufsmount *ump = VFSTOUFS(mp);
848	struct fs *fs;
849	struct timeval tv;
850	int error, allerror = 0;
851
852	fs = ump->um_fs;
853	if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {		/* XXX */
854		printf("fs = %s\n", fs->fs_fsmnt);
855		panic("ffs_sync: rofs mod");
856	}
857	/*
858	 * Write back each (modified) inode.
859	 */
860	simple_lock(&mntvnode_slock);
861loop:
862	for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
863		/*
864		 * If the vnode that we are about to sync is no longer
865		 * associated with this mount point, start over.
866		 */
867		if (vp->v_mount != mp)
868			goto loop;
869		simple_lock(&vp->v_interlock);
870		nvp = vp->v_mntvnodes.le_next;
871		ip = VTOI(vp);
872		if (((ip->i_flag &
873		     (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) &&
874		    vp->v_dirtyblkhd.lh_first == NULL) {
875			simple_unlock(&vp->v_interlock);
876			continue;
877		}
878		if (vp->v_type != VCHR) {
879			simple_unlock(&mntvnode_slock);
880			error =
881			  vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
882			if (error) {
883				simple_lock(&mntvnode_slock);
884				if (error == ENOENT)
885					goto loop;
886				continue;
887			}
888			if (error = VOP_FSYNC(vp, cred, waitfor, p))
889				allerror = error;
890			VOP_UNLOCK(vp, 0, p);
891			vrele(vp);
892			simple_lock(&mntvnode_slock);
893		} else {
894			simple_unlock(&mntvnode_slock);
895			simple_unlock(&vp->v_interlock);
896			gettime(&tv);
897			/* UFS_UPDATE(vp, &tv, &tv, waitfor == MNT_WAIT); */
898			UFS_UPDATE(vp, &tv, &tv, 0);
899			simple_lock(&mntvnode_slock);
900		}
901	}
902	simple_unlock(&mntvnode_slock);
903	/*
904	 * Force stale file system control information to be flushed.
905	 */
906	error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p);
907	if (error)
908		allerror = error;
909#ifdef QUOTA
910	qsync(mp);
911#endif
912	/*
913	 * Write back modified superblock.
914	 */
915	if (fs->fs_fmod != 0) {
916		fs->fs_fmod = 0;
917		fs->fs_time = time.tv_sec;
918		if (error = ffs_sbupdate(ump, waitfor))
919			allerror = error;
920	}
921	return (allerror);
922}
923
924/*
925 * Look up a FFS dinode number to find its incore vnode, otherwise read it
926 * in from disk.  If it is in core, wait for the lock bit to clear, then
927 * return the inode locked.  Detection and handling of mount points must be
928 * done by the calling routine.
929 */
930static int ffs_inode_hash_lock;
931
932int
933ffs_vget(mp, ino, vpp)
934	struct mount *mp;
935	ino_t ino;
936	struct vnode **vpp;
937{
938	struct fs *fs;
939	struct inode *ip;
940	struct ufsmount *ump;
941	struct buf *bp;
942	struct vnode *vp;
943	dev_t dev;
944	int error;
945
946	ump = VFSTOUFS(mp);
947	dev = ump->um_dev;
948restart:
949	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
950		return (0);
951
952	/*
953	 * Lock out the creation of new entries in the FFS hash table in
954	 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
955	 * may occur!
956	 */
957	if (ffs_inode_hash_lock) {
958		while (ffs_inode_hash_lock) {
959			ffs_inode_hash_lock = -1;
960			tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0);
961		}
962		goto restart;
963	}
964	ffs_inode_hash_lock = 1;
965
966	/*
967	 * If this MALLOC() is performed after the getnewvnode()
968	 * it might block, leaving a vnode with a NULL v_data to be
969	 * found by ffs_sync() if a sync happens to fire right then,
970	 * which will cause a panic because ffs_sync() blindly
971	 * dereferences vp->v_data (as well it should).
972	 */
973	MALLOC(ip, struct inode *, sizeof(struct inode),
974	    ump->um_malloctype, M_WAITOK);
975
976	/* Allocate a new vnode/inode. */
977	error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp);
978	if (error) {
979		if (ffs_inode_hash_lock < 0)
980			wakeup(&ffs_inode_hash_lock);
981		ffs_inode_hash_lock = 0;
982		*vpp = NULL;
983		FREE(ip, ump->um_malloctype);
984		return (error);
985	}
986	bzero((caddr_t)ip, sizeof(struct inode));
987	lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
988	vp->v_data = ip;
989	ip->i_vnode = vp;
990	ip->i_fs = fs = ump->um_fs;
991	ip->i_dev = dev;
992	ip->i_number = ino;
993#ifdef QUOTA
994	{
995		int i;
996		for (i = 0; i < MAXQUOTAS; i++)
997			ip->i_dquot[i] = NODQUOT;
998	}
999#endif
1000	/*
1001	 * Put it onto its hash chain and lock it so that other requests for
1002	 * this inode will block if they arrive while we are sleeping waiting
1003	 * for old data structures to be purged or for the contents of the
1004	 * disk portion of this inode to be read.
1005	 */
1006	ufs_ihashins(ip);
1007
1008	if (ffs_inode_hash_lock < 0)
1009		wakeup(&ffs_inode_hash_lock);
1010	ffs_inode_hash_lock = 0;
1011
1012	/* Read in the disk contents for the inode, copy into the inode. */
1013	error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1014	    (int)fs->fs_bsize, NOCRED, &bp);
1015	if (error) {
1016		/*
1017		 * The inode does not contain anything useful, so it would
1018		 * be misleading to leave it on its hash chain. With mode
1019		 * still zero, it will be unlinked and returned to the free
1020		 * list by vput().
1021		 */
1022		brelse(bp);
1023		vput(vp);
1024		*vpp = NULL;
1025		return (error);
1026	}
1027	ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1028	bqrelse(bp);
1029
1030	/*
1031	 * Initialize the vnode from the inode, check for aliases.
1032	 * Note that the underlying vnode may have changed.
1033	 */
1034	error = ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
1035	if (error) {
1036		vput(vp);
1037		*vpp = NULL;
1038		return (error);
1039	}
1040	/*
1041	 * Finish inode initialization now that aliasing has been resolved.
1042	 */
1043	ip->i_devvp = ump->um_devvp;
1044	VREF(ip->i_devvp);
1045	/*
1046	 * Set up a generation number for this inode if it does not
1047	 * already have one. This should only happen on old filesystems.
1048	 */
1049	if (ip->i_gen == 0) {
1050		ip->i_gen = random() / 2 + 1;
1051		if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1052			ip->i_flag |= IN_MODIFIED;
1053	}
1054	/*
1055	 * Ensure that uid and gid are correct. This is a temporary
1056	 * fix until fsck has been changed to do the update.
1057	 */
1058	if (fs->fs_inodefmt < FS_44INODEFMT) {		/* XXX */
1059		ip->i_uid = ip->i_din.di_ouid;		/* XXX */
1060		ip->i_gid = ip->i_din.di_ogid;		/* XXX */
1061	}						/* XXX */
1062
1063	*vpp = vp;
1064	return (0);
1065}
1066
1067/*
1068 * File handle to vnode
1069 *
1070 * Have to be really careful about stale file handles:
1071 * - check that the inode number is valid
1072 * - call ffs_vget() to get the locked inode
1073 * - check for an unallocated inode (i_mode == 0)
1074 * - check that the given client host has export rights and return
1075 *   those rights via. exflagsp and credanonp
1076 */
1077int
1078ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
1079	register struct mount *mp;
1080	struct fid *fhp;
1081	struct sockaddr *nam;
1082	struct vnode **vpp;
1083	int *exflagsp;
1084	struct ucred **credanonp;
1085{
1086	register struct ufid *ufhp;
1087	struct fs *fs;
1088
1089	ufhp = (struct ufid *)fhp;
1090	fs = VFSTOUFS(mp)->um_fs;
1091	if (ufhp->ufid_ino < ROOTINO ||
1092	    ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1093		return (ESTALE);
1094	return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
1095}
1096
1097/*
1098 * Vnode pointer to File handle
1099 */
1100/* ARGSUSED */
1101int
1102ffs_vptofh(vp, fhp)
1103	struct vnode *vp;
1104	struct fid *fhp;
1105{
1106	register struct inode *ip;
1107	register struct ufid *ufhp;
1108
1109	ip = VTOI(vp);
1110	ufhp = (struct ufid *)fhp;
1111	ufhp->ufid_len = sizeof(struct ufid);
1112	ufhp->ufid_ino = ip->i_number;
1113	ufhp->ufid_gen = ip->i_gen;
1114	return (0);
1115}
1116
1117/*
1118 * Initialize the filesystem; just use ufs_init.
1119 */
1120static int
1121ffs_init(vfsp)
1122	struct vfsconf *vfsp;
1123{
1124
1125	return (ufs_init(vfsp));
1126}
1127
1128/*
1129 * Write a superblock and associated information back to disk.
1130 */
1131static int
1132ffs_sbupdate(mp, waitfor)
1133	struct ufsmount *mp;
1134	int waitfor;
1135{
1136	register struct fs *dfs, *fs = mp->um_fs;
1137	register struct buf *bp;
1138	int blks;
1139	caddr_t space;
1140	int i, size, error, allerror = 0;
1141
1142	/*
1143	 * First write back the summary information.
1144	 */
1145	blks = howmany(fs->fs_cssize, fs->fs_fsize);
1146	space = (caddr_t)fs->fs_csp[0];
1147	for (i = 0; i < blks; i += fs->fs_frag) {
1148		size = fs->fs_bsize;
1149		if (i + fs->fs_frag > blks)
1150			size = (blks - i) * fs->fs_fsize;
1151		bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1152		    size, 0, 0);
1153		bcopy(space, bp->b_data, (u_int)size);
1154		space += size;
1155		if (waitfor != MNT_WAIT)
1156			bawrite(bp);
1157		else if (error = bwrite(bp))
1158			allerror = error;
1159	}
1160	/*
1161	 * Now write back the superblock itself. If any errors occurred
1162	 * up to this point, then fail so that the superblock avoids
1163	 * being written out as clean.
1164	 */
1165	if (allerror)
1166		return (allerror);
1167	bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
1168	bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
1169	/* Restore compatibility to old file systems.		   XXX */
1170	dfs = (struct fs *)bp->b_data;				/* XXX */
1171	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
1172		dfs->fs_nrpos = -1;				/* XXX */
1173	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
1174		int32_t *lp, tmp;				/* XXX */
1175								/* XXX */
1176		lp = (int32_t *)&dfs->fs_qbmask;		/* XXX */
1177		tmp = lp[4];					/* XXX */
1178		for (i = 4; i > 0; i--)				/* XXX */
1179			lp[i] = lp[i-1];			/* XXX */
1180		lp[0] = tmp;					/* XXX */
1181	}							/* XXX */
1182	dfs->fs_maxfilesize = mp->um_savedmaxfilesize;		/* XXX */
1183	if (waitfor != MNT_WAIT)
1184		bawrite(bp);
1185	else if (error = bwrite(bp))
1186		allerror = error;
1187	return (allerror);
1188}
1189