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