1 /* 2 * Copyright (c) 1989, 1991, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ffs_vfsops.c 8.20 (Berkeley) 03/22/95 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/namei.h> 13 #include <sys/proc.h> 14 #include <sys/kernel.h> 15 #include <sys/vnode.h> 16 #include <sys/socket.h> 17 #include <sys/mount.h> 18 #include <sys/buf.h> 19 #include <sys/mbuf.h> 20 #include <sys/file.h> 21 #include <sys/disklabel.h> 22 #include <sys/ioctl.h> 23 #include <sys/errno.h> 24 #include <sys/malloc.h> 25 26 #include <miscfs/specfs/specdev.h> 27 28 #include <ufs/ufs/quota.h> 29 #include <ufs/ufs/ufsmount.h> 30 #include <ufs/ufs/inode.h> 31 #include <ufs/ufs/ufs_extern.h> 32 33 #include <ufs/ffs/fs.h> 34 #include <ufs/ffs/ffs_extern.h> 35 36 int ffs_sbupdate __P((struct ufsmount *, int)); 37 38 struct vfsops ufs_vfsops = { 39 ffs_mount, 40 ufs_start, 41 ffs_unmount, 42 ufs_root, 43 ufs_quotactl, 44 ffs_statfs, 45 ffs_sync, 46 ffs_vget, 47 ffs_fhtovp, 48 ffs_vptofh, 49 ffs_init, 50 }; 51 52 extern u_long nextgennumber; 53 54 /* 55 * Called by main() when ufs is going to be mounted as root. 56 * 57 * Name is updated by mount(8) after booting. 58 */ 59 #define ROOTNAME "root_device" 60 61 ffs_mountroot() 62 { 63 extern struct vnode *rootvp; 64 register struct fs *fs; 65 register struct mount *mp; 66 struct proc *p = curproc; /* XXX */ 67 struct ufsmount *ump; 68 u_int size; 69 int error; 70 71 /* 72 * Get vnodes for swapdev and rootdev. 73 */ 74 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) 75 panic("ffs_mountroot: can't setup bdevvp's"); 76 77 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 78 bzero((char *)mp, (u_long)sizeof(struct mount)); 79 mp->mnt_op = &ufs_vfsops; 80 mp->mnt_flag = MNT_RDONLY; 81 if (error = ffs_mountfs(rootvp, mp, p)) { 82 free(mp, M_MOUNT); 83 return (error); 84 } 85 if (error = vfs_lock(mp)) { 86 (void)ffs_unmount(mp, 0, p); 87 free(mp, M_MOUNT); 88 return (error); 89 } 90 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 91 mp->mnt_flag |= MNT_ROOTFS; 92 mp->mnt_vnodecovered = NULLVP; 93 ump = VFSTOUFS(mp); 94 fs = ump->um_fs; 95 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 96 fs->fs_fsmnt[0] = '/'; 97 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 98 MNAMELEN); 99 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 100 &size); 101 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 102 (void)ffs_statfs(mp, &mp->mnt_stat, p); 103 vfs_unlock(mp); 104 inittodr(fs->fs_time); 105 return (0); 106 } 107 108 /* 109 * VFS Operations. 110 * 111 * mount system call 112 */ 113 int 114 ffs_mount(mp, path, data, ndp, p) 115 register struct mount *mp; 116 char *path; 117 caddr_t data; 118 struct nameidata *ndp; 119 struct proc *p; 120 { 121 struct vnode *devvp; 122 struct ufs_args args; 123 struct ufsmount *ump; 124 register struct fs *fs; 125 u_int size; 126 int error, flags; 127 mode_t accessmode; 128 129 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 130 return (error); 131 /* 132 * If updating, check whether changing from read-only to 133 * read/write; if there is no device name, that's all we do. 134 */ 135 if (mp->mnt_flag & MNT_UPDATE) { 136 ump = VFSTOUFS(mp); 137 fs = ump->um_fs; 138 error = 0; 139 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 140 flags = WRITECLOSE; 141 if (mp->mnt_flag & MNT_FORCE) 142 flags |= FORCECLOSE; 143 if (vfs_busy(mp)) 144 return (EBUSY); 145 error = ffs_flushfiles(mp, flags, p); 146 vfs_unbusy(mp); 147 } 148 if (!error && (mp->mnt_flag & MNT_RELOAD)) 149 error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); 150 if (error) 151 return (error); 152 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { 153 /* 154 * If upgrade to read-write by non-root, then verify 155 * that user has necessary permissions on the device. 156 */ 157 if (p->p_ucred->cr_uid != 0) { 158 devvp = ump->um_devvp; 159 VOP_LOCK(devvp); 160 if (error = VOP_ACCESS(devvp, VREAD | VWRITE, 161 p->p_ucred, p)) { 162 VOP_UNLOCK(devvp); 163 return (error); 164 } 165 VOP_UNLOCK(devvp); 166 } 167 fs->fs_ronly = 0; 168 } 169 if (args.fspec == 0) { 170 /* 171 * Process export requests. 172 */ 173 return (vfs_export(mp, &ump->um_export, &args.export)); 174 } 175 } 176 /* 177 * Not an update, or updating the name: look up the name 178 * and verify that it refers to a sensible block device. 179 */ 180 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 181 if (error = namei(ndp)) 182 return (error); 183 devvp = ndp->ni_vp; 184 185 if (devvp->v_type != VBLK) { 186 vrele(devvp); 187 return (ENOTBLK); 188 } 189 if (major(devvp->v_rdev) >= nblkdev) { 190 vrele(devvp); 191 return (ENXIO); 192 } 193 /* 194 * If mount by non-root, then verify that user has necessary 195 * permissions on the device. 196 */ 197 if (p->p_ucred->cr_uid != 0) { 198 accessmode = VREAD; 199 if ((mp->mnt_flag & MNT_RDONLY) == 0) 200 accessmode |= VWRITE; 201 VOP_LOCK(devvp); 202 if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) { 203 vput(devvp); 204 return (error); 205 } 206 VOP_UNLOCK(devvp); 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 ffs_reload(mountp, cred, p) 247 register struct mount *mountp; 248 struct ucred *cred; 249 struct proc *p; 250 { 251 register struct vnode *vp, *nvp, *devvp; 252 struct inode *ip; 253 struct csum *space; 254 struct buf *bp; 255 struct fs *fs, *newfs; 256 struct partinfo dpart; 257 int i, blks, size, error; 258 long *lp; 259 260 if ((mountp->mnt_flag & MNT_RDONLY) == 0) 261 return (EINVAL); 262 /* 263 * Step 1: invalidate all cached meta-data. 264 */ 265 devvp = VFSTOUFS(mountp)->um_devvp; 266 if (vinvalbuf(devvp, 0, cred, p, 0, 0)) 267 panic("ffs_reload: dirty1"); 268 /* 269 * Step 2: re-read superblock from disk. 270 */ 271 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 272 size = DEV_BSIZE; 273 else 274 size = dpart.disklab->d_secsize; 275 if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) 276 return (error); 277 newfs = (struct fs *)bp->b_data; 278 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE || 279 newfs->fs_bsize < sizeof(struct fs)) { 280 brelse(bp); 281 return (EIO); /* XXX needs translation */ 282 } 283 fs = VFSTOUFS(mountp)->um_fs; 284 /* 285 * Copy pointer fields back into superblock before copying in XXX 286 * new superblock. These should really be in the ufsmount. XXX 287 * Note that important parameters (eg fs_ncg) are unchanged. 288 */ 289 bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp)); 290 newfs->fs_maxcluster = fs->fs_maxcluster; 291 bcopy(newfs, fs, (u_int)fs->fs_sbsize); 292 if (fs->fs_sbsize < SBSIZE) 293 bp->b_flags |= B_INVAL; 294 brelse(bp); 295 mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 296 ffs_oldfscompat(fs); 297 /* 298 * Step 3: re-read summary information from disk. 299 */ 300 blks = howmany(fs->fs_cssize, fs->fs_fsize); 301 space = fs->fs_csp[0]; 302 for (i = 0; i < blks; i += fs->fs_frag) { 303 size = fs->fs_bsize; 304 if (i + fs->fs_frag > blks) 305 size = (blks - i) * fs->fs_fsize; 306 if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 307 NOCRED, &bp)) 308 return (error); 309 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size); 310 brelse(bp); 311 } 312 /* 313 * We no longer know anything about clusters per cylinder group. 314 */ 315 if (fs->fs_contigsumsize > 0) { 316 lp = fs->fs_maxcluster; 317 for (i = 0; i < fs->fs_ncg; i++) 318 *lp++ = fs->fs_contigsumsize; 319 } 320 loop: 321 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 322 nvp = vp->v_mntvnodes.le_next; 323 /* 324 * Step 4: invalidate all inactive vnodes. 325 */ 326 if (vp->v_usecount == 0) { 327 vgone(vp); 328 continue; 329 } 330 /* 331 * Step 5: invalidate all cached file data. 332 */ 333 if (vget(vp, 1)) 334 goto loop; 335 if (vinvalbuf(vp, 0, cred, p, 0, 0)) 336 panic("ffs_reload: dirty2"); 337 /* 338 * Step 6: re-read inode data for all active vnodes. 339 */ 340 ip = VTOI(vp); 341 if (error = 342 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 343 (int)fs->fs_bsize, NOCRED, &bp)) { 344 vput(vp); 345 return (error); 346 } 347 ip->i_din = *((struct dinode *)bp->b_data + 348 ino_to_fsbo(fs, ip->i_number)); 349 brelse(bp); 350 vput(vp); 351 if (vp->v_mount != mountp) 352 goto loop; 353 } 354 return (0); 355 } 356 357 /* 358 * Common code for mount and mountroot 359 */ 360 int 361 ffs_mountfs(devvp, mp, p) 362 register struct vnode *devvp; 363 struct mount *mp; 364 struct proc *p; 365 { 366 register struct ufsmount *ump; 367 struct buf *bp; 368 register struct fs *fs; 369 dev_t dev; 370 struct partinfo dpart; 371 caddr_t base, space; 372 int error, i, blks, size, ronly; 373 int32_t *lp; 374 struct ucred *cred; 375 extern struct vnode *rootvp; 376 u_int64_t maxfilesize; /* XXX */ 377 378 dev = devvp->v_rdev; 379 cred = p ? p->p_ucred : NOCRED; 380 /* 381 * Disallow multiple mounts of the same device. 382 * Disallow mounting of a device that is currently in use 383 * (except for root, which might share swap device for miniroot). 384 * Flush out any old buffers remaining from a previous use. 385 */ 386 if (error = vfs_mountedon(devvp)) 387 return (error); 388 if (vcount(devvp) > 1 && devvp != rootvp) 389 return (EBUSY); 390 if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) 391 return (error); 392 393 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 394 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) 395 return (error); 396 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) 397 size = DEV_BSIZE; 398 else 399 size = dpart.disklab->d_secsize; 400 401 bp = NULL; 402 ump = NULL; 403 if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, cred, &bp)) 404 goto out; 405 fs = (struct fs *)bp->b_data; 406 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 407 fs->fs_bsize < sizeof(struct fs)) { 408 error = EINVAL; /* XXX needs translation */ 409 goto out; 410 } 411 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ 412 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { 413 error = EROFS; /* needs translation */ 414 goto out; 415 } 416 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 417 bzero((caddr_t)ump, sizeof *ump); 418 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, 419 M_WAITOK); 420 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize); 421 if (fs->fs_sbsize < SBSIZE) 422 bp->b_flags |= B_INVAL; 423 brelse(bp); 424 bp = NULL; 425 fs = ump->um_fs; 426 fs->fs_ronly = ronly; 427 if (ronly == 0) 428 fs->fs_fmod = 1; 429 size = fs->fs_cssize; 430 blks = howmany(size, fs->fs_fsize); 431 if (fs->fs_contigsumsize > 0) 432 size += fs->fs_ncg * sizeof(int32_t); 433 base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK); 434 for (i = 0; i < blks; i += fs->fs_frag) { 435 size = fs->fs_bsize; 436 if (i + fs->fs_frag > blks) 437 size = (blks - i) * fs->fs_fsize; 438 if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 439 cred, &bp)) { 440 free(base, M_UFSMNT); 441 goto out; 442 } 443 bcopy(bp->b_data, space, (u_int)size); 444 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 445 space += size; 446 brelse(bp); 447 bp = NULL; 448 } 449 if (fs->fs_contigsumsize > 0) { 450 fs->fs_maxcluster = lp = (int32_t *)space; 451 for (i = 0; i < fs->fs_ncg; i++) 452 *lp++ = fs->fs_contigsumsize; 453 } 454 mp->mnt_data = (qaddr_t)ump; 455 mp->mnt_stat.f_fsid.val[0] = (long)dev; 456 mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS; 457 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 458 mp->mnt_flag |= MNT_LOCAL; 459 ump->um_mountp = mp; 460 ump->um_dev = dev; 461 ump->um_devvp = devvp; 462 ump->um_nindir = fs->fs_nindir; 463 ump->um_bptrtodb = fs->fs_fsbtodb; 464 ump->um_seqinc = fs->fs_frag; 465 for (i = 0; i < MAXQUOTAS; i++) 466 ump->um_quotas[i] = NULLVP; 467 devvp->v_specflags |= SI_MOUNTEDON; 468 ffs_oldfscompat(fs); 469 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */ 470 maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */ 471 if (fs->fs_maxfilesize > maxfilesize) /* XXX */ 472 fs->fs_maxfilesize = maxfilesize; /* XXX */ 473 return (0); 474 out: 475 if (bp) 476 brelse(bp); 477 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); 478 if (ump) { 479 free(ump->um_fs, M_UFSMNT); 480 free(ump, M_UFSMNT); 481 mp->mnt_data = (qaddr_t)0; 482 } 483 return (error); 484 } 485 486 /* 487 * Sanity checks for old file systems. 488 * 489 * XXX - goes away some day. 490 */ 491 ffs_oldfscompat(fs) 492 struct fs *fs; 493 { 494 int i; 495 496 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ 497 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ 498 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 499 fs->fs_nrpos = 8; /* XXX */ 500 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 501 u_int64_t sizepb = fs->fs_bsize; /* XXX */ 502 /* XXX */ 503 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ 504 for (i = 0; i < NIADDR; i++) { /* XXX */ 505 sizepb *= NINDIR(fs); /* XXX */ 506 fs->fs_maxfilesize += sizepb; /* XXX */ 507 } /* XXX */ 508 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ 509 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ 510 } /* XXX */ 511 return (0); 512 } 513 514 /* 515 * unmount system call 516 */ 517 int 518 ffs_unmount(mp, mntflags, p) 519 struct mount *mp; 520 int mntflags; 521 struct proc *p; 522 { 523 register struct ufsmount *ump; 524 register struct fs *fs; 525 int error, flags; 526 527 flags = 0; 528 if (mntflags & MNT_FORCE) { 529 if (mp->mnt_flag & MNT_ROOTFS) 530 return (EINVAL); 531 flags |= FORCECLOSE; 532 } 533 if (error = ffs_flushfiles(mp, flags, p)) 534 return (error); 535 ump = VFSTOUFS(mp); 536 fs = ump->um_fs; 537 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 538 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, 539 NOCRED, p); 540 vrele(ump->um_devvp); 541 free(fs->fs_csp[0], M_UFSMNT); 542 free(fs, M_UFSMNT); 543 free(ump, M_UFSMNT); 544 mp->mnt_data = (qaddr_t)0; 545 mp->mnt_flag &= ~MNT_LOCAL; 546 return (error); 547 } 548 549 /* 550 * Flush out all the files in a filesystem. 551 */ 552 ffs_flushfiles(mp, flags, p) 553 register struct mount *mp; 554 int flags; 555 struct proc *p; 556 { 557 extern int doforce; 558 register struct ufsmount *ump; 559 int i, error; 560 561 if (!doforce) 562 flags &= ~FORCECLOSE; 563 ump = VFSTOUFS(mp); 564 #ifdef QUOTA 565 if (mp->mnt_flag & MNT_QUOTA) { 566 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) 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 if (error = VOP_FSYNC(vp, cred, waitfor, p)) 676 allerror = error; 677 vput(vp); 678 } 679 /* 680 * Force stale file system control information to be flushed. 681 */ 682 if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) 683 allerror = error; 684 #ifdef QUOTA 685 qsync(mp); 686 #endif 687 return (allerror); 688 } 689 690 /* 691 * Look up a FFS dinode number to find its incore vnode, otherwise read it 692 * in from disk. If it is in core, wait for the lock bit to clear, then 693 * return the inode locked. Detection and handling of mount points must be 694 * done by the calling routine. 695 */ 696 int 697 ffs_vget(mp, ino, vpp) 698 struct mount *mp; 699 ino_t ino; 700 struct vnode **vpp; 701 { 702 register struct fs *fs; 703 register struct inode *ip; 704 struct ufsmount *ump; 705 struct buf *bp; 706 struct vnode *vp; 707 dev_t dev; 708 int i, type, error; 709 710 ump = VFSTOUFS(mp); 711 dev = ump->um_dev; 712 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 713 return (0); 714 715 /* Allocate a new vnode/inode. */ 716 if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) { 717 *vpp = NULL; 718 return (error); 719 } 720 type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */ 721 MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK); 722 bzero((caddr_t)ip, sizeof(struct inode)); 723 vp->v_data = ip; 724 ip->i_vnode = vp; 725 ip->i_fs = fs = ump->um_fs; 726 ip->i_dev = dev; 727 ip->i_number = ino; 728 #ifdef QUOTA 729 for (i = 0; i < MAXQUOTAS; i++) 730 ip->i_dquot[i] = NODQUOT; 731 #endif 732 /* 733 * Put it onto its hash chain and lock it so that other requests for 734 * this inode will block if they arrive while we are sleeping waiting 735 * for old data structures to be purged or for the contents of the 736 * disk portion of this inode to be read. 737 */ 738 ufs_ihashins(ip); 739 740 /* Read in the disk contents for the inode, copy into the inode. */ 741 if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), 742 (int)fs->fs_bsize, NOCRED, &bp)) { 743 /* 744 * The inode does not contain anything useful, so it would 745 * be misleading to leave it on its hash chain. With mode 746 * still zero, it will be unlinked and returned to the free 747 * list by vput(). 748 */ 749 vput(vp); 750 brelse(bp); 751 *vpp = NULL; 752 return (error); 753 } 754 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 755 brelse(bp); 756 757 /* 758 * Initialize the vnode from the inode, check for aliases. 759 * Note that the underlying vnode may have changed. 760 */ 761 if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) { 762 vput(vp); 763 *vpp = NULL; 764 return (error); 765 } 766 /* 767 * Finish inode initialization now that aliasing has been resolved. 768 */ 769 ip->i_devvp = ump->um_devvp; 770 VREF(ip->i_devvp); 771 /* 772 * Set up a generation number for this inode if it does not 773 * already have one. This should only happen on old filesystems. 774 */ 775 if (ip->i_gen == 0) { 776 if (++nextgennumber < (u_long)time.tv_sec) 777 nextgennumber = time.tv_sec; 778 ip->i_gen = nextgennumber; 779 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 780 ip->i_flag |= IN_MODIFIED; 781 } 782 /* 783 * Ensure that uid and gid are correct. This is a temporary 784 * fix until fsck has been changed to do the update. 785 */ 786 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 787 ip->i_uid = ip->i_din.di_ouid; /* XXX */ 788 ip->i_gid = ip->i_din.di_ogid; /* XXX */ 789 } /* XXX */ 790 791 *vpp = vp; 792 return (0); 793 } 794 795 /* 796 * File handle to vnode 797 * 798 * Have to be really careful about stale file handles: 799 * - check that the inode number is valid 800 * - call ffs_vget() to get the locked inode 801 * - check for an unallocated inode (i_mode == 0) 802 * - check that the given client host has export rights and return 803 * those rights via. exflagsp and credanonp 804 */ 805 int 806 ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 807 register struct mount *mp; 808 struct fid *fhp; 809 struct mbuf *nam; 810 struct vnode **vpp; 811 int *exflagsp; 812 struct ucred **credanonp; 813 { 814 register struct ufid *ufhp; 815 struct fs *fs; 816 817 ufhp = (struct ufid *)fhp; 818 fs = VFSTOUFS(mp)->um_fs; 819 if (ufhp->ufid_ino < ROOTINO || 820 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 821 return (ESTALE); 822 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 823 } 824 825 /* 826 * Vnode pointer to File handle 827 */ 828 /* ARGSUSED */ 829 ffs_vptofh(vp, fhp) 830 struct vnode *vp; 831 struct fid *fhp; 832 { 833 register struct inode *ip; 834 register struct ufid *ufhp; 835 836 ip = VTOI(vp); 837 ufhp = (struct ufid *)fhp; 838 ufhp->ufid_len = sizeof(struct ufid); 839 ufhp->ufid_ino = ip->i_number; 840 ufhp->ufid_gen = ip->i_gen; 841 return (0); 842 } 843 844 /* 845 * Write a superblock and associated information back to disk. 846 */ 847 int 848 ffs_sbupdate(mp, waitfor) 849 struct ufsmount *mp; 850 int waitfor; 851 { 852 register struct fs *dfs, *fs = mp->um_fs; 853 register struct buf *bp; 854 int blks; 855 caddr_t space; 856 int i, size, error = 0; 857 858 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0); 859 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize); 860 /* Restore compatibility to old file systems. XXX */ 861 dfs = (struct fs *)bp->b_data; /* XXX */ 862 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 863 dfs->fs_nrpos = -1; /* XXX */ 864 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 865 int32_t *lp, tmp; /* XXX */ 866 /* XXX */ 867 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */ 868 tmp = lp[4]; /* XXX */ 869 for (i = 4; i > 0; i--) /* XXX */ 870 lp[i] = lp[i-1]; /* XXX */ 871 lp[0] = tmp; /* XXX */ 872 } /* XXX */ 873 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */ 874 if (waitfor == MNT_WAIT) 875 error = bwrite(bp); 876 else 877 bawrite(bp); 878 blks = howmany(fs->fs_cssize, fs->fs_fsize); 879 space = (caddr_t)fs->fs_csp[0]; 880 for (i = 0; i < blks; i += fs->fs_frag) { 881 size = fs->fs_bsize; 882 if (i + fs->fs_frag > blks) 883 size = (blks - i) * fs->fs_fsize; 884 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), 885 size, 0, 0); 886 bcopy(space, bp->b_data, (u_int)size); 887 space += size; 888 if (waitfor == MNT_WAIT) 889 error = bwrite(bp); 890 else 891 bawrite(bp); 892 } 893 return (error); 894 } 895