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