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