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