ffs_vfsops.c revision 18104
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.40 1996/08/21 21:56:09 dyson Exp $ 35 */ 36 37#include "opt_quota.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/namei.h> 42#include <sys/proc.h> 43#include <sys/kernel.h> 44#include <sys/vnode.h> 45#include <sys/socket.h> 46#include <sys/mount.h> 47#include <sys/buf.h> 48#include <sys/mbuf.h> 49#include <sys/file.h> 50#include <sys/disklabel.h> 51#include <sys/ioctl.h> 52#include <sys/errno.h> 53#include <sys/malloc.h> 54 55#include <miscfs/specfs/specdev.h> 56 57#include <ufs/ufs/quota.h> 58#include <ufs/ufs/ufsmount.h> 59#include <ufs/ufs/inode.h> 60#include <ufs/ufs/ufs_extern.h> 61 62#include <ufs/ffs/fs.h> 63#include <ufs/ffs/ffs_extern.h> 64 65#include <vm/vm.h> 66#include <vm/vm_param.h> 67#include <vm/vm_prot.h> 68#include <vm/vm_page.h> 69#include <vm/vm_object.h> 70#include <vm/vm_extern.h> 71 72static int ffs_sbupdate __P((struct ufsmount *, int)); 73static int ffs_reload __P((struct mount *,struct ucred *,struct proc *)); 74static int ffs_oldfscompat __P((struct fs *)); 75static int ffs_mount __P((struct mount *, 76 char *, caddr_t, struct nameidata *, struct proc *)); 77 78struct vfsops ufs_vfsops = { 79 ffs_mount, 80 ufs_start, 81 ffs_unmount, 82 ufs_root, 83 ufs_quotactl, 84 ffs_statfs, 85 ffs_sync, 86 ffs_vget, 87 ffs_fhtovp, 88 ffs_vptofh, 89 ffs_init, 90}; 91 92VFS_SET(ufs_vfsops, ufs, MOUNT_UFS, 0); 93 94extern u_long nextgennumber; 95 96 97/* 98 * ffs_mount 99 * 100 * Called when mounting local physical media 101 * 102 * PARAMETERS: 103 * mountroot 104 * mp mount point structure 105 * path NULL (flag for root mount!!!) 106 * data <unused> 107 * ndp <unused> 108 * p process (user credentials check [statfs]) 109 * 110 * mount 111 * mp mount point structure 112 * path path to mount point 113 * data pointer to argument struct in user space 114 * ndp mount point namei() return (used for 115 * credentials on reload), reused to look 116 * up block device. 117 * p process (user credentials check) 118 * 119 * RETURNS: 0 Success 120 * !0 error number (errno.h) 121 * 122 * LOCK STATE: 123 * 124 * ENTRY 125 * mount point is locked 126 * EXIT 127 * mount point is locked 128 * 129 * NOTES: 130 * A NULL path can be used for a flag since the mount 131 * system call will fail with EFAULT in copyinstr in 132 * namei() if it is a genuine NULL from the user. 133 */ 134static int 135ffs_mount( mp, path, data, ndp, p) 136 register struct mount *mp; /* mount struct pointer*/ 137 char *path; /* path to mount point*/ 138 caddr_t data; /* arguments to FS specific mount*/ 139 struct nameidata *ndp; /* mount point credentials*/ 140 struct proc *p; /* process requesting mount*/ 141{ 142 u_int size; 143 int err = 0; 144 struct vnode *devvp; 145 146 struct ufs_args args; 147 struct ufsmount *ump = 0; 148 register struct fs *fs; 149 int flags; 150 151 /* 152 * Use NULL path to flag a root mount 153 */ 154 if( path == NULL) { 155 /* 156 *** 157 * Mounting root file system 158 *** 159 */ 160 161 /* Get vnode for root device*/ 162 if( bdevvp( rootdev, &rootvp)) 163 panic("ffs_mountroot: can't setup bdevvp for root"); 164 165 /* 166 * FS specific handling 167 */ 168 mp->mnt_flag |= MNT_RDONLY; /* XXX globally applicable?*/ 169 170 /* 171 * Attempt mount 172 */ 173 if( ( err = ffs_mountfs(rootvp, mp, p)) != 0) { 174 /* fs specific cleanup (if any)*/ 175 goto error_1; 176 } 177 178 goto dostatfs; /* success*/ 179 180 } 181 182 /* 183 *** 184 * Mounting non-root file system or updating a file system 185 *** 186 */ 187 188 /* copy in user arguments*/ 189 err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); 190 if (err) 191 goto error_1; /* can't get arguments*/ 192 193 /* 194 * If updating, check whether changing from read-only to 195 * read/write; if there is no device name, that's all we do. 196 */ 197 if (mp->mnt_flag & MNT_UPDATE) { 198 ump = VFSTOUFS(mp); 199 fs = ump->um_fs; 200 err = 0; 201 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 202 flags = WRITECLOSE; 203 if (mp->mnt_flag & MNT_FORCE) 204 flags |= FORCECLOSE; 205 if (vfs_busy(mp)) { 206 err = EBUSY; 207 goto error_1; 208 } 209 err = ffs_flushfiles(mp, flags, p); 210 vfs_unbusy(mp); 211 } 212 if (!err && (mp->mnt_flag & MNT_RELOAD)) 213 err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); 214 if (err) { 215 goto error_1; 216 } 217 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { 218 if (!fs->fs_clean) { 219 if (mp->mnt_flag & MNT_FORCE) { 220 printf("WARNING: %s was not properly dismounted.\n",fs->fs_fsmnt); 221 } else { 222 printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck.\n", 223 fs->fs_fsmnt); 224 err = EPERM; 225 goto error_1; 226 } 227 } 228 fs->fs_ronly = 0; 229 } 230 if (fs->fs_ronly == 0) { 231 fs->fs_clean = 0; 232 ffs_sbupdate(ump, MNT_WAIT); 233 } 234 /* if not updating name...*/ 235 if (args.fspec == 0) { 236 /* 237 * Process export requests. Jumping to "success" 238 * will return the vfs_export() error code. 239 */ 240 err = vfs_export(mp, &ump->um_export, &args.export); 241 goto success; 242 } 243 } 244 245 /* 246 * Not an update, or updating the name: look up the name 247 * and verify that it refers to a sensible block device. 248 */ 249 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 250 err = namei(ndp); 251 if (err) { 252 /* can't get devvp!*/ 253 goto error_1; 254 } 255 256 devvp = ndp->ni_vp; 257 258 if (devvp->v_type != VBLK) { 259 err = ENOTBLK; 260 goto error_2; 261 } 262 if (major(devvp->v_rdev) >= nblkdev) { 263 err = ENXIO; 264 goto error_2; 265 } 266 if (mp->mnt_flag & MNT_UPDATE) { 267 /* 268 ******************** 269 * UPDATE 270 ******************** 271 */ 272 273 if (devvp != ump->um_devvp) 274 err = EINVAL; /* needs translation */ 275 else 276 vrele(devvp); 277 /* 278 * Update device name only on success 279 */ 280 if( !err) { 281 /* Save "mounted from" info for mount point (NULL pad)*/ 282 copyinstr( args.fspec, 283 mp->mnt_stat.f_mntfromname, 284 MNAMELEN - 1, 285 &size); 286 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 287 } 288 } else { 289 /* 290 ******************** 291 * NEW MOUNT 292 ******************** 293 */ 294 295 /* 296 * Since this is a new mount, we want the names for 297 * the device and the mount point copied in. If an 298 * error occurs, the mountpoint is discarded by the 299 * upper level code. 300 */ 301 /* Save "last mounted on" info for mount point (NULL pad)*/ 302 copyinstr( path, /* mount point*/ 303 mp->mnt_stat.f_mntonname, /* save area*/ 304 MNAMELEN - 1, /* max size*/ 305 &size); /* real size*/ 306 bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 307 308 /* Save "mounted from" info for mount point (NULL pad)*/ 309 copyinstr( args.fspec, /* device name*/ 310 mp->mnt_stat.f_mntfromname, /* save area*/ 311 MNAMELEN - 1, /* max size*/ 312 &size); /* real size*/ 313 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 314 315 err = ffs_mountfs(devvp, mp, p); 316 } 317 if (err) { 318 goto error_2; 319 } 320 321dostatfs: 322 /* 323 * Initialize FS stat information in mount struct; uses both 324 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname 325 * 326 * This code is common to root and non-root mounts 327 */ 328 (void)VFS_STATFS(mp, &mp->mnt_stat, p); 329 330 goto success; 331 332 333error_2: /* error with devvp held*/ 334 335 /* release devvp before failing*/ 336 vrele(devvp); 337 338error_1: /* no state to back out*/ 339 340success: 341 return( err); 342} 343 344 345/* 346 * Reload all incore data for a filesystem (used after running fsck on 347 * the root filesystem and finding things to fix). The filesystem must 348 * be mounted read-only. 349 * 350 * Things to do to update the mount: 351 * 1) invalidate all cached meta-data. 352 * 2) re-read superblock from disk. 353 * 3) re-read summary information from disk. 354 * 4) invalidate all inactive vnodes. 355 * 5) invalidate all cached file data. 356 * 6) re-read inode data for all active vnodes. 357 */ 358static int 359ffs_reload(mp, cred, p) 360 register struct mount *mp; 361 struct ucred *cred; 362 struct proc *p; 363{ 364 register struct vnode *vp, *nvp, *devvp; 365 struct inode *ip; 366 struct csum *space; 367 struct buf *bp; 368 struct fs *fs; 369 int i, blks, size, error; 370 371 if ((mp->mnt_flag & MNT_RDONLY) == 0) 372 return (EINVAL); 373 /* 374 * Step 1: invalidate all cached meta-data. 375 */ 376 devvp = VFSTOUFS(mp)->um_devvp; 377 if (vinvalbuf(devvp, 0, cred, p, 0, 0)) 378 panic("ffs_reload: dirty1"); 379 /* 380 * Step 2: re-read superblock from disk. 381 */ 382 error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp); 383 if (error) 384 return (error); 385 fs = (struct fs *)bp->b_data; 386 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 387 fs->fs_bsize < sizeof(struct fs)) { 388 brelse(bp); 389 return (EIO); /* XXX needs translation */ 390 } 391 fs = VFSTOUFS(mp)->um_fs; 392 bcopy(&fs->fs_csp[0], &((struct fs *)bp->b_data)->fs_csp[0], 393 sizeof(fs->fs_csp)); 394 bcopy(bp->b_data, fs, (u_int)fs->fs_sbsize); 395 if (fs->fs_sbsize < SBSIZE) 396 bp->b_flags |= B_INVAL; 397 brelse(bp); 398 ffs_oldfscompat(fs); 399 /* 400 * Step 3: re-read summary information from disk. 401 */ 402 blks = howmany(fs->fs_cssize, fs->fs_fsize); 403 space = fs->fs_csp[0]; 404 for (i = 0; i < blks; i += fs->fs_frag) { 405 size = fs->fs_bsize; 406 if (i + fs->fs_frag > blks) 407 size = (blks - i) * fs->fs_fsize; 408 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 409 NOCRED, &bp); 410 if (error) 411 return (error); 412 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size); 413 brelse(bp); 414 } 415loop: 416 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 417 nvp = vp->v_mntvnodes.le_next; 418 /* 419 * Step 4: invalidate all inactive vnodes. 420 */ 421 if (vp->v_usecount == 0) { 422 vgone(vp); 423 continue; 424 } 425 /* 426 * Step 5: invalidate all cached file data. 427 */ 428 if (vget(vp, 1)) 429 goto loop; 430 if (vinvalbuf(vp, 0, cred, p, 0, 0)) 431 panic("ffs_reload: dirty2"); 432 /* 433 * Step 6: re-read inode data for all active vnodes. 434 */ 435 ip = VTOI(vp); 436 error = 437 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 438 (int)fs->fs_bsize, NOCRED, &bp); 439 if (error) { 440 vput(vp); 441 return (error); 442 } 443 ip->i_din = *((struct dinode *)bp->b_data + 444 ino_to_fsbo(fs, ip->i_number)); 445 brelse(bp); 446 vput(vp); 447 if (vp->v_mount != mp) 448 goto loop; 449 } 450 return (0); 451} 452 453/* 454 * Common code for mount and mountroot 455 */ 456int 457ffs_mountfs(devvp, mp, p) 458 register struct vnode *devvp; 459 struct mount *mp; 460 struct proc *p; 461{ 462 register struct ufsmount *ump; 463 struct buf *bp; 464 register struct fs *fs; 465 dev_t dev = devvp->v_rdev; 466 struct partinfo dpart; 467 caddr_t base, space; 468 int havepart = 0, blks; 469 int error, i, size; 470 int ronly; 471 u_int strsize; 472 int ncount; 473 474 /* 475 * Disallow multiple mounts of the same device. 476 * Disallow mounting of a device that is currently in use 477 * (except for root, which might share swap device for miniroot). 478 * Flush out any old buffers remaining from a previous use. 479 */ 480 error = vfs_mountedon(devvp); 481 if (error) 482 return (error); 483 ncount = vcount(devvp); 484 if (devvp->v_object) 485 ncount -= 1; 486 if (ncount > 1 && devvp != rootvp) 487 return (EBUSY); 488 error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0); 489 if (error) 490 return (error); 491 492 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 493 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 494 if (error) 495 return (error); 496 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 497 size = DEV_BSIZE; 498 else { 499 havepart = 1; 500 size = dpart.disklab->d_secsize; 501 } 502 503 bp = NULL; 504 ump = NULL; 505 error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp); 506 if (error) 507 goto out; 508 fs = (struct fs *)bp->b_data; 509 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 510 fs->fs_bsize < sizeof(struct fs)) { 511 error = EINVAL; /* XXX needs translation */ 512 goto out; 513 } 514 if (!fs->fs_clean) { 515 if (ronly || (mp->mnt_flag & MNT_FORCE)) { 516 printf("WARNING: %s was not properly dismounted.\n",fs->fs_fsmnt); 517 } else { 518 printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck.\n",fs->fs_fsmnt); 519 error = EPERM; 520 goto out; 521 } 522 } 523 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 524 bzero((caddr_t)ump, sizeof *ump); 525 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, 526 M_WAITOK); 527 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize); 528 if (fs->fs_sbsize < SBSIZE) 529 bp->b_flags |= B_INVAL; 530 brelse(bp); 531 bp = NULL; 532 fs = ump->um_fs; 533 fs->fs_ronly = ronly; 534 if (ronly == 0) { 535 fs->fs_fmod = 1; 536 fs->fs_clean = 0; 537 } 538 blks = howmany(fs->fs_cssize, fs->fs_fsize); 539 base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT, 540 M_WAITOK); 541 for (i = 0; i < blks; i += fs->fs_frag) { 542 size = fs->fs_bsize; 543 if (i + fs->fs_frag > blks) 544 size = (blks - i) * fs->fs_fsize; 545 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 546 NOCRED, &bp); 547 if (error) { 548 free(base, M_UFSMNT); 549 goto out; 550 } 551 bcopy(bp->b_data, space, (u_int)size); 552 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 553 space += size; 554 brelse(bp); 555 bp = NULL; 556 } 557 mp->mnt_data = (qaddr_t)ump; 558 mp->mnt_stat.f_fsid.val[0] = (long)dev; 559 mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS; 560 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 561 mp->mnt_flag |= MNT_LOCAL; 562 ump->um_mountp = mp; 563 ump->um_dev = dev; 564 ump->um_devvp = devvp; 565 ump->um_nindir = fs->fs_nindir; 566 ump->um_bptrtodb = fs->fs_fsbtodb; 567 ump->um_seqinc = fs->fs_frag; 568 for (i = 0; i < MAXQUOTAS; i++) 569 ump->um_quotas[i] = NULLVP; 570 devvp->v_specflags |= SI_MOUNTEDON; 571 ffs_oldfscompat(fs); 572 573 /* 574 * Set FS local "last mounted on" information (NULL pad) 575 */ 576 copystr( mp->mnt_stat.f_mntonname, /* mount point*/ 577 fs->fs_fsmnt, /* copy area*/ 578 sizeof(fs->fs_fsmnt) - 1, /* max size*/ 579 &strsize); /* real size*/ 580 bzero( fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize); 581 582 if( mp->mnt_flag & MNT_ROOTFS) { 583 /* 584 * Root mount; update timestamp in mount structure. 585 * this will be used by the common root mount code 586 * to update the system clock. 587 */ 588 mp->mnt_time = fs->fs_time; 589 } 590 if (ronly == 0) 591 ffs_sbupdate(ump, MNT_WAIT); 592 /* 593 * Only VMIO the backing device if the backing device is a real 594 * block device. This excludes the original MFS implementation. 595 * Note that it is optional that the backing device be VMIOed. This 596 * increases the opportunity for metadata caching. 597 */ 598 if ((devvp->v_type == VBLK) && (major(devvp->v_rdev) < nblkdev)) { 599 vfs_object_create(devvp, p, p->p_ucred, 0); 600 } 601 return (0); 602out: 603 if (bp) 604 brelse(bp); 605 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 606 if (ump) { 607 free(ump->um_fs, M_UFSMNT); 608 free(ump, M_UFSMNT); 609 mp->mnt_data = (qaddr_t)0; 610 } 611 return (error); 612} 613 614/* 615 * Sanity checks for old file systems. 616 * 617 * XXX - goes away some day. 618 */ 619static int 620ffs_oldfscompat(fs) 621 struct fs *fs; 622{ 623 624 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ 625 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ 626 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 627 fs->fs_nrpos = 8; /* XXX */ 628 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 629#if 0 630 int i; /* XXX */ 631 quad_t sizepb = fs->fs_bsize; /* XXX */ 632 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ 633 for (i = 0; i < NIADDR; i++) { /* XXX */ 634 sizepb *= NINDIR(fs); /* XXX */ 635 fs->fs_maxfilesize += sizepb; /* XXX */ 636 } /* XXX */ 637#endif 638 fs->fs_maxfilesize = (u_quad_t) 1LL << 39; 639 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ 640 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ 641 } /* XXX */ 642 return (0); 643} 644 645/* 646 * unmount system call 647 */ 648int 649ffs_unmount(mp, mntflags, p) 650 struct mount *mp; 651 int mntflags; 652 struct proc *p; 653{ 654 register struct ufsmount *ump; 655 register struct fs *fs; 656 int error, flags, ronly; 657 658 flags = 0; 659 if (mntflags & MNT_FORCE) { 660 flags |= FORCECLOSE; 661 } 662 error = ffs_flushfiles(mp, flags, p); 663 if (error) 664 return (error); 665 ump = VFSTOUFS(mp); 666 fs = ump->um_fs; 667 ronly = fs->fs_ronly; 668 if (!ronly) { 669 fs->fs_clean = 1; 670 ffs_sbupdate(ump, MNT_WAIT); 671 } 672 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 673 674 VOP_LOCK(ump->um_devvp); 675 vnode_pager_uncache(ump->um_devvp); 676 VOP_UNLOCK(ump->um_devvp); 677 678 error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, 679 NOCRED, p); 680 681 vrele(ump->um_devvp); 682 683 free(fs->fs_csp[0], M_UFSMNT); 684 free(fs, M_UFSMNT); 685 free(ump, M_UFSMNT); 686 mp->mnt_data = (qaddr_t)0; 687 mp->mnt_flag &= ~MNT_LOCAL; 688 return (error); 689} 690 691/* 692 * Flush out all the files in a filesystem. 693 */ 694int 695ffs_flushfiles(mp, flags, p) 696 register struct mount *mp; 697 int flags; 698 struct proc *p; 699{ 700 register struct ufsmount *ump; 701 int error; 702 703 if (!doforce) 704 flags &= ~FORCECLOSE; 705 ump = VFSTOUFS(mp); 706#ifdef QUOTA 707 if (mp->mnt_flag & MNT_QUOTA) { 708 int i; 709 error = vflush(mp, NULLVP, SKIPSYSTEM|flags); 710 if (error) 711 return (error); 712 for (i = 0; i < MAXQUOTAS; i++) { 713 if (ump->um_quotas[i] == NULLVP) 714 continue; 715 quotaoff(p, mp, i); 716 } 717 /* 718 * Here we fall through to vflush again to ensure 719 * that we have gotten rid of all the system vnodes. 720 */ 721 } 722#endif 723 error = vflush(mp, NULLVP, flags); 724 return (error); 725} 726 727/* 728 * Get file system statistics. 729 */ 730int 731ffs_statfs(mp, sbp, p) 732 struct mount *mp; 733 register struct statfs *sbp; 734 struct proc *p; 735{ 736 register struct ufsmount *ump; 737 register struct fs *fs; 738 739 ump = VFSTOUFS(mp); 740 fs = ump->um_fs; 741 if (fs->fs_magic != FS_MAGIC) 742 panic("ffs_statfs"); 743 sbp->f_type = MOUNT_UFS; 744 sbp->f_bsize = fs->fs_fsize; 745 sbp->f_iosize = fs->fs_bsize; 746 sbp->f_blocks = fs->fs_dsize; 747 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 748 fs->fs_cstotal.cs_nffree; 749 sbp->f_bavail = freespace(fs, fs->fs_minfree); 750 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 751 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 752 if (sbp != &mp->mnt_stat) { 753 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 754 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 755 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 756 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 757 } 758 return (0); 759} 760 761/* 762 * Go through the disk queues to initiate sandbagged IO; 763 * go through the inodes to write those that have been modified; 764 * initiate the writing of the super block if it has been modified. 765 * 766 * Note: we are always called with the filesystem marked `MPBUSY'. 767 */ 768int 769ffs_sync(mp, waitfor, cred, p) 770 struct mount *mp; 771 int waitfor; 772 struct ucred *cred; 773 struct proc *p; 774{ 775 register struct vnode *vp, *nvp; 776 register struct inode *ip; 777 register struct ufsmount *ump = VFSTOUFS(mp); 778 register struct fs *fs; 779 struct timeval tv; 780 int error, allerror = 0; 781 782 fs = ump->um_fs; 783 /* 784 * Write back modified superblock. 785 * Consistency check that the superblock 786 * is still in the buffer cache. 787 */ 788 if (fs->fs_fmod != 0) { 789 if (fs->fs_ronly != 0) { /* XXX */ 790 printf("fs = %s\n", fs->fs_fsmnt); 791 panic("update: rofs mod"); 792 } 793 fs->fs_fmod = 0; 794 fs->fs_time = time.tv_sec; 795 allerror = ffs_sbupdate(ump, waitfor); 796 } 797 /* 798 * Write back each (modified) inode. 799 */ 800loop: 801 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 802 /* 803 * If the vnode that we are about to sync is no longer 804 * associated with this mount point, start over. 805 */ 806 if (vp->v_mount != mp) 807 goto loop; 808 nvp = vp->v_mntvnodes.le_next; 809 if (VOP_ISLOCKED(vp)) 810 continue; 811 ip = VTOI(vp); 812 if ((((ip->i_flag & 813 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)) && 814 vp->v_dirtyblkhd.lh_first == NULL) 815 continue; 816 if (vp->v_type != VCHR) { 817 if (vget(vp, 1)) 818 goto loop; 819 error = VOP_FSYNC(vp, cred, waitfor, p); 820 if (error) 821 allerror = error; 822 vput(vp); 823 } else { 824 tv = time; 825 /* VOP_UPDATE(vp, &tv, &tv, waitfor == MNT_WAIT); */ 826 VOP_UPDATE(vp, &tv, &tv, 0); 827 } 828 } 829 /* 830 * Force stale file system control information to be flushed. 831 */ 832 error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p); 833 if (error) 834 allerror = error; 835#ifdef QUOTA 836 qsync(mp); 837#endif 838 return (allerror); 839} 840 841/* 842 * Look up a FFS dinode number to find its incore vnode, otherwise read it 843 * in from disk. If it is in core, wait for the lock bit to clear, then 844 * return the inode locked. Detection and handling of mount points must be 845 * done by the calling routine. 846 */ 847static int ffs_inode_hash_lock; 848 849int 850ffs_vget(mp, ino, vpp) 851 struct mount *mp; 852 ino_t ino; 853 struct vnode **vpp; 854{ 855 register struct fs *fs; 856 register struct inode *ip; 857 struct ufsmount *ump; 858 struct buf *bp; 859 struct vnode *vp; 860 dev_t dev; 861 int type, error; 862 863 ump = VFSTOUFS(mp); 864 dev = ump->um_dev; 865restart: 866 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 867 return (0); 868 869 /* 870 * Lock out the creation of new entries in the FFS hash table in 871 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate 872 * may occur! 873 */ 874 if (ffs_inode_hash_lock) { 875 while (ffs_inode_hash_lock) { 876 ffs_inode_hash_lock = -1; 877 tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0); 878 } 879 goto restart; 880 } 881 ffs_inode_hash_lock = 1; 882 883 /* 884 * If this MALLOC() is performed after the getnewvnode() 885 * it might block, leaving a vnode with a NULL v_data to be 886 * found by ffs_sync() if a sync happens to fire right then, 887 * which will cause a panic because ffs_sync() blindly 888 * dereferences vp->v_data (as well it should). 889 */ 890 type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */ 891 MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK); 892 893 /* Allocate a new vnode/inode. */ 894 error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp); 895 if (error) { 896 if (ffs_inode_hash_lock < 0) 897 wakeup(&ffs_inode_hash_lock); 898 ffs_inode_hash_lock = 0; 899 *vpp = NULL; 900 FREE(ip, type); 901 return (error); 902 } 903 bzero((caddr_t)ip, sizeof(struct inode)); 904 vp->v_data = ip; 905 ip->i_vnode = vp; 906 ip->i_fs = fs = ump->um_fs; 907 ip->i_dev = dev; 908 ip->i_number = ino; 909#ifdef QUOTA 910 { 911 int i; 912 for (i = 0; i < MAXQUOTAS; i++) 913 ip->i_dquot[i] = NODQUOT; 914 } 915#endif 916 /* 917 * Put it onto its hash chain and lock it so that other requests for 918 * this inode will block if they arrive while we are sleeping waiting 919 * for old data structures to be purged or for the contents of the 920 * disk portion of this inode to be read. 921 */ 922 ufs_ihashins(ip); 923 924 if (ffs_inode_hash_lock < 0) 925 wakeup(&ffs_inode_hash_lock); 926 ffs_inode_hash_lock = 0; 927 928 /* Read in the disk contents for the inode, copy into the inode. */ 929 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), 930 (int)fs->fs_bsize, NOCRED, &bp); 931 if (error) { 932 /* 933 * The inode does not contain anything useful, so it would 934 * be misleading to leave it on its hash chain. With mode 935 * still zero, it will be unlinked and returned to the free 936 * list by vput(). 937 */ 938 brelse(bp); 939 vput(vp); 940 *vpp = NULL; 941 return (error); 942 } 943 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 944 bqrelse(bp); 945 946 /* 947 * Initialize the vnode from the inode, check for aliases. 948 * Note that the underlying vnode may have changed. 949 */ 950 error = ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp); 951 if (error) { 952 vput(vp); 953 *vpp = NULL; 954 return (error); 955 } 956 /* 957 * Finish inode initialization now that aliasing has been resolved. 958 */ 959 ip->i_devvp = ump->um_devvp; 960 VREF(ip->i_devvp); 961 /* 962 * Set up a generation number for this inode if it does not 963 * already have one. This should only happen on old filesystems. 964 */ 965 if (ip->i_gen == 0) { 966 if (++nextgennumber < (u_long)time.tv_sec) 967 nextgennumber = time.tv_sec; 968 ip->i_gen = nextgennumber; 969 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 970 ip->i_flag |= IN_MODIFIED; 971 } 972 /* 973 * Ensure that uid and gid are correct. This is a temporary 974 * fix until fsck has been changed to do the update. 975 */ 976 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 977 ip->i_uid = ip->i_din.di_ouid; /* XXX */ 978 ip->i_gid = ip->i_din.di_ogid; /* XXX */ 979 } /* XXX */ 980 981 *vpp = vp; 982 return (0); 983} 984 985/* 986 * File handle to vnode 987 * 988 * Have to be really careful about stale file handles: 989 * - check that the inode number is valid 990 * - call ffs_vget() to get the locked inode 991 * - check for an unallocated inode (i_mode == 0) 992 * - check that the given client host has export rights and return 993 * those rights via. exflagsp and credanonp 994 */ 995int 996ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 997 register struct mount *mp; 998 struct fid *fhp; 999 struct mbuf *nam; 1000 struct vnode **vpp; 1001 int *exflagsp; 1002 struct ucred **credanonp; 1003{ 1004 register struct ufid *ufhp; 1005 struct fs *fs; 1006 1007 ufhp = (struct ufid *)fhp; 1008 fs = VFSTOUFS(mp)->um_fs; 1009 if (ufhp->ufid_ino < ROOTINO || 1010 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 1011 return (ESTALE); 1012 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 1013} 1014 1015/* 1016 * Vnode pointer to File handle 1017 */ 1018/* ARGSUSED */ 1019int 1020ffs_vptofh(vp, fhp) 1021 struct vnode *vp; 1022 struct fid *fhp; 1023{ 1024 register struct inode *ip; 1025 register struct ufid *ufhp; 1026 1027 ip = VTOI(vp); 1028 ufhp = (struct ufid *)fhp; 1029 ufhp->ufid_len = sizeof(struct ufid); 1030 ufhp->ufid_ino = ip->i_number; 1031 ufhp->ufid_gen = ip->i_gen; 1032 return (0); 1033} 1034 1035/* 1036 * Write a superblock and associated information back to disk. 1037 */ 1038static int 1039ffs_sbupdate(mp, waitfor) 1040 struct ufsmount *mp; 1041 int waitfor; 1042{ 1043 register struct fs *fs = mp->um_fs; 1044 register struct buf *bp; 1045 int blks; 1046 caddr_t space; 1047 int i, size, error = 0; 1048 1049 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0); 1050 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize); 1051 /* Restore compatibility to old file systems. XXX */ 1052 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 1053 ((struct fs *)bp->b_data)->fs_nrpos = -1; /* XXX */ 1054 if (waitfor == MNT_WAIT) 1055 error = bwrite(bp); 1056 else 1057 bawrite(bp); 1058 blks = howmany(fs->fs_cssize, fs->fs_fsize); 1059 space = (caddr_t)fs->fs_csp[0]; 1060 for (i = 0; i < blks; i += fs->fs_frag) { 1061 size = fs->fs_bsize; 1062 if (i + fs->fs_frag > blks) 1063 size = (blks - i) * fs->fs_fsize; 1064 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), 1065 size, 0, 0); 1066 bcopy(space, bp->b_data, (u_int)size); 1067 space += size; 1068 if (waitfor == MNT_WAIT) 1069 error = bwrite(bp); 1070 else 1071 bawrite(bp); 1072 } 1073 return (error); 1074} 1075