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