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