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