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