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. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 30 * $FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.117.2.10 2002/06/23 22:34:52 iedowse Exp $ 31 */ 32 33 #include "opt_quota.h" 34 35 #include <sys/disk.h> 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/proc.h> 39 #include <sys/nlookup.h> 40 #include <sys/kernel.h> 41 #include <sys/vnode.h> 42 #include <sys/mount.h> 43 #include <sys/buf.h> 44 #include <sys/conf.h> 45 #include <sys/fcntl.h> 46 #include <sys/diskslice.h> 47 #include <sys/malloc.h> 48 49 #include "quota.h" 50 #include "ufsmount.h" 51 #include "inode.h" 52 #include "ufs_extern.h" 53 54 #include "fs.h" 55 #include "ffs_extern.h" 56 57 #include <vm/vm.h> 58 #include <vm/vm_page.h> 59 #include <vm/vm_zone.h> 60 61 #include <sys/buf2.h> 62 63 static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part"); 64 65 static int ffs_sbupdate (struct ufsmount *, int); 66 static int ffs_reload (struct mount *, struct ucred *); 67 static int ffs_oldfscompat (struct fs *); 68 static int ffs_mount (struct mount *, char *, caddr_t, struct ucred *); 69 static int ffs_init (struct vfsconf *); 70 71 static struct vfsops ufs_vfsops = { 72 .vfs_mount = ffs_mount, 73 .vfs_unmount = ffs_unmount, 74 .vfs_root = ufs_root, 75 .vfs_quotactl = ufs_quotactl, 76 .vfs_statfs = ffs_statfs, 77 .vfs_sync = ffs_sync, 78 .vfs_vget = ffs_vget, 79 .vfs_fhtovp = ffs_fhtovp, 80 .vfs_checkexp = ufs_check_export, 81 .vfs_vptofh = ffs_vptofh, 82 .vfs_init = ffs_init, 83 }; 84 85 VFS_SET(ufs_vfsops, ufs, 0); 86 MODULE_VERSION(ufs, 1); 87 88 extern struct vop_ops ffs_vnode_vops; 89 extern struct vop_ops ffs_spec_vops; 90 extern struct vop_ops ffs_fifo_vops; 91 92 /* 93 * ffs_mount 94 * 95 * Called when mounting local physical media 96 * 97 * PARAMETERS: 98 * mountroot 99 * mp mount point structure 100 * path NULL (flag for root mount!!!) 101 * data <unused> 102 * p process (user credentials check [statfs]) 103 * 104 * mount 105 * mp mount point structure 106 * path path to mount point 107 * data pointer to argument struct in user space 108 * p process (user credentials check) 109 * 110 * RETURNS: 0 Success 111 * !0 error number (errno.h) 112 * 113 * LOCK STATE: 114 * 115 * ENTRY 116 * mount point is locked 117 * EXIT 118 * mount point is locked 119 * 120 * NOTES: 121 * A NULL path can be used for a flag since the mount 122 * system call will fail with EFAULT in copyinstr in 123 * nlookup() if it is a genuine NULL from the user. 124 */ 125 static int 126 ffs_mount(struct mount *mp, /* mount struct pointer */ 127 char *path, /* path to mount point */ 128 caddr_t data, /* arguments to FS specific mount */ 129 struct ucred *cred) /* process requesting mount */ 130 { 131 size_t size; 132 int error; 133 struct vnode *devvp; 134 135 struct ufs_args args; 136 struct ufsmount *ump = NULL; 137 struct fs *fs; 138 int flags, ronly = 0; 139 mode_t accessmode; 140 struct nlookupdata nd; 141 struct vnode *rootvp; 142 143 devvp = NULL; 144 error = 0; 145 146 /* 147 * Use NULL path to flag a root mount 148 */ 149 if (path == NULL) { 150 /* 151 *** 152 * Mounting root filesystem 153 *** 154 */ 155 156 if ((error = bdevvp(rootdev, &rootvp))) { 157 kprintf("ffs_mountroot: can't find rootvp\n"); 158 return (error); 159 } 160 161 if( ( error = ffs_mountfs(rootvp, mp, M_FFSNODE)) != 0) { 162 /* fs specific cleanup (if any)*/ 163 goto error_1; 164 } 165 devvp = rootvp; 166 167 goto dostatfs; /* success*/ 168 169 } 170 171 /* 172 *** 173 * Mounting non-root filesystem or updating a filesystem 174 *** 175 */ 176 177 /* copy in user arguments*/ 178 error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); 179 if (error) 180 goto error_1; /* can't get arguments*/ 181 182 /* 183 * If updating, check whether changing from read-only to 184 * read/write; if there is no device name, that's all we do. 185 */ 186 if (mp->mnt_flag & MNT_UPDATE) { 187 ump = VFSTOUFS(mp); 188 fs = ump->um_fs; 189 devvp = ump->um_devvp; 190 error = 0; 191 ronly = fs->fs_ronly; /* MNT_RELOAD might change this */ 192 if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 193 /* 194 * Flush any dirty data. 195 */ 196 VFS_SYNC(mp, MNT_WAIT); 197 /* 198 * Check for and optionally get rid of files open 199 * for writing. 200 */ 201 flags = WRITECLOSE; 202 if (mp->mnt_flag & MNT_FORCE) 203 flags |= FORCECLOSE; 204 if (mp->mnt_flag & MNT_SOFTDEP) { 205 error = softdep_flushfiles(mp, flags); 206 } else { 207 error = ffs_flushfiles(mp, flags); 208 } 209 ronly = 1; 210 } 211 if (!error && (mp->mnt_flag & MNT_RELOAD)) { 212 error = ffs_reload(mp, NULL); 213 } 214 if (error) { 215 goto error_1; 216 } 217 if (ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) { 218 /* 219 * If upgrade to read-write by non-root, then verify 220 * that user has necessary permissions on the device. 221 */ 222 if (cred->cr_uid != 0) { 223 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 224 if ((error = VOP_EACCESS(devvp, VREAD | VWRITE, 225 cred)) != 0) { 226 vn_unlock(devvp); 227 return (error); 228 } 229 vn_unlock(devvp); 230 } 231 232 fs->fs_flags &= ~FS_UNCLEAN; 233 if (fs->fs_clean == 0) { 234 fs->fs_flags |= FS_UNCLEAN; 235 if (mp->mnt_flag & MNT_FORCE) { 236 kprintf( 237 "WARNING: %s was not properly dismounted\n", 238 fs->fs_fsmnt); 239 } else { 240 kprintf( 241 "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", 242 fs->fs_fsmnt); 243 error = EPERM; 244 goto error_1; 245 } 246 } 247 248 /* check to see if we need to start softdep */ 249 if (fs->fs_flags & FS_DOSOFTDEP) { 250 error = softdep_mount(devvp, mp, fs); 251 if (error) 252 goto error_1; 253 } 254 ronly = 0; 255 } 256 /* 257 * Soft updates is incompatible with "async", 258 * so if we are doing softupdates stop the user 259 * from setting the async flag in an update. 260 * Softdep_mount() clears it in an initial mount 261 * or ro->rw remount. 262 */ 263 if (mp->mnt_flag & MNT_SOFTDEP) { 264 mp->mnt_flag &= ~MNT_ASYNC; 265 } 266 /* if not updating name...*/ 267 if (args.fspec == 0) { 268 /* 269 * Process export requests. Jumping to "success" 270 * will return the vfs_export() error code. 271 */ 272 error = vfs_export(mp, &ump->um_export, &args.export); 273 goto success; 274 } 275 } 276 277 /* 278 * Not an update, or updating the name: look up the name 279 * and verify that it refers to a sensible block device. 280 */ 281 devvp = NULL; 282 error = nlookup_init(&nd, args.fspec, UIO_USERSPACE, NLC_FOLLOW); 283 if (error == 0) 284 error = nlookup(&nd); 285 if (error == 0) 286 error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp); 287 nlookup_done(&nd); 288 if (error) 289 goto error_1; 290 291 if (!vn_isdisk(devvp, &error)) 292 goto error_2; 293 294 /* 295 * If mount by non-root, then verify that user has necessary 296 * permissions on the device. 297 */ 298 if (cred->cr_uid != 0) { 299 accessmode = VREAD; 300 if ((mp->mnt_flag & MNT_RDONLY) == 0) 301 accessmode |= VWRITE; 302 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 303 if ((error = VOP_EACCESS(devvp, accessmode, cred)) != 0) { 304 vput(devvp); 305 return (error); 306 } 307 vn_unlock(devvp); 308 } 309 310 if (mp->mnt_flag & MNT_UPDATE) { 311 /* 312 * UPDATE - make sure the resolved vnode represents the same 313 * device. Since devfs, devvp->v_rdev can be used directly as 314 * it is always associated as long as the vnode exists. 315 * 316 * Our current open/writecount state is associated with 317 * um_devvp, so continue using um_devvp and throw away devvp. 318 */ 319 if (devvp != ump->um_devvp) { 320 if (devvp->v_rdev == ump->um_devvp->v_rdev) { 321 vrele(devvp); 322 devvp = ump->um_devvp; 323 } else { 324 kprintf("cannot update mount, v_rdev does" 325 " not match (%p vs %p)\n", 326 devvp->v_rdev, ump->um_devvp->v_rdev); 327 error = EINVAL; /* needs translation */ 328 } 329 } else { 330 vrele(devvp); 331 } 332 /* 333 * Update device name only on success 334 */ 335 if (!error) { 336 /* Save "mounted from" info for mount point (NULL pad)*/ 337 copyinstr( args.fspec, 338 mp->mnt_stat.f_mntfromname, 339 MNAMELEN - 1, 340 &size); 341 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 342 } 343 } else { 344 /* 345 ******************** 346 * NEW MOUNT 347 ******************** 348 */ 349 350 /* Save "mounted from" info for mount point (NULL pad)*/ 351 copyinstr( args.fspec, /* device name*/ 352 mp->mnt_stat.f_mntfromname, /* save area*/ 353 MNAMELEN - 1, /* max size*/ 354 &size); /* real size*/ 355 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 356 357 /* Save "last mounted on" info for mount point (NULL pad)*/ 358 bzero(mp->mnt_stat.f_mntonname, 359 sizeof(mp->mnt_stat.f_mntonname)); 360 if (path) { 361 copyinstr(path, mp->mnt_stat.f_mntonname, 362 sizeof(mp->mnt_stat.f_mntonname) - 1, 363 &size); 364 } else { /* Root mount */ 365 mp->mnt_stat.f_mntonname[0] = '/'; 366 } 367 368 error = ffs_mountfs(devvp, mp, M_FFSNODE); 369 } 370 if (error) { 371 goto error_2; 372 } 373 374 dostatfs: 375 /* 376 * Initialize FS stat information in mount struct; uses 377 * mp->mnt_stat.f_mntfromname. 378 * 379 * This code is common to root and non-root mounts 380 */ 381 (void)VFS_STATFS(mp, &mp->mnt_stat, cred); 382 383 goto success; 384 385 386 error_2: /* error with devvp held*/ 387 388 /* release devvp before failing*/ 389 vrele(devvp); 390 391 error_1: /* no state to back out*/ 392 393 success: 394 if (!error && path && (mp->mnt_flag & MNT_UPDATE)) { 395 /* Update clean flag after changing read-onlyness. */ 396 fs = ump->um_fs; 397 if (ronly != fs->fs_ronly) { 398 fs->fs_ronly = ronly; 399 fs->fs_clean = ronly && 400 (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0; 401 402 /* 403 * The device must be re-opened as appropriate or 404 * the device close at unmount time will panic. 405 */ 406 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 407 if (ronly) { 408 VOP_OPEN(devvp, FREAD, FSCRED, NULL); 409 VOP_CLOSE(devvp, FREAD|FWRITE, NULL); 410 } else { 411 VOP_OPEN(devvp, FREAD|FWRITE, FSCRED, NULL); 412 VOP_CLOSE(devvp, FREAD, NULL); 413 } 414 vn_unlock(devvp); 415 ffs_sbupdate(ump, MNT_WAIT); 416 } 417 } 418 return (error); 419 } 420 421 /* 422 * Reload all incore data for a filesystem (used after running fsck on 423 * the root filesystem and finding things to fix). The filesystem must 424 * be mounted read-only. 425 * 426 * Things to do to update the mount: 427 * 1) invalidate all cached meta-data. 428 * 2) re-read superblock from disk. 429 * 3) re-read summary information from disk. 430 * 4) invalidate all inactive vnodes. 431 * 5) invalidate all cached file data. 432 * 6) re-read inode data for all active vnodes. 433 */ 434 435 static int ffs_reload_scan2(struct mount *mp, struct vnode *vp, void *data); 436 437 struct scaninfo { 438 int rescan; 439 struct fs *fs; 440 struct vnode *devvp; 441 int waitfor; 442 int allerror; 443 }; 444 445 static int 446 ffs_reload(struct mount *mp, struct ucred *cred) 447 { 448 struct vnode *devvp; 449 void *space; 450 struct buf *bp; 451 struct fs *fs, *newfs; 452 int i, blks, size, error; 453 struct scaninfo scaninfo; 454 int32_t *lp; 455 456 if ((mp->mnt_flag & MNT_RDONLY) == 0) 457 return (EINVAL); 458 /* 459 * Step 1: invalidate all cached meta-data. 460 */ 461 devvp = VFSTOUFS(mp)->um_devvp; 462 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 463 error = vinvalbuf(devvp, 0, 0, 0); 464 vn_unlock(devvp); 465 if (error) 466 panic("ffs_reload: dirty1"); 467 468 /* 469 * The backing device must be VMIO-capable because we use getblk(). 470 * NOTE: the MFS driver now returns a VMIO-enabled descriptor. 471 */ 472 if (devvp->v_object == NULL) 473 panic("ffs_reload: devvp has no VM object!"); 474 475 /* 476 * Step 2: re-read superblock from disk. 477 */ 478 if ((error = bread(devvp, SBOFF, SBSIZE, &bp)) != 0) { 479 brelse(bp); 480 return (error); 481 } 482 newfs = (struct fs *)bp->b_data; 483 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE || 484 newfs->fs_bsize < sizeof(struct fs)) { 485 brelse(bp); 486 return (EIO); /* XXX needs translation */ 487 } 488 fs = VFSTOUFS(mp)->um_fs; 489 /* 490 * Copy pointer fields back into superblock before copying in XXX 491 * new superblock. These should really be in the ufsmount. XXX 492 * Note that important parameters (eg fs_ncg) are unchanged. 493 */ 494 newfs->fs_csp = fs->fs_csp; 495 newfs->fs_maxcluster = fs->fs_maxcluster; 496 newfs->fs_contigdirs = fs->fs_contigdirs; 497 /* The filesystem is still read-only. */ 498 newfs->fs_ronly = 1; 499 bcopy(newfs, fs, (uint)fs->fs_sbsize); 500 if (fs->fs_sbsize < SBSIZE) 501 bp->b_flags |= B_INVAL; 502 brelse(bp); 503 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 504 ffs_oldfscompat(fs); 505 /* An old fsck may have zeroed these fields, so recheck them. */ 506 if (fs->fs_avgfilesize <= 0) /* XXX */ 507 fs->fs_avgfilesize = AVFILESIZ; /* XXX */ 508 if (fs->fs_avgfpdir <= 0) /* XXX */ 509 fs->fs_avgfpdir = AFPDIR; /* XXX */ 510 511 /* 512 * Step 3: re-read summary information from disk. 513 */ 514 blks = howmany(fs->fs_cssize, fs->fs_fsize); 515 space = fs->fs_csp; 516 for (i = 0; i < blks; i += fs->fs_frag) { 517 size = fs->fs_bsize; 518 if (i + fs->fs_frag > blks) 519 size = (blks - i) * fs->fs_fsize; 520 error = bread(devvp, fsbtodoff(fs, fs->fs_csaddr + i), size, &bp); 521 if (error) { 522 brelse(bp); 523 return (error); 524 } 525 bcopy(bp->b_data, space, (uint)size); 526 space = (char *)space + size; 527 brelse(bp); 528 } 529 /* 530 * We no longer know anything about clusters per cylinder group. 531 */ 532 if (fs->fs_contigsumsize > 0) { 533 lp = fs->fs_maxcluster; 534 for (i = 0; i < fs->fs_ncg; i++) 535 *lp++ = fs->fs_contigsumsize; 536 } 537 538 scaninfo.rescan = 0; 539 scaninfo.fs = fs; 540 scaninfo.devvp = devvp; 541 while (error == 0 && scaninfo.rescan) { 542 scaninfo.rescan = 0; 543 error = vmntvnodescan(mp, VMSC_GETVX, 544 NULL, ffs_reload_scan2, &scaninfo); 545 } 546 return(error); 547 } 548 549 static int 550 ffs_reload_scan2(struct mount *mp, struct vnode *vp, void *data) 551 { 552 struct scaninfo *info = data; 553 struct inode *ip; 554 struct buf *bp; 555 int error; 556 557 /* 558 * Try to recycle 559 */ 560 if (vrecycle(vp)) 561 return(0); 562 563 if (vinvalbuf(vp, 0, 0, 0)) 564 panic("ffs_reload: dirty2"); 565 /* 566 * Step 6: re-read inode data for all active vnodes. 567 */ 568 ip = VTOI(vp); 569 error = bread(info->devvp, 570 fsbtodoff(info->fs, ino_to_fsba(info->fs, ip->i_number)), 571 (int)info->fs->fs_bsize, &bp); 572 if (error) { 573 brelse(bp); 574 return (error); 575 } 576 ip->i_din = *((struct ufs1_dinode *)bp->b_data + 577 ino_to_fsbo(info->fs, ip->i_number)); 578 ip->i_effnlink = ip->i_nlink; 579 brelse(bp); 580 return(0); 581 } 582 583 /* 584 * Common code for mount and mountroot 585 */ 586 int 587 ffs_mountfs(struct vnode *devvp, struct mount *mp, struct malloc_type *mtype) 588 { 589 struct ufsmount *ump; 590 struct buf *bp; 591 struct fs *fs; 592 cdev_t dev; 593 void *space; 594 int error, i, blks, size, ronly; 595 int32_t *lp; 596 uint64_t maxfilesize; /* XXX */ 597 598 /* 599 * Disallow multiple mounts of the same device. 600 * Disallow mounting of a device that is currently in use 601 * Flush out any old buffers remaining from a previous use. 602 */ 603 error = vfs_mountedon(devvp); 604 if (error) 605 return (error); 606 if (vcount(devvp) > 0) 607 return (EBUSY); 608 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 609 error = vinvalbuf(devvp, V_SAVE, 0, 0); 610 vn_unlock(devvp); 611 if (error) 612 return (error); 613 614 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 615 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 616 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, NULL); 617 vn_unlock(devvp); 618 if (error) 619 return (error); 620 dev = devvp->v_rdev; 621 if (dev->si_iosize_max != 0) 622 mp->mnt_iosize_max = dev->si_iosize_max; 623 if (mp->mnt_iosize_max > MAXPHYS) 624 mp->mnt_iosize_max = MAXPHYS; 625 626 /* 627 * Filesystem supports native FSMIDs 628 */ 629 mp->mnt_kern_flag |= MNTK_FSMID; 630 631 /* 632 * The backing device must be VMIO-capable because we use getblk(). 633 * NOTE: the MFS driver now returns a VMIO-enabled descriptor. 634 * The VOP_OPEN() call above should have associated a VM object 635 * with devvp. 636 */ 637 if (devvp->v_object == NULL) 638 panic("ffs_reload: devvp has no VM object!"); 639 640 bp = NULL; 641 ump = NULL; 642 if ((error = bread(devvp, SBOFF, SBSIZE, &bp)) != 0) 643 goto out; 644 fs = (struct fs *)bp->b_data; 645 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 646 fs->fs_bsize < sizeof(struct fs)) { 647 error = EINVAL; /* XXX needs translation */ 648 goto out; 649 } 650 fs->fs_fmod = 0; 651 fs->fs_flags &= ~FS_UNCLEAN; 652 if (fs->fs_clean == 0) { 653 fs->fs_flags |= FS_UNCLEAN; 654 if (ronly || (mp->mnt_flag & MNT_FORCE)) { 655 kprintf( 656 "WARNING: %s was not properly dismounted\n", 657 fs->fs_fsmnt); 658 } else { 659 kprintf( 660 "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", 661 fs->fs_fsmnt); 662 error = EPERM; 663 goto out; 664 } 665 } 666 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ 667 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { 668 error = EROFS; /* needs translation */ 669 goto out; 670 } 671 ump = kmalloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO); 672 ump->um_malloctype = mtype; 673 ump->um_i_effnlink_valid = 1; 674 ump->um_fs = kmalloc((u_long)fs->fs_sbsize, M_UFSMNT, 675 M_WAITOK); 676 bcopy(bp->b_data, ump->um_fs, (uint)fs->fs_sbsize); 677 if (fs->fs_sbsize < SBSIZE) 678 bp->b_flags |= B_INVAL; 679 brelse(bp); 680 bp = NULL; 681 fs = ump->um_fs; 682 fs->fs_ronly = ronly; 683 size = fs->fs_cssize; 684 blks = howmany(size, fs->fs_fsize); 685 if (fs->fs_contigsumsize > 0) 686 size += fs->fs_ncg * sizeof(int32_t); 687 size += fs->fs_ncg * sizeof(uint8_t); 688 space = kmalloc((u_long)size, M_UFSMNT, M_WAITOK); 689 fs->fs_csp = space; 690 for (i = 0; i < blks; i += fs->fs_frag) { 691 size = fs->fs_bsize; 692 if (i + fs->fs_frag > blks) 693 size = (blks - i) * fs->fs_fsize; 694 if ((error = bread(devvp, fsbtodoff(fs, fs->fs_csaddr + i), 695 size, &bp)) != 0) { 696 kfree(fs->fs_csp, M_UFSMNT); 697 goto out; 698 } 699 bcopy(bp->b_data, space, (uint)size); 700 space = (char *)space + size; 701 brelse(bp); 702 bp = NULL; 703 } 704 if (fs->fs_contigsumsize > 0) { 705 fs->fs_maxcluster = lp = space; 706 for (i = 0; i < fs->fs_ncg; i++) 707 *lp++ = fs->fs_contigsumsize; 708 space = lp; 709 } 710 size = fs->fs_ncg * sizeof(uint8_t); 711 fs->fs_contigdirs = (uint8_t *)space; 712 bzero(fs->fs_contigdirs, size); 713 /* Compatibility for old filesystems XXX */ 714 if (fs->fs_avgfilesize <= 0) /* XXX */ 715 fs->fs_avgfilesize = AVFILESIZ; /* XXX */ 716 if (fs->fs_avgfpdir <= 0) /* XXX */ 717 fs->fs_avgfpdir = AFPDIR; /* XXX */ 718 mp->mnt_data = (qaddr_t)ump; 719 mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0]; 720 mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1]; 721 if (fs->fs_id[0] == 0 || fs->fs_id[1] == 0 || 722 vfs_getvfs(&mp->mnt_stat.f_fsid)) 723 vfs_getnewfsid(mp); 724 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 725 mp->mnt_flag |= MNT_LOCAL; 726 ump->um_mountp = mp; 727 ump->um_dev = dev; 728 ump->um_devvp = devvp; 729 ump->um_nindir = fs->fs_nindir; 730 ump->um_bptrtodb = fs->fs_fsbtodb; 731 ump->um_seqinc = fs->fs_frag; 732 for (i = 0; i < MAXQUOTAS; i++) 733 ump->um_quotas[i] = NULLVP; 734 dev->si_mountpoint = mp; 735 ffs_oldfscompat(fs); 736 737 /* restore "last mounted on" here */ 738 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 739 ksnprintf(fs->fs_fsmnt, sizeof(fs->fs_fsmnt), 740 "%s", mp->mnt_stat.f_mntonname); 741 742 if( mp->mnt_flag & MNT_ROOTFS) { 743 /* 744 * Root mount; update timestamp in mount structure. 745 * this will be used by the common root mount code 746 * to update the system clock. 747 */ 748 mp->mnt_time = fs->fs_time; 749 } 750 751 ufs_ihashinit(ump); 752 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */ 753 maxfilesize = (uint64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */ 754 /* Enforce limit caused by vm object backing (32 bits vm_pindex_t). */ 755 if (maxfilesize > (uint64_t)0x80000000u * PAGE_SIZE - 1) 756 maxfilesize = (uint64_t)0x80000000u * PAGE_SIZE - 1; 757 if (fs->fs_maxfilesize > maxfilesize) /* XXX */ 758 fs->fs_maxfilesize = maxfilesize; /* XXX */ 759 if (ronly == 0) { 760 if ((fs->fs_flags & FS_DOSOFTDEP) && 761 (error = softdep_mount(devvp, mp, fs)) != 0) { 762 kfree(fs->fs_csp, M_UFSMNT); 763 goto out; 764 } 765 fs->fs_fmod = 1; 766 fs->fs_clean = 0; 767 (void) ffs_sbupdate(ump, MNT_WAIT); 768 } 769 vfs_add_vnodeops(mp, &ffs_vnode_vops, &mp->mnt_vn_norm_ops); 770 vfs_add_vnodeops(mp, &ffs_spec_vops, &mp->mnt_vn_spec_ops); 771 vfs_add_vnodeops(mp, &ffs_fifo_vops, &mp->mnt_vn_fifo_ops); 772 773 return (0); 774 out: 775 dev->si_mountpoint = NULL; 776 if (bp) 777 brelse(bp); 778 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 779 VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NULL); 780 vn_unlock(devvp); 781 if (ump) { 782 ufs_ihashuninit(ump); 783 kfree(ump->um_fs, M_UFSMNT); 784 kfree(ump, M_UFSMNT); 785 mp->mnt_data = (qaddr_t)0; 786 } 787 return (error); 788 } 789 790 /* 791 * Sanity checks for old filesystems. 792 * 793 * XXX - goes away some day. 794 */ 795 static int 796 ffs_oldfscompat(struct fs *fs) 797 { 798 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ 799 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ 800 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 801 fs->fs_nrpos = 8; /* XXX */ 802 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 803 #if 0 804 int i; /* XXX */ 805 uint64_t sizepb = fs->fs_bsize; /* XXX */ 806 /* XXX */ 807 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ 808 for (i = 0; i < NIADDR; i++) { /* XXX */ 809 sizepb *= NINDIR(fs); /* XXX */ 810 fs->fs_maxfilesize += sizepb; /* XXX */ 811 } /* XXX */ 812 #endif 813 fs->fs_maxfilesize = (u_quad_t) 1LL << 39; 814 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ 815 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ 816 } /* XXX */ 817 return (0); 818 } 819 820 /* 821 * unmount system call 822 */ 823 int 824 ffs_unmount(struct mount *mp, int mntflags) 825 { 826 struct ufsmount *ump; 827 struct fs *fs; 828 int error, flags; 829 830 flags = 0; 831 if (mntflags & MNT_FORCE) { 832 flags |= FORCECLOSE; 833 } 834 if (mp->mnt_flag & MNT_SOFTDEP) { 835 if ((error = softdep_flushfiles(mp, flags)) != 0) 836 return (error); 837 } else { 838 if ((error = ffs_flushfiles(mp, flags)) != 0) 839 return (error); 840 } 841 ump = VFSTOUFS(mp); 842 fs = ump->um_fs; 843 if (fs->fs_ronly == 0) { 844 fs->fs_clean = fs->fs_flags & FS_UNCLEAN ? 0 : 1; 845 error = ffs_sbupdate(ump, MNT_WAIT); 846 if (error) { 847 fs->fs_clean = 0; 848 return (error); 849 } 850 } 851 ump->um_devvp->v_rdev->si_mountpoint = NULL; 852 853 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 854 vinvalbuf(ump->um_devvp, V_SAVE, 0, 0); 855 error = VOP_CLOSE(ump->um_devvp, 856 fs->fs_ronly ? FREAD : FREAD|FWRITE, 857 NULL); 858 vn_unlock(ump->um_devvp); 859 860 vrele(ump->um_devvp); 861 862 ufs_ihashuninit(ump); 863 kfree(fs->fs_csp, M_UFSMNT); 864 kfree(fs, M_UFSMNT); 865 kfree(ump, M_UFSMNT); 866 mp->mnt_data = (qaddr_t)0; 867 mp->mnt_flag &= ~MNT_LOCAL; 868 return (error); 869 } 870 871 /* 872 * Flush out all the files in a filesystem. 873 */ 874 int 875 ffs_flushfiles(struct mount *mp, int flags) 876 { 877 struct ufsmount *ump; 878 int error; 879 880 ump = VFSTOUFS(mp); 881 #ifdef QUOTA 882 if (mp->mnt_flag & MNT_QUOTA) { 883 int i; 884 error = vflush(mp, 0, SKIPSYSTEM|flags); 885 if (error) 886 return (error); 887 /* Find out how many quota files we have open. */ 888 for (i = 0; i < MAXQUOTAS; i++) { 889 if (ump->um_quotas[i] == NULLVP) 890 continue; 891 ufs_quotaoff(mp, i); 892 } 893 /* 894 * Here we fall through to vflush again to ensure 895 * that we have gotten rid of all the system vnodes. 896 */ 897 } 898 #endif 899 /* 900 * Flush all the files. 901 */ 902 if ((error = vflush(mp, 0, flags)) != 0) 903 return (error); 904 /* 905 * Flush filesystem metadata. 906 */ 907 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 908 error = VOP_FSYNC(ump->um_devvp, MNT_WAIT, 0); 909 vn_unlock(ump->um_devvp); 910 return (error); 911 } 912 913 /* 914 * Get filesystem statistics. 915 */ 916 int 917 ffs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) 918 { 919 struct ufsmount *ump; 920 struct fs *fs; 921 922 ump = VFSTOUFS(mp); 923 fs = ump->um_fs; 924 if (fs->fs_magic != FS_MAGIC) 925 panic("ffs_statfs"); 926 sbp->f_bsize = fs->fs_fsize; 927 sbp->f_iosize = fs->fs_bsize; 928 sbp->f_blocks = fs->fs_dsize; 929 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 930 fs->fs_cstotal.cs_nffree; 931 sbp->f_bavail = freespace(fs, fs->fs_minfree); 932 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 933 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 934 if (sbp != &mp->mnt_stat) { 935 sbp->f_type = mp->mnt_vfc->vfc_typenum; 936 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 937 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 938 } 939 return (0); 940 } 941 942 /* 943 * Go through the disk queues to initiate sandbagged IO; 944 * go through the inodes to write those that have been modified; 945 * initiate the writing of the super block if it has been modified. 946 * 947 * Note: we are always called with the filesystem marked `MPBUSY'. 948 */ 949 950 951 static int ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data); 952 static int ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data); 953 954 int 955 ffs_sync(struct mount *mp, int waitfor) 956 { 957 struct ufsmount *ump = VFSTOUFS(mp); 958 struct fs *fs; 959 int error; 960 struct scaninfo scaninfo; 961 962 fs = ump->um_fs; 963 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */ 964 kprintf("fs = %s\n", fs->fs_fsmnt); 965 panic("ffs_sync: rofs mod"); 966 } 967 968 /* 969 * Write back each (modified) inode. 970 */ 971 scaninfo.allerror = 0; 972 scaninfo.rescan = 1; 973 scaninfo.waitfor = waitfor; 974 while (scaninfo.rescan) { 975 scaninfo.rescan = 0; 976 vmntvnodescan(mp, VMSC_GETVP|VMSC_NOWAIT, 977 ffs_sync_scan1, ffs_sync_scan2, &scaninfo); 978 } 979 980 /* 981 * Force stale filesystem control information to be flushed. 982 */ 983 if ((waitfor & MNT_LAZY) == 0) { 984 if (ump->um_mountp->mnt_flag & MNT_SOFTDEP) 985 waitfor = MNT_NOWAIT; 986 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 987 if ((error = VOP_FSYNC(ump->um_devvp, waitfor, 0)) != 0) 988 scaninfo.allerror = error; 989 vn_unlock(ump->um_devvp); 990 } 991 #ifdef QUOTA 992 ufs_qsync(mp); 993 #endif 994 /* 995 * Write back modified superblock. 996 */ 997 if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0) 998 scaninfo.allerror = error; 999 return (scaninfo.allerror); 1000 } 1001 1002 static int 1003 ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data) 1004 { 1005 struct inode *ip; 1006 1007 /* 1008 * Depend on the mount list's vnode lock to keep things stable 1009 * enough for a quick test. Since there might be hundreds of 1010 * thousands of vnodes, we cannot afford even a subroutine 1011 * call unless there's a good chance that we have work to do. 1012 */ 1013 ip = VTOI(vp); 1014 /* Restart out whole search if this guy is locked 1015 * or is being reclaimed. 1016 */ 1017 if (vp->v_type == VNON || (ip == NULL) || ((ip->i_flag & 1018 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && 1019 RB_EMPTY(&vp->v_rbdirty_tree))) { 1020 return(-1); 1021 } 1022 return(0); 1023 } 1024 1025 static int 1026 ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data) 1027 { 1028 struct scaninfo *info = data; 1029 struct inode *ip; 1030 int error; 1031 1032 /* 1033 * We have to recheck after having obtained the vnode interlock. 1034 */ 1035 ip = VTOI(vp); 1036 if (vp->v_type == VNON || vp->v_type == VBAD || 1037 ((ip->i_flag & 1038 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && 1039 RB_EMPTY(&vp->v_rbdirty_tree))) { 1040 return(0); 1041 } 1042 if (vp->v_type != VCHR) { 1043 if ((error = VOP_FSYNC(vp, info->waitfor, 0)) != 0) 1044 info->allerror = error; 1045 } else { 1046 /* 1047 * We must reference the vp to prevent it from 1048 * getting ripped out from under ffs_update, since 1049 * we are not holding a vnode lock. 1050 */ 1051 /* ffs_update(vp, waitfor == MNT_WAIT); */ 1052 ffs_update(vp, 0); 1053 } 1054 return(0); 1055 } 1056 1057 /* 1058 * Look up a FFS dinode number to find its incore vnode, otherwise read it 1059 * in from disk. If it is in core, wait for the lock bit to clear, then 1060 * return the inode locked. Detection and handling of mount points must be 1061 * done by the calling routine. 1062 */ 1063 1064 int 1065 ffs_vget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp) 1066 { 1067 struct fs *fs; 1068 struct inode *ip; 1069 struct ufsmount *ump; 1070 struct buf *bp; 1071 struct vnode *vp; 1072 cdev_t dev; 1073 int error; 1074 1075 ump = VFSTOUFS(mp); 1076 dev = ump->um_dev; 1077 1078 retry: 1079 if ((*vpp = ufs_ihashget(ump, dev, ino)) != NULL) { 1080 return (0); 1081 } 1082 1083 /* 1084 * If this MALLOC() is performed after the getnewvnode() 1085 * it might block, leaving a vnode with a NULL v_data to be 1086 * found by ffs_sync() if a sync happens to fire right then, 1087 * which will cause a panic because ffs_sync() blindly 1088 * dereferences vp->v_data (as well it should). 1089 * 1090 * XXX this may no longer be true since getnewvnode returns a 1091 * VX locked vnode now. 1092 */ 1093 ip = kmalloc(sizeof(struct inode), ump->um_malloctype, 1094 M_WAITOK | M_ZERO); 1095 1096 /* Allocate a new vnode/inode. */ 1097 error = getnewvnode(VT_UFS, mp, &vp, VLKTIMEOUT, LK_CANRECURSE); 1098 if (error) { 1099 *vpp = NULL; 1100 kfree(ip, ump->um_malloctype); 1101 return (error); 1102 } 1103 ip->i_vnode = vp; 1104 ip->i_fs = fs = ump->um_fs; 1105 ip->i_dev = dev; 1106 ip->i_number = ino; 1107 #ifdef QUOTA 1108 { 1109 int i; 1110 for (i = 0; i < MAXQUOTAS; i++) 1111 ip->i_dquot[i] = NODQUOT; 1112 } 1113 #endif 1114 1115 /* 1116 * Insert it into the inode hash table. 1117 */ 1118 if (ufs_ihashins(ump, ip) != 0) { 1119 kprintf("debug: ufs ihashins collision, retrying inode %ld\n", 1120 (long) ip->i_number); 1121 *vpp = NULL; 1122 vp->v_type = VBAD; 1123 vx_put(vp); 1124 kfree(ip, ump->um_malloctype); 1125 goto retry; 1126 } 1127 vp->v_data = ip; 1128 1129 /* Read in the disk contents for the inode, copy into the inode. */ 1130 error = bread(ump->um_devvp, fsbtodoff(fs, ino_to_fsba(fs, ino)), 1131 (int)fs->fs_bsize, &bp); 1132 if (error) { 1133 /* 1134 * The inode does not contain anything useful, so it would 1135 * be misleading to leave it on its hash chain. With mode 1136 * still zero, it will be unlinked and returned to the free 1137 * list by vput(). 1138 */ 1139 vp->v_type = VBAD; 1140 brelse(bp); 1141 vx_put(vp); 1142 *vpp = NULL; 1143 return (error); 1144 } 1145 ip->i_din = *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 1146 if (DOINGSOFTDEP(vp)) 1147 softdep_load_inodeblock(ip); 1148 else 1149 ip->i_effnlink = ip->i_nlink; 1150 bqrelse(bp); 1151 1152 /* 1153 * Initialize the vnode from the inode, check for aliases. 1154 * Note that the underlying vnode may have changed. 1155 */ 1156 error = ufs_vinit(mp, &vp); 1157 if (error) { 1158 vp->v_type = VBAD; 1159 vx_put(vp); 1160 *vpp = NULL; 1161 return (error); 1162 } 1163 /* 1164 * Finish inode initialization now that aliasing has been resolved. 1165 */ 1166 ip->i_devvp = ump->um_devvp; 1167 vref(ip->i_devvp); 1168 /* 1169 * Set up a generation number for this inode if it does not 1170 * already have one. This should only happen on old filesystems. 1171 */ 1172 if (ip->i_gen == 0) { 1173 ip->i_gen = krandom() / 2 + 1; 1174 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 1175 ip->i_flag |= IN_MODIFIED; 1176 } 1177 /* 1178 * Ensure that uid and gid are correct. This is a temporary 1179 * fix until fsck has been changed to do the update. 1180 */ 1181 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 1182 ip->i_uid = ip->i_din.di_ouid; /* XXX */ 1183 ip->i_gid = ip->i_din.di_ogid; /* XXX */ 1184 } /* XXX */ 1185 1186 /* 1187 * return a VX locked and refd vnode (VX == same as normal vget() 1188 * vnode so we are ok) 1189 */ 1190 *vpp = vp; 1191 return (0); 1192 } 1193 1194 /* 1195 * File handle to vnode 1196 * 1197 * Have to be really careful about stale file handles: 1198 * - check that the inode number is valid 1199 * - call ffs_vget() to get the locked inode 1200 * - check for an unallocated inode (i_mode == 0) 1201 * - check that the given client host has export rights and return 1202 * those rights via. exflagsp and credanonp 1203 */ 1204 int 1205 ffs_fhtovp(struct mount *mp, struct vnode *rootvp, 1206 struct fid *fhp, struct vnode **vpp) 1207 { 1208 struct ufid *ufhp; 1209 struct fs *fs; 1210 1211 ufhp = (struct ufid *)fhp; 1212 fs = VFSTOUFS(mp)->um_fs; 1213 if (ufhp->ufid_ino < ROOTINO || 1214 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 1215 return (ESTALE); 1216 return (ufs_fhtovp(mp, rootvp, ufhp, vpp)); 1217 } 1218 1219 /* 1220 * Vnode pointer to File handle 1221 */ 1222 /* ARGSUSED */ 1223 int 1224 ffs_vptofh(struct vnode *vp, struct fid *fhp) 1225 { 1226 struct inode *ip; 1227 struct ufid *ufhp; 1228 1229 ip = VTOI(vp); 1230 ufhp = (struct ufid *)fhp; 1231 ufhp->ufid_len = sizeof(struct ufid); 1232 ufhp->ufid_ino = ip->i_number; 1233 ufhp->ufid_gen = ip->i_gen; 1234 return (0); 1235 } 1236 1237 /* 1238 * Initialize the filesystem; just use ufs_init. 1239 */ 1240 static int 1241 ffs_init(struct vfsconf *vfsp) 1242 { 1243 softdep_initialize(); 1244 kmalloc_raise_limit(M_FFSNODE, 0); 1245 return (ufs_init(vfsp)); 1246 } 1247 1248 /* 1249 * Write a superblock and associated information back to disk. 1250 */ 1251 static int 1252 ffs_sbupdate(struct ufsmount *mp, int waitfor) 1253 { 1254 struct fs *dfs, *fs = mp->um_fs; 1255 struct buf *bp; 1256 int blks; 1257 void *space; 1258 int i, size, error, allerror = 0; 1259 1260 /* 1261 * First write back the summary information. 1262 * 1263 * NOTE: the getblk is relative to the device vnode so bio1 1264 * contains the device block number. 1265 */ 1266 blks = howmany(fs->fs_cssize, fs->fs_fsize); 1267 space = fs->fs_csp; 1268 for (i = 0; i < blks; i += fs->fs_frag) { 1269 size = fs->fs_bsize; 1270 if (i + fs->fs_frag > blks) 1271 size = (blks - i) * fs->fs_fsize; 1272 bp = getblk(mp->um_devvp, fsbtodoff(fs, fs->fs_csaddr + i), 1273 size, 0, 0); 1274 bcopy(space, bp->b_data, (uint)size); 1275 space = (char *)space + size; 1276 if (waitfor != MNT_WAIT) 1277 bawrite(bp); 1278 else if ((error = bwrite(bp)) != 0) 1279 allerror = error; 1280 } 1281 /* 1282 * Now write back the superblock itself. If any errors occurred 1283 * up to this point, then fail so that the superblock avoids 1284 * being written out as clean. 1285 */ 1286 if (allerror) 1287 return (allerror); 1288 bp = getblk(mp->um_devvp, SBOFF, (int)fs->fs_sbsize, 0, 0); 1289 fs->fs_fmod = 0; 1290 fs->fs_time = time_second; 1291 bcopy((caddr_t)fs, bp->b_data, (uint)fs->fs_sbsize); 1292 /* Restore compatibility to old filesystems. XXX */ 1293 dfs = (struct fs *)bp->b_data; /* XXX */ 1294 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 1295 dfs->fs_nrpos = -1; /* XXX */ 1296 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 1297 int32_t *lp, tmp; /* XXX */ 1298 /* XXX */ 1299 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */ 1300 tmp = lp[4]; /* XXX */ 1301 for (i = 4; i > 0; i--) /* XXX */ 1302 lp[i] = lp[i-1]; /* XXX */ 1303 lp[0] = tmp; /* XXX */ 1304 } /* XXX */ 1305 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */ 1306 if (waitfor != MNT_WAIT) 1307 bawrite(bp); 1308 else if ((error = bwrite(bp)) != 0) 1309 allerror = error; 1310 return (allerror); 1311 } 1312