1 /* $OpenBSD: ffs_vfsops.c,v 1.48 2001/12/19 08:58:07 art Exp $ */ 2 /* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1991, 1993, 1994 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/namei.h> 42 #include <sys/proc.h> 43 #include <sys/kernel.h> 44 #include <sys/vnode.h> 45 #include <sys/socket.h> 46 #include <sys/mount.h> 47 #include <sys/buf.h> 48 #include <sys/mbuf.h> 49 #include <sys/file.h> 50 #include <sys/disklabel.h> 51 #include <sys/ioctl.h> 52 #include <sys/errno.h> 53 #include <sys/malloc.h> 54 #include <sys/sysctl.h> 55 #include <sys/pool.h> 56 57 #include <dev/rndvar.h> 58 59 #include <miscfs/specfs/specdev.h> 60 61 #include <ufs/ufs/quota.h> 62 #include <ufs/ufs/ufsmount.h> 63 #include <ufs/ufs/inode.h> 64 #include <ufs/ufs/dir.h> 65 #include <ufs/ufs/ufs_extern.h> 66 67 #include <ufs/ffs/fs.h> 68 #include <ufs/ffs/ffs_extern.h> 69 70 int ffs_sbupdate __P((struct ufsmount *, int)); 71 int ffs_reload_vnode(struct vnode *, void *); 72 int ffs_sync_vnode(struct vnode *, void *); 73 74 struct vfsops ffs_vfsops = { 75 ffs_mount, 76 ufs_start, 77 ffs_unmount, 78 ufs_root, 79 ufs_quotactl, 80 ffs_statfs, 81 ffs_sync, 82 ffs_vget, 83 ffs_fhtovp, 84 ffs_vptofh, 85 ffs_init, 86 ffs_sysctl, 87 ufs_check_export 88 }; 89 90 struct inode_vtbl ffs_vtbl = { 91 ffs_truncate, 92 ffs_update, 93 ffs_inode_alloc, 94 ffs_inode_free, 95 ffs_balloc, 96 ffs_bufatoff 97 }; 98 99 extern u_long nextgennumber; 100 101 /* 102 * Called by main() when ufs is going to be mounted as root. 103 */ 104 105 struct pool ffs_ino_pool; 106 107 int 108 ffs_mountroot() 109 { 110 extern struct vnode *rootvp; 111 struct fs *fs; 112 struct mount *mp; 113 struct proc *p = curproc; /* XXX */ 114 struct ufsmount *ump; 115 int error; 116 117 /* 118 * Get vnodes for swapdev and rootdev. 119 */ 120 if ((error = bdevvp(swapdev, &swapdev_vp)) || 121 (error = bdevvp(rootdev, &rootvp))) { 122 printf("ffs_mountroot: can't setup bdevvp's"); 123 return (error); 124 } 125 126 if ((error = vfs_rootmountalloc("ffs", "root_device", &mp)) != 0) 127 return (error); 128 if ((error = ffs_mountfs(rootvp, mp, p)) != 0) { 129 mp->mnt_vfc->vfc_refcount--; 130 vfs_unbusy(mp, p); 131 free(mp, M_MOUNT); 132 return (error); 133 } 134 simple_lock(&mountlist_slock); 135 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 136 simple_unlock(&mountlist_slock); 137 ump = VFSTOUFS(mp); 138 fs = ump->um_fs; 139 (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0); 140 (void)ffs_statfs(mp, &mp->mnt_stat, p); 141 vfs_unbusy(mp, p); 142 inittodr(fs->fs_time); 143 return (0); 144 } 145 146 /* 147 * VFS Operations. 148 * 149 * mount system call 150 */ 151 int 152 ffs_mount(mp, path, data, ndp, p) 153 register struct mount *mp; 154 const char *path; 155 void *data; 156 struct nameidata *ndp; 157 struct proc *p; 158 { 159 struct vnode *devvp; 160 struct ufs_args args; 161 struct ufsmount *ump = NULL; 162 register struct fs *fs; 163 int error = 0, flags; 164 int ronly; 165 mode_t accessmode; 166 size_t size; 167 168 error = copyin(data, &args, sizeof (struct ufs_args)); 169 if (error) 170 return (error); 171 172 #ifndef FFS_SOFTUPDATES 173 if (mp->mnt_flag & MNT_SOFTDEP) { 174 printf("WARNING: soft updates isn't compiled in\n"); 175 mp->mnt_flag &= ~MNT_SOFTDEP; 176 } 177 #endif 178 179 /* 180 * Soft updates is incompatible with "async", 181 * so if we are doing softupdates stop the user 182 * from setting the async flag. 183 */ 184 if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) == 185 (MNT_SOFTDEP | MNT_ASYNC)) { 186 return (EINVAL); 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; 198 199 if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 200 flags = WRITECLOSE; 201 if (mp->mnt_flag & MNT_FORCE) 202 flags |= FORCECLOSE; 203 if (fs->fs_flags & FS_DOSOFTDEP) { 204 error = softdep_flushfiles(mp, flags, p); 205 mp->mnt_flag &= ~MNT_SOFTDEP; 206 } else 207 error = ffs_flushfiles(mp, flags, p); 208 ronly = 1; 209 } 210 211 /* 212 * Flush soft dependencies if disabling it via an update 213 * mount. This may leave some items to be processed, 214 * so don't do this yet XXX. 215 */ 216 if ((fs->fs_flags & FS_DOSOFTDEP) && 217 !(mp->mnt_flag & MNT_SOFTDEP) && 218 !(mp->mnt_flag & MNT_RDONLY) && fs->fs_ronly == 0) { 219 #if 0 220 flags = WRITECLOSE; 221 if (mp->mnt_flag & MNT_FORCE) 222 flags |= FORCECLOSE; 223 error = softdep_flushfiles(mp, flags, p); 224 #elif FFS_SOFTUPDATES 225 mp->mnt_flag |= MNT_SOFTDEP; 226 #endif 227 } 228 /* 229 * When upgrading to a softdep mount, we must first flush 230 * all vnodes. (not done yet -- see above) 231 */ 232 if (!(fs->fs_flags & FS_DOSOFTDEP) && 233 (mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) { 234 #if 0 235 flags = WRITECLOSE; 236 if (mp->mnt_flag & MNT_FORCE) 237 flags |= FORCECLOSE; 238 error = ffs_flushfiles(mp, flags, p); 239 #else 240 mp->mnt_flag &= ~MNT_SOFTDEP; 241 #endif 242 } 243 244 if (!error && (mp->mnt_flag & MNT_RELOAD)) 245 error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); 246 if (error) 247 goto error_1; 248 249 if (ronly && (mp->mnt_flag & MNT_WANTRDWR)) { 250 /* 251 * If upgrade to read-write by non-root, then verify 252 * that user has necessary permissions on the device. 253 */ 254 if (p->p_ucred->cr_uid != 0) { 255 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 256 error = VOP_ACCESS(devvp, VREAD | VWRITE, 257 p->p_ucred, p); 258 VOP_UNLOCK(devvp, 0, p); 259 if (error) 260 goto error_1; 261 } 262 263 if (fs->fs_clean == 0) { 264 #if 0 265 /* 266 * It is safe mount unclean file system 267 * if it was previously mounted with softdep 268 * but we may loss space and must 269 * sometimes run fsck manually. 270 */ 271 if (fs->fs_flags & FS_DOSOFTDEP) 272 printf( 273 "WARNING: %s was not properly unmounted\n", 274 fs->fs_fsmnt); 275 else 276 #endif 277 if (mp->mnt_flag & MNT_FORCE) { 278 printf( 279 "WARNING: %s was not properly unmounted\n", 280 fs->fs_fsmnt); 281 } else { 282 printf( 283 "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", 284 fs->fs_fsmnt); 285 error = EPERM; 286 goto error_1; 287 } 288 } 289 290 if ((fs->fs_flags & FS_DOSOFTDEP)) { 291 error = softdep_mount(devvp, mp, fs, 292 p->p_ucred); 293 if (error) 294 goto error_1; 295 } 296 fs->fs_contigdirs=(u_int8_t*)malloc((u_long)fs->fs_ncg, 297 M_UFSMNT, M_WAITOK); 298 bzero(fs->fs_contigdirs, fs->fs_ncg); 299 300 ronly = 0; 301 } 302 if (args.fspec == 0) { 303 /* 304 * Process export requests. 305 */ 306 error = vfs_export(mp, &ump->um_export, &args.export); 307 if (error) 308 goto error_1; 309 else 310 goto success; 311 } 312 } 313 /* 314 * Not an update, or updating the name: look up the name 315 * and verify that it refers to a sensible block device. 316 */ 317 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 318 if ((error = namei(ndp)) != 0) 319 goto error_1; 320 321 devvp = ndp->ni_vp; 322 323 if (devvp->v_type != VBLK) { 324 error = ENOTBLK; 325 goto error_2; 326 } 327 328 if (major(devvp->v_rdev) >= nblkdev) { 329 error = ENXIO; 330 goto error_2; 331 } 332 333 /* 334 * If mount by non-root, then verify that user has necessary 335 * permissions on the device. 336 */ 337 if (p->p_ucred->cr_uid != 0) { 338 accessmode = VREAD; 339 if ((mp->mnt_flag & MNT_RDONLY) == 0) 340 accessmode |= VWRITE; 341 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 342 error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p); 343 VOP_UNLOCK(devvp, 0, p); 344 if (error) 345 goto error_2; 346 } 347 348 if (mp->mnt_flag & MNT_UPDATE) { 349 /* 350 * UPDATE 351 * If it's not the same vnode, or at least the same device 352 * then it's not correct. 353 */ 354 355 if (devvp != ump->um_devvp) { 356 if (devvp->v_rdev == ump->um_devvp->v_rdev) { 357 vrele(devvp); 358 } else { 359 error = EINVAL; /* needs translation */ 360 } 361 } else 362 vrele(devvp); 363 /* 364 * Update device name only on success 365 */ 366 if (!error) { 367 /* 368 * Save "mounted from" info for mount point (NULL pad) 369 */ 370 copyinstr(args.fspec, 371 mp->mnt_stat.f_mntfromname, 372 MNAMELEN - 1, 373 &size); 374 bzero(mp->mnt_stat.f_mntfromname + size, 375 MNAMELEN - size); 376 } 377 } else { 378 /* 379 * Since this is a new mount, we want the names for 380 * the device and the mount point copied in. If an 381 * error occurs, the mountpoint is discarded by the 382 * upper level code. 383 */ 384 /* Save "last mounted on" info for mount point (NULL pad)*/ 385 copyinstr(path, /* mount point*/ 386 mp->mnt_stat.f_mntonname, /* save area*/ 387 MNAMELEN - 1, /* max size*/ 388 &size); /* real size*/ 389 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 390 391 /* Save "mounted from" info for mount point (NULL pad)*/ 392 copyinstr(args.fspec, /* device name*/ 393 mp->mnt_stat.f_mntfromname, /* save area*/ 394 MNAMELEN - 1, /* max size*/ 395 &size); /* real size*/ 396 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 397 398 error = ffs_mountfs(devvp, mp, p); 399 } 400 401 if (error) 402 goto error_2; 403 404 /* 405 * Initialize FS stat information in mount struct; uses both 406 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname 407 * 408 * This code is common to root and non-root mounts 409 */ 410 bcopy(&args, &mp->mnt_stat.mount_info.ufs_args, sizeof(args)); 411 (void)VFS_STATFS(mp, &mp->mnt_stat, p); 412 413 success: 414 if (path && (mp->mnt_flag & MNT_UPDATE)) { 415 /* Update clean flag after changing read-onlyness. */ 416 fs = ump->um_fs; 417 if (ronly != fs->fs_ronly) { 418 fs->fs_ronly = ronly; 419 fs->fs_clean = ronly && 420 (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0; 421 if (ronly) 422 free(fs->fs_contigdirs, M_UFSMNT); 423 } 424 if (!ronly) { 425 if (mp->mnt_flag & MNT_SOFTDEP) 426 fs->fs_flags |= FS_DOSOFTDEP; 427 else 428 fs->fs_flags &= ~FS_DOSOFTDEP; 429 } 430 ffs_sbupdate(ump, MNT_WAIT); 431 } 432 return (0); 433 434 error_2: /* error with devvp held */ 435 vrele (devvp); 436 error_1: /* no state to back out */ 437 return (error); 438 } 439 440 441 struct ffs_reload_args { 442 struct fs *fs; 443 struct proc *p; 444 struct ucred *cred; 445 struct vnode *devvp; 446 }; 447 448 int 449 ffs_reload_vnode(struct vnode *vp, void *args) 450 { 451 struct ffs_reload_args *fra = args; 452 struct inode *ip; 453 struct buf *bp; 454 int error; 455 456 /* 457 * Step 4: invalidate all inactive vnodes. 458 */ 459 if (vp->v_usecount == 0) { 460 vgonel(vp, fra->p); 461 return (0); 462 } 463 464 /* 465 * Step 5: invalidate all cached file data. 466 */ 467 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, fra->p)) 468 return (0); 469 470 if (vinvalbuf(vp, 0, fra->cred, fra->p, 0, 0)) 471 panic("ffs_reload: dirty2"); 472 /* 473 * Step 6: re-read inode data for all active vnodes. 474 */ 475 ip = VTOI(vp); 476 error = bread(fra->devvp, 477 fsbtodb(fra->fs, ino_to_fsba(fra->fs, ip->i_number)), 478 (int)fra->fs->fs_bsize, NOCRED, &bp); 479 if (error) { 480 vput(vp); 481 return (error); 482 } 483 ip->i_din.ffs_din = *((struct dinode *)bp->b_data + 484 ino_to_fsbo(fra->fs, ip->i_number)); 485 ip->i_effnlink = ip->i_ffs_nlink; 486 brelse(bp); 487 vput(vp); 488 return (0); 489 } 490 491 /* 492 * Reload all incore data for a filesystem (used after running fsck on 493 * the root filesystem and finding things to fix). The filesystem must 494 * be mounted read-only. 495 * 496 * Things to do to update the mount: 497 * 1) invalidate all cached meta-data. 498 * 2) re-read superblock from disk. 499 * 3) re-read summary information from disk. 500 * 4) invalidate all inactive vnodes. 501 * 5) invalidate all cached file data. 502 * 6) re-read inode data for all active vnodes. 503 */ 504 int 505 ffs_reload(mountp, cred, p) 506 register struct mount *mountp; 507 struct ucred *cred; 508 struct proc *p; 509 { 510 struct vnode *devvp; 511 caddr_t space; 512 struct fs *fs, *newfs; 513 struct partinfo dpart; 514 int i, blks, size, error; 515 int32_t *lp; 516 struct buf *bp = NULL; 517 struct ffs_reload_args fra; 518 519 if ((mountp->mnt_flag & MNT_RDONLY) == 0) 520 return (EINVAL); 521 /* 522 * Step 1: invalidate all cached meta-data. 523 */ 524 devvp = VFSTOUFS(mountp)->um_devvp; 525 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 526 error = vinvalbuf(devvp, 0, cred, p, 0, 0); 527 VOP_UNLOCK(devvp, 0, p); 528 if (error) 529 panic("ffs_reload: dirty1"); 530 531 /* 532 * Step 2: re-read superblock from disk. 533 */ 534 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 535 size = DEV_BSIZE; 536 else 537 size = dpart.disklab->d_secsize; 538 error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp); 539 if (error) 540 return (error); 541 newfs = (struct fs *)bp->b_data; 542 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE || 543 newfs->fs_bsize < sizeof(struct fs)) { 544 brelse(bp); 545 return (EIO); /* XXX needs translation */ 546 } 547 fs = VFSTOUFS(mountp)->um_fs; 548 /* 549 * Copy pointer fields back into superblock before copying in XXX 550 * new superblock. These should really be in the ufsmount. XXX 551 * Note that important parameters (eg fs_ncg) are unchanged. 552 */ 553 newfs->fs_csp = fs->fs_csp; 554 newfs->fs_maxcluster = fs->fs_maxcluster; 555 newfs->fs_ronly = fs->fs_ronly; 556 bcopy(newfs, fs, (u_int)fs->fs_sbsize); 557 if (fs->fs_sbsize < SBSIZE) 558 bp->b_flags |= B_INVAL; 559 brelse(bp); 560 mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 561 ffs_oldfscompat(fs); 562 (void)ffs_statfs(mountp, &mountp->mnt_stat, p); 563 /* 564 * Step 3: re-read summary information from disk. 565 */ 566 blks = howmany(fs->fs_cssize, fs->fs_fsize); 567 space = (caddr_t)fs->fs_csp; 568 for (i = 0; i < blks; i += fs->fs_frag) { 569 size = fs->fs_bsize; 570 if (i + fs->fs_frag > blks) 571 size = (blks - i) * fs->fs_fsize; 572 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 573 NOCRED, &bp); 574 if (error) 575 return (error); 576 bcopy(bp->b_data, space, (u_int)size); 577 space += size; 578 brelse(bp); 579 } 580 if ((fs->fs_flags & FS_DOSOFTDEP)) 581 (void) softdep_mount(devvp, mountp, fs, cred); 582 /* 583 * We no longer know anything about clusters per cylinder group. 584 */ 585 if (fs->fs_contigsumsize > 0) { 586 lp = fs->fs_maxcluster; 587 for (i = 0; i < fs->fs_ncg; i++) 588 *lp++ = fs->fs_contigsumsize; 589 } 590 591 fra.p = p; 592 fra.cred = cred; 593 fra.fs = fs; 594 fra.devvp = devvp; 595 596 error = vfs_mount_foreach_vnode(mountp, ffs_reload_vnode, &fra); 597 598 return (error); 599 } 600 601 /* 602 * Common code for mount and mountroot 603 */ 604 int 605 ffs_mountfs(devvp, mp, p) 606 register struct vnode *devvp; 607 struct mount *mp; 608 struct proc *p; 609 { 610 register struct ufsmount *ump; 611 struct buf *bp; 612 register struct fs *fs; 613 dev_t dev; 614 struct partinfo dpart; 615 caddr_t space; 616 int error, i, blks, size, ronly; 617 int32_t *lp; 618 size_t strsize; 619 struct ucred *cred; 620 extern struct vnode *rootvp; 621 u_int64_t maxfilesize; /* XXX */ 622 623 dev = devvp->v_rdev; 624 cred = p ? p->p_ucred : NOCRED; 625 /* 626 * Disallow multiple mounts of the same device. 627 * Disallow mounting of a device that is currently in use 628 * (except for root, which might share swap device for miniroot). 629 * Flush out any old buffers remaining from a previous use. 630 */ 631 if ((error = vfs_mountedon(devvp)) != 0) 632 return (error); 633 if (vcount(devvp) > 1 && devvp != rootvp) 634 return (EBUSY); 635 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 636 error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0); 637 VOP_UNLOCK(devvp, 0, p); 638 if (error) 639 return (error); 640 641 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 642 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 643 if (error) 644 return (error); 645 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) 646 size = DEV_BSIZE; 647 else 648 size = dpart.disklab->d_secsize; 649 650 bp = NULL; 651 ump = NULL; 652 error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, cred, &bp); 653 if (error) 654 goto out; 655 fs = (struct fs *)bp->b_data; 656 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 657 fs->fs_bsize < sizeof(struct fs)) { 658 error = EFTYPE; /* Inappropriate format */ 659 goto out; 660 } 661 fs->fs_fmod = 0; 662 fs->fs_flags &= ~FS_UNCLEAN; 663 if (fs->fs_clean == 0) { 664 fs->fs_flags |= FS_UNCLEAN; 665 #if 0 666 /* 667 * It is safe mount unclean file system 668 * if it was previously mounted with softdep 669 * but we may loss space and must 670 * sometimes run fsck manually. 671 */ 672 if (fs->fs_flags & FS_DOSOFTDEP) 673 printf( 674 "WARNING: %s was not properly unmounted\n", 675 fs->fs_fsmnt); 676 else 677 #endif 678 if (ronly || (mp->mnt_flag & MNT_FORCE)) { 679 printf( 680 "WARNING: %s was not properly unmounted\n", 681 fs->fs_fsmnt); 682 } else { 683 printf( 684 "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", 685 fs->fs_fsmnt); 686 error = EPERM; 687 goto out; 688 } 689 } 690 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ 691 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { 692 error = EROFS; /* XXX what should be returned? */ 693 goto out; 694 } 695 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 696 bzero((caddr_t)ump, sizeof *ump); 697 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, 698 M_WAITOK); 699 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize); 700 if (fs->fs_sbsize < SBSIZE) 701 bp->b_flags |= B_INVAL; 702 brelse(bp); 703 bp = NULL; 704 fs = ump->um_fs; 705 fs->fs_ronly = ronly; 706 size = fs->fs_cssize; 707 blks = howmany(size, fs->fs_fsize); 708 if (fs->fs_contigsumsize > 0) 709 size += fs->fs_ncg * sizeof(int32_t); 710 space = malloc((u_long)size, M_UFSMNT, M_WAITOK); 711 fs->fs_csp = (struct csum *)space; 712 for (i = 0; i < blks; i += fs->fs_frag) { 713 size = fs->fs_bsize; 714 if (i + fs->fs_frag > blks) 715 size = (blks - i) * fs->fs_fsize; 716 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 717 cred, &bp); 718 if (error) { 719 free(fs->fs_csp, M_UFSMNT); 720 goto out; 721 } 722 bcopy(bp->b_data, space, (u_int)size); 723 space += size; 724 brelse(bp); 725 bp = NULL; 726 } 727 if (fs->fs_contigsumsize > 0) { 728 fs->fs_maxcluster = lp = (int32_t *)space; 729 for (i = 0; i < fs->fs_ncg; i++) 730 *lp++ = fs->fs_contigsumsize; 731 } 732 mp->mnt_data = (qaddr_t)ump; 733 mp->mnt_stat.f_fsid.val[0] = (long)dev; 734 /* Use on-disk fsid if it exists, else fake it */ 735 if (fs->fs_id[0] != 0 && fs->fs_id[1] != 0) 736 mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1]; 737 else 738 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 739 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 740 mp->mnt_flag |= MNT_LOCAL; 741 ump->um_mountp = mp; 742 ump->um_dev = dev; 743 ump->um_devvp = devvp; 744 ump->um_nindir = fs->fs_nindir; 745 ump->um_bptrtodb = fs->fs_fsbtodb; 746 ump->um_seqinc = fs->fs_frag; 747 for (i = 0; i < MAXQUOTAS; i++) 748 ump->um_quotas[i] = NULLVP; 749 devvp->v_specmountpoint = mp; 750 ffs_oldfscompat(fs); 751 752 if (ronly) 753 fs->fs_contigdirs = NULL; 754 else { 755 fs->fs_contigdirs = (u_int8_t*)malloc((u_long)fs->fs_ncg, 756 M_UFSMNT, M_WAITOK); 757 bzero(fs->fs_contigdirs, fs->fs_ncg); 758 } 759 760 /* 761 * Set FS local "last mounted on" information (NULL pad) 762 */ 763 copystr(mp->mnt_stat.f_mntonname, /* mount point*/ 764 fs->fs_fsmnt, /* copy area*/ 765 sizeof(fs->fs_fsmnt) - 1, /* max size*/ 766 &strsize); /* real size*/ 767 bzero(fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize); 768 769 #if 0 770 if( mp->mnt_flag & MNT_ROOTFS) { 771 /* 772 * Root mount; update timestamp in mount structure. 773 * this will be used by the common root mount code 774 * to update the system clock. 775 */ 776 mp->mnt_time = fs->fs_time; 777 } 778 #endif 779 780 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */ 781 maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1; /* XXX */ 782 if (fs->fs_maxfilesize > maxfilesize) /* XXX */ 783 fs->fs_maxfilesize = maxfilesize; /* XXX */ 784 if (ronly == 0) { 785 if ((fs->fs_flags & FS_DOSOFTDEP) && 786 (error = softdep_mount(devvp, mp, fs, cred)) != 0) { 787 free(fs->fs_csp, M_UFSMNT); 788 free(fs->fs_contigdirs, M_UFSMNT); 789 goto out; 790 } 791 fs->fs_fmod = 1; 792 fs->fs_clean = 0; 793 if (mp->mnt_flag & MNT_SOFTDEP) 794 fs->fs_flags |= FS_DOSOFTDEP; 795 else 796 fs->fs_flags &= ~FS_DOSOFTDEP; 797 (void) ffs_sbupdate(ump, MNT_WAIT); 798 } 799 return (0); 800 out: 801 devvp->v_specmountpoint = NULL; 802 if (bp) 803 brelse(bp); 804 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); 805 if (ump) { 806 free(ump->um_fs, M_UFSMNT); 807 free(ump, M_UFSMNT); 808 mp->mnt_data = (qaddr_t)0; 809 } 810 return (error); 811 } 812 813 /* 814 * Sanity checks for old file systems. 815 * 816 * XXX - goes away some day. 817 */ 818 int 819 ffs_oldfscompat(fs) 820 struct fs *fs; 821 { 822 int i; 823 824 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ 825 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ 826 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 827 fs->fs_nrpos = 8; /* XXX */ 828 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 829 u_int64_t sizepb = fs->fs_bsize; /* XXX */ 830 /* XXX */ 831 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ 832 for (i = 0; i < NIADDR; i++) { /* XXX */ 833 sizepb *= NINDIR(fs); /* XXX */ 834 fs->fs_maxfilesize += sizepb; /* XXX */ 835 } /* XXX */ 836 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ 837 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ 838 } /* XXX */ 839 if (fs->fs_avgfilesize <= 0) /* XXX */ 840 fs->fs_avgfilesize = AVFILESIZ; /* XXX */ 841 if (fs->fs_avgfpdir <= 0) /* XXX */ 842 fs->fs_avgfpdir = AFPDIR; /* XXX */ 843 return (0); 844 } 845 846 /* 847 * unmount system call 848 */ 849 int 850 ffs_unmount(mp, mntflags, p) 851 struct mount *mp; 852 int mntflags; 853 struct proc *p; 854 { 855 register struct ufsmount *ump; 856 register struct fs *fs; 857 int error, flags; 858 859 flags = 0; 860 if (mntflags & MNT_FORCE) 861 flags |= FORCECLOSE; 862 863 ump = VFSTOUFS(mp); 864 fs = ump->um_fs; 865 if (mp->mnt_flag & MNT_SOFTDEP) 866 error = softdep_flushfiles(mp, flags, p); 867 else 868 error = ffs_flushfiles(mp, flags, p); 869 if (error != 0) 870 return (error); 871 872 if (fs->fs_ronly == 0) { 873 fs->fs_clean = (fs->fs_flags & FS_UNCLEAN) ? 0 : 1; 874 error = ffs_sbupdate(ump, MNT_WAIT); 875 if (error) { 876 fs->fs_clean = 0; 877 return (error); 878 } 879 free(fs->fs_contigdirs, M_UFSMNT); 880 } 881 ump->um_devvp->v_specmountpoint = NULL; 882 883 vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0); 884 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, 885 NOCRED, p); 886 vrele(ump->um_devvp); 887 free(fs->fs_csp, M_UFSMNT); 888 free(fs, M_UFSMNT); 889 free(ump, M_UFSMNT); 890 mp->mnt_data = (qaddr_t)0; 891 mp->mnt_flag &= ~MNT_LOCAL; 892 return (error); 893 } 894 895 /* 896 * Flush out all the files in a filesystem. 897 */ 898 int 899 ffs_flushfiles(mp, flags, p) 900 register struct mount *mp; 901 int flags; 902 struct proc *p; 903 { 904 register struct ufsmount *ump; 905 int error; 906 907 ump = VFSTOUFS(mp); 908 if (mp->mnt_flag & MNT_QUOTA) { 909 int i; 910 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0) 911 return (error); 912 for (i = 0; i < MAXQUOTAS; i++) { 913 if (ump->um_quotas[i] == NULLVP) 914 continue; 915 quotaoff(p, mp, i); 916 } 917 /* 918 * Here we fall through to vflush again to ensure 919 * that we have gotten rid of all the system vnodes. 920 */ 921 } 922 923 /* 924 * Flush all the files. 925 */ 926 if ((error = vflush(mp, NULL, flags)) != 0) 927 return (error); 928 /* 929 * Flush filesystem metadata. 930 */ 931 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); 932 error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p); 933 VOP_UNLOCK(ump->um_devvp, 0, p); 934 return (error); 935 } 936 937 /* 938 * Get file system statistics. 939 */ 940 int 941 ffs_statfs(mp, sbp, p) 942 struct mount *mp; 943 register struct statfs *sbp; 944 struct proc *p; 945 { 946 register struct ufsmount *ump; 947 register struct fs *fs; 948 949 ump = VFSTOUFS(mp); 950 fs = ump->um_fs; 951 if (fs->fs_magic != FS_MAGIC) 952 panic("ffs_statfs"); 953 sbp->f_bsize = fs->fs_fsize; 954 sbp->f_iosize = fs->fs_bsize; 955 sbp->f_blocks = fs->fs_dsize; 956 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 957 fs->fs_cstotal.cs_nffree; 958 sbp->f_bavail = sbp->f_bfree - fs->fs_dsize * fs->fs_minfree / 100; 959 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 960 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 961 if (sbp != &mp->mnt_stat) { 962 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 963 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 964 bcopy(&mp->mnt_stat.mount_info.ufs_args, 965 &sbp->mount_info.ufs_args, sizeof(struct ufs_args)); 966 } 967 strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN); 968 return (0); 969 } 970 971 972 struct ffs_sync_args { 973 int allerror; 974 struct proc *p; 975 int waitfor; 976 struct ucred *cred; 977 }; 978 979 int 980 ffs_sync_vnode(struct vnode *vp, void *arg) { 981 struct ffs_sync_args *fsa = arg; 982 struct inode *ip; 983 int error; 984 985 ip = VTOI(vp); 986 if (fsa->waitfor == MNT_LAZY || 987 vp->v_type == VNON || 988 ((ip->i_flag & 989 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && 990 LIST_EMPTY(&vp->v_dirtyblkhd)) ) { 991 simple_unlock(&vp->v_interlock); 992 return (0); 993 } 994 995 if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, fsa->p)) 996 return (0); 997 998 if ((error = VOP_FSYNC(vp, fsa->cred, fsa->waitfor, fsa->p))) 999 fsa->allerror = error; 1000 VOP_UNLOCK(vp, 0, fsa->p); 1001 vrele(vp); 1002 1003 return (0); 1004 } 1005 1006 /* 1007 * Go through the disk queues to initiate sandbagged IO; 1008 * go through the inodes to write those that have been modified; 1009 * initiate the writing of the super block if it has been modified. 1010 * 1011 * Note: we are always called with the filesystem marked `MPBUSY'. 1012 */ 1013 int 1014 ffs_sync(mp, waitfor, cred, p) 1015 struct mount *mp; 1016 int waitfor; 1017 struct ucred *cred; 1018 struct proc *p; 1019 { 1020 struct ufsmount *ump = VFSTOUFS(mp); 1021 struct fs *fs; 1022 int error, allerror = 0, count; 1023 struct ffs_sync_args fsa; 1024 1025 fs = ump->um_fs; 1026 /* 1027 * Write back modified superblock. 1028 * Consistency check that the superblock 1029 * is still in the buffer cache. 1030 */ 1031 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { 1032 printf("fs = %s\n", fs->fs_fsmnt); 1033 panic("update: rofs mod"); 1034 } 1035 1036 loop: 1037 /* 1038 * Write back each (modified) inode. 1039 */ 1040 fsa.allerror = 0; 1041 fsa.p = p; 1042 fsa.cred = cred; 1043 fsa.waitfor = waitfor; 1044 1045 vfs_mount_foreach_vnode(mp, ffs_sync_vnode, &fsa); 1046 1047 if (fsa.allerror != 0) 1048 allerror = fsa.allerror; 1049 /* 1050 * Force stale file system control information to be flushed. 1051 */ 1052 if ((ump->um_mountp->mnt_flag & MNT_SOFTDEP) && waitfor == MNT_WAIT) { 1053 if ((error = softdep_flushworklist(ump->um_mountp, &count, p))) 1054 allerror = error; 1055 /* Flushed work items may create new vnodes to clean */ 1056 if (count) 1057 goto loop; 1058 } 1059 if (waitfor != MNT_LAZY) { 1060 if (ump->um_mountp->mnt_flag & MNT_SOFTDEP) 1061 waitfor = MNT_NOWAIT; 1062 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); 1063 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0) 1064 allerror = error; 1065 VOP_UNLOCK(ump->um_devvp, 0, p); 1066 } 1067 qsync(mp); 1068 /* 1069 * Write back modified superblock. 1070 */ 1071 1072 if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0) 1073 allerror = error; 1074 1075 return (allerror); 1076 } 1077 1078 /* 1079 * Look up a FFS dinode number to find its incore vnode, otherwise read it 1080 * in from disk. If it is in core, wait for the lock bit to clear, then 1081 * return the inode locked. Detection and handling of mount points must be 1082 * done by the calling routine. 1083 */ 1084 int 1085 ffs_vget(mp, ino, vpp) 1086 struct mount *mp; 1087 ino_t ino; 1088 struct vnode **vpp; 1089 { 1090 register struct fs *fs; 1091 register struct inode *ip; 1092 struct ufsmount *ump; 1093 struct buf *bp; 1094 struct vnode *vp; 1095 dev_t dev; 1096 int error; 1097 1098 ump = VFSTOUFS(mp); 1099 dev = ump->um_dev; 1100 1101 retry: 1102 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 1103 return (0); 1104 1105 /* Allocate a new vnode/inode. */ 1106 if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) { 1107 *vpp = NULL; 1108 return (error); 1109 } 1110 #ifdef LOCKDEBUG 1111 vp->v_flag |= VLOCKSWORK; 1112 #endif 1113 /* XXX - we use the same pool for ffs and mfs */ 1114 ip = pool_get(&ffs_ino_pool, PR_WAITOK); 1115 bzero((caddr_t)ip, sizeof(struct inode)); 1116 lockinit(&ip->i_lock, PINOD, "inode", 0, 0); 1117 vp->v_data = ip; 1118 ip->i_vnode = vp; 1119 ip->i_fs = fs = ump->um_fs; 1120 ip->i_dev = dev; 1121 ip->i_number = ino; 1122 ip->i_vtbl = &ffs_vtbl; 1123 1124 /* 1125 * Put it onto its hash chain and lock it so that other requests for 1126 * this inode will block if they arrive while we are sleeping waiting 1127 * for old data structures to be purged or for the contents of the 1128 * disk portion of this inode to be read. 1129 */ 1130 error = ufs_ihashins(ip); 1131 1132 if (error) { 1133 /* 1134 * VOP_INACTIVE will treat this as a stale file 1135 * and recycle it quickly 1136 */ 1137 vrele(vp); 1138 1139 if (error == EEXIST) 1140 goto retry; 1141 1142 return (error); 1143 } 1144 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, NOCRED, &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 vput(vp); 1157 brelse(bp); 1158 *vpp = NULL; 1159 return (error); 1160 } 1161 ip->i_din.ffs_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_ffs_nlink; 1166 brelse(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, ffs_specop_p, FFS_FIFOOPS, &vp); 1173 if (error) { 1174 vput(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_ffs_gen == 0) { 1188 ip->i_ffs_gen = arc4random(); 1189 if (ip->i_ffs_gen == 0 || ip->i_ffs_gen == -1) 1190 ip->i_ffs_gen = 1; /* shouldn't happen */ 1191 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 1192 ip->i_flag |= IN_MODIFIED; 1193 } 1194 /* 1195 * Ensure that uid and gid are correct. This is a temporary 1196 * fix until fsck has been changed to do the update. 1197 */ 1198 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 1199 ip->i_ffs_uid = ip->i_din.ffs_din.di_ouid; /* XXX */ 1200 ip->i_ffs_gid = ip->i_din.ffs_din.di_ogid; /* XXX */ 1201 } /* XXX */ 1202 1203 *vpp = vp; 1204 return (0); 1205 } 1206 1207 /* 1208 * File handle to vnode 1209 * 1210 * Have to be really careful about stale file handles: 1211 * - check that the inode number is valid 1212 * - call ffs_vget() to get the locked inode 1213 * - check for an unallocated inode (i_mode == 0) 1214 */ 1215 int 1216 ffs_fhtovp(mp, fhp, vpp) 1217 register struct mount *mp; 1218 struct fid *fhp; 1219 struct vnode **vpp; 1220 { 1221 register struct ufid *ufhp; 1222 struct fs *fs; 1223 1224 ufhp = (struct ufid *)fhp; 1225 fs = VFSTOUFS(mp)->um_fs; 1226 if (ufhp->ufid_ino < ROOTINO || 1227 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 1228 return (ESTALE); 1229 return (ufs_fhtovp(mp, ufhp, vpp)); 1230 } 1231 1232 /* 1233 * Vnode pointer to File handle 1234 */ 1235 /* ARGSUSED */ 1236 int 1237 ffs_vptofh(vp, fhp) 1238 struct vnode *vp; 1239 struct fid *fhp; 1240 { 1241 register struct inode *ip; 1242 register struct ufid *ufhp; 1243 1244 ip = VTOI(vp); 1245 ufhp = (struct ufid *)fhp; 1246 ufhp->ufid_len = sizeof(struct ufid); 1247 ufhp->ufid_ino = ip->i_number; 1248 ufhp->ufid_gen = ip->i_ffs_gen; 1249 return (0); 1250 } 1251 1252 /* 1253 * Write a superblock and associated information back to disk. 1254 */ 1255 int 1256 ffs_sbupdate(mp, waitfor) 1257 struct ufsmount *mp; 1258 int waitfor; 1259 { 1260 register struct fs *dfs, *fs = mp->um_fs; 1261 register struct buf *bp; 1262 int blks; 1263 caddr_t space; 1264 int i, size, error, allerror = 0; 1265 1266 /* 1267 * First write back the summary information. 1268 */ 1269 blks = howmany(fs->fs_cssize, fs->fs_fsize); 1270 space = (caddr_t)fs->fs_csp; 1271 for (i = 0; i < blks; i += fs->fs_frag) { 1272 size = fs->fs_bsize; 1273 if (i + fs->fs_frag > blks) 1274 size = (blks - i) * fs->fs_fsize; 1275 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), 1276 size, 0, 0); 1277 bcopy(space, bp->b_data, (u_int)size); 1278 space += size; 1279 if (waitfor != MNT_WAIT) 1280 bawrite(bp); 1281 else if ((error = bwrite(bp))) 1282 allerror = error; 1283 } 1284 /* 1285 * Now write back the superblock itself. If any errors occurred 1286 * up to this point, then fail so that the superblock avoids 1287 * being written out as clean. 1288 */ 1289 if (allerror) 1290 return (allerror); 1291 1292 bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb), 1293 (int)fs->fs_sbsize, 0, 0); 1294 fs->fs_fmod = 0; 1295 fs->fs_time = time.tv_sec; 1296 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize); 1297 /* Restore compatibility to old file systems. XXX */ 1298 dfs = (struct fs *)bp->b_data; /* XXX */ 1299 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 1300 dfs->fs_nrpos = -1; /* XXX */ 1301 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 1302 int32_t *lp, tmp; /* XXX */ 1303 /* XXX */ 1304 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */ 1305 tmp = lp[4]; /* XXX */ 1306 for (i = 4; i > 0; i--) /* XXX */ 1307 lp[i] = lp[i-1]; /* XXX */ 1308 lp[0] = tmp; /* XXX */ 1309 } /* XXX */ 1310 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */ 1311 if (waitfor != MNT_WAIT) 1312 bawrite(bp); 1313 else if ((error = bwrite(bp))) 1314 allerror = error; 1315 return (allerror); 1316 } 1317 1318 int 1319 ffs_init(vfsp) 1320 struct vfsconf *vfsp; 1321 { 1322 static int done; 1323 1324 if (done) 1325 return (0); 1326 done = 1; 1327 pool_init(&ffs_ino_pool, sizeof(struct inode), 0, 0, 0, "ffsino", 1328 0, pool_page_alloc_nointr, pool_page_free_nointr, M_FFSNODE); 1329 softdep_initialize(); 1330 return (ufs_init(vfsp)); 1331 } 1332 1333 /* 1334 * fast filesystem related variables. 1335 */ 1336 int 1337 ffs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 1338 int *name; 1339 u_int namelen; 1340 void *oldp; 1341 size_t *oldlenp; 1342 void *newp; 1343 size_t newlen; 1344 struct proc *p; 1345 { 1346 extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree; 1347 1348 /* all sysctl names at this level are terminal */ 1349 if (namelen != 1) 1350 return (ENOTDIR); /* overloaded */ 1351 1352 switch (name[0]) { 1353 case FFS_CLUSTERREAD: 1354 return (sysctl_int(oldp, oldlenp, newp, newlen, 1355 &doclusterread)); 1356 case FFS_CLUSTERWRITE: 1357 return (sysctl_int(oldp, oldlenp, newp, newlen, 1358 &doclusterwrite)); 1359 case FFS_REALLOCBLKS: 1360 return (sysctl_int(oldp, oldlenp, newp, newlen, 1361 &doreallocblks)); 1362 case FFS_ASYNCFREE: 1363 return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree)); 1364 default: 1365 return (EOPNOTSUPP); 1366 } 1367 /* NOTREACHED */ 1368 } 1369