xref: /freebsd/sys/ufs/ffs/ffs_vfsops.c (revision 8e6b01171e30297084bb0b4457c4183c2746aacc)
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.8 (Berkeley) 4/18/94
34  * $Id: ffs_vfsops.c,v 1.27 1995/08/11 11:31:15 davidg Exp $
35  */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/namei.h>
40 #include <sys/proc.h>
41 #include <sys/kernel.h>
42 #include <sys/vnode.h>
43 #include <sys/socket.h>
44 #include <sys/mount.h>
45 #include <sys/buf.h>
46 #include <sys/mbuf.h>
47 #include <sys/file.h>
48 #include <sys/disklabel.h>
49 #include <sys/ioctl.h>
50 #include <sys/errno.h>
51 #include <sys/malloc.h>
52 
53 #include <miscfs/specfs/specdev.h>
54 
55 #include <ufs/ufs/quota.h>
56 #include <ufs/ufs/ufsmount.h>
57 #include <ufs/ufs/inode.h>
58 #include <ufs/ufs/ufs_extern.h>
59 
60 #include <ufs/ffs/fs.h>
61 #include <ufs/ffs/ffs_extern.h>
62 
63 #include <vm/vm.h>
64 #include <vm/vm_page.h>
65 #include <vm/vm_object.h>
66 
67 int	ffs_sbupdate __P((struct ufsmount *, int));
68 int	ffs_reload __P((struct mount *,struct ucred *,struct proc *));
69 int	ffs_oldfscompat __P((struct fs *));
70 void ffs_vmlimits __P((struct fs *));
71 
72 struct vfsops ufs_vfsops = {
73 	ffs_mount,
74 	ufs_start,
75 	ffs_unmount,
76 	ufs_root,
77 	ufs_quotactl,
78 	ffs_statfs,
79 	ffs_sync,
80 	ffs_vget,
81 	ffs_fhtovp,
82 	ffs_vptofh,
83 	ffs_init,
84 };
85 
86 VFS_SET(ufs_vfsops, ufs, MOUNT_UFS, 0);
87 
88 extern u_long nextgennumber;
89 
90 
91 /*
92  * ffs_mount
93  *
94  * Called when mounting local physical media
95  *
96  * PARAMETERS:
97  *		mountroot
98  *			mp	mount point structure
99  *			path	NULL (flag for root mount!!!)
100  *			data	<unused>
101  *			ndp	<unused>
102  *			p	process (user credentials check [statfs])
103  *
104  *		mount
105  *			mp	mount point structure
106  *			path	path to mount point
107  *			data	pointer to argument struct in user space
108  *			ndp	mount point namei() return (used for
109  *				credentials on reload), reused to look
110  *				up block device.
111  *			p	process (user credentials check)
112  *
113  * RETURNS:	0	Success
114  *		!0	error number (errno.h)
115  *
116  * LOCK STATE:
117  *
118  *		ENTRY
119  *			mount point is locked
120  *		EXIT
121  *			mount point is locked
122  *
123  * NOTES:
124  *		A NULL path can be used for a flag since the mount
125  *		system call will fail with EFAULT in copyinstr in
126  *		namei() if it is a genuine NULL from the user.
127  */
128 int
129 ffs_mount( mp, path, data, ndp, p)
130         register struct mount	*mp;	/* mount struct pointer*/
131         char			*path;	/* path to mount point*/
132         caddr_t			data;	/* arguments to FS specific mount*/
133         struct nameidata	*ndp;	/* mount point credentials*/
134         struct proc		*p;	/* process requesting mount*/
135 {
136 	u_int		size;
137 	int		err = 0;
138 	struct vnode	*devvp;
139 
140 	struct ufs_args args;
141 	struct ufsmount *ump = 0;
142 	register struct fs *fs;
143 	int flags;
144 
145 	/*
146 	 * Use NULL path to flag a root mount
147 	 */
148 	if( path == NULL) {
149 		/*
150 		 ***
151 		 * Mounting root file system
152 		 ***
153 		 */
154 
155 		/* Get vnode for root device*/
156 		if( bdevvp( rootdev, &rootvp))
157 			panic("ffs_mountroot: can't setup bdevvp for root");
158 
159 		/*
160 		 * FS specific handling
161 		 */
162 		mp->mnt_flag |= MNT_RDONLY;	/* XXX globally applicable?*/
163 
164 		/*
165 		 * Attempt mount
166 		 */
167 		if( ( err = ffs_mountfs(rootvp, mp, p)) != 0) {
168 			/* fs specific cleanup (if any)*/
169 			goto error_1;
170 		}
171 
172 		goto dostatfs;		/* success*/
173 
174 	}
175 
176 	/*
177 	 ***
178 	 * Mounting non-root file system or updating a file system
179 	 ***
180 	 */
181 
182 	/* copy in user arguments*/
183 	err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
184 	if (err)
185 		goto error_1;		/* can't get arguments*/
186 
187 	/*
188 	 * If updating, check whether changing from read-only to
189 	 * read/write; if there is no device name, that's all we do.
190 	 */
191 	if (mp->mnt_flag & MNT_UPDATE) {
192 		ump = VFSTOUFS(mp);
193 		fs = ump->um_fs;
194 		err = 0;
195 		if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
196 			flags = WRITECLOSE;
197 			if (mp->mnt_flag & MNT_FORCE)
198 				flags |= FORCECLOSE;
199 			if (vfs_busy(mp)) {
200 				err = EBUSY;
201 				goto error_1;
202 			}
203 			err = ffs_flushfiles(mp, flags, p);
204 			vfs_unbusy(mp);
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_flag & MNT_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 		/*
290 		 * Since this is a new mount, we want the names for
291 		 * the device and the mount point copied in.  If an
292 		 * error occurs,  the mountpoint is discarded by the
293 		 * upper level code.
294 		 */
295 		/* Save "last mounted on" info for mount point (NULL pad)*/
296 		copyinstr(	path,				/* mount point*/
297 				mp->mnt_stat.f_mntonname,	/* save area*/
298 				MNAMELEN - 1,			/* max size*/
299 				&size);				/* real size*/
300 		bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
301 
302 		/* Save "mounted from" info for mount point (NULL pad)*/
303 		copyinstr(	args.fspec,			/* device name*/
304 				mp->mnt_stat.f_mntfromname,	/* save area*/
305 				MNAMELEN - 1,			/* max size*/
306 				&size);				/* real size*/
307 		bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
308 
309 		err = ffs_mountfs(devvp, mp, p);
310 	}
311 	if (err) {
312 		goto error_2;
313 	}
314 
315 dostatfs:
316 	/*
317 	 * Initialize FS stat information in mount struct; uses both
318 	 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
319 	 *
320 	 * This code is common to root and non-root mounts
321 	 */
322 	(void)VFS_STATFS(mp, &mp->mnt_stat, p);
323 
324 	goto success;
325 
326 
327 error_2:	/* error with devvp held*/
328 
329 	/* release devvp before failing*/
330 	vrele(devvp);
331 
332 error_1:	/* no state to back out*/
333 
334 success:
335 	return( err);
336 }
337 
338 
339 /*
340  * Reload all incore data for a filesystem (used after running fsck on
341  * the root filesystem and finding things to fix). The filesystem must
342  * be mounted read-only.
343  *
344  * Things to do to update the mount:
345  *	1) invalidate all cached meta-data.
346  *	2) re-read superblock from disk.
347  *	3) re-read summary information from disk.
348  *	4) invalidate all inactive vnodes.
349  *	5) invalidate all cached file data.
350  *	6) re-read inode data for all active vnodes.
351  */
352 int
353 ffs_reload(mp, cred, p)
354 	register struct mount *mp;
355 	struct ucred *cred;
356 	struct proc *p;
357 {
358 	register struct vnode *vp, *nvp, *devvp;
359 	struct inode *ip;
360 	struct csum *space;
361 	struct buf *bp;
362 	struct fs *fs;
363 	int i, blks, size, error;
364 
365 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
366 		return (EINVAL);
367 	/*
368 	 * Step 1: invalidate all cached meta-data.
369 	 */
370 	devvp = VFSTOUFS(mp)->um_devvp;
371 	if (vinvalbuf(devvp, 0, cred, p, 0, 0))
372 		panic("ffs_reload: dirty1");
373 	/*
374 	 * Step 2: re-read superblock from disk.
375 	 */
376 	error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp);
377 	if (error)
378 		return (error);
379 	fs = (struct fs *)bp->b_data;
380 	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
381 	    fs->fs_bsize < sizeof(struct fs)) {
382 		brelse(bp);
383 		return (EIO);		/* XXX needs translation */
384 	}
385 	fs = VFSTOUFS(mp)->um_fs;
386 	bcopy(&fs->fs_csp[0], &((struct fs *)bp->b_data)->fs_csp[0],
387 	    sizeof(fs->fs_csp));
388 	bcopy(bp->b_data, fs, (u_int)fs->fs_sbsize);
389 	if (fs->fs_sbsize < SBSIZE)
390 		bp->b_flags |= B_INVAL;
391 	brelse(bp);
392 	ffs_oldfscompat(fs);
393 	ffs_vmlimits(fs);
394 	/*
395 	 * Step 3: re-read summary information from disk.
396 	 */
397 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
398 	space = fs->fs_csp[0];
399 	for (i = 0; i < blks; i += fs->fs_frag) {
400 		size = fs->fs_bsize;
401 		if (i + fs->fs_frag > blks)
402 			size = (blks - i) * fs->fs_fsize;
403 		error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
404 		    NOCRED, &bp);
405 		if (error)
406 			return (error);
407 		bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
408 		brelse(bp);
409 	}
410 loop:
411 	for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
412 		nvp = vp->v_mntvnodes.le_next;
413 		/*
414 		 * Step 4: invalidate all inactive vnodes.
415 		 */
416 		if (vp->v_usecount == 0) {
417 			vgone(vp);
418 			continue;
419 		}
420 		/*
421 		 * Step 5: invalidate all cached file data.
422 		 */
423 		if (vget(vp, 1))
424 			goto loop;
425 		if (vinvalbuf(vp, 0, cred, p, 0, 0))
426 			panic("ffs_reload: dirty2");
427 		/*
428 		 * Step 6: re-read inode data for all active vnodes.
429 		 */
430 		ip = VTOI(vp);
431 		error =
432 		    bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
433 		    (int)fs->fs_bsize, NOCRED, &bp);
434 		if (error) {
435 			vput(vp);
436 			return (error);
437 		}
438 		ip->i_din = *((struct dinode *)bp->b_data +
439 		    ino_to_fsbo(fs, ip->i_number));
440 		brelse(bp);
441 		vput(vp);
442 		if (vp->v_mount != mp)
443 			goto loop;
444 	}
445 	return (0);
446 }
447 
448 /*
449  * Common code for mount and mountroot
450  */
451 int
452 ffs_mountfs(devvp, mp, p)
453 	register struct vnode *devvp;
454 	struct mount *mp;
455 	struct proc *p;
456 {
457 	register struct ufsmount *ump;
458 	struct buf *bp;
459 	register struct fs *fs;
460 	dev_t dev = devvp->v_rdev;
461 	struct partinfo dpart;
462 	caddr_t base, space;
463 	int havepart = 0, blks;
464 	int error, i, size;
465 	int ronly;
466 	u_int strsize;
467 
468 	/*
469 	 * Disallow multiple mounts of the same device.
470 	 * Disallow mounting of a device that is currently in use
471 	 * (except for root, which might share swap device for miniroot).
472 	 * Flush out any old buffers remaining from a previous use.
473 	 */
474 	error = vfs_mountedon(devvp);
475 	if (error)
476 		return (error);
477 	if (vcount(devvp) > 1 && devvp != rootvp)
478 		return (EBUSY);
479 	error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
480 	if (error)
481 		return (error);
482 
483 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
484 	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
485 	if (error)
486 		return (error);
487 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
488 		size = DEV_BSIZE;
489 	else {
490 		havepart = 1;
491 		size = dpart.disklab->d_secsize;
492 	}
493 
494 	bp = NULL;
495 	ump = NULL;
496 	error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp);
497 	if (error)
498 		goto out;
499 	fs = (struct fs *)bp->b_data;
500 	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
501 	    fs->fs_bsize < sizeof(struct fs)) {
502 		error = EINVAL;		/* XXX needs translation */
503 		goto out;
504 	}
505 	if (!fs->fs_clean) {
506 		if (ronly || (mp->mnt_flag & MNT_FORCE)) {
507 			printf("WARNING: %s was not properly dismounted.\n",fs->fs_fsmnt);
508 		} else {
509 			printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck.\n",fs->fs_fsmnt);
510 			error = EPERM;
511 			goto out;
512 		}
513 	}
514 	ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
515 	bzero((caddr_t)ump, sizeof *ump);
516 	ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
517 	    M_WAITOK);
518 	bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
519 	if (fs->fs_sbsize < SBSIZE)
520 		bp->b_flags |= B_INVAL;
521 	brelse(bp);
522 	bp = NULL;
523 	fs = ump->um_fs;
524 	fs->fs_ronly = ronly;
525 	if (ronly == 0) {
526 		fs->fs_fmod = 1;
527 		fs->fs_clean = 0;
528 	}
529 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
530 	base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT,
531 	    M_WAITOK);
532 	for (i = 0; i < blks; i += fs->fs_frag) {
533 		size = fs->fs_bsize;
534 		if (i + fs->fs_frag > blks)
535 			size = (blks - i) * fs->fs_fsize;
536 		error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
537 			NOCRED, &bp);
538 		if (error) {
539 			free(base, M_UFSMNT);
540 			goto out;
541 		}
542 		bcopy(bp->b_data, space, (u_int)size);
543 		fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
544 		space += size;
545 		brelse(bp);
546 		bp = NULL;
547 	}
548 	mp->mnt_data = (qaddr_t)ump;
549 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
550 	mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS;
551 	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
552 	mp->mnt_flag |= MNT_LOCAL;
553 	ump->um_mountp = mp;
554 	ump->um_dev = dev;
555 	ump->um_devvp = devvp;
556 	ump->um_nindir = fs->fs_nindir;
557 	ump->um_bptrtodb = fs->fs_fsbtodb;
558 	ump->um_seqinc = fs->fs_frag;
559 	for (i = 0; i < MAXQUOTAS; i++)
560 		ump->um_quotas[i] = NULLVP;
561 	devvp->v_specflags |= SI_MOUNTEDON;
562 	ffs_oldfscompat(fs);
563 	ffs_vmlimits(fs);
564 
565 	/*
566 	 * Set FS local "last mounted on" information (NULL pad)
567 	 */
568 	copystr(	mp->mnt_stat.f_mntonname,	/* mount point*/
569 			fs->fs_fsmnt,			/* copy area*/
570 			sizeof(fs->fs_fsmnt) - 1,	/* max size*/
571 			&strsize);			/* real size*/
572 	bzero( fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize);
573 
574 	if( mp->mnt_flag & MNT_ROOTFS) {
575 		/*
576 		 * Root mount; update timestamp in mount structure.
577 		 * this will be used by the common root mount code
578 		 * to update the system clock.
579 		 */
580 		mp->mnt_time = fs->fs_time;
581 	}
582 	if (ronly == 0)
583 		ffs_sbupdate(ump, MNT_WAIT);
584 	return (0);
585 out:
586 	if (bp)
587 		brelse(bp);
588 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
589 	if (ump) {
590 		free(ump->um_fs, M_UFSMNT);
591 		free(ump, M_UFSMNT);
592 		mp->mnt_data = (qaddr_t)0;
593 	}
594 	return (error);
595 }
596 
597 /*
598  * Sanity checks for old file systems.
599  *
600  * XXX - goes away some day.
601  */
602 int
603 ffs_oldfscompat(fs)
604 	struct fs *fs;
605 {
606 	int i;
607 
608 	fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);	/* XXX */
609 	fs->fs_interleave = max(fs->fs_interleave, 1);		/* XXX */
610 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
611 		fs->fs_nrpos = 8;				/* XXX */
612 	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
613 		quad_t sizepb = fs->fs_bsize;			/* XXX */
614 								/* XXX */
615 #if 0
616 		fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;	/* XXX */
617 		for (i = 0; i < NIADDR; i++) {			/* XXX */
618 			sizepb *= NINDIR(fs);			/* XXX */
619 			fs->fs_maxfilesize += sizepb;		/* XXX */
620 		}						/* XXX */
621 #endif
622 		fs->fs_maxfilesize = (u_quad_t) 1 << 39;
623 		fs->fs_qbmask = ~fs->fs_bmask;			/* XXX */
624 		fs->fs_qfmask = ~fs->fs_fmask;			/* XXX */
625 	}							/* XXX */
626 	return (0);
627 }
628 
629 /*
630  * Sanity check for VM file size limits -- temporary until
631  * VM system can support > 32bit offsets
632  */
633 void
634 ffs_vmlimits(fs)
635 	struct fs *fs;
636 {
637 	if( fs->fs_maxfilesize > (((u_quad_t) 1 << 31) - 1))
638 		fs->fs_maxfilesize = ((u_quad_t) 1 << 31) - 1;
639 }
640 
641 /*
642  * unmount system call
643  */
644 int
645 ffs_unmount(mp, mntflags, p)
646 	struct mount *mp;
647 	int mntflags;
648 	struct proc *p;
649 {
650 	register struct ufsmount *ump;
651 	register struct fs *fs;
652 	int error, flags, ronly;
653 
654 	flags = 0;
655 	if (mntflags & MNT_FORCE) {
656 		flags |= FORCECLOSE;
657 	}
658 	error = ffs_flushfiles(mp, flags, p);
659 	if (error)
660 		return (error);
661 	ump = VFSTOUFS(mp);
662 	fs = ump->um_fs;
663 	ronly = fs->fs_ronly;
664 	if (!ronly) {
665 		fs->fs_clean = 1;
666 		ffs_sbupdate(ump, MNT_WAIT);
667 	}
668 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
669 	error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
670 		NOCRED, p);
671 	vrele(ump->um_devvp);
672 	free(fs->fs_csp[0], M_UFSMNT);
673 	free(fs, M_UFSMNT);
674 	free(ump, M_UFSMNT);
675 	mp->mnt_data = (qaddr_t)0;
676 	mp->mnt_flag &= ~MNT_LOCAL;
677 	return (error);
678 }
679 
680 /*
681  * Flush out all the files in a filesystem.
682  */
683 int
684 ffs_flushfiles(mp, flags, p)
685 	register struct mount *mp;
686 	int flags;
687 	struct proc *p;
688 {
689 	register struct ufsmount *ump;
690 	int error;
691 
692 	if (!doforce)
693 		flags &= ~FORCECLOSE;
694 	ump = VFSTOUFS(mp);
695 #ifdef QUOTA
696 	if (mp->mnt_flag & MNT_QUOTA) {
697 		int i;
698 		error = vflush(mp, NULLVP, SKIPSYSTEM|flags);
699 		if (error)
700 			return (error);
701 		for (i = 0; i < MAXQUOTAS; i++) {
702 			if (ump->um_quotas[i] == NULLVP)
703 				continue;
704 			quotaoff(p, mp, i);
705 		}
706 		/*
707 		 * Here we fall through to vflush again to ensure
708 		 * that we have gotten rid of all the system vnodes.
709 		 */
710 	}
711 #endif
712 	error = vflush(mp, NULLVP, flags);
713 	return (error);
714 }
715 
716 /*
717  * Get file system statistics.
718  */
719 int
720 ffs_statfs(mp, sbp, p)
721 	struct mount *mp;
722 	register struct statfs *sbp;
723 	struct proc *p;
724 {
725 	register struct ufsmount *ump;
726 	register struct fs *fs;
727 
728 	ump = VFSTOUFS(mp);
729 	fs = ump->um_fs;
730 	if (fs->fs_magic != FS_MAGIC)
731 		panic("ffs_statfs");
732 	sbp->f_type = MOUNT_UFS;
733 	sbp->f_bsize = fs->fs_fsize;
734 	sbp->f_iosize = fs->fs_bsize;
735 	sbp->f_blocks = fs->fs_dsize;
736 	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
737 		fs->fs_cstotal.cs_nffree;
738 	sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
739 		(fs->fs_dsize - sbp->f_bfree);
740 	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
741 	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
742 	if (sbp != &mp->mnt_stat) {
743 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
744 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
745 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
746 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
747 	}
748 	return (0);
749 }
750 
751 /*
752  * Go through the disk queues to initiate sandbagged IO;
753  * go through the inodes to write those that have been modified;
754  * initiate the writing of the super block if it has been modified.
755  *
756  * Note: we are always called with the filesystem marked `MPBUSY'.
757  */
758 int
759 ffs_sync(mp, waitfor, cred, p)
760 	struct mount *mp;
761 	int waitfor;
762 	struct ucred *cred;
763 	struct proc *p;
764 {
765 	register struct vnode *vp;
766 	register struct inode *ip;
767 	register struct ufsmount *ump = VFSTOUFS(mp);
768 	register struct fs *fs;
769 	struct timeval tv;
770 	int error, allerror = 0;
771 
772 	fs = ump->um_fs;
773 	/*
774 	 * Write back modified superblock.
775 	 * Consistency check that the superblock
776 	 * is still in the buffer cache.
777 	 */
778 	if (fs->fs_fmod != 0) {
779 		if (fs->fs_ronly != 0) {		/* XXX */
780 			printf("fs = %s\n", fs->fs_fsmnt);
781 			panic("update: rofs mod");
782 		}
783 		fs->fs_fmod = 0;
784 		fs->fs_time = time.tv_sec;
785 		allerror = ffs_sbupdate(ump, waitfor);
786 	}
787 	/*
788 	 * Write back each (modified) inode.
789 	 */
790 loop:
791 	for (vp = mp->mnt_vnodelist.lh_first;
792 	     vp != NULL;
793 	     vp = vp->v_mntvnodes.le_next) {
794 		/*
795 		 * If the vnode that we are about to sync is no longer
796 		 * associated with this mount point, start over.
797 		 */
798 		if (vp->v_mount != mp)
799 			goto loop;
800 		if (VOP_ISLOCKED(vp))
801 			continue;
802 		ip = VTOI(vp);
803 		if ((((ip->i_flag &
804 		    (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)) &&
805 		    vp->v_dirtyblkhd.lh_first == NULL)
806 			continue;
807 		if (vp->v_type != VCHR) {
808 			if (vget(vp, 1))
809 				goto loop;
810 			error = VOP_FSYNC(vp, cred, waitfor, p);
811 			if (error)
812 				allerror = error;
813 			vput(vp);
814 		} else {
815 			tv = time;
816 			VOP_UPDATE(vp, &tv, &tv, waitfor == MNT_WAIT);
817 		}
818 	}
819 	/*
820 	 * Force stale file system control information to be flushed.
821 	 */
822 	error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p);
823 	if (error)
824 		allerror = error;
825 #ifdef QUOTA
826 	qsync(mp);
827 #endif
828 	return (allerror);
829 }
830 
831 /*
832  * Look up a FFS dinode number to find its incore vnode, otherwise read it
833  * in from disk.  If it is in core, wait for the lock bit to clear, then
834  * return the inode locked.  Detection and handling of mount points must be
835  * done by the calling routine.
836  */
837 int ffs_inode_hash_lock;
838 
839 int
840 ffs_vget(mp, ino, vpp)
841 	struct mount *mp;
842 	ino_t ino;
843 	struct vnode **vpp;
844 {
845 	register struct fs *fs;
846 	register struct inode *ip;
847 	struct ufsmount *ump;
848 	struct buf *bp;
849 	struct vnode *vp;
850 	dev_t dev;
851 	int type, error;
852 
853 	ump = VFSTOUFS(mp);
854 	dev = ump->um_dev;
855 restart:
856 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
857 		return (0);
858 
859 	/*
860 	 * Lock out the creation of new entries in the FFS hash table in
861 	 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
862 	 * may occur!
863 	 */
864 	if (ffs_inode_hash_lock) {
865 		while (ffs_inode_hash_lock) {
866 			ffs_inode_hash_lock = -1;
867 			tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0);
868 		}
869 		goto restart;
870 	}
871 	ffs_inode_hash_lock = 1;
872 
873 	/* Allocate a new vnode/inode. */
874 	error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp);
875 	if (error) {
876 		if (ffs_inode_hash_lock < 0)
877 			wakeup(&ffs_inode_hash_lock);
878 		ffs_inode_hash_lock = 0;
879 		*vpp = NULL;
880 		return (error);
881 	}
882 	type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
883 	MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
884 	bzero((caddr_t)ip, sizeof(struct inode));
885 	vp->v_data = ip;
886 	ip->i_vnode = vp;
887 	ip->i_fs = fs = ump->um_fs;
888 	ip->i_dev = dev;
889 	ip->i_number = ino;
890 #ifdef QUOTA
891 	{
892 		int i;
893 		for (i = 0; i < MAXQUOTAS; i++)
894 			ip->i_dquot[i] = NODQUOT;
895 	}
896 #endif
897 	/*
898 	 * Put it onto its hash chain and lock it so that other requests for
899 	 * this inode will block if they arrive while we are sleeping waiting
900 	 * for old data structures to be purged or for the contents of the
901 	 * disk portion of this inode to be read.
902 	 */
903 	ufs_ihashins(ip);
904 
905 	if (ffs_inode_hash_lock < 0)
906 		wakeup(&ffs_inode_hash_lock);
907 	ffs_inode_hash_lock = 0;
908 
909 	/* Read in the disk contents for the inode, copy into the inode. */
910 	error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
911 	    (int)fs->fs_bsize, NOCRED, &bp);
912 	if (error) {
913 		/*
914 		 * The inode does not contain anything useful, so it would
915 		 * be misleading to leave it on its hash chain. With mode
916 		 * still zero, it will be unlinked and returned to the free
917 		 * list by vput().
918 		 */
919 		vput(vp);
920 		brelse(bp);
921 		*vpp = NULL;
922 		return (error);
923 	}
924 	ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
925 	brelse(bp);
926 
927 	/*
928 	 * Initialize the vnode from the inode, check for aliases.
929 	 * Note that the underlying vnode may have changed.
930 	 */
931 	error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp);
932 	if (error) {
933 		vput(vp);
934 		*vpp = NULL;
935 		return (error);
936 	}
937 	/*
938 	 * Finish inode initialization now that aliasing has been resolved.
939 	 */
940 	ip->i_devvp = ump->um_devvp;
941 	VREF(ip->i_devvp);
942 	/*
943 	 * Set up a generation number for this inode if it does not
944 	 * already have one. This should only happen on old filesystems.
945 	 */
946 	if (ip->i_gen == 0) {
947 		if (++nextgennumber < (u_long)time.tv_sec)
948 			nextgennumber = time.tv_sec;
949 		ip->i_gen = nextgennumber;
950 		if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
951 			ip->i_flag |= IN_MODIFIED;
952 	}
953 	/*
954 	 * Ensure that uid and gid are correct. This is a temporary
955 	 * fix until fsck has been changed to do the update.
956 	 */
957 	if (fs->fs_inodefmt < FS_44INODEFMT) {		/* XXX */
958 		ip->i_uid = ip->i_din.di_ouid;		/* XXX */
959 		ip->i_gid = ip->i_din.di_ogid;		/* XXX */
960 	}						/* XXX */
961 
962 	*vpp = vp;
963 	return (0);
964 }
965 
966 /*
967  * File handle to vnode
968  *
969  * Have to be really careful about stale file handles:
970  * - check that the inode number is valid
971  * - call ffs_vget() to get the locked inode
972  * - check for an unallocated inode (i_mode == 0)
973  * - check that the given client host has export rights and return
974  *   those rights via. exflagsp and credanonp
975  */
976 int
977 ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
978 	register struct mount *mp;
979 	struct fid *fhp;
980 	struct mbuf *nam;
981 	struct vnode **vpp;
982 	int *exflagsp;
983 	struct ucred **credanonp;
984 {
985 	register struct ufid *ufhp;
986 	struct fs *fs;
987 
988 	ufhp = (struct ufid *)fhp;
989 	fs = VFSTOUFS(mp)->um_fs;
990 	if (ufhp->ufid_ino < ROOTINO ||
991 	    ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
992 		return (ESTALE);
993 	return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
994 }
995 
996 /*
997  * Vnode pointer to File handle
998  */
999 /* ARGSUSED */
1000 int
1001 ffs_vptofh(vp, fhp)
1002 	struct vnode *vp;
1003 	struct fid *fhp;
1004 {
1005 	register struct inode *ip;
1006 	register struct ufid *ufhp;
1007 
1008 	ip = VTOI(vp);
1009 	ufhp = (struct ufid *)fhp;
1010 	ufhp->ufid_len = sizeof(struct ufid);
1011 	ufhp->ufid_ino = ip->i_number;
1012 	ufhp->ufid_gen = ip->i_gen;
1013 	return (0);
1014 }
1015 
1016 /*
1017  * Write a superblock and associated information back to disk.
1018  */
1019 int
1020 ffs_sbupdate(mp, waitfor)
1021 	struct ufsmount *mp;
1022 	int waitfor;
1023 {
1024 	register struct fs *fs = mp->um_fs;
1025 	register struct buf *bp;
1026 	int blks;
1027 	caddr_t space;
1028 	int i, size, error = 0;
1029 
1030 	bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
1031 	bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
1032 	/* Restore compatibility to old file systems.		   XXX */
1033 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
1034 		((struct fs *)bp->b_data)->fs_nrpos = -1;	/* XXX */
1035 	if (waitfor == MNT_WAIT)
1036 		error = bwrite(bp);
1037 	else
1038 		bawrite(bp);
1039 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
1040 	space = (caddr_t)fs->fs_csp[0];
1041 	for (i = 0; i < blks; i += fs->fs_frag) {
1042 		size = fs->fs_bsize;
1043 		if (i + fs->fs_frag > blks)
1044 			size = (blks - i) * fs->fs_fsize;
1045 		bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1046 		    size, 0, 0);
1047 		bcopy(space, bp->b_data, (u_int)size);
1048 		space += size;
1049 		if (waitfor == MNT_WAIT)
1050 			error = bwrite(bp);
1051 		else
1052 			bawrite(bp);
1053 	}
1054 	return (error);
1055 }
1056