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