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