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