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