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