ffs_vfsops.c revision 2112
1/* 2 * Copyright (c) 1989, 1991, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94 34 * $Id: ffs_vfsops.c,v 1.3 1994/08/02 07:54:24 davidg Exp $ 35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/namei.h> 40#include <sys/proc.h> 41#include <sys/kernel.h> 42#include <sys/vnode.h> 43#include <sys/socket.h> 44#include <sys/mount.h> 45#include <sys/buf.h> 46#include <sys/mbuf.h> 47#include <sys/file.h> 48#include <sys/disklabel.h> 49#include <sys/ioctl.h> 50#include <sys/errno.h> 51#include <sys/malloc.h> 52 53#include <miscfs/specfs/specdev.h> 54 55#include <ufs/ufs/quota.h> 56#include <ufs/ufs/ufsmount.h> 57#include <ufs/ufs/inode.h> 58#include <ufs/ufs/ufs_extern.h> 59 60#include <ufs/ffs/fs.h> 61#include <ufs/ffs/ffs_extern.h> 62 63int ffs_sbupdate __P((struct ufsmount *, int)); 64 65struct vfsops ufs_vfsops = { 66 ffs_mount, 67 ufs_start, 68 ffs_unmount, 69 ufs_root, 70 ufs_quotactl, 71 ffs_statfs, 72 ffs_sync, 73 ffs_vget, 74 ffs_fhtovp, 75 ffs_vptofh, 76 ffs_init, 77}; 78 79extern u_long nextgennumber; 80 81/* 82 * Called by main() when ufs is going to be mounted as root. 83 * 84 * Name is updated by mount(8) after booting. 85 */ 86#define ROOTNAME "root_device" 87 88int 89ffs_mountroot() 90{ 91 register struct fs *fs; 92 register struct mount *mp; 93 struct proc *p = curproc; /* XXX */ 94 struct ufsmount *ump; 95 u_int size; 96 int error; 97 98 /* 99 * Get vnodes for swapdev and rootdev. 100 */ 101 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) 102 panic("ffs_mountroot: can't setup bdevvp's"); 103 104 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 105 bzero((char *)mp, (u_long)sizeof(struct mount)); 106 mp->mnt_op = &ufs_vfsops; 107 mp->mnt_flag = MNT_RDONLY; 108 if (error = ffs_mountfs(rootvp, mp, p)) { 109 free(mp, M_MOUNT); 110 return (error); 111 } 112 if (error = vfs_lock(mp)) { 113 (void)ffs_unmount(mp, 0, p); 114 free(mp, M_MOUNT); 115 return (error); 116 } 117 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 118 mp->mnt_flag |= MNT_ROOTFS; 119 mp->mnt_vnodecovered = NULLVP; 120 ump = VFSTOUFS(mp); 121 fs = ump->um_fs; 122 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 123 fs->fs_fsmnt[0] = '/'; 124 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 125 MNAMELEN); 126 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 127 &size); 128 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 129 (void)ffs_statfs(mp, &mp->mnt_stat, p); 130 vfs_unlock(mp); 131 inittodr(fs->fs_time); 132 return (0); 133} 134 135/* 136 * VFS Operations. 137 * 138 * mount system call 139 */ 140int 141ffs_mount(mp, path, data, ndp, p) 142 register struct mount *mp; 143 char *path; 144 caddr_t data; 145 struct nameidata *ndp; 146 struct proc *p; 147{ 148 struct vnode *devvp; 149 struct ufs_args args; 150 struct ufsmount *ump = 0; 151 register struct fs *fs; 152 u_int size; 153 int error, flags; 154 155 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 156 return (error); 157 /* 158 * If updating, check whether changing from read-only to 159 * read/write; if there is no device name, that's all we do. 160 */ 161 if (mp->mnt_flag & MNT_UPDATE) { 162 ump = VFSTOUFS(mp); 163 fs = ump->um_fs; 164 error = 0; 165 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 166 flags = WRITECLOSE; 167 if (mp->mnt_flag & MNT_FORCE) 168 flags |= FORCECLOSE; 169 if (vfs_busy(mp)) 170 return (EBUSY); 171 error = ffs_flushfiles(mp, flags, p); 172 vfs_unbusy(mp); 173 } 174 if (!error && (mp->mnt_flag & MNT_RELOAD)) 175 error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); 176 if (error) 177 return (error); 178 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) 179 fs->fs_ronly = 0; 180 if (args.fspec == 0) { 181 /* 182 * Process export requests. 183 */ 184 return (vfs_export(mp, &ump->um_export, &args.export)); 185 } 186 } 187 /* 188 * Not an update, or updating the name: look up the name 189 * and verify that it refers to a sensible block device. 190 */ 191 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 192 if (error = namei(ndp)) 193 return (error); 194 devvp = ndp->ni_vp; 195 196 if (devvp->v_type != VBLK) { 197 vrele(devvp); 198 return (ENOTBLK); 199 } 200 if (major(devvp->v_rdev) >= nblkdev) { 201 vrele(devvp); 202 return (ENXIO); 203 } 204 if ((mp->mnt_flag & MNT_UPDATE) == 0) 205 error = ffs_mountfs(devvp, mp, p); 206 else { 207 if (devvp != ump->um_devvp) 208 error = EINVAL; /* needs translation */ 209 else 210 vrele(devvp); 211 } 212 if (error) { 213 vrele(devvp); 214 return (error); 215 } 216 ump = VFSTOUFS(mp); 217 fs = ump->um_fs; 218 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 219 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 220 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 221 MNAMELEN); 222 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 223 &size); 224 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 225 (void)ffs_statfs(mp, &mp->mnt_stat, p); 226 return (0); 227} 228 229/* 230 * Reload all incore data for a filesystem (used after running fsck on 231 * the root filesystem and finding things to fix). The filesystem must 232 * be mounted read-only. 233 * 234 * Things to do to update the mount: 235 * 1) invalidate all cached meta-data. 236 * 2) re-read superblock from disk. 237 * 3) re-read summary information from disk. 238 * 4) invalidate all inactive vnodes. 239 * 5) invalidate all cached file data. 240 * 6) re-read inode data for all active vnodes. 241 */ 242int 243ffs_reload(mountp, cred, p) 244 register struct mount *mountp; 245 struct ucred *cred; 246 struct proc *p; 247{ 248 register struct vnode *vp, *nvp, *devvp; 249 struct inode *ip; 250 struct csum *space; 251 struct buf *bp; 252 struct fs *fs; 253 int i, blks, size, error; 254 255 if ((mountp->mnt_flag & MNT_RDONLY) == 0) 256 return (EINVAL); 257 /* 258 * Step 1: invalidate all cached meta-data. 259 */ 260 devvp = VFSTOUFS(mountp)->um_devvp; 261 if (vinvalbuf(devvp, 0, cred, p, 0, 0)) 262 panic("ffs_reload: dirty1"); 263 /* 264 * Step 2: re-read superblock from disk. 265 */ 266 if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) 267 return (error); 268 fs = (struct fs *)bp->b_data; 269 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 270 fs->fs_bsize < sizeof(struct fs)) { 271 brelse(bp); 272 return (EIO); /* XXX needs translation */ 273 } 274 fs = VFSTOUFS(mountp)->um_fs; 275 bcopy(&fs->fs_csp[0], &((struct fs *)bp->b_data)->fs_csp[0], 276 sizeof(fs->fs_csp)); 277 bcopy(bp->b_data, fs, (u_int)fs->fs_sbsize); 278 if (fs->fs_sbsize < SBSIZE) 279 bp->b_flags |= B_INVAL; 280 brelse(bp); 281 ffs_oldfscompat(fs); 282 /* 283 * Step 3: re-read summary information from disk. 284 */ 285 blks = howmany(fs->fs_cssize, fs->fs_fsize); 286 space = fs->fs_csp[0]; 287 for (i = 0; i < blks; i += fs->fs_frag) { 288 size = fs->fs_bsize; 289 if (i + fs->fs_frag > blks) 290 size = (blks - i) * fs->fs_fsize; 291 if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 292 NOCRED, &bp)) 293 return (error); 294 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size); 295 brelse(bp); 296 } 297loop: 298 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 299 nvp = vp->v_mntvnodes.le_next; 300 /* 301 * Step 4: invalidate all inactive vnodes. 302 */ 303 if (vp->v_usecount == 0) { 304 vgone(vp); 305 continue; 306 } 307 /* 308 * Step 5: invalidate all cached file data. 309 */ 310 if (vget(vp, 1)) 311 goto loop; 312 if (vinvalbuf(vp, 0, cred, p, 0, 0)) 313 panic("ffs_reload: dirty2"); 314 /* 315 * Step 6: re-read inode data for all active vnodes. 316 */ 317 ip = VTOI(vp); 318 if (error = 319 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 320 (int)fs->fs_bsize, NOCRED, &bp)) { 321 vput(vp); 322 return (error); 323 } 324 ip->i_din = *((struct dinode *)bp->b_data + 325 ino_to_fsbo(fs, ip->i_number)); 326 brelse(bp); 327 vput(vp); 328 if (vp->v_mount != mountp) 329 goto loop; 330 } 331 return (0); 332} 333 334/* 335 * Common code for mount and mountroot 336 */ 337int 338ffs_mountfs(devvp, mp, p) 339 register struct vnode *devvp; 340 struct mount *mp; 341 struct proc *p; 342{ 343 register struct ufsmount *ump; 344 struct buf *bp; 345 register struct fs *fs; 346 dev_t dev = devvp->v_rdev; 347 struct partinfo dpart; 348 caddr_t base, space; 349 int havepart = 0, blks; 350 int error, i, size; 351 int ronly; 352 353 /* 354 * Disallow multiple mounts of the same device. 355 * Disallow mounting of a device that is currently in use 356 * (except for root, which might share swap device for miniroot). 357 * Flush out any old buffers remaining from a previous use. 358 */ 359 if (error = vfs_mountedon(devvp)) 360 return (error); 361 if (vcount(devvp) > 1 && devvp != rootvp) 362 return (EBUSY); 363 if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) 364 return (error); 365 366 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 367 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) 368 return (error); 369 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 370 size = DEV_BSIZE; 371 else { 372 havepart = 1; 373 size = dpart.disklab->d_secsize; 374 } 375 376 bp = NULL; 377 ump = NULL; 378 if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) 379 goto out; 380 fs = (struct fs *)bp->b_data; 381 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 382 fs->fs_bsize < sizeof(struct fs)) { 383 error = EINVAL; /* XXX needs translation */ 384 goto out; 385 } 386 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 387 bzero((caddr_t)ump, sizeof *ump); 388 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, 389 M_WAITOK); 390 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize); 391 if (fs->fs_sbsize < SBSIZE) 392 bp->b_flags |= B_INVAL; 393 brelse(bp); 394 bp = NULL; 395 fs = ump->um_fs; 396 fs->fs_ronly = ronly; 397 if (ronly == 0) 398 fs->fs_fmod = 1; 399 blks = howmany(fs->fs_cssize, fs->fs_fsize); 400 base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT, 401 M_WAITOK); 402 for (i = 0; i < blks; i += fs->fs_frag) { 403 size = fs->fs_bsize; 404 if (i + fs->fs_frag > blks) 405 size = (blks - i) * fs->fs_fsize; 406 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 407 NOCRED, &bp); 408 if (error) { 409 free(base, M_UFSMNT); 410 goto out; 411 } 412 bcopy(bp->b_data, space, (u_int)size); 413 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 414 space += size; 415 brelse(bp); 416 bp = NULL; 417 } 418 mp->mnt_data = (qaddr_t)ump; 419 mp->mnt_stat.f_fsid.val[0] = (long)dev; 420 mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS; 421 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 422 mp->mnt_flag |= MNT_LOCAL; 423 ump->um_mountp = mp; 424 ump->um_dev = dev; 425 ump->um_devvp = devvp; 426 ump->um_nindir = fs->fs_nindir; 427 ump->um_bptrtodb = fs->fs_fsbtodb; 428 ump->um_seqinc = fs->fs_frag; 429 for (i = 0; i < MAXQUOTAS; i++) 430 ump->um_quotas[i] = NULLVP; 431 devvp->v_specflags |= SI_MOUNTEDON; 432 ffs_oldfscompat(fs); 433 return (0); 434out: 435 if (bp) 436 brelse(bp); 437 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 438 if (ump) { 439 free(ump->um_fs, M_UFSMNT); 440 free(ump, M_UFSMNT); 441 mp->mnt_data = (qaddr_t)0; 442 } 443 return (error); 444} 445 446/* 447 * Sanity checks for old file systems. 448 * 449 * XXX - goes away some day. 450 */ 451int 452ffs_oldfscompat(fs) 453 struct fs *fs; 454{ 455 int i; 456 457 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ 458 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ 459 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 460 fs->fs_nrpos = 8; /* XXX */ 461 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 462 quad_t sizepb = fs->fs_bsize; /* XXX */ 463 /* XXX */ 464 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ 465 for (i = 0; i < NIADDR; i++) { /* XXX */ 466 sizepb *= NINDIR(fs); /* XXX */ 467 fs->fs_maxfilesize += sizepb; /* XXX */ 468 } /* XXX */ 469 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ 470 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ 471 } /* XXX */ 472 return (0); 473} 474 475/* 476 * unmount system call 477 */ 478int 479ffs_unmount(mp, mntflags, p) 480 struct mount *mp; 481 int mntflags; 482 struct proc *p; 483{ 484 register struct ufsmount *ump; 485 register struct fs *fs; 486 int error, flags, ronly; 487 488 flags = 0; 489 if (mntflags & MNT_FORCE) { 490 if (mp->mnt_flag & MNT_ROOTFS) 491 return (EINVAL); 492 flags |= FORCECLOSE; 493 } 494 if (error = ffs_flushfiles(mp, flags, p)) 495 return (error); 496 ump = VFSTOUFS(mp); 497 fs = ump->um_fs; 498 ronly = !fs->fs_ronly; 499 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 500 error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, 501 NOCRED, p); 502 vrele(ump->um_devvp); 503 free(fs->fs_csp[0], M_UFSMNT); 504 free(fs, M_UFSMNT); 505 free(ump, M_UFSMNT); 506 mp->mnt_data = (qaddr_t)0; 507 mp->mnt_flag &= ~MNT_LOCAL; 508 return (error); 509} 510 511/* 512 * Flush out all the files in a filesystem. 513 */ 514int 515ffs_flushfiles(mp, flags, p) 516 register struct mount *mp; 517 int flags; 518 struct proc *p; 519{ 520 extern int doforce; 521 register struct ufsmount *ump; 522 int i, error; 523 524 if (!doforce) 525 flags &= ~FORCECLOSE; 526 ump = VFSTOUFS(mp); 527#ifdef QUOTA 528 if (mp->mnt_flag & MNT_QUOTA) { 529 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) 530 return (error); 531 for (i = 0; i < MAXQUOTAS; i++) { 532 if (ump->um_quotas[i] == NULLVP) 533 continue; 534 quotaoff(p, mp, i); 535 } 536 /* 537 * Here we fall through to vflush again to ensure 538 * that we have gotten rid of all the system vnodes. 539 */ 540 } 541#endif 542 error = vflush(mp, NULLVP, flags); 543 return (error); 544} 545 546/* 547 * Get file system statistics. 548 */ 549int 550ffs_statfs(mp, sbp, p) 551 struct mount *mp; 552 register struct statfs *sbp; 553 struct proc *p; 554{ 555 register struct ufsmount *ump; 556 register struct fs *fs; 557 558 ump = VFSTOUFS(mp); 559 fs = ump->um_fs; 560 if (fs->fs_magic != FS_MAGIC) 561 panic("ffs_statfs"); 562 sbp->f_type = MOUNT_UFS; 563 sbp->f_bsize = fs->fs_fsize; 564 sbp->f_iosize = fs->fs_bsize; 565 sbp->f_blocks = fs->fs_dsize; 566 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 567 fs->fs_cstotal.cs_nffree; 568 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 569 (fs->fs_dsize - sbp->f_bfree); 570 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 571 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 572 if (sbp != &mp->mnt_stat) { 573 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 574 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 575 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 576 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 577 } 578 return (0); 579} 580 581/* 582 * Go through the disk queues to initiate sandbagged IO; 583 * go through the inodes to write those that have been modified; 584 * initiate the writing of the super block if it has been modified. 585 * 586 * Note: we are always called with the filesystem marked `MPBUSY'. 587 */ 588int 589ffs_sync(mp, waitfor, cred, p) 590 struct mount *mp; 591 int waitfor; 592 struct ucred *cred; 593 struct proc *p; 594{ 595 register struct vnode *vp; 596 register struct inode *ip; 597 register struct ufsmount *ump = VFSTOUFS(mp); 598 register struct fs *fs; 599 int error, allerror = 0; 600 601 fs = ump->um_fs; 602 /* 603 * Write back modified superblock. 604 * Consistency check that the superblock 605 * is still in the buffer cache. 606 */ 607 if (fs->fs_fmod != 0) { 608 if (fs->fs_ronly != 0) { /* XXX */ 609 printf("fs = %s\n", fs->fs_fsmnt); 610 panic("update: rofs mod"); 611 } 612 fs->fs_fmod = 0; 613 fs->fs_time = time.tv_sec; 614 allerror = ffs_sbupdate(ump, waitfor); 615 } 616 /* 617 * Write back each (modified) inode. 618 */ 619loop: 620 for (vp = mp->mnt_vnodelist.lh_first; 621 vp != NULL; 622 vp = vp->v_mntvnodes.le_next) { 623 /* 624 * If the vnode that we are about to sync is no longer 625 * associated with this mount point, start over. 626 */ 627 if (vp->v_mount != mp) 628 goto loop; 629 if (VOP_ISLOCKED(vp)) 630 continue; 631 ip = VTOI(vp); 632 if ((ip->i_flag & 633 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && 634 vp->v_dirtyblkhd.lh_first == NULL) 635 continue; 636 if (vget(vp, 1)) 637 goto loop; 638 if (error = VOP_FSYNC(vp, cred, waitfor, p)) 639 allerror = error; 640 vput(vp); 641 } 642 /* 643 * Force stale file system control information to be flushed. 644 */ 645 if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) 646 allerror = error; 647#ifdef QUOTA 648 qsync(mp); 649#endif 650 return (allerror); 651} 652 653/* 654 * Look up a FFS dinode number to find its incore vnode, otherwise read it 655 * in from disk. If it is in core, wait for the lock bit to clear, then 656 * return the inode locked. Detection and handling of mount points must be 657 * done by the calling routine. 658 */ 659int 660ffs_vget(mp, ino, vpp) 661 struct mount *mp; 662 ino_t ino; 663 struct vnode **vpp; 664{ 665 register struct fs *fs; 666 register struct inode *ip; 667 struct ufsmount *ump; 668 struct buf *bp; 669 struct vnode *vp; 670 dev_t dev; 671 int i, type, error; 672 673 ump = VFSTOUFS(mp); 674 dev = ump->um_dev; 675 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 676 return (0); 677 678 /* Allocate a new vnode/inode. */ 679 if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) { 680 *vpp = NULL; 681 return (error); 682 } 683 type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */ 684 MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK); 685 bzero((caddr_t)ip, sizeof(struct inode)); 686 vp->v_data = ip; 687 ip->i_vnode = vp; 688 ip->i_fs = fs = ump->um_fs; 689 ip->i_dev = dev; 690 ip->i_number = ino; 691#ifdef QUOTA 692 for (i = 0; i < MAXQUOTAS; i++) 693 ip->i_dquot[i] = NODQUOT; 694#endif 695 /* 696 * Put it onto its hash chain and lock it so that other requests for 697 * this inode will block if they arrive while we are sleeping waiting 698 * for old data structures to be purged or for the contents of the 699 * disk portion of this inode to be read. 700 */ 701 ufs_ihashins(ip); 702 703 /* Read in the disk contents for the inode, copy into the inode. */ 704 if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), 705 (int)fs->fs_bsize, NOCRED, &bp)) { 706 /* 707 * The inode does not contain anything useful, so it would 708 * be misleading to leave it on its hash chain. With mode 709 * still zero, it will be unlinked and returned to the free 710 * list by vput(). 711 */ 712 vput(vp); 713 brelse(bp); 714 *vpp = NULL; 715 return (error); 716 } 717 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 718 brelse(bp); 719 720 /* 721 * Initialize the vnode from the inode, check for aliases. 722 * Note that the underlying vnode may have changed. 723 */ 724 if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) { 725 vput(vp); 726 *vpp = NULL; 727 return (error); 728 } 729 /* 730 * Finish inode initialization now that aliasing has been resolved. 731 */ 732 ip->i_devvp = ump->um_devvp; 733 VREF(ip->i_devvp); 734 /* 735 * Set up a generation number for this inode if it does not 736 * already have one. This should only happen on old filesystems. 737 */ 738 if (ip->i_gen == 0) { 739 if (++nextgennumber < (u_long)time.tv_sec) 740 nextgennumber = time.tv_sec; 741 ip->i_gen = nextgennumber; 742 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 743 ip->i_flag |= IN_MODIFIED; 744 } 745 /* 746 * Ensure that uid and gid are correct. This is a temporary 747 * fix until fsck has been changed to do the update. 748 */ 749 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 750 ip->i_uid = ip->i_din.di_ouid; /* XXX */ 751 ip->i_gid = ip->i_din.di_ogid; /* XXX */ 752 } /* XXX */ 753 754 *vpp = vp; 755 return (0); 756} 757 758/* 759 * File handle to vnode 760 * 761 * Have to be really careful about stale file handles: 762 * - check that the inode number is valid 763 * - call ffs_vget() to get the locked inode 764 * - check for an unallocated inode (i_mode == 0) 765 * - check that the given client host has export rights and return 766 * those rights via. exflagsp and credanonp 767 */ 768int 769ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 770 register struct mount *mp; 771 struct fid *fhp; 772 struct mbuf *nam; 773 struct vnode **vpp; 774 int *exflagsp; 775 struct ucred **credanonp; 776{ 777 register struct ufid *ufhp; 778 struct fs *fs; 779 780 ufhp = (struct ufid *)fhp; 781 fs = VFSTOUFS(mp)->um_fs; 782 if (ufhp->ufid_ino < ROOTINO || 783 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 784 return (ESTALE); 785 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 786} 787 788/* 789 * Vnode pointer to File handle 790 */ 791/* ARGSUSED */ 792int 793ffs_vptofh(vp, fhp) 794 struct vnode *vp; 795 struct fid *fhp; 796{ 797 register struct inode *ip; 798 register struct ufid *ufhp; 799 800 ip = VTOI(vp); 801 ufhp = (struct ufid *)fhp; 802 ufhp->ufid_len = sizeof(struct ufid); 803 ufhp->ufid_ino = ip->i_number; 804 ufhp->ufid_gen = ip->i_gen; 805 return (0); 806} 807 808/* 809 * Write a superblock and associated information back to disk. 810 */ 811int 812ffs_sbupdate(mp, waitfor) 813 struct ufsmount *mp; 814 int waitfor; 815{ 816 register struct fs *fs = mp->um_fs; 817 register struct buf *bp; 818 int blks; 819 caddr_t space; 820 int i, size, error = 0; 821 822 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0); 823 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize); 824 /* Restore compatibility to old file systems. XXX */ 825 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 826 ((struct fs *)bp->b_data)->fs_nrpos = -1; /* XXX */ 827 if (waitfor == MNT_WAIT) 828 error = bwrite(bp); 829 else 830 bawrite(bp); 831 blks = howmany(fs->fs_cssize, fs->fs_fsize); 832 space = (caddr_t)fs->fs_csp[0]; 833 for (i = 0; i < blks; i += fs->fs_frag) { 834 size = fs->fs_bsize; 835 if (i + fs->fs_frag > blks) 836 size = (blks - i) * fs->fs_fsize; 837 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), 838 size, 0, 0); 839 bcopy(space, bp->b_data, (u_int)size); 840 space += size; 841 if (waitfor == MNT_WAIT) 842 error = bwrite(bp); 843 else 844 bawrite(bp); 845 } 846 return (error); 847} 848