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 mount *mptmp; 590 struct ufsmount *ump; 591 struct buf *bp; 592 struct fs *fs; 593 cdev_t dev; 594 void *space; 595 int error, i, blks, size, ronly; 596 int32_t *lp; 597 uint64_t maxfilesize; /* XXX */ 598 599 /* 600 * Disallow multiple mounts of the same device. 601 * Disallow mounting of a device that is currently in use 602 * Flush out any old buffers remaining from a previous use. 603 */ 604 error = vfs_mountedon(devvp); 605 if (error) 606 return (error); 607 if (vcount(devvp) > 0) 608 return (EBUSY); 609 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 610 error = vinvalbuf(devvp, V_SAVE, 0, 0); 611 vn_unlock(devvp); 612 if (error) 613 return (error); 614 615 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 616 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 617 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, NULL); 618 vn_unlock(devvp); 619 if (error) 620 return (error); 621 dev = devvp->v_rdev; 622 if (dev->si_iosize_max != 0) 623 mp->mnt_iosize_max = dev->si_iosize_max; 624 if (mp->mnt_iosize_max > MAXPHYS) 625 mp->mnt_iosize_max = MAXPHYS; 626 627 /* 628 * Filesystem supports native FSMIDs 629 */ 630 mp->mnt_kern_flag |= MNTK_FSMID; 631 632 /* 633 * The backing device must be VMIO-capable because we use getblk(). 634 * NOTE: the MFS driver now returns a VMIO-enabled descriptor. 635 * The VOP_OPEN() call above should have associated a VM object 636 * with devvp. 637 */ 638 if (devvp->v_object == NULL) 639 panic("ffs_reload: devvp has no VM object!"); 640 641 bp = NULL; 642 ump = NULL; 643 if ((error = bread(devvp, SBOFF, SBSIZE, &bp)) != 0) 644 goto out; 645 fs = (struct fs *)bp->b_data; 646 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 647 fs->fs_bsize < sizeof(struct fs)) { 648 error = EINVAL; /* XXX needs translation */ 649 goto out; 650 } 651 fs->fs_fmod = 0; 652 fs->fs_flags &= ~FS_UNCLEAN; 653 if (fs->fs_clean == 0) { 654 fs->fs_flags |= FS_UNCLEAN; 655 if (ronly || (mp->mnt_flag & MNT_FORCE)) { 656 kprintf( 657 "WARNING: %s was not properly dismounted\n", 658 fs->fs_fsmnt); 659 } else { 660 kprintf( 661 "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", 662 fs->fs_fsmnt); 663 error = EPERM; 664 goto out; 665 } 666 } 667 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ 668 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { 669 error = EROFS; /* needs translation */ 670 goto out; 671 } 672 ump = kmalloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO); 673 ump->um_malloctype = mtype; 674 ump->um_i_effnlink_valid = 1; 675 ump->um_fs = kmalloc((u_long)fs->fs_sbsize, M_UFSMNT, 676 M_WAITOK); 677 bcopy(bp->b_data, ump->um_fs, (uint)fs->fs_sbsize); 678 if (fs->fs_sbsize < SBSIZE) 679 bp->b_flags |= B_INVAL; 680 brelse(bp); 681 bp = NULL; 682 fs = ump->um_fs; 683 fs->fs_ronly = ronly; 684 size = fs->fs_cssize; 685 blks = howmany(size, fs->fs_fsize); 686 if (fs->fs_contigsumsize > 0) 687 size += fs->fs_ncg * sizeof(int32_t); 688 size += fs->fs_ncg * sizeof(uint8_t); 689 space = kmalloc((u_long)size, M_UFSMNT, M_WAITOK); 690 fs->fs_csp = space; 691 for (i = 0; i < blks; i += fs->fs_frag) { 692 size = fs->fs_bsize; 693 if (i + fs->fs_frag > blks) 694 size = (blks - i) * fs->fs_fsize; 695 if ((error = bread(devvp, fsbtodoff(fs, fs->fs_csaddr + i), 696 size, &bp)) != 0) { 697 kfree(fs->fs_csp, M_UFSMNT); 698 goto out; 699 } 700 bcopy(bp->b_data, space, (uint)size); 701 space = (char *)space + size; 702 brelse(bp); 703 bp = NULL; 704 } 705 if (fs->fs_contigsumsize > 0) { 706 fs->fs_maxcluster = lp = space; 707 for (i = 0; i < fs->fs_ncg; i++) 708 *lp++ = fs->fs_contigsumsize; 709 space = lp; 710 } 711 size = fs->fs_ncg * sizeof(uint8_t); 712 fs->fs_contigdirs = (uint8_t *)space; 713 bzero(fs->fs_contigdirs, size); 714 /* Compatibility for old filesystems XXX */ 715 if (fs->fs_avgfilesize <= 0) /* XXX */ 716 fs->fs_avgfilesize = AVFILESIZ; /* XXX */ 717 if (fs->fs_avgfpdir <= 0) /* XXX */ 718 fs->fs_avgfpdir = AFPDIR; /* XXX */ 719 mp->mnt_data = (qaddr_t)ump; 720 mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0]; 721 mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1]; 722 if (fs->fs_id[0] == 0 || fs->fs_id[1] == 0) { 723 vfs_getnewfsid(mp); 724 } else if ((mptmp = vfs_getvfs(&mp->mnt_stat.f_fsid)) != NULL) { 725 vfs_getnewfsid(mp); 726 mount_drop(mptmp); 727 } 728 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 729 mp->mnt_flag |= MNT_LOCAL; 730 ump->um_mountp = mp; 731 ump->um_dev = dev; 732 ump->um_devvp = devvp; 733 ump->um_nindir = fs->fs_nindir; 734 ump->um_bptrtodb = fs->fs_fsbtodb; 735 ump->um_seqinc = fs->fs_frag; 736 for (i = 0; i < MAXQUOTAS; i++) 737 ump->um_quotas[i] = NULLVP; 738 dev->si_mountpoint = mp; 739 ffs_oldfscompat(fs); 740 741 /* restore "last mounted on" here */ 742 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 743 ksnprintf(fs->fs_fsmnt, sizeof(fs->fs_fsmnt), 744 "%s", mp->mnt_stat.f_mntonname); 745 746 if( mp->mnt_flag & MNT_ROOTFS) { 747 /* 748 * Root mount; update timestamp in mount structure. 749 * this will be used by the common root mount code 750 * to update the system clock. 751 */ 752 mp->mnt_time = fs->fs_time; 753 } 754 755 ufs_ihashinit(ump); 756 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */ 757 maxfilesize = (uint64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */ 758 /* Enforce limit caused by vm object backing (32 bits vm_pindex_t). */ 759 if (maxfilesize > (uint64_t)0x80000000u * PAGE_SIZE - 1) 760 maxfilesize = (uint64_t)0x80000000u * PAGE_SIZE - 1; 761 if (fs->fs_maxfilesize > maxfilesize) /* XXX */ 762 fs->fs_maxfilesize = maxfilesize; /* XXX */ 763 if (ronly == 0) { 764 if ((fs->fs_flags & FS_DOSOFTDEP) && 765 (error = softdep_mount(devvp, mp, fs)) != 0) { 766 kfree(fs->fs_csp, M_UFSMNT); 767 goto out; 768 } 769 fs->fs_fmod = 1; 770 fs->fs_clean = 0; 771 (void) ffs_sbupdate(ump, MNT_WAIT); 772 } 773 vfs_add_vnodeops(mp, &ffs_vnode_vops, &mp->mnt_vn_norm_ops); 774 vfs_add_vnodeops(mp, &ffs_spec_vops, &mp->mnt_vn_spec_ops); 775 vfs_add_vnodeops(mp, &ffs_fifo_vops, &mp->mnt_vn_fifo_ops); 776 777 return (0); 778 out: 779 dev->si_mountpoint = NULL; 780 if (bp) 781 brelse(bp); 782 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 783 VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NULL); 784 vn_unlock(devvp); 785 if (ump) { 786 ufs_ihashuninit(ump); 787 kfree(ump->um_fs, M_UFSMNT); 788 kfree(ump, M_UFSMNT); 789 mp->mnt_data = (qaddr_t)0; 790 } 791 return (error); 792 } 793 794 /* 795 * Sanity checks for old filesystems. 796 * 797 * XXX - goes away some day. 798 */ 799 static int 800 ffs_oldfscompat(struct fs *fs) 801 { 802 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ 803 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ 804 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 805 fs->fs_nrpos = 8; /* XXX */ 806 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 807 #if 0 808 int i; /* XXX */ 809 uint64_t sizepb = fs->fs_bsize; /* XXX */ 810 /* XXX */ 811 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ 812 for (i = 0; i < NIADDR; i++) { /* XXX */ 813 sizepb *= NINDIR(fs); /* XXX */ 814 fs->fs_maxfilesize += sizepb; /* XXX */ 815 } /* XXX */ 816 #endif 817 fs->fs_maxfilesize = (u_quad_t) 1LL << 39; 818 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ 819 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ 820 } /* XXX */ 821 return (0); 822 } 823 824 /* 825 * unmount system call 826 */ 827 int 828 ffs_unmount(struct mount *mp, int mntflags) 829 { 830 struct ufsmount *ump; 831 struct fs *fs; 832 int error, flags; 833 834 flags = 0; 835 if (mntflags & MNT_FORCE) { 836 flags |= FORCECLOSE; 837 } 838 if (mp->mnt_flag & MNT_SOFTDEP) { 839 if ((error = softdep_flushfiles(mp, flags)) != 0) 840 return (error); 841 } else { 842 if ((error = ffs_flushfiles(mp, flags)) != 0) 843 return (error); 844 } 845 ump = VFSTOUFS(mp); 846 fs = ump->um_fs; 847 if (fs->fs_ronly == 0) { 848 fs->fs_clean = fs->fs_flags & FS_UNCLEAN ? 0 : 1; 849 error = ffs_sbupdate(ump, MNT_WAIT); 850 if (error) { 851 fs->fs_clean = 0; 852 return (error); 853 } 854 } 855 ump->um_devvp->v_rdev->si_mountpoint = NULL; 856 857 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 858 vinvalbuf(ump->um_devvp, V_SAVE, 0, 0); 859 error = VOP_CLOSE(ump->um_devvp, 860 fs->fs_ronly ? FREAD : FREAD|FWRITE, 861 NULL); 862 vn_unlock(ump->um_devvp); 863 864 vrele(ump->um_devvp); 865 866 ufs_ihashuninit(ump); 867 kfree(fs->fs_csp, M_UFSMNT); 868 kfree(fs, M_UFSMNT); 869 kfree(ump, M_UFSMNT); 870 mp->mnt_data = (qaddr_t)0; 871 mp->mnt_flag &= ~MNT_LOCAL; 872 return (error); 873 } 874 875 /* 876 * Flush out all the files in a filesystem. 877 */ 878 int 879 ffs_flushfiles(struct mount *mp, int flags) 880 { 881 struct ufsmount *ump; 882 int error; 883 884 ump = VFSTOUFS(mp); 885 #ifdef QUOTA 886 if (mp->mnt_flag & MNT_QUOTA) { 887 int i; 888 error = vflush(mp, 0, SKIPSYSTEM|flags); 889 if (error) 890 return (error); 891 /* Find out how many quota files we have open. */ 892 for (i = 0; i < MAXQUOTAS; i++) { 893 if (ump->um_quotas[i] == NULLVP) 894 continue; 895 ufs_quotaoff(mp, i); 896 } 897 /* 898 * Here we fall through to vflush again to ensure 899 * that we have gotten rid of all the system vnodes. 900 */ 901 } 902 #endif 903 /* 904 * Flush all the files. 905 */ 906 if ((error = vflush(mp, 0, flags)) != 0) 907 return (error); 908 /* 909 * Flush filesystem metadata. 910 */ 911 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 912 error = VOP_FSYNC(ump->um_devvp, MNT_WAIT, 0); 913 vn_unlock(ump->um_devvp); 914 return (error); 915 } 916 917 /* 918 * Get filesystem statistics. 919 */ 920 int 921 ffs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) 922 { 923 struct ufsmount *ump; 924 struct fs *fs; 925 926 ump = VFSTOUFS(mp); 927 fs = ump->um_fs; 928 if (fs->fs_magic != FS_MAGIC) 929 panic("ffs_statfs"); 930 sbp->f_bsize = fs->fs_fsize; 931 sbp->f_iosize = fs->fs_bsize; 932 sbp->f_blocks = fs->fs_dsize; 933 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 934 fs->fs_cstotal.cs_nffree; 935 sbp->f_bavail = freespace(fs, fs->fs_minfree); 936 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 937 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 938 if (sbp != &mp->mnt_stat) { 939 sbp->f_type = mp->mnt_vfc->vfc_typenum; 940 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 941 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 942 } 943 return (0); 944 } 945 946 /* 947 * Go through the disk queues to initiate sandbagged IO; 948 * go through the inodes to write those that have been modified; 949 * initiate the writing of the super block if it has been modified. 950 * 951 * Note: we are always called with the filesystem marked `MPBUSY'. 952 */ 953 954 955 static int ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data); 956 static int ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data); 957 958 int 959 ffs_sync(struct mount *mp, int waitfor) 960 { 961 struct ufsmount *ump = VFSTOUFS(mp); 962 struct fs *fs; 963 int error; 964 struct scaninfo scaninfo; 965 966 fs = ump->um_fs; 967 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */ 968 kprintf("fs = %s\n", fs->fs_fsmnt); 969 panic("ffs_sync: rofs mod"); 970 } 971 972 /* 973 * Write back each (modified) inode. 974 */ 975 scaninfo.allerror = 0; 976 scaninfo.rescan = 1; 977 scaninfo.waitfor = waitfor; 978 while (scaninfo.rescan) { 979 scaninfo.rescan = 0; 980 vmntvnodescan(mp, VMSC_GETVP|VMSC_NOWAIT, 981 ffs_sync_scan1, ffs_sync_scan2, &scaninfo); 982 } 983 984 /* 985 * Force stale filesystem control information to be flushed. 986 */ 987 if ((waitfor & MNT_LAZY) == 0) { 988 if (ump->um_mountp->mnt_flag & MNT_SOFTDEP) 989 waitfor = MNT_NOWAIT; 990 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 991 if ((error = VOP_FSYNC(ump->um_devvp, waitfor, 0)) != 0) 992 scaninfo.allerror = error; 993 vn_unlock(ump->um_devvp); 994 } 995 #ifdef QUOTA 996 ufs_qsync(mp); 997 #endif 998 /* 999 * Write back modified superblock. 1000 */ 1001 if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0) 1002 scaninfo.allerror = error; 1003 return (scaninfo.allerror); 1004 } 1005 1006 static int 1007 ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data) 1008 { 1009 struct inode *ip; 1010 1011 /* 1012 * Depend on the mount list's vnode lock to keep things stable 1013 * enough for a quick test. Since there might be hundreds of 1014 * thousands of vnodes, we cannot afford even a subroutine 1015 * call unless there's a good chance that we have work to do. 1016 */ 1017 ip = VTOI(vp); 1018 /* Restart out whole search if this guy is locked 1019 * or is being reclaimed. 1020 */ 1021 if (vp->v_type == VNON || (ip == NULL) || ((ip->i_flag & 1022 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && 1023 RB_EMPTY(&vp->v_rbdirty_tree))) { 1024 return(-1); 1025 } 1026 return(0); 1027 } 1028 1029 static int 1030 ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data) 1031 { 1032 struct scaninfo *info = data; 1033 struct inode *ip; 1034 int error; 1035 1036 /* 1037 * We have to recheck after having obtained the vnode interlock. 1038 */ 1039 ip = VTOI(vp); 1040 if (vp->v_type == VNON || vp->v_type == VBAD || 1041 ((ip->i_flag & 1042 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && 1043 RB_EMPTY(&vp->v_rbdirty_tree))) { 1044 return(0); 1045 } 1046 if (vp->v_type != VCHR) { 1047 if ((error = VOP_FSYNC(vp, info->waitfor, 0)) != 0) 1048 info->allerror = error; 1049 } else { 1050 /* 1051 * We must reference the vp to prevent it from 1052 * getting ripped out from under ffs_update, since 1053 * we are not holding a vnode lock. 1054 */ 1055 /* ffs_update(vp, waitfor == MNT_WAIT); */ 1056 ffs_update(vp, 0); 1057 } 1058 return(0); 1059 } 1060 1061 /* 1062 * Look up a FFS dinode number to find its incore vnode, otherwise read it 1063 * in from disk. If it is in core, wait for the lock bit to clear, then 1064 * return the inode locked. Detection and handling of mount points must be 1065 * done by the calling routine. 1066 */ 1067 1068 int 1069 ffs_vget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp) 1070 { 1071 struct fs *fs; 1072 struct inode *ip; 1073 struct ufsmount *ump; 1074 struct buf *bp; 1075 struct vnode *vp; 1076 cdev_t dev; 1077 int error; 1078 1079 ump = VFSTOUFS(mp); 1080 dev = ump->um_dev; 1081 1082 retry: 1083 if ((*vpp = ufs_ihashget(ump, dev, ino)) != NULL) { 1084 return (0); 1085 } 1086 1087 /* 1088 * If this MALLOC() is performed after the getnewvnode() 1089 * it might block, leaving a vnode with a NULL v_data to be 1090 * found by ffs_sync() if a sync happens to fire right then, 1091 * which will cause a panic because ffs_sync() blindly 1092 * dereferences vp->v_data (as well it should). 1093 * 1094 * XXX this may no longer be true since getnewvnode returns a 1095 * VX locked vnode now. 1096 */ 1097 ip = kmalloc(sizeof(struct inode), ump->um_malloctype, 1098 M_WAITOK | M_ZERO); 1099 1100 /* Allocate a new vnode/inode. */ 1101 error = getnewvnode(VT_UFS, mp, &vp, VLKTIMEOUT, LK_CANRECURSE); 1102 if (error) { 1103 *vpp = NULL; 1104 kfree(ip, ump->um_malloctype); 1105 return (error); 1106 } 1107 ip->i_vnode = vp; 1108 ip->i_fs = fs = ump->um_fs; 1109 ip->i_dev = dev; 1110 ip->i_number = ino; 1111 #ifdef QUOTA 1112 { 1113 int i; 1114 for (i = 0; i < MAXQUOTAS; i++) 1115 ip->i_dquot[i] = NODQUOT; 1116 } 1117 #endif 1118 1119 /* 1120 * Insert it into the inode hash table. 1121 */ 1122 if (ufs_ihashins(ump, ip) != 0) { 1123 kprintf("debug: ufs ihashins collision, retrying inode %ld\n", 1124 (long) ip->i_number); 1125 *vpp = NULL; 1126 vp->v_type = VBAD; 1127 vx_put(vp); 1128 kfree(ip, ump->um_malloctype); 1129 goto retry; 1130 } 1131 vp->v_data = ip; 1132 1133 /* Read in the disk contents for the inode, copy into the inode. */ 1134 error = bread(ump->um_devvp, fsbtodoff(fs, ino_to_fsba(fs, ino)), 1135 (int)fs->fs_bsize, &bp); 1136 if (error) { 1137 /* 1138 * The inode does not contain anything useful, so it would 1139 * be misleading to leave it on its hash chain. With mode 1140 * still zero, it will be unlinked and returned to the free 1141 * list by vput(). 1142 */ 1143 vp->v_type = VBAD; 1144 brelse(bp); 1145 vx_put(vp); 1146 *vpp = NULL; 1147 return (error); 1148 } 1149 ip->i_din = *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 1150 if (DOINGSOFTDEP(vp)) 1151 softdep_load_inodeblock(ip); 1152 else 1153 ip->i_effnlink = ip->i_nlink; 1154 bqrelse(bp); 1155 1156 /* 1157 * Initialize the vnode from the inode, check for aliases. 1158 * Note that the underlying vnode may have changed. 1159 */ 1160 error = ufs_vinit(mp, &vp); 1161 if (error) { 1162 vp->v_type = VBAD; 1163 vx_put(vp); 1164 *vpp = NULL; 1165 return (error); 1166 } 1167 /* 1168 * Finish inode initialization now that aliasing has been resolved. 1169 */ 1170 ip->i_devvp = ump->um_devvp; 1171 vref(ip->i_devvp); 1172 /* 1173 * Set up a generation number for this inode if it does not 1174 * already have one. This should only happen on old filesystems. 1175 */ 1176 if (ip->i_gen == 0) { 1177 ip->i_gen = krandom() / 2 + 1; 1178 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 1179 ip->i_flag |= IN_MODIFIED; 1180 } 1181 /* 1182 * Ensure that uid and gid are correct. This is a temporary 1183 * fix until fsck has been changed to do the update. 1184 */ 1185 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 1186 ip->i_uid = ip->i_din.di_ouid; /* XXX */ 1187 ip->i_gid = ip->i_din.di_ogid; /* XXX */ 1188 } /* XXX */ 1189 1190 /* 1191 * return a VX locked and refd vnode (VX == same as normal vget() 1192 * vnode so we are ok) 1193 */ 1194 *vpp = vp; 1195 return (0); 1196 } 1197 1198 /* 1199 * File handle to vnode 1200 * 1201 * Have to be really careful about stale file handles: 1202 * - check that the inode number is valid 1203 * - call ffs_vget() to get the locked inode 1204 * - check for an unallocated inode (i_mode == 0) 1205 * - check that the given client host has export rights and return 1206 * those rights via. exflagsp and credanonp 1207 */ 1208 int 1209 ffs_fhtovp(struct mount *mp, struct vnode *rootvp, 1210 struct fid *fhp, struct vnode **vpp) 1211 { 1212 struct ufid *ufhp; 1213 struct fs *fs; 1214 1215 ufhp = (struct ufid *)fhp; 1216 fs = VFSTOUFS(mp)->um_fs; 1217 if (ufhp->ufid_ino < ROOTINO || 1218 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 1219 return (ESTALE); 1220 return (ufs_fhtovp(mp, rootvp, ufhp, vpp)); 1221 } 1222 1223 /* 1224 * Vnode pointer to File handle 1225 */ 1226 /* ARGSUSED */ 1227 int 1228 ffs_vptofh(struct vnode *vp, struct fid *fhp) 1229 { 1230 struct inode *ip; 1231 struct ufid *ufhp; 1232 1233 ip = VTOI(vp); 1234 ufhp = (struct ufid *)fhp; 1235 ufhp->ufid_len = sizeof(struct ufid); 1236 ufhp->ufid_ino = ip->i_number; 1237 ufhp->ufid_gen = ip->i_gen; 1238 return (0); 1239 } 1240 1241 /* 1242 * Initialize the filesystem; just use ufs_init. 1243 */ 1244 static int 1245 ffs_init(struct vfsconf *vfsp) 1246 { 1247 softdep_initialize(); 1248 kmalloc_raise_limit(M_FFSNODE, 0); 1249 return (ufs_init(vfsp)); 1250 } 1251 1252 /* 1253 * Write a superblock and associated information back to disk. 1254 */ 1255 static int 1256 ffs_sbupdate(struct ufsmount *mp, int waitfor) 1257 { 1258 struct fs *dfs, *fs = mp->um_fs; 1259 struct buf *bp; 1260 int blks; 1261 void *space; 1262 int i, size, error, allerror = 0; 1263 1264 /* 1265 * First write back the summary information. 1266 * 1267 * NOTE: the getblk is relative to the device vnode so bio1 1268 * contains the device block number. 1269 */ 1270 blks = howmany(fs->fs_cssize, fs->fs_fsize); 1271 space = fs->fs_csp; 1272 for (i = 0; i < blks; i += fs->fs_frag) { 1273 size = fs->fs_bsize; 1274 if (i + fs->fs_frag > blks) 1275 size = (blks - i) * fs->fs_fsize; 1276 bp = getblk(mp->um_devvp, fsbtodoff(fs, fs->fs_csaddr + i), 1277 size, 0, 0); 1278 bcopy(space, bp->b_data, (uint)size); 1279 space = (char *)space + size; 1280 if (waitfor != MNT_WAIT) 1281 bawrite(bp); 1282 else if ((error = bwrite(bp)) != 0) 1283 allerror = error; 1284 } 1285 /* 1286 * Now write back the superblock itself. If any errors occurred 1287 * up to this point, then fail so that the superblock avoids 1288 * being written out as clean. 1289 */ 1290 if (allerror) 1291 return (allerror); 1292 bp = getblk(mp->um_devvp, SBOFF, (int)fs->fs_sbsize, 0, 0); 1293 fs->fs_fmod = 0; 1294 fs->fs_time = time_second; 1295 bcopy((caddr_t)fs, bp->b_data, (uint)fs->fs_sbsize); 1296 /* Restore compatibility to old filesystems. XXX */ 1297 dfs = (struct fs *)bp->b_data; /* XXX */ 1298 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 1299 dfs->fs_nrpos = -1; /* XXX */ 1300 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 1301 int32_t *lp, tmp; /* XXX */ 1302 /* XXX */ 1303 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */ 1304 tmp = lp[4]; /* XXX */ 1305 for (i = 4; i > 0; i--) /* XXX */ 1306 lp[i] = lp[i-1]; /* XXX */ 1307 lp[0] = tmp; /* XXX */ 1308 } /* XXX */ 1309 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */ 1310 if (waitfor != MNT_WAIT) 1311 bawrite(bp); 1312 else if ((error = bwrite(bp)) != 0) 1313 allerror = error; 1314 return (allerror); 1315 } 1316