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