ffs_vfsops.c revision 1.4.2.1 1 /* $NetBSD: ffs_vfsops.c,v 1.4.2.1 1994/11/23 08:49:59 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
36 */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/namei.h>
41 #include <sys/proc.h>
42 #include <sys/kernel.h>
43 #include <sys/vnode.h>
44 #include <sys/socket.h>
45 #include <sys/mount.h>
46 #include <sys/buf.h>
47 #include <sys/mbuf.h>
48 #include <sys/file.h>
49 #include <sys/disklabel.h>
50 #include <sys/ioctl.h>
51 #include <sys/errno.h>
52 #include <sys/malloc.h>
53
54 #include <miscfs/specfs/specdev.h>
55
56 #include <ufs/ufs/quota.h>
57 #include <ufs/ufs/ufsmount.h>
58 #include <ufs/ufs/inode.h>
59 #include <ufs/ufs/ufs_extern.h>
60
61 #include <ufs/ffs/fs.h>
62 #include <ufs/ffs/ffs_extern.h>
63
64 int ffs_sbupdate __P((struct ufsmount *, int));
65
66 struct vfsops ufs_vfsops = {
67 MOUNT_UFS,
68 ffs_mount,
69 ufs_start,
70 ffs_unmount,
71 ufs_root,
72 ufs_quotactl,
73 ffs_statfs,
74 ffs_sync,
75 ffs_vget,
76 ffs_fhtovp,
77 ffs_vptofh,
78 ffs_init,
79 };
80
81 extern u_long nextgennumber;
82
83 /*
84 * Called by main() when ufs is going to be mounted as root.
85 *
86 * Name is updated by mount(8) after booting.
87 */
88 #define ROOTNAME "root_device"
89
90 ffs_mountroot()
91 {
92 extern struct vnode *rootvp;
93 register struct fs *fs;
94 register struct mount *mp;
95 struct proc *p = curproc; /* XXX */
96 struct ufsmount *ump;
97 u_int size;
98 int error;
99
100 /*
101 * Get vnodes for swapdev and rootdev.
102 */
103 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
104 panic("ffs_mountroot: can't setup bdevvp's");
105
106 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
107 bzero((char *)mp, (u_long)sizeof(struct mount));
108 mp->mnt_op = &ufs_vfsops;
109 mp->mnt_flag = MNT_RDONLY;
110 if (error = ffs_mountfs(rootvp, mp, p)) {
111 free(mp, M_MOUNT);
112 return (error);
113 }
114 if (error = vfs_lock(mp)) {
115 (void)ffs_unmount(mp, 0, p);
116 free(mp, M_MOUNT);
117 return (error);
118 }
119 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
120 mp->mnt_flag |= MNT_ROOTFS;
121 mp->mnt_vnodecovered = NULLVP;
122 ump = VFSTOUFS(mp);
123 fs = ump->um_fs;
124 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
125 fs->fs_fsmnt[0] = '/';
126 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
127 MNAMELEN);
128 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
129 &size);
130 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
131 (void)ffs_statfs(mp, &mp->mnt_stat, p);
132 vfs_unlock(mp);
133 inittodr(fs->fs_time);
134 return (0);
135 }
136
137 /*
138 * VFS Operations.
139 *
140 * mount system call
141 */
142 int
143 ffs_mount(mp, path, data, ndp, p)
144 register struct mount *mp;
145 char *path;
146 caddr_t data;
147 struct nameidata *ndp;
148 struct proc *p;
149 {
150 struct vnode *devvp;
151 struct ufs_args args;
152 struct ufsmount *ump;
153 register struct fs *fs;
154 u_int size;
155 int error, flags;
156
157 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
158 return (error);
159 /*
160 * If updating, check whether changing from read-only to
161 * read/write; if there is no device name, that's all we do.
162 */
163 if (mp->mnt_flag & MNT_UPDATE) {
164 ump = VFSTOUFS(mp);
165 fs = ump->um_fs;
166 error = 0;
167 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
168 flags = WRITECLOSE;
169 if (mp->mnt_flag & MNT_FORCE)
170 flags |= FORCECLOSE;
171 if (vfs_busy(mp))
172 return (EBUSY);
173 error = ffs_flushfiles(mp, flags, p);
174 vfs_unbusy(mp);
175 }
176 if (!error && (mp->mnt_flag & MNT_RELOAD))
177 error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
178 if (error)
179 return (error);
180 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR))
181 fs->fs_ronly = 0;
182 if (args.fspec == 0) {
183 /*
184 * Process export requests.
185 */
186 return (vfs_export(mp, &ump->um_export, &args.export));
187 }
188 }
189 /*
190 * Not an update, or updating the name: look up the name
191 * and verify that it refers to a sensible block device.
192 */
193 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
194 if (error = namei(ndp))
195 return (error);
196 devvp = ndp->ni_vp;
197
198 if (devvp->v_type != VBLK) {
199 vrele(devvp);
200 return (ENOTBLK);
201 }
202 if (major(devvp->v_rdev) >= nblkdev) {
203 vrele(devvp);
204 return (ENXIO);
205 }
206 if ((mp->mnt_flag & MNT_UPDATE) == 0)
207 error = ffs_mountfs(devvp, mp, p);
208 else {
209 if (devvp != ump->um_devvp)
210 error = EINVAL; /* needs translation */
211 else
212 vrele(devvp);
213 }
214 if (error) {
215 vrele(devvp);
216 return (error);
217 }
218 ump = VFSTOUFS(mp);
219 fs = ump->um_fs;
220 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
221 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
222 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
223 MNAMELEN);
224 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
225 &size);
226 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
227 (void)ffs_statfs(mp, &mp->mnt_stat, p);
228 return (0);
229 }
230
231 /*
232 * Reload all incore data for a filesystem (used after running fsck on
233 * the root filesystem and finding things to fix). The filesystem must
234 * be mounted read-only.
235 *
236 * Things to do to update the mount:
237 * 1) invalidate all cached meta-data.
238 * 2) re-read superblock from disk.
239 * 3) re-read summary information from disk.
240 * 4) invalidate all inactive vnodes.
241 * 5) invalidate all cached file data.
242 * 6) re-read inode data for all active vnodes.
243 */
244 ffs_reload(mountp, cred, p)
245 register struct mount *mountp;
246 struct ucred *cred;
247 struct proc *p;
248 {
249 register struct vnode *vp, *nvp, *devvp;
250 struct inode *ip;
251 struct csum *space;
252 struct buf *bp;
253 struct fs *fs;
254 struct partinfo dpart;
255 int i, blks, size, error;
256
257 if ((mountp->mnt_flag & MNT_RDONLY) == 0)
258 return (EINVAL);
259 /*
260 * Step 1: invalidate all cached meta-data.
261 */
262 devvp = VFSTOUFS(mountp)->um_devvp;
263 if (vinvalbuf(devvp, 0, cred, p, 0, 0))
264 panic("ffs_reload: dirty1");
265 /*
266 * Step 2: re-read superblock from disk.
267 */
268 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
269 size = DEV_BSIZE;
270 else
271 size = dpart.disklab->d_secsize;
272 if (error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp))
273 return (error);
274 fs = (struct fs *)bp->b_data;
275 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
276 fs->fs_bsize < sizeof(struct fs)) {
277 brelse(bp);
278 return (EIO); /* XXX needs translation */
279 }
280 fs = VFSTOUFS(mountp)->um_fs;
281 bcopy(&fs->fs_csp[0], &((struct fs *)bp->b_data)->fs_csp[0],
282 sizeof(fs->fs_csp));
283 bcopy(bp->b_data, fs, (u_int)fs->fs_sbsize);
284 if (fs->fs_sbsize < SBSIZE)
285 bp->b_flags |= B_INVAL;
286 brelse(bp);
287 mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
288 ffs_oldfscompat(fs);
289 /*
290 * Step 3: re-read summary information from disk.
291 */
292 blks = howmany(fs->fs_cssize, fs->fs_fsize);
293 space = fs->fs_csp[0];
294 for (i = 0; i < blks; i += fs->fs_frag) {
295 size = fs->fs_bsize;
296 if (i + fs->fs_frag > blks)
297 size = (blks - i) * fs->fs_fsize;
298 if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
299 NOCRED, &bp))
300 return (error);
301 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
302 brelse(bp);
303 }
304 loop:
305 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
306 nvp = vp->v_mntvnodes.le_next;
307 /*
308 * Step 4: invalidate all inactive vnodes.
309 */
310 if (vp->v_usecount == 0) {
311 vgone(vp);
312 continue;
313 }
314 /*
315 * Step 5: invalidate all cached file data.
316 */
317 if (vget(vp, 1))
318 goto loop;
319 if (vinvalbuf(vp, 0, cred, p, 0, 0))
320 panic("ffs_reload: dirty2");
321 /*
322 * Step 6: re-read inode data for all active vnodes.
323 */
324 ip = VTOI(vp);
325 if (error =
326 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
327 (int)fs->fs_bsize, NOCRED, &bp)) {
328 vput(vp);
329 return (error);
330 }
331 ip->i_din = *((struct dinode *)bp->b_data +
332 ino_to_fsbo(fs, ip->i_number));
333 brelse(bp);
334 vput(vp);
335 if (vp->v_mount != mountp)
336 goto loop;
337 }
338 return (0);
339 }
340
341 /*
342 * Common code for mount and mountroot
343 */
344 int
345 ffs_mountfs(devvp, mp, p)
346 register struct vnode *devvp;
347 struct mount *mp;
348 struct proc *p;
349 {
350 register struct ufsmount *ump;
351 struct buf *bp;
352 register struct fs *fs;
353 dev_t dev = devvp->v_rdev;
354 struct partinfo dpart;
355 caddr_t base, space;
356 int blks;
357 int error, i, size;
358 int ronly;
359 extern struct vnode *rootvp;
360
361 /*
362 * Disallow multiple mounts of the same device.
363 * Disallow mounting of a device that is currently in use
364 * (except for root, which might share swap device for miniroot).
365 * Flush out any old buffers remaining from a previous use.
366 */
367 if (error = vfs_mountedon(devvp))
368 return (error);
369 if (vcount(devvp) > 1 && devvp != rootvp)
370 return (EBUSY);
371 if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0))
372 return (error);
373
374 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
375 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
376 return (error);
377 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
378 size = DEV_BSIZE;
379 else
380 size = dpart.disklab->d_secsize;
381
382 bp = NULL;
383 ump = NULL;
384 if (error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp))
385 goto out;
386 fs = (struct fs *)bp->b_data;
387 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
388 fs->fs_bsize < sizeof(struct fs)) {
389 error = EINVAL; /* XXX needs translation */
390 goto out;
391 }
392 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
393 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
394 error = EROFS; /* XXX what should be returned? */
395 goto out;
396 }
397 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
398 bzero((caddr_t)ump, sizeof *ump);
399 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
400 M_WAITOK);
401 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
402 if (fs->fs_sbsize < SBSIZE)
403 bp->b_flags |= B_INVAL;
404 brelse(bp);
405 bp = NULL;
406 fs = ump->um_fs;
407 fs->fs_ronly = ronly;
408 if (ronly == 0)
409 fs->fs_fmod = 1;
410 blks = howmany(fs->fs_cssize, fs->fs_fsize);
411 base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT,
412 M_WAITOK);
413 for (i = 0; i < blks; i += fs->fs_frag) {
414 size = fs->fs_bsize;
415 if (i + fs->fs_frag > blks)
416 size = (blks - i) * fs->fs_fsize;
417 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
418 NOCRED, &bp);
419 if (error) {
420 free(base, M_UFSMNT);
421 goto out;
422 }
423 bcopy(bp->b_data, space, (u_int)size);
424 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
425 space += size;
426 brelse(bp);
427 bp = NULL;
428 }
429 mp->mnt_data = (qaddr_t)ump;
430 mp->mnt_stat.f_fsid.val[0] = (long)dev;
431 mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_UFS);
432 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
433 mp->mnt_flag |= MNT_LOCAL;
434 ump->um_mountp = mp;
435 ump->um_dev = dev;
436 ump->um_devvp = devvp;
437 ump->um_nindir = fs->fs_nindir;
438 ump->um_bptrtodb = fs->fs_fsbtodb;
439 ump->um_seqinc = fs->fs_frag;
440 for (i = 0; i < MAXQUOTAS; i++)
441 ump->um_quotas[i] = NULLVP;
442 devvp->v_specflags |= SI_MOUNTEDON;
443 ffs_oldfscompat(fs);
444 return (0);
445 out:
446 if (bp)
447 brelse(bp);
448 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
449 if (ump) {
450 free(ump->um_fs, M_UFSMNT);
451 free(ump, M_UFSMNT);
452 mp->mnt_data = (qaddr_t)0;
453 }
454 return (error);
455 }
456
457 /*
458 * Sanity checks for old file systems.
459 *
460 * XXX - goes away some day.
461 */
462 ffs_oldfscompat(fs)
463 struct fs *fs;
464 {
465 int i;
466
467 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
468 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
469 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
470 fs->fs_nrpos = 8; /* XXX */
471 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
472 quad_t sizepb = fs->fs_bsize; /* XXX */
473 /* XXX */
474 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
475 for (i = 0; i < NIADDR; i++) { /* XXX */
476 sizepb *= NINDIR(fs); /* XXX */
477 fs->fs_maxfilesize += sizepb; /* XXX */
478 } /* XXX */
479 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
480 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
481 } /* XXX */
482 #ifndef KLUGE_BEGONE
483 {
484 quad_t maxfilesize;
485
486 maxfilesize = (quad_t)0x80000000 * fs->fs_bsize - 1;
487 if (fs->fs_maxfilesize > maxfilesize)
488 fs->fs_maxfilesize = maxfilesize;
489 }
490 #endif
491 return (0);
492 }
493
494 /*
495 * unmount system call
496 */
497 int
498 ffs_unmount(mp, mntflags, p)
499 struct mount *mp;
500 int mntflags;
501 struct proc *p;
502 {
503 register struct ufsmount *ump;
504 register struct fs *fs;
505 int error, flags, ronly;
506
507 flags = 0;
508 if (mntflags & MNT_FORCE) {
509 if (mp->mnt_flag & MNT_ROOTFS)
510 return (EINVAL);
511 flags |= FORCECLOSE;
512 }
513 if (error = ffs_flushfiles(mp, flags, p))
514 return (error);
515 ump = VFSTOUFS(mp);
516 fs = ump->um_fs;
517 ronly = !fs->fs_ronly;
518 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
519 error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
520 NOCRED, p);
521 vrele(ump->um_devvp);
522 free(fs->fs_csp[0], M_UFSMNT);
523 free(fs, M_UFSMNT);
524 free(ump, M_UFSMNT);
525 mp->mnt_data = (qaddr_t)0;
526 mp->mnt_flag &= ~MNT_LOCAL;
527 return (error);
528 }
529
530 /*
531 * Flush out all the files in a filesystem.
532 */
533 ffs_flushfiles(mp, flags, p)
534 register struct mount *mp;
535 int flags;
536 struct proc *p;
537 {
538 extern int doforce;
539 register struct ufsmount *ump;
540 int i, error;
541
542 if (!doforce)
543 flags &= ~FORCECLOSE;
544 ump = VFSTOUFS(mp);
545 #ifdef QUOTA
546 if (mp->mnt_flag & MNT_QUOTA) {
547 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
548 return (error);
549 for (i = 0; i < MAXQUOTAS; i++) {
550 if (ump->um_quotas[i] == NULLVP)
551 continue;
552 quotaoff(p, mp, i);
553 }
554 /*
555 * Here we fall through to vflush again to ensure
556 * that we have gotten rid of all the system vnodes.
557 */
558 }
559 #endif
560 error = vflush(mp, NULLVP, flags);
561 return (error);
562 }
563
564 /*
565 * Get file system statistics.
566 */
567 int
568 ffs_statfs(mp, sbp, p)
569 struct mount *mp;
570 register struct statfs *sbp;
571 struct proc *p;
572 {
573 register struct ufsmount *ump;
574 register struct fs *fs;
575
576 ump = VFSTOUFS(mp);
577 fs = ump->um_fs;
578 if (fs->fs_magic != FS_MAGIC)
579 panic("ffs_statfs");
580 #ifdef COMPAT_09
581 sbp->f_type = 1;
582 #else
583 sbp->f_type = 0;
584 #endif
585 sbp->f_bsize = fs->fs_fsize;
586 sbp->f_iosize = fs->fs_bsize;
587 sbp->f_blocks = fs->fs_dsize;
588 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
589 fs->fs_cstotal.cs_nffree;
590 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
591 (fs->fs_dsize - sbp->f_bfree);
592 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
593 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
594 if (sbp != &mp->mnt_stat) {
595 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
596 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
597 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
598 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
599 }
600 strncpy(&sbp->f_fstypename[0], mp->mnt_op->vfs_name, MFSNAMELEN);
601 sbp->f_fstypename[MFSNAMELEN] = '\0';
602 return (0);
603 }
604
605 /*
606 * Go through the disk queues to initiate sandbagged IO;
607 * go through the inodes to write those that have been modified;
608 * initiate the writing of the super block if it has been modified.
609 *
610 * Note: we are always called with the filesystem marked `MPBUSY'.
611 */
612 int
613 ffs_sync(mp, waitfor, cred, p)
614 struct mount *mp;
615 int waitfor;
616 struct ucred *cred;
617 struct proc *p;
618 {
619 register struct vnode *vp;
620 register struct inode *ip;
621 register struct ufsmount *ump = VFSTOUFS(mp);
622 register struct fs *fs;
623 int error, allerror = 0;
624
625 fs = ump->um_fs;
626 /*
627 * Write back modified superblock.
628 * Consistency check that the superblock
629 * is still in the buffer cache.
630 */
631 if (fs->fs_fmod != 0) {
632 if (fs->fs_ronly != 0) { /* XXX */
633 printf("fs = %s\n", fs->fs_fsmnt);
634 panic("update: rofs mod");
635 }
636 fs->fs_fmod = 0;
637 fs->fs_time = time.tv_sec;
638 allerror = ffs_sbupdate(ump, waitfor);
639 }
640 /*
641 * Write back each (modified) inode.
642 */
643 loop:
644 for (vp = mp->mnt_vnodelist.lh_first;
645 vp != NULL;
646 vp = vp->v_mntvnodes.le_next) {
647 /*
648 * If the vnode that we are about to sync is no longer
649 * associated with this mount point, start over.
650 */
651 if (vp->v_mount != mp)
652 goto loop;
653 if (VOP_ISLOCKED(vp))
654 continue;
655 ip = VTOI(vp);
656 if ((ip->i_flag &
657 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
658 vp->v_dirtyblkhd.lh_first == NULL)
659 continue;
660 if (vget(vp, 1))
661 goto loop;
662 if (error = VOP_FSYNC(vp, cred, waitfor, p))
663 allerror = error;
664 vput(vp);
665 }
666 /*
667 * Force stale file system control information to be flushed.
668 */
669 if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p))
670 allerror = error;
671 #ifdef QUOTA
672 qsync(mp);
673 #endif
674 return (allerror);
675 }
676
677 /*
678 * Look up a FFS dinode number to find its incore vnode, otherwise read it
679 * in from disk. If it is in core, wait for the lock bit to clear, then
680 * return the inode locked. Detection and handling of mount points must be
681 * done by the calling routine.
682 */
683 int
684 ffs_vget(mp, ino, vpp)
685 struct mount *mp;
686 ino_t ino;
687 struct vnode **vpp;
688 {
689 register struct fs *fs;
690 register struct inode *ip;
691 struct ufsmount *ump;
692 struct buf *bp;
693 struct vnode *vp;
694 dev_t dev;
695 int i, type, error;
696
697 ump = VFSTOUFS(mp);
698 dev = ump->um_dev;
699 if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
700 return (0);
701
702 /* Allocate a new vnode/inode. */
703 if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) {
704 *vpp = NULL;
705 return (error);
706 }
707 type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
708 MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
709 bzero((caddr_t)ip, sizeof(struct inode));
710 vp->v_data = ip;
711 ip->i_vnode = vp;
712 ip->i_fs = fs = ump->um_fs;
713 ip->i_dev = dev;
714 ip->i_number = ino;
715 #ifdef QUOTA
716 for (i = 0; i < MAXQUOTAS; i++)
717 ip->i_dquot[i] = NODQUOT;
718 #endif
719 /*
720 * Put it onto its hash chain and lock it so that other requests for
721 * this inode will block if they arrive while we are sleeping waiting
722 * for old data structures to be purged or for the contents of the
723 * disk portion of this inode to be read.
724 */
725 ufs_ihashins(ip);
726
727 /* Read in the disk contents for the inode, copy into the inode. */
728 if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
729 (int)fs->fs_bsize, NOCRED, &bp)) {
730 /*
731 * The inode does not contain anything useful, so it would
732 * be misleading to leave it on its hash chain. With mode
733 * still zero, it will be unlinked and returned to the free
734 * list by vput().
735 */
736 vput(vp);
737 brelse(bp);
738 *vpp = NULL;
739 return (error);
740 }
741 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
742 brelse(bp);
743
744 /*
745 * Initialize the vnode from the inode, check for aliases.
746 * Note that the underlying vnode may have changed.
747 */
748 if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) {
749 vput(vp);
750 *vpp = NULL;
751 return (error);
752 }
753 /*
754 * Finish inode initialization now that aliasing has been resolved.
755 */
756 ip->i_devvp = ump->um_devvp;
757 VREF(ip->i_devvp);
758 /*
759 * Set up a generation number for this inode if it does not
760 * already have one. This should only happen on old filesystems.
761 */
762 if (ip->i_gen == 0) {
763 if (++nextgennumber < (u_long)time.tv_sec)
764 nextgennumber = time.tv_sec;
765 ip->i_gen = nextgennumber;
766 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
767 ip->i_flag |= IN_MODIFIED;
768 }
769 /*
770 * Ensure that uid and gid are correct. This is a temporary
771 * fix until fsck has been changed to do the update.
772 */
773 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
774 ip->i_uid = ip->i_din.di_ouid; /* XXX */
775 ip->i_gid = ip->i_din.di_ogid; /* XXX */
776 } /* XXX */
777
778 *vpp = vp;
779 return (0);
780 }
781
782 /*
783 * File handle to vnode
784 *
785 * Have to be really careful about stale file handles:
786 * - check that the inode number is valid
787 * - call ffs_vget() to get the locked inode
788 * - check for an unallocated inode (i_mode == 0)
789 * - check that the given client host has export rights and return
790 * those rights via. exflagsp and credanonp
791 */
792 int
793 ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
794 register struct mount *mp;
795 struct fid *fhp;
796 struct mbuf *nam;
797 struct vnode **vpp;
798 int *exflagsp;
799 struct ucred **credanonp;
800 {
801 register struct ufid *ufhp;
802 struct fs *fs;
803
804 ufhp = (struct ufid *)fhp;
805 fs = VFSTOUFS(mp)->um_fs;
806 if (ufhp->ufid_ino < ROOTINO ||
807 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
808 return (ESTALE);
809 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
810 }
811
812 /*
813 * Vnode pointer to File handle
814 */
815 /* ARGSUSED */
816 ffs_vptofh(vp, fhp)
817 struct vnode *vp;
818 struct fid *fhp;
819 {
820 register struct inode *ip;
821 register struct ufid *ufhp;
822
823 ip = VTOI(vp);
824 ufhp = (struct ufid *)fhp;
825 ufhp->ufid_len = sizeof(struct ufid);
826 ufhp->ufid_ino = ip->i_number;
827 ufhp->ufid_gen = ip->i_gen;
828 return (0);
829 }
830
831 /*
832 * Write a superblock and associated information back to disk.
833 */
834 int
835 ffs_sbupdate(mp, waitfor)
836 struct ufsmount *mp;
837 int waitfor;
838 {
839 register struct fs *fs = mp->um_fs;
840 register struct buf *bp;
841 int blks;
842 caddr_t space;
843 int i, size, error = 0;
844 struct fs *cfs;
845
846 bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb),
847 (int)fs->fs_sbsize, 0, 0);
848 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
849 cfs = (struct fs *)bp->b_data;
850 /* Restore compatibility to old file systems. XXX */
851 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
852 cfs->fs_nrpos = -1; /* XXX */
853 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
854 long *lp, tmp; /* XXX */
855 /* XXX */
856 lp = (long *)&((struct fs *)bp->b_data)->fs_qbmask; /* XXX */
857 tmp = lp[4]; /* XXX */
858 for (i = 4; i > 0; i--) /* XXX */
859 lp[i] = lp[i-1]; /* XXX */
860 lp[0] = tmp; /* XXX */
861 } /* XXX */
862 #ifndef KLUGE_BEGONE
863 {
864 quad_t sizepb = fs->fs_bsize; /* XXX */
865 /* XXX */
866 cfs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
867 for (i = 0; i < NIADDR; i++) { /* XXX */
868 sizepb *= NINDIR(fs); /* XXX */
869 cfs->fs_maxfilesize += sizepb; /* XXX */
870 } /* XXX */
871 }
872 #endif
873 if (waitfor == MNT_WAIT)
874 error = bwrite(bp);
875 else
876 bawrite(bp);
877 blks = howmany(fs->fs_cssize, fs->fs_fsize);
878 space = (caddr_t)fs->fs_csp[0];
879 for (i = 0; i < blks; i += fs->fs_frag) {
880 size = fs->fs_bsize;
881 if (i + fs->fs_frag > blks)
882 size = (blks - i) * fs->fs_fsize;
883 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
884 size, 0, 0);
885 bcopy(space, bp->b_data, (u_int)size);
886 space += size;
887 if (waitfor == MNT_WAIT)
888 error = bwrite(bp);
889 else
890 bawrite(bp);
891 }
892 return (error);
893 }
894