1 /* $NetBSD: ffs_vfsops.c,v 1.385 2026/07/22 14:44:49 hannken Exp $ */ 2 3 /*- 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wasabi Systems, Inc, and by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1989, 1991, 1993, 1994 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.385 2026/07/22 14:44:49 hannken Exp $"); 65 66 #if defined(_KERNEL_OPT) 67 #include "opt_ffs.h" 68 #include "opt_quota.h" 69 #include "opt_wapbl.h" 70 #endif 71 72 #include <sys/param.h> 73 #include <sys/systm.h> 74 #include <sys/namei.h> 75 #include <sys/proc.h> 76 #include <sys/kernel.h> 77 #include <sys/vnode.h> 78 #include <sys/fstrans.h> 79 #include <sys/socket.h> 80 #include <sys/mount.h> 81 #include <sys/buf.h> 82 #include <sys/device.h> 83 #include <sys/disk.h> 84 #include <sys/file.h> 85 #include <sys/disklabel.h> 86 #include <sys/ioctl.h> 87 #include <sys/errno.h> 88 #include <sys/kmem.h> 89 #include <sys/pool.h> 90 #include <sys/lock.h> 91 #include <sys/sysctl.h> 92 #include <sys/conf.h> 93 #include <sys/kauth.h> 94 #include <sys/wapbl.h> 95 #include <sys/module.h> 96 97 #include <miscfs/genfs/genfs.h> 98 #include <miscfs/specfs/specdev.h> 99 100 #include <ufs/ufs/quota.h> 101 #include <ufs/ufs/ufsmount.h> 102 #include <ufs/ufs/inode.h> 103 #include <ufs/ufs/dir.h> 104 #include <ufs/ufs/ufs_extern.h> 105 #include <ufs/ufs/ufs_bswap.h> 106 #include <ufs/ufs/ufs_wapbl.h> 107 108 #include <ufs/ffs/fs.h> 109 #include <ufs/ffs/ffs_extern.h> 110 111 #ifdef WAPBL 112 MODULE(MODULE_CLASS_VFS, ffs, "ufs,wapbl"); 113 #else 114 MODULE(MODULE_CLASS_VFS, ffs, "ufs"); 115 #endif 116 117 static int ffs_vfs_fsync(vnode_t *, int); 118 static int ffs_superblock_validate(struct fs *); 119 static int ffs_is_appleufs(struct vnode *, struct fs *); 120 121 static int ffs_init_vnode(struct ufsmount *, struct vnode *, ino_t); 122 static void ffs_deinit_vnode(struct ufsmount *, struct vnode *); 123 124 static kauth_listener_t ffs_snapshot_listener; 125 126 /* how many times ffs_init() was called */ 127 int ffs_initcount = 0; 128 129 #ifdef DEBUG_FFS_MOUNT 130 #define DPRINTF(_fmt, args...) printf("%s: " _fmt "\n", __func__, ##args) 131 #else 132 #define DPRINTF(_fmt, args...) do {} while (/*CONSTCOND*/0) 133 #endif 134 135 extern const struct vnodeopv_desc ffs_vnodeop_opv_desc; 136 extern const struct vnodeopv_desc ffs_specop_opv_desc; 137 extern const struct vnodeopv_desc ffs_fifoop_opv_desc; 138 139 const struct vnodeopv_desc * const ffs_vnodeopv_descs[] = { 140 &ffs_vnodeop_opv_desc, 141 &ffs_specop_opv_desc, 142 &ffs_fifoop_opv_desc, 143 NULL, 144 }; 145 146 struct vfsops ffs_vfsops = { 147 .vfs_name = MOUNT_FFS, 148 .vfs_min_mount_data = sizeof (struct ufs_args), 149 .vfs_mount = ffs_mount, 150 .vfs_start = ufs_start, 151 .vfs_unmount = ffs_unmount, 152 .vfs_root = ufs_root, 153 .vfs_quotactl = ufs_quotactl, 154 .vfs_statvfs = ffs_statvfs, 155 .vfs_sync = ffs_sync, 156 .vfs_vget = ufs_vget, 157 .vfs_loadvnode = ffs_loadvnode, 158 .vfs_newvnode = ffs_newvnode, 159 .vfs_fhtovp = ffs_fhtovp, 160 .vfs_vptofh = ffs_vptofh, 161 .vfs_init = ffs_init, 162 .vfs_reinit = ffs_reinit, 163 .vfs_done = ffs_done, 164 .vfs_mountroot = ffs_mountroot, 165 #ifndef FFS_NO_SNAPSHOT 166 .vfs_snapshot = ffs_snapshot, 167 #else 168 .vfs_snapshot = (void *)eopnotsupp, 169 #endif 170 .vfs_extattrctl = ffs_extattrctl, 171 .vfs_suspendctl = genfs_suspendctl, 172 .vfs_renamelock_enter = genfs_renamelock_enter, 173 .vfs_renamelock_exit = genfs_renamelock_exit, 174 .vfs_fsync = ffs_vfs_fsync, 175 .vfs_opv_descs = ffs_vnodeopv_descs 176 }; 177 178 static const struct genfs_ops ffs_genfsops = { 179 .gop_size = ffs_gop_size, 180 .gop_alloc = ufs_gop_alloc, 181 .gop_write = genfs_gop_write, 182 .gop_markupdate = ufs_gop_markupdate, 183 .gop_putrange = genfs_gop_putrange, 184 }; 185 186 static const struct ufs_ops ffs_ufsops = { 187 .uo_itimes = ffs_itimes, 188 .uo_update = ffs_update, 189 .uo_truncate = ffs_truncate, 190 .uo_balloc = ffs_balloc, 191 .uo_snapgone = ffs_snapgone, 192 .uo_bufrd = ffs_bufrd, 193 .uo_bufwr = ffs_bufwr, 194 }; 195 196 #ifdef FFS_NO_SNAPSHOT 197 void 198 ffs_snapgone(struct vnode *vp) 199 { 200 201 panic("%s: unexpected snapshot", __func__); 202 } 203 #endif 204 205 static int 206 ffs_checkrange(struct mount *mp, ino_t ino) 207 { 208 struct fs *fs = VFSTOUFS(mp)->um_fs; 209 210 if (ino < UFS_ROOTINO || ino >= fs->fs_ncg * fs->fs_ipg) { 211 DPRINTF("out of range %" PRIu64 "\n", ino); 212 return ESTALE; 213 } 214 215 /* 216 * Need to check if inode is initialized because ffsv2 does 217 * lazy initialization and we can get here from nfs_fhtovp 218 */ 219 if (fs->fs_magic != FS_UFS2_MAGIC) 220 return 0; 221 222 struct buf *bp; 223 int cg = ino_to_cg(fs, ino); 224 struct ufsmount *ump = VFSTOUFS(mp); 225 226 int error = bread(ump->um_devvp, FFS_FSBTODB(fs, cgtod(fs, cg)), 227 (int)fs->fs_cgsize, B_MODIFY, &bp); 228 if (error) { 229 DPRINTF("error %d reading cg %d ino %" PRIu64 "\n", 230 error, cg, ino); 231 return error; 232 } 233 234 const int needswap = UFS_FSNEEDSWAP(fs); 235 236 struct cg *cgp = (struct cg *)bp->b_data; 237 if (!cg_chkmagic(cgp, needswap)) { 238 brelse(bp, 0); 239 DPRINTF("bad cylinder group magic cg %d ino %" PRIu64 "\n", 240 cg, ino); 241 return ESTALE; 242 } 243 244 int32_t initediblk = ufs_rw32(cgp->cg_initediblk, needswap); 245 brelse(bp, 0); 246 247 if (cg * fs->fs_ipg + initediblk < ino) { 248 DPRINTF("cg=%d fs->fs_ipg=%d initediblk=%d ino=%" PRIu64 "\n", 249 cg, fs->fs_ipg, initediblk, ino); 250 return ESTALE; 251 } 252 return 0; 253 } 254 255 static int 256 ffs_snapshot_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 257 void *arg0, void *arg1, void *arg2, void *arg3) 258 { 259 vnode_t *vp = arg2; 260 int result = KAUTH_RESULT_DEFER; 261 262 if (action != KAUTH_SYSTEM_FS_SNAPSHOT) 263 return result; 264 265 if (VTOI(vp)->i_uid == kauth_cred_geteuid(cred)) 266 result = KAUTH_RESULT_ALLOW; 267 268 return result; 269 } 270 271 SYSCTL_SETUP(ffs_sysctl_setup, "ffs sysctls") 272 { 273 #ifdef UFS_EXTATTR 274 extern int ufs_extattr_autocreate; 275 #endif 276 extern int ffs_log_changeopt; 277 278 sysctl_createv(clog, 0, NULL, NULL, 279 CTLFLAG_PERMANENT, 280 CTLTYPE_NODE, "ffs", 281 SYSCTL_DESCR("Berkeley Fast File System"), 282 NULL, 0, NULL, 0, 283 CTL_VFS, 1, CTL_EOL); 284 /* 285 * @@@ should we even bother with these first three? 286 */ 287 sysctl_createv(clog, 0, NULL, NULL, 288 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 289 CTLTYPE_INT, "doclusterread", NULL, 290 sysctl_notavail, 0, NULL, 0, 291 CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL); 292 sysctl_createv(clog, 0, NULL, NULL, 293 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 294 CTLTYPE_INT, "doclusterwrite", NULL, 295 sysctl_notavail, 0, NULL, 0, 296 CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL); 297 sysctl_createv(clog, 0, NULL, NULL, 298 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 299 CTLTYPE_INT, "doreallocblks", NULL, 300 sysctl_notavail, 0, NULL, 0, 301 CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL); 302 #if 0 303 sysctl_createv(clog, 0, NULL, NULL, 304 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 305 CTLTYPE_INT, "doasyncfree", 306 SYSCTL_DESCR("Release dirty blocks asynchronously"), 307 NULL, 0, &doasyncfree, 0, 308 CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL); 309 #endif 310 sysctl_createv(clog, 0, NULL, NULL, 311 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 312 CTLTYPE_INT, "log_changeopt", 313 SYSCTL_DESCR("Log changes in optimization strategy"), 314 NULL, 0, &ffs_log_changeopt, 0, 315 CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL); 316 #ifdef UFS_EXTATTR 317 sysctl_createv(clog, 0, NULL, NULL, 318 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 319 CTLTYPE_INT, "extattr_autocreate", 320 SYSCTL_DESCR("Size of attribute for " 321 "backing file autocreation"), 322 NULL, 0, &ufs_extattr_autocreate, 0, 323 CTL_VFS, 1, FFS_EXTATTR_AUTOCREATE, CTL_EOL); 324 325 #endif /* UFS_EXTATTR */ 326 } 327 328 static int 329 ffs_modcmd(modcmd_t cmd, void *arg) 330 { 331 int error; 332 333 #if 0 334 extern int doasyncfree; 335 #endif 336 337 switch (cmd) { 338 case MODULE_CMD_INIT: 339 error = vfs_attach(&ffs_vfsops); 340 if (error != 0) 341 break; 342 343 ffs_snapshot_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 344 ffs_snapshot_cb, NULL); 345 if (ffs_snapshot_listener == NULL) 346 printf("ffs_modcmd: can't listen on system scope.\n"); 347 348 break; 349 case MODULE_CMD_FINI: 350 error = vfs_detach(&ffs_vfsops); 351 if (error != 0) 352 break; 353 if (ffs_snapshot_listener != NULL) 354 kauth_unlisten_scope(ffs_snapshot_listener); 355 break; 356 default: 357 error = ENOTTY; 358 break; 359 } 360 361 return (error); 362 } 363 364 pool_cache_t ffs_inode_cache; 365 pool_cache_t ffs_dinode1_cache; 366 pool_cache_t ffs_dinode2_cache; 367 368 static void ffs_oldfscompat_read(struct fs *, struct ufsmount *, daddr_t); 369 static void ffs_oldfscompat_write(struct fs *, struct ufsmount *); 370 371 /* 372 * Called by main() when ffs is going to be mounted as root. 373 */ 374 375 int 376 ffs_mountroot(void) 377 { 378 struct fs *fs; 379 struct mount *mp; 380 struct lwp *l = curlwp; /* XXX */ 381 struct ufsmount *ump; 382 int error; 383 384 if (device_class(root_device) != DV_DISK) 385 return (ENODEV); 386 387 if ((error = vfs_rootmountalloc(MOUNT_FFS, "root_device", &mp))) { 388 vrele(rootvp); 389 return (error); 390 } 391 392 /* 393 * We always need to be able to mount the root file system. 394 */ 395 mp->mnt_flag |= MNT_FORCE; 396 if ((error = ffs_mountfs(rootvp, mp, l)) != 0) { 397 vfs_unbusy(mp); 398 vfs_rele(mp); 399 return (error); 400 } 401 mp->mnt_flag &= ~MNT_FORCE; 402 mountlist_append(mp); 403 ump = VFSTOUFS(mp); 404 fs = ump->um_fs; 405 memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt)); 406 (void)copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0); 407 (void)ffs_statvfs(mp, &mp->mnt_stat); 408 vfs_unbusy(mp); 409 setrootfstime((time_t)fs->fs_time); 410 return (0); 411 } 412 413 static int 414 ffs_acls(struct mount *mp, int fs_flags) 415 { 416 struct ufsmount *ump; 417 418 ump = VFSTOUFS(mp); 419 if (ump->um_fstype == UFS2 && (ump->um_flags & UFS_EA) == 0 && 420 ((mp->mnt_flag & (MNT_POSIX1EACLS | MNT_NFS4ACLS)) != 0 || 421 (fs_flags & (FS_POSIX1EACLS | FS_NFS4ACLS)) != 0)) { 422 printf("%s: ACLs requested but not supported by this fs\n", 423 mp->mnt_stat.f_mntonname); 424 return EINVAL; 425 } 426 427 if ((fs_flags & FS_POSIX1EACLS) != 0) { 428 #ifdef UFS_ACL 429 if (mp->mnt_flag & MNT_NFS4ACLS) 430 printf("WARNING: %s: POSIX.1e ACLs flag on fs conflicts " 431 "with \"nfsv4acls\" mount option; option ignored\n", 432 mp->mnt_stat.f_mntonname); 433 mp->mnt_flag &= ~MNT_NFS4ACLS; 434 mp->mnt_flag |= MNT_POSIX1EACLS; 435 #else 436 printf("WARNING: %s: POSIX.1e ACLs flag on fs but no " 437 "ACLs support\n", mp->mnt_stat.f_mntonname); 438 #endif 439 } 440 if ((fs_flags & FS_NFS4ACLS) != 0) { 441 #ifdef UFS_ACL 442 if (mp->mnt_flag & MNT_POSIX1EACLS) 443 printf("WARNING: %s: NFSv4 ACLs flag on fs conflicts " 444 "with \"posix1eacls\" mount option; option ignored\n", 445 mp->mnt_stat.f_mntonname); 446 mp->mnt_flag &= ~MNT_POSIX1EACLS; 447 mp->mnt_flag |= MNT_NFS4ACLS; 448 449 #else 450 printf("WARNING: %s: NFSv4 ACLs flag on fs but no " 451 "ACLs support\n", mp->mnt_stat.f_mntonname); 452 #endif 453 } 454 if ((mp->mnt_flag & (MNT_NFS4ACLS | MNT_POSIX1EACLS)) 455 == (MNT_NFS4ACLS | MNT_POSIX1EACLS)) 456 { 457 printf("%s: \"posix1eacls\" and \"nfsv4acls\" options " 458 "are mutually exclusive\n", 459 mp->mnt_stat.f_mntonname); 460 return EINVAL; 461 } 462 463 if (mp->mnt_flag & (MNT_NFS4ACLS | MNT_POSIX1EACLS)) 464 mp->mnt_iflag &= ~(IMNT_SHRLOOKUP|IMNT_NCLOOKUP); 465 else 466 mp->mnt_iflag |= IMNT_SHRLOOKUP|IMNT_NCLOOKUP; 467 return 0; 468 } 469 470 /* 471 * VFS Operations. 472 * 473 * mount system call 474 */ 475 int 476 ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) 477 { 478 struct lwp *l = curlwp; 479 struct vnode *devvp = NULL; 480 struct ufs_args *args = data; 481 struct ufsmount *ump = NULL; 482 struct fs *fs; 483 int error = 0, flags, update; 484 mode_t accessmode; 485 486 if (args == NULL) { 487 DPRINTF("NULL args"); 488 return EINVAL; 489 } 490 if (*data_len < sizeof(*args)) { 491 DPRINTF("bad size args %zu != %zu", *data_len, sizeof(*args)); 492 return EINVAL; 493 } 494 495 ump = VFSTOUFS(mp); 496 if ((mp->mnt_flag & (MNT_GETARGS|MNT_UPDATE)) && ump == NULL) { 497 DPRINTF("no ump"); 498 return EIO; 499 } 500 501 if (mp->mnt_flag & MNT_GETARGS) { 502 args->fspec = NULL; 503 *data_len = sizeof *args; 504 return 0; 505 } 506 507 update = mp->mnt_flag & MNT_UPDATE; 508 509 /* Check arguments */ 510 if (args->fspec == NULL) { 511 if (!update) { 512 /* New mounts must have a filename for the device */ 513 DPRINTF("no filename for mount"); 514 return EINVAL; 515 } 516 } else { 517 /* 518 * Look up the name and verify that it's sane. 519 */ 520 error = namei_simple_user(args->fspec, 521 NSM_FOLLOW_NOEMULROOT, &devvp); 522 if (error != 0) { 523 DPRINTF("namei_simple_user returned %d", error); 524 return error; 525 } 526 527 /* 528 * Be sure this is a valid block device 529 */ 530 if (devvp->v_type != VBLK) { 531 DPRINTF("non block device %d", devvp->v_type); 532 error = ENOTBLK; 533 goto fail; 534 } 535 536 if (bdevsw_lookup(devvp->v_rdev) == NULL) { 537 DPRINTF("can't find block device 0x%jx", 538 devvp->v_rdev); 539 error = ENXIO; 540 goto fail; 541 } 542 543 if (update) { 544 /* 545 * Be sure we're still naming the same device 546 * used for our initial mount 547 */ 548 if (devvp != ump->um_devvp && 549 devvp->v_rdev != ump->um_devvp->v_rdev) { 550 DPRINTF("wrong device 0x%jx != 0x%jx", 551 (uintmax_t)devvp->v_rdev, 552 (uintmax_t)ump->um_devvp->v_rdev); 553 error = EINVAL; 554 goto fail; 555 } 556 vrele(devvp); 557 devvp = NULL; 558 } 559 } 560 561 if (devvp == NULL) { 562 devvp = ump->um_devvp; 563 vref(devvp); 564 } 565 566 /* 567 * If mount by non-root, then verify that user has necessary 568 * permissions on the device. 569 * 570 * Permission to update a mount is checked higher, so here we presume 571 * updating the mount is okay (for example, as far as securelevel goes) 572 * which leaves us with the normal check. 573 */ 574 accessmode = VREAD; 575 if (update ? (mp->mnt_iflag & IMNT_WANTRDWR) != 0 : 576 (mp->mnt_flag & MNT_RDONLY) == 0) 577 accessmode |= VWRITE; 578 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 579 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 580 KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode)); 581 VOP_UNLOCK(devvp); 582 if (error) { 583 DPRINTF("kauth returned %d", error); 584 goto fail; 585 } 586 587 #ifdef WAPBL 588 /* WAPBL can only be enabled on a r/w mount. */ 589 if (((mp->mnt_flag & MNT_RDONLY) && !(mp->mnt_iflag & IMNT_WANTRDWR)) || 590 (mp->mnt_iflag & IMNT_WANTRDONLY)) { 591 mp->mnt_flag &= ~MNT_LOG; 592 } 593 #else /* !WAPBL */ 594 mp->mnt_flag &= ~MNT_LOG; 595 #endif /* !WAPBL */ 596 597 error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, 598 UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l); 599 if (error) 600 goto fail; 601 602 if (!update) { 603 int xflags; 604 605 if (mp->mnt_flag & MNT_RDONLY) 606 xflags = FREAD; 607 else 608 xflags = FREAD | FWRITE; 609 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 610 error = VOP_OPEN(devvp, xflags, FSCRED); 611 VOP_UNLOCK(devvp); 612 if (error) { 613 DPRINTF("VOP_OPEN returned %d", error); 614 goto fail; 615 } 616 /* Need fstrans_start() for assertion in ufs_strategy(). */ 617 if ((mp->mnt_flag & MNT_RDONLY) == 0) 618 fstrans_start(mp); 619 error = ffs_mountfs(devvp, mp, l); 620 if ((mp->mnt_flag & MNT_RDONLY) == 0) 621 fstrans_done(mp); 622 if (error) { 623 DPRINTF("ffs_mountfs returned %d", error); 624 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 625 (void)VOP_CLOSE(devvp, xflags, NOCRED); 626 VOP_UNLOCK(devvp); 627 goto fail; 628 } 629 630 ump = VFSTOUFS(mp); 631 fs = ump->um_fs; 632 } else { 633 /* 634 * Update the mount. The file system is suspended. 635 */ 636 KASSERT(fstrans_is_owner(mp)); 637 638 /* 639 * The initial mount got a reference on this 640 * device, so drop the one obtained via 641 * namei(), above. 642 */ 643 vrele(devvp); 644 645 ump = VFSTOUFS(mp); 646 fs = ump->um_fs; 647 if (fs->fs_ronly == 0 && (mp->mnt_iflag & IMNT_WANTRDONLY)) { 648 /* 649 * Changing from r/w to r/o 650 */ 651 flags = WRITECLOSE; 652 if (mp->mnt_flag & MNT_FORCE) 653 flags |= FORCECLOSE; 654 error = ffs_flushfiles(mp, flags, l); 655 if (error) 656 return error; 657 658 error = UFS_WAPBL_BEGIN(mp); 659 if (error) { 660 DPRINTF("wapbl %d", error); 661 return error; 662 } 663 664 if (ffs_cgupdate(ump, MNT_WAIT) == 0 && 665 fs->fs_clean & FS_WASCLEAN) { 666 if (mp->mnt_flag & MNT_SOFTDEP) 667 fs->fs_flags &= ~FS_DOSOFTDEP; 668 fs->fs_clean = FS_ISCLEAN; 669 (void) ffs_sbupdate(ump, MNT_WAIT); 670 } 671 672 UFS_WAPBL_END(mp); 673 } 674 675 #ifdef WAPBL 676 if ((mp->mnt_flag & MNT_LOG) == 0) { 677 error = ffs_wapbl_stop(mp, mp->mnt_flag & MNT_FORCE); 678 if (error) { 679 DPRINTF("ffs_wapbl_stop returned %d", error); 680 return error; 681 } 682 } 683 #endif /* WAPBL */ 684 685 if (fs->fs_ronly == 0 && (mp->mnt_iflag & IMNT_WANTRDONLY)) { 686 /* 687 * Finish change from r/w to r/o 688 */ 689 fs->fs_ronly = 1; 690 fs->fs_fmod = 0; 691 } 692 693 error = ffs_acls(mp, fs->fs_flags); 694 if (error) 695 return error; 696 if (mp->mnt_flag & MNT_RELOAD) { 697 error = ffs_reload(mp, l->l_cred, l); 698 if (error) { 699 DPRINTF("ffs_reload returned %d", error); 700 return error; 701 } 702 } 703 704 if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) { 705 /* 706 * Changing from read-only to read/write 707 */ 708 #ifndef QUOTA2 709 if (fs->fs_flags & FS_DOQUOTA2) { 710 ump->um_flags |= UFS_QUOTA2; 711 uprintf("%s: options QUOTA2 not enabled%s\n", 712 mp->mnt_stat.f_mntonname, 713 (mp->mnt_flag & MNT_FORCE) ? "" : 714 ", not mounting"); 715 DPRINTF("ffs_quota2 %d", EINVAL); 716 return EINVAL; 717 } 718 #endif 719 fs->fs_ronly = 0; 720 fs->fs_clean = 721 fs->fs_clean == FS_ISCLEAN ? FS_WASCLEAN : 0; 722 fs->fs_fmod = 1; 723 #ifdef WAPBL 724 if (fs->fs_flags & FS_DOWAPBL) { 725 const char *nm = mp->mnt_stat.f_mntonname; 726 if (!mp->mnt_wapbl_replay) { 727 printf("%s: log corrupted;" 728 " replay cancelled\n", nm); 729 return EFTYPE; 730 } 731 printf("%s: replaying log to disk\n", nm); 732 error = wapbl_replay_write(mp->mnt_wapbl_replay, 733 devvp); 734 if (error) { 735 DPRINTF("%s: wapbl_replay_write %d", 736 nm, error); 737 return error; 738 } 739 wapbl_replay_stop(mp->mnt_wapbl_replay); 740 fs->fs_clean = FS_WASCLEAN; 741 } 742 #endif /* WAPBL */ 743 if (fs->fs_snapinum[0] != 0) 744 #ifndef FFS_NO_SNAPSHOT 745 ffs_snapshot_mount(mp); 746 #else 747 return EINVAL; 748 #endif 749 } 750 751 #ifdef WAPBL 752 error = ffs_wapbl_start(mp); 753 if (error) { 754 DPRINTF("ffs_wapbl_start returned %d", error); 755 return error; 756 } 757 #endif /* WAPBL */ 758 759 #ifdef QUOTA2 760 if (!fs->fs_ronly) { 761 error = ffs_quota2_mount(mp); 762 if (error) { 763 DPRINTF("ffs_quota2_mount returned %d", error); 764 return error; 765 } 766 } 767 #endif 768 769 if ((mp->mnt_flag & MNT_DISCARD) && !(ump->um_discarddata)) 770 ump->um_discarddata = ffs_discard_init(devvp, fs); 771 772 if (args->fspec == NULL) 773 return 0; 774 } 775 776 (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, 777 sizeof(fs->fs_fsmnt)); 778 779 fs->fs_flags &= ~FS_DOSOFTDEP; 780 781 if ((fs->fs_ronly && (fs->fs_clean & FS_ISCLEAN) == 0) || 782 (!fs->fs_ronly && (fs->fs_clean & FS_WASCLEAN) == 0)) { 783 printf("%s: file system not clean (fs_clean=%#x); " 784 "please fsck(8)\n", mp->mnt_stat.f_mntfromname, 785 fs->fs_clean); 786 } 787 788 if (UFS_WAPBL_BEGIN(mp) == 0) { 789 mutex_enter(&ump->um_lock); 790 if (fs->fs_fmod != 0) { 791 KASSERT(!fs->fs_ronly); 792 793 if (fs->fs_clean & FS_WASCLEAN) 794 fs->fs_time = time_second; 795 fs->fs_fmod = 0; 796 mutex_exit(&ump->um_lock); 797 (void) ffs_cgupdate(ump, MNT_WAIT); 798 } else { 799 mutex_exit(&ump->um_lock); 800 } 801 UFS_WAPBL_END(mp); 802 } 803 if ((mp->mnt_flag & MNT_SOFTDEP) != 0) { 804 printf("%s: `-o softdep' is no longer supported, " 805 "consider `-o log'\n", mp->mnt_stat.f_mntfromname); 806 mp->mnt_flag &= ~MNT_SOFTDEP; 807 } 808 809 return (error); 810 811 fail: 812 vrele(devvp); 813 return (error); 814 } 815 816 /* 817 * Reload all incore data for a filesystem (used after running fsck on 818 * the root filesystem and finding things to fix). The filesystem must 819 * be mounted read-only. 820 * 821 * Things to do to update the mount: 822 * 1) invalidate all cached meta-data. 823 * 2) re-read superblock from disk. 824 * 3) re-read summary information from disk. 825 * 4) invalidate all inactive vnodes. 826 * 5) invalidate all cached file data. 827 * 6) re-read inode data for all active vnodes. 828 */ 829 int 830 ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l) 831 { 832 struct vnode *vp, *devvp; 833 struct inode *ip; 834 void *space; 835 struct buf *bp; 836 struct fs *fs, *newfs; 837 int i, bsize, blks, error; 838 int32_t *lp, fs_sbsize; 839 struct ufsmount *ump; 840 daddr_t sblockloc; 841 struct vnode_iterator *marker; 842 843 if ((mp->mnt_flag & MNT_RDONLY) == 0) 844 return (EINVAL); 845 846 ump = VFSTOUFS(mp); 847 848 /* 849 * Step 1: invalidate all cached meta-data. 850 */ 851 devvp = ump->um_devvp; 852 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 853 error = vinvalbuf(devvp, 0, cred, l, 0, 0); 854 VOP_UNLOCK(devvp); 855 if (error) 856 panic("%s: dirty1", __func__); 857 858 /* 859 * Step 2: re-read superblock from disk. XXX: We don't handle 860 * possibility that superblock moved. Which implies that we don't 861 * want its size to change either. 862 */ 863 fs = ump->um_fs; 864 fs_sbsize = fs->fs_sbsize; 865 error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE, fs_sbsize, 866 0, &bp); 867 if (error) 868 return (error); 869 newfs = kmem_alloc(fs_sbsize, KM_SLEEP); 870 memcpy(newfs, bp->b_data, fs_sbsize); 871 872 #ifdef FFS_EI 873 if (ump->um_flags & UFS_NEEDSWAP) { 874 ffs_sb_swap((struct fs *)bp->b_data, newfs); 875 newfs->fs_flags |= FS_SWAPPED; 876 } else 877 #endif 878 newfs->fs_flags &= ~FS_SWAPPED; 879 880 brelse(bp, 0); 881 882 /* Allow converting from UFS2 to UFS2EA but not vice versa. */ 883 if (newfs->fs_magic == FS_UFS2EA_MAGIC) { 884 ump->um_flags |= UFS_EA; 885 newfs->fs_magic = FS_UFS2_MAGIC; 886 } else { 887 if ((ump->um_flags & UFS_EA) != 0) 888 return EINVAL; 889 } 890 891 if ((newfs->fs_magic != FS_UFS1_MAGIC) && 892 (newfs->fs_magic != FS_UFS2_MAGIC)) { 893 kmem_free(newfs, fs_sbsize); 894 return (EIO); /* XXX needs translation */ 895 } 896 if (!ffs_superblock_validate(newfs)) { 897 kmem_free(newfs, fs_sbsize); 898 return (EINVAL); 899 } 900 901 /* 902 * The current implementation doesn't handle the possibility that 903 * these values may have changed. 904 */ 905 if ((newfs->fs_sbsize != fs_sbsize) || 906 (newfs->fs_cssize != fs->fs_cssize) || 907 (newfs->fs_contigsumsize != fs->fs_contigsumsize) || 908 (newfs->fs_ncg != fs->fs_ncg)) { 909 kmem_free(newfs, fs_sbsize); 910 return (EINVAL); 911 } 912 913 /* Store off old fs_sblockloc for fs_oldfscompat_read. */ 914 sblockloc = fs->fs_sblockloc; 915 /* 916 * Copy pointer fields back into superblock before copying in XXX 917 * new superblock. These should really be in the ufsmount. XXX 918 * Note that important parameters (eg fs_ncg) are unchanged. 919 */ 920 newfs->fs_csp = fs->fs_csp; 921 newfs->fs_maxcluster = fs->fs_maxcluster; 922 newfs->fs_contigdirs = fs->fs_contigdirs; 923 newfs->fs_ronly = fs->fs_ronly; 924 newfs->fs_active = fs->fs_active; 925 memcpy(fs, newfs, (u_int)fs_sbsize); 926 kmem_free(newfs, fs_sbsize); 927 928 /* 929 * Recheck for Apple UFS filesystem. 930 */ 931 ump->um_flags &= ~UFS_ISAPPLEUFS; 932 if (ffs_is_appleufs(devvp, fs)) { 933 #ifdef APPLE_UFS 934 ump->um_flags |= UFS_ISAPPLEUFS; 935 #else 936 DPRINTF("AppleUFS not supported"); 937 return (EIO); /* XXX: really? */ 938 #endif 939 } 940 941 if (UFS_MPISAPPLEUFS(ump)) { 942 /* see comment about NeXT below */ 943 ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN; 944 ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ; 945 mp->mnt_iflag |= IMNT_DTYPE; 946 } else { 947 ump->um_maxsymlinklen = fs->fs_maxsymlinklen; 948 ump->um_dirblksiz = UFS_DIRBLKSIZ; 949 if (ump->um_maxsymlinklen > 0) 950 mp->mnt_iflag |= IMNT_DTYPE; 951 else 952 mp->mnt_iflag &= ~IMNT_DTYPE; 953 } 954 ffs_oldfscompat_read(fs, ump, sblockloc); 955 956 mutex_enter(&ump->um_lock); 957 ump->um_maxfilesize = fs->fs_maxfilesize; 958 if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) { 959 uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n", 960 mp->mnt_stat.f_mntonname, fs->fs_flags, 961 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting"); 962 if ((mp->mnt_flag & MNT_FORCE) == 0) { 963 mutex_exit(&ump->um_lock); 964 return (EINVAL); 965 } 966 } 967 968 if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { 969 fs->fs_pendingblocks = 0; 970 fs->fs_pendinginodes = 0; 971 } 972 mutex_exit(&ump->um_lock); 973 974 ffs_statvfs(mp, &mp->mnt_stat); 975 /* 976 * Step 3: re-read summary information from disk. 977 */ 978 blks = howmany(fs->fs_cssize, fs->fs_fsize); 979 space = fs->fs_csp; 980 for (i = 0; i < blks; i += fs->fs_frag) { 981 bsize = fs->fs_bsize; 982 if (i + fs->fs_frag > blks) 983 bsize = (blks - i) * fs->fs_fsize; 984 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize, 985 0, &bp); 986 if (error) { 987 return (error); 988 } 989 #ifdef FFS_EI 990 if (UFS_FSNEEDSWAP(fs)) 991 ffs_csum_swap((struct csum *)bp->b_data, 992 (struct csum *)space, bsize); 993 else 994 #endif 995 memcpy(space, bp->b_data, (size_t)bsize); 996 space = (char *)space + bsize; 997 brelse(bp, 0); 998 } 999 /* 1000 * We no longer know anything about clusters per cylinder group. 1001 */ 1002 if (fs->fs_contigsumsize > 0) { 1003 lp = fs->fs_maxcluster; 1004 for (i = 0; i < fs->fs_ncg; i++) 1005 *lp++ = fs->fs_contigsumsize; 1006 } 1007 1008 vfs_vnode_iterator_init(mp, &marker); 1009 while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { 1010 /* 1011 * Step 4: invalidate all inactive vnodes. 1012 */ 1013 if (vrecycle(vp)) 1014 continue; 1015 /* 1016 * Step 5: invalidate all cached file data. 1017 */ 1018 if (vn_lock(vp, LK_EXCLUSIVE)) { 1019 vrele(vp); 1020 continue; 1021 } 1022 if (vinvalbuf(vp, 0, cred, l, 0, 0)) 1023 panic("%s: dirty2", __func__); 1024 /* 1025 * Step 6: re-read inode data for all active vnodes. 1026 */ 1027 ip = VTOI(vp); 1028 error = bread(devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ip->i_number)), 1029 (int)fs->fs_bsize, 0, &bp); 1030 if (error) { 1031 vput(vp); 1032 break; 1033 } 1034 ffs_load_inode(bp, ip, fs, ip->i_number); 1035 brelse(bp, 0); 1036 vput(vp); 1037 } 1038 vfs_vnode_iterator_destroy(marker); 1039 return (error); 1040 } 1041 1042 /* 1043 * Possible superblock locations ordered from most to least likely. 1044 */ 1045 static const int sblock_try[] = SBLOCKSEARCH; 1046 1047 1048 static int 1049 ffs_superblock_validate(struct fs *fs) 1050 { 1051 int32_t i, fs_bshift = 0, fs_fshift = 0, fs_fragshift = 0, fs_frag; 1052 int32_t fs_inopb; 1053 1054 /* Check the superblock size */ 1055 if (fs->fs_sbsize > SBLOCKSIZE || fs->fs_sbsize < sizeof(struct fs)) 1056 return 0; 1057 1058 /* Check the file system blocksize */ 1059 if (fs->fs_bsize > MAXBSIZE || fs->fs_bsize < MINBSIZE) 1060 return 0; 1061 if (!powerof2(fs->fs_bsize)) 1062 return 0; 1063 1064 /* Check the size of frag blocks */ 1065 if (!powerof2(fs->fs_fsize)) 1066 return 0; 1067 if (fs->fs_fsize == 0) 1068 return 0; 1069 1070 /* 1071 * XXX: these values are just zero-checked to prevent obvious 1072 * bugs. We need more strict checks. 1073 */ 1074 if (fs->fs_size == 0 && fs->fs_old_size == 0) 1075 return 0; 1076 if (fs->fs_cssize == 0) 1077 return 0; 1078 if (fs->fs_ipg == 0) 1079 return 0; 1080 if (fs->fs_fpg == 0) 1081 return 0; 1082 if (fs->fs_ncg == 0) 1083 return 0; 1084 if (fs->fs_maxbpg == 0) 1085 return 0; 1086 1087 /* Check the number of inodes per block */ 1088 if (fs->fs_magic == FS_UFS1_MAGIC) 1089 fs_inopb = fs->fs_bsize / sizeof(struct ufs1_dinode); 1090 else /* fs->fs_magic == FS_UFS2_MAGIC */ 1091 fs_inopb = fs->fs_bsize / sizeof(struct ufs2_dinode); 1092 if (fs->fs_inopb != fs_inopb) 1093 return 0; 1094 1095 /* Block size cannot be smaller than fragment size */ 1096 if (fs->fs_bsize < fs->fs_fsize) 1097 return 0; 1098 1099 /* Compute fs_bshift and ensure it is consistent */ 1100 for (i = fs->fs_bsize; i > 1; i >>= 1) 1101 fs_bshift++; 1102 if (fs->fs_bshift != fs_bshift) 1103 return 0; 1104 1105 /* Compute fs_fshift and ensure it is consistent */ 1106 for (i = fs->fs_fsize; i > 1; i >>= 1) 1107 fs_fshift++; 1108 if (fs->fs_fshift != fs_fshift) 1109 return 0; 1110 1111 /* Compute fs_fragshift and ensure it is consistent */ 1112 for (i = fs->fs_frag; i > 1; i >>= 1) 1113 fs_fragshift++; 1114 if (fs->fs_fragshift != fs_fragshift) 1115 return 0; 1116 1117 /* Check the masks */ 1118 if (fs->fs_bmask != ~(fs->fs_bsize - 1)) 1119 return 0; 1120 if (fs->fs_fmask != ~(fs->fs_fsize - 1)) 1121 return 0; 1122 1123 /* 1124 * Now that the shifts and masks are sanitized, we can use the ffs_ API. 1125 */ 1126 1127 /* Check the number of frag blocks */ 1128 if ((fs_frag = ffs_numfrags(fs, fs->fs_bsize)) > MAXFRAG) 1129 return 0; 1130 if (fs->fs_frag != fs_frag) 1131 return 0; 1132 1133 /* Check the size of cylinder groups */ 1134 if ((fs->fs_cgsize < sizeof(struct cg)) || 1135 (fs->fs_cgsize > fs->fs_bsize)) 1136 return 0; 1137 1138 return 1; 1139 } 1140 1141 static int 1142 ffs_is_appleufs(struct vnode *devvp, struct fs *fs) 1143 { 1144 struct dkwedge_info dkw; 1145 int ret = 0; 1146 1147 /* 1148 * First check to see if this is tagged as an Apple UFS filesystem 1149 * in the disklabel. 1150 */ 1151 if (getdiskinfo(devvp, &dkw) == 0 && 1152 strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0) 1153 ret = 1; 1154 #ifdef APPLE_UFS 1155 else { 1156 struct appleufslabel *applefs; 1157 struct buf *bp; 1158 daddr_t blkno = APPLEUFS_LABEL_OFFSET / DEV_BSIZE; 1159 int error; 1160 1161 /* 1162 * Manually look for an Apple UFS label, and if a valid one 1163 * is found, then treat it like an Apple UFS filesystem anyway. 1164 */ 1165 error = bread(devvp, blkno, APPLEUFS_LABEL_SIZE, 0, &bp); 1166 if (error) { 1167 DPRINTF("bread@0x%jx returned %d", (intmax_t)blkno, error); 1168 return 0; 1169 } 1170 applefs = (struct appleufslabel *)bp->b_data; 1171 error = ffs_appleufs_validate(fs->fs_fsmnt, applefs, NULL); 1172 if (error == 0) 1173 ret = 1; 1174 brelse(bp, 0); 1175 } 1176 #endif 1177 1178 return ret; 1179 } 1180 1181 /* 1182 * Common code for mount and mountroot 1183 */ 1184 int 1185 ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l) 1186 { 1187 struct ufsmount *ump = NULL; 1188 struct buf *bp = NULL; 1189 struct fs *fs = NULL; 1190 dev_t dev; 1191 void *space; 1192 daddr_t sblockloc = 0; 1193 int blks, fstype = 0; 1194 int error, i, bsize, ronly, bset = 0; 1195 #ifdef FFS_EI 1196 int needswap = 0; /* keep gcc happy */ 1197 #endif 1198 int32_t *lp; 1199 kauth_cred_t cred; 1200 u_int32_t allocsbsize, fs_sbsize = 0; 1201 1202 dev = devvp->v_rdev; 1203 cred = l ? l->l_cred : NOCRED; 1204 1205 /* Flush out any old buffers remaining from a previous use. */ 1206 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 1207 error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0); 1208 VOP_UNLOCK(devvp); 1209 if (error) { 1210 DPRINTF("vinvalbuf returned %d", error); 1211 return error; 1212 } 1213 1214 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 1215 1216 ump = kmem_zalloc(sizeof(*ump), KM_SLEEP); 1217 mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE); 1218 #ifndef FFS_NO_SNAPSHOT 1219 error = ffs_snapshot_init(ump); 1220 #endif 1221 if (error) { 1222 DPRINTF("ffs_snapshot_init returned %d", error); 1223 goto out; 1224 } 1225 ump->um_ops = &ffs_ufsops; 1226 1227 #ifdef WAPBL 1228 sbagain: 1229 #endif 1230 /* 1231 * Try reading the superblock in each of its possible locations. 1232 */ 1233 for (i = 0; ; i++) { 1234 daddr_t fs_sblockloc; 1235 1236 if (bp != NULL) { 1237 brelse(bp, BC_NOCACHE); 1238 bp = NULL; 1239 } 1240 if (sblock_try[i] == -1) { 1241 DPRINTF("no superblock found"); 1242 error = EINVAL; 1243 fs = NULL; 1244 goto out; 1245 } 1246 1247 error = bread(devvp, sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, 1248 0, &bp); 1249 if (error) { 1250 DPRINTF("bread@0x%x returned %d", 1251 sblock_try[i] / DEV_BSIZE, error); 1252 fs = NULL; 1253 goto out; 1254 } 1255 fs = (struct fs *)bp->b_data; 1256 1257 sblockloc = sblock_try[i]; 1258 DPRINTF("fs_magic 0x%x", fs->fs_magic); 1259 1260 /* 1261 * Swap: here, we swap fs->fs_sbsize in order to get the correct 1262 * size to read the superblock. Once read, we swap the whole 1263 * superblock structure. 1264 */ 1265 if (fs->fs_magic == FS_UFS2EA_MAGIC) { 1266 ump->um_flags |= UFS_EA; 1267 fs->fs_magic = FS_UFS2_MAGIC; 1268 } else if (fs->fs_magic == FS_UFS2EA_MAGIC_SWAPPED) { 1269 ump->um_flags |= UFS_EA; 1270 fs->fs_magic = FS_UFS2_MAGIC_SWAPPED; 1271 } 1272 if (fs->fs_magic == FS_UFS1_MAGIC) { 1273 fs_sbsize = fs->fs_sbsize; 1274 fstype = UFS1; 1275 #ifdef FFS_EI 1276 needswap = 0; 1277 } else if (fs->fs_magic == FS_UFS1_MAGIC_SWAPPED) { 1278 fs_sbsize = bswap32(fs->fs_sbsize); 1279 fstype = UFS1; 1280 needswap = 1; 1281 #endif 1282 } else if (fs->fs_magic == FS_UFS2_MAGIC) { 1283 fs_sbsize = fs->fs_sbsize; 1284 fstype = UFS2; 1285 #ifdef FFS_EI 1286 needswap = 0; 1287 } else if (fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) { 1288 fs_sbsize = bswap32(fs->fs_sbsize); 1289 fstype = UFS2; 1290 needswap = 1; 1291 #endif 1292 } else 1293 continue; 1294 1295 /* fs->fs_sblockloc isn't defined for old filesystems */ 1296 if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) { 1297 if (sblockloc == SBLOCK_UFS2) 1298 /* 1299 * This is likely to be the first alternate 1300 * in a filesystem with 64k blocks. 1301 * Don't use it. 1302 */ 1303 continue; 1304 fs_sblockloc = sblockloc; 1305 } else { 1306 fs_sblockloc = fs->fs_sblockloc; 1307 #ifdef FFS_EI 1308 if (needswap) 1309 fs_sblockloc = bswap64(fs_sblockloc); 1310 #endif 1311 } 1312 1313 /* Check we haven't found an alternate superblock */ 1314 if (fs_sblockloc != sblockloc) 1315 continue; 1316 1317 /* Check the superblock size */ 1318 if (fs_sbsize > SBLOCKSIZE || fs_sbsize < sizeof(struct fs)) 1319 continue; 1320 fs = kmem_alloc((u_long)fs_sbsize, KM_SLEEP); 1321 memcpy(fs, bp->b_data, fs_sbsize); 1322 1323 /* Swap the whole superblock structure, if necessary. */ 1324 #ifdef FFS_EI 1325 if (needswap) { 1326 ffs_sb_swap((struct fs*)bp->b_data, fs); 1327 fs->fs_flags |= FS_SWAPPED; 1328 } else 1329 #endif 1330 fs->fs_flags &= ~FS_SWAPPED; 1331 1332 /* 1333 * Now that everything is swapped, the superblock is ready to 1334 * be sanitized. 1335 */ 1336 if (!ffs_superblock_validate(fs)) { 1337 kmem_free(fs, fs_sbsize); 1338 continue; 1339 } 1340 1341 /* Ok seems to be a good superblock */ 1342 break; 1343 } 1344 1345 ump->um_fs = fs; 1346 1347 #ifdef WAPBL 1348 if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) { 1349 error = ffs_wapbl_replay_start(mp, fs, devvp); 1350 if (error && (mp->mnt_flag & MNT_FORCE) == 0) { 1351 DPRINTF("ffs_wapbl_replay_start returned %d", error); 1352 goto out; 1353 } 1354 if (!error) { 1355 if (!ronly) { 1356 /* XXX fsmnt may be stale. */ 1357 printf("%s: replaying log to disk\n", 1358 fs->fs_fsmnt); 1359 error = wapbl_replay_write(mp->mnt_wapbl_replay, 1360 devvp); 1361 if (error) { 1362 DPRINTF("wapbl_replay_write returned %d", 1363 error); 1364 goto out; 1365 } 1366 wapbl_replay_stop(mp->mnt_wapbl_replay); 1367 fs->fs_clean = FS_WASCLEAN; 1368 } else { 1369 /* XXX fsmnt may be stale */ 1370 printf("%s: replaying log to memory\n", 1371 fs->fs_fsmnt); 1372 } 1373 1374 /* Force a re-read of the superblock */ 1375 brelse(bp, BC_INVAL); 1376 bp = NULL; 1377 kmem_free(fs, fs_sbsize); 1378 fs = NULL; 1379 goto sbagain; 1380 } 1381 } 1382 #else /* !WAPBL */ 1383 if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) { 1384 error = EPERM; 1385 DPRINTF("no force %d", error); 1386 goto out; 1387 } 1388 #endif /* !WAPBL */ 1389 1390 ffs_oldfscompat_read(fs, ump, sblockloc); 1391 ump->um_maxfilesize = fs->fs_maxfilesize; 1392 1393 if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) { 1394 uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n", 1395 mp->mnt_stat.f_mntonname, fs->fs_flags, 1396 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting"); 1397 if ((mp->mnt_flag & MNT_FORCE) == 0) { 1398 error = EINVAL; 1399 DPRINTF("no force %d", error); 1400 goto out; 1401 } 1402 } 1403 1404 fs->fs_fmod = 0; 1405 if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { 1406 fs->fs_pendingblocks = 0; 1407 fs->fs_pendinginodes = 0; 1408 } 1409 1410 ump->um_fstype = fstype; 1411 if (fs->fs_sbsize < SBLOCKSIZE) 1412 brelse(bp, BC_INVAL); 1413 else 1414 brelse(bp, 0); 1415 bp = NULL; 1416 1417 if (ffs_is_appleufs(devvp, fs)) { 1418 #ifdef APPLE_UFS 1419 ump->um_flags |= UFS_ISAPPLEUFS; 1420 #else 1421 DPRINTF("AppleUFS not supported"); 1422 error = EINVAL; 1423 goto out; 1424 #endif 1425 } 1426 1427 #if 0 1428 /* 1429 * XXX This code changes the behaviour of mounting dirty filesystems, to 1430 * XXX require "mount -f ..." to mount them. This doesn't match what 1431 * XXX mount(8) describes and is disabled for now. 1432 */ 1433 /* 1434 * If the file system is not clean, don't allow it to be mounted 1435 * unless MNT_FORCE is specified. (Note: MNT_FORCE is always set 1436 * for the root file system.) 1437 */ 1438 if (fs->fs_flags & FS_DOWAPBL) { 1439 /* 1440 * wapbl normally expects to be FS_WASCLEAN when the FS_DOWAPBL 1441 * bit is set, although there's a window in unmount where it 1442 * could be FS_ISCLEAN 1443 */ 1444 if ((mp->mnt_flag & MNT_FORCE) == 0 && 1445 (fs->fs_clean & (FS_WASCLEAN | FS_ISCLEAN)) == 0) { 1446 error = EPERM; 1447 goto out; 1448 } 1449 } else 1450 if ((fs->fs_clean & FS_ISCLEAN) == 0 && 1451 (mp->mnt_flag & MNT_FORCE) == 0) { 1452 error = EPERM; 1453 goto out; 1454 } 1455 #endif 1456 1457 /* 1458 * Verify that we can access the last block in the fs 1459 * if we're mounting read/write. 1460 */ 1461 if (!ronly) { 1462 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_size - 1), 1463 fs->fs_fsize, 0, &bp); 1464 if (error) { 1465 DPRINTF("bread@0x%jx returned %d", 1466 (intmax_t)FFS_FSBTODB(fs, fs->fs_size - 1), 1467 error); 1468 bset = BC_INVAL; 1469 goto out; 1470 } 1471 if (bp->b_bcount != fs->fs_fsize) { 1472 DPRINTF("bcount %x != fsize %x", bp->b_bcount, 1473 fs->fs_fsize); 1474 error = EINVAL; 1475 bset = BC_INVAL; 1476 goto out; 1477 } 1478 brelse(bp, BC_INVAL); 1479 bp = NULL; 1480 } 1481 1482 fs->fs_ronly = ronly; 1483 /* Don't bump fs_clean if we're replaying journal */ 1484 if (!((fs->fs_flags & FS_DOWAPBL) && (fs->fs_clean & FS_WASCLEAN))) { 1485 if (ronly == 0) { 1486 fs->fs_clean = 1487 fs->fs_clean == FS_ISCLEAN ? FS_WASCLEAN : 0; 1488 fs->fs_fmod = 1; 1489 } 1490 } 1491 1492 bsize = fs->fs_cssize; 1493 blks = howmany(bsize, fs->fs_fsize); 1494 if (fs->fs_contigsumsize > 0) 1495 bsize += fs->fs_ncg * sizeof(int32_t); 1496 bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs); 1497 allocsbsize = bsize; 1498 space = kmem_alloc((u_long)allocsbsize, KM_SLEEP); 1499 fs->fs_csp = space; 1500 1501 for (i = 0; i < blks; i += fs->fs_frag) { 1502 bsize = fs->fs_bsize; 1503 if (i + fs->fs_frag > blks) 1504 bsize = (blks - i) * fs->fs_fsize; 1505 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize, 1506 0, &bp); 1507 if (error) { 1508 DPRINTF("bread@0x%jx %d", 1509 (intmax_t)FFS_FSBTODB(fs, fs->fs_csaddr + i), 1510 error); 1511 goto out1; 1512 } 1513 #ifdef FFS_EI 1514 if (needswap) 1515 ffs_csum_swap((struct csum *)bp->b_data, 1516 (struct csum *)space, bsize); 1517 else 1518 #endif 1519 memcpy(space, bp->b_data, (u_int)bsize); 1520 1521 space = (char *)space + bsize; 1522 brelse(bp, 0); 1523 bp = NULL; 1524 } 1525 if (fs->fs_contigsumsize > 0) { 1526 fs->fs_maxcluster = lp = space; 1527 for (i = 0; i < fs->fs_ncg; i++) 1528 *lp++ = fs->fs_contigsumsize; 1529 space = lp; 1530 } 1531 bsize = fs->fs_ncg * sizeof(*fs->fs_contigdirs); 1532 fs->fs_contigdirs = space; 1533 space = (char *)space + bsize; 1534 memset(fs->fs_contigdirs, 0, bsize); 1535 1536 /* Compatibility for old filesystems - XXX */ 1537 if (fs->fs_avgfilesize <= 0) 1538 fs->fs_avgfilesize = AVFILESIZ; 1539 if (fs->fs_avgfpdir <= 0) 1540 fs->fs_avgfpdir = AFPDIR; 1541 fs->fs_active = NULL; 1542 1543 mp->mnt_data = ump; 1544 mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev; 1545 mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FFS); 1546 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 1547 mp->mnt_stat.f_namemax = FFS_MAXNAMLEN; 1548 if (UFS_MPISAPPLEUFS(ump)) { 1549 /* NeXT used to keep short symlinks in the inode even 1550 * when using FS_42INODEFMT. In that case fs->fs_maxsymlinklen 1551 * is probably -1, but we still need to be able to identify 1552 * short symlinks. 1553 */ 1554 ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN; 1555 ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ; 1556 mp->mnt_iflag |= IMNT_DTYPE; 1557 } else { 1558 ump->um_maxsymlinklen = fs->fs_maxsymlinklen; 1559 ump->um_dirblksiz = UFS_DIRBLKSIZ; 1560 if (ump->um_maxsymlinklen > 0) 1561 mp->mnt_iflag |= IMNT_DTYPE; 1562 else 1563 mp->mnt_iflag &= ~IMNT_DTYPE; 1564 } 1565 mp->mnt_fs_bshift = fs->fs_bshift; 1566 mp->mnt_dev_bshift = DEV_BSHIFT; /* XXX */ 1567 mp->mnt_flag |= MNT_LOCAL; 1568 mp->mnt_iflag |= IMNT_MPSAFE | IMNT_CAN_RWTORO | IMNT_SHRLOOKUP | 1569 IMNT_NCLOOKUP; 1570 #ifdef FFS_EI 1571 if (needswap) 1572 ump->um_flags |= UFS_NEEDSWAP; 1573 #endif 1574 error = ffs_acls(mp, fs->fs_flags); 1575 if (error) 1576 goto out1; 1577 ump->um_mountp = mp; 1578 ump->um_dev = dev; 1579 ump->um_devvp = devvp; 1580 ump->um_nindir = fs->fs_nindir; 1581 ump->um_lognindir = ffs(fs->fs_nindir) - 1; 1582 ump->um_bptrtodb = fs->fs_fshift - DEV_BSHIFT; 1583 ump->um_seqinc = fs->fs_frag; 1584 for (i = 0; i < MAXQUOTAS; i++) 1585 ump->um_quotas[i] = NULLVP; 1586 spec_node_setmountedfs(devvp, mp); 1587 if (ronly == 0 && fs->fs_snapinum[0] != 0) { 1588 #ifndef FFS_NO_SNAPSHOT 1589 ffs_snapshot_mount(mp); 1590 #else 1591 error = EINVAL; 1592 goto out1; 1593 #endif 1594 } 1595 #ifdef WAPBL 1596 if (!ronly) { 1597 KDASSERT(fs->fs_ronly == 0); 1598 /* 1599 * ffs_wapbl_start() needs mp->mnt_stat initialised if it 1600 * needs to create a new log file in-filesystem. 1601 */ 1602 error = ffs_statvfs(mp, &mp->mnt_stat); 1603 if (error) { 1604 DPRINTF("ffs_statvfs returned %d", error); 1605 goto out1; 1606 } 1607 1608 error = ffs_wapbl_start(mp); 1609 if (error) { 1610 DPRINTF("ffs_wapbl_start returned %d", error); 1611 goto out1; 1612 } 1613 } 1614 #endif /* WAPBL */ 1615 if (ronly == 0) { 1616 #ifdef QUOTA2 1617 error = ffs_quota2_mount(mp); 1618 if (error) { 1619 DPRINTF("ffs_quota2_mount returned %d", error); 1620 goto out1; 1621 } 1622 #else 1623 if (fs->fs_flags & FS_DOQUOTA2) { 1624 ump->um_flags |= UFS_QUOTA2; 1625 uprintf("%s: options QUOTA2 not enabled%s\n", 1626 mp->mnt_stat.f_mntonname, 1627 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting"); 1628 if ((mp->mnt_flag & MNT_FORCE) == 0) { 1629 error = EINVAL; 1630 DPRINTF("quota disabled %d", error); 1631 goto out1; 1632 } 1633 } 1634 #endif 1635 } 1636 1637 if (mp->mnt_flag & MNT_DISCARD) 1638 ump->um_discarddata = ffs_discard_init(devvp, fs); 1639 1640 return (0); 1641 out1: 1642 kmem_free(fs->fs_csp, allocsbsize); 1643 out: 1644 #ifdef WAPBL 1645 if (mp->mnt_wapbl_replay) { 1646 wapbl_replay_stop(mp->mnt_wapbl_replay); 1647 wapbl_replay_free(mp->mnt_wapbl_replay); 1648 mp->mnt_wapbl_replay = 0; 1649 } 1650 #endif 1651 1652 if (fs) 1653 kmem_free(fs, fs->fs_sbsize); 1654 spec_node_setmountedfs(devvp, NULL); 1655 if (bp) 1656 brelse(bp, bset); 1657 if (ump) { 1658 if (ump->um_oldfscompat) 1659 kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t)); 1660 mutex_destroy(&ump->um_lock); 1661 kmem_free(ump, sizeof(*ump)); 1662 mp->mnt_data = NULL; 1663 } 1664 return (error); 1665 } 1666 1667 /* 1668 * Sanity checks for loading old filesystem superblocks. 1669 * See ffs_oldfscompat_write below for unwound actions. 1670 * 1671 * XXX - Parts get retired eventually. 1672 * Unfortunately new bits get added. 1673 */ 1674 static void 1675 ffs_oldfscompat_read(struct fs *fs, struct ufsmount *ump, daddr_t sblockloc) 1676 { 1677 off_t maxfilesize; 1678 int32_t *extrasave; 1679 1680 if ((fs->fs_magic != FS_UFS1_MAGIC) || 1681 (fs->fs_old_flags & FS_FLAGS_UPDATED)) 1682 return; 1683 1684 if (!ump->um_oldfscompat) 1685 ump->um_oldfscompat = kmem_alloc(512 + 3*sizeof(int32_t), 1686 KM_SLEEP); 1687 1688 memcpy(ump->um_oldfscompat, &fs->fs_old_postbl_start, 512); 1689 extrasave = ump->um_oldfscompat; 1690 extrasave += 512/sizeof(int32_t); 1691 extrasave[0] = fs->fs_old_npsect; 1692 extrasave[1] = fs->fs_old_interleave; 1693 extrasave[2] = fs->fs_old_trackskew; 1694 1695 /* These fields will be overwritten by their 1696 * original values in fs_oldfscompat_write, so it is harmless 1697 * to modify them here. 1698 */ 1699 fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir; 1700 fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree; 1701 fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree; 1702 fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree; 1703 1704 fs->fs_maxbsize = fs->fs_bsize; 1705 fs->fs_time = fs->fs_old_time; 1706 fs->fs_size = fs->fs_old_size; 1707 fs->fs_dsize = fs->fs_old_dsize; 1708 fs->fs_csaddr = fs->fs_old_csaddr; 1709 fs->fs_sblockloc = sblockloc; 1710 1711 fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL); 1712 1713 if (fs->fs_old_postblformat == FS_42POSTBLFMT) { 1714 fs->fs_old_nrpos = 8; 1715 fs->fs_old_npsect = fs->fs_old_nsect; 1716 fs->fs_old_interleave = 1; 1717 fs->fs_old_trackskew = 0; 1718 } 1719 1720 if (fs->fs_magic == FS_UFS1_MAGIC && 1721 fs->fs_old_inodefmt < FS_44INODEFMT) { 1722 fs->fs_maxfilesize = (u_quad_t) 1LL << 39; 1723 fs->fs_qbmask = ~fs->fs_bmask; 1724 fs->fs_qfmask = ~fs->fs_fmask; 1725 } 1726 1727 maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1; 1728 if (fs->fs_maxfilesize > maxfilesize) 1729 fs->fs_maxfilesize = maxfilesize; 1730 1731 /* Compatibility for old filesystems */ 1732 if (fs->fs_avgfilesize <= 0) 1733 fs->fs_avgfilesize = AVFILESIZ; 1734 if (fs->fs_avgfpdir <= 0) 1735 fs->fs_avgfpdir = AFPDIR; 1736 1737 #if 0 1738 if (bigcgs) { 1739 fs->fs_save_cgsize = fs->fs_cgsize; 1740 fs->fs_cgsize = fs->fs_bsize; 1741 } 1742 #endif 1743 } 1744 1745 /* 1746 * Unwinding superblock updates for old filesystems. 1747 * See ffs_oldfscompat_read above for details. 1748 * 1749 * XXX - Parts get retired eventually. 1750 * Unfortunately new bits get added. 1751 */ 1752 static void 1753 ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump) 1754 { 1755 int32_t *extrasave; 1756 1757 if ((fs->fs_magic != FS_UFS1_MAGIC) || 1758 (fs->fs_old_flags & FS_FLAGS_UPDATED)) 1759 return; 1760 1761 fs->fs_old_time = fs->fs_time; 1762 fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir; 1763 fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree; 1764 fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree; 1765 fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree; 1766 fs->fs_old_flags = fs->fs_flags; 1767 1768 #if 0 1769 if (bigcgs) { 1770 fs->fs_cgsize = fs->fs_save_cgsize; 1771 } 1772 #endif 1773 1774 memcpy(&fs->fs_old_postbl_start, ump->um_oldfscompat, 512); 1775 extrasave = ump->um_oldfscompat; 1776 extrasave += 512/sizeof(int32_t); 1777 fs->fs_old_npsect = extrasave[0]; 1778 fs->fs_old_interleave = extrasave[1]; 1779 fs->fs_old_trackskew = extrasave[2]; 1780 1781 } 1782 1783 /* 1784 * unmount vfs operation 1785 */ 1786 int 1787 ffs_unmount(struct mount *mp, int mntflags) 1788 { 1789 struct lwp *l = curlwp; 1790 struct ufsmount *ump = VFSTOUFS(mp); 1791 struct fs *fs = ump->um_fs; 1792 int error, flags; 1793 u_int32_t bsize; 1794 #ifdef WAPBL 1795 extern int doforce; 1796 #endif 1797 1798 /* The file system is suspended. */ 1799 KASSERT(fstrans_is_owner(mp)); 1800 1801 if (ump->um_discarddata) { 1802 ffs_discard_finish(ump->um_discarddata, mntflags); 1803 ump->um_discarddata = NULL; 1804 } 1805 1806 flags = 0; 1807 if (mntflags & MNT_FORCE) 1808 flags |= FORCECLOSE; 1809 if ((error = ffs_flushfiles(mp, flags, l)) != 0) 1810 return (error); 1811 if (fs->fs_ronly == 0 && UFS_WAPBL_BEGIN(mp) == 0) { 1812 if (ffs_cgupdate(ump, MNT_WAIT) == 0 && 1813 fs->fs_clean & FS_WASCLEAN) { 1814 mutex_enter(&ump->um_lock); 1815 fs->fs_clean = FS_ISCLEAN; 1816 fs->fs_fmod = 0; 1817 mutex_exit(&ump->um_lock); 1818 (void) ffs_sbupdate(ump, MNT_WAIT); 1819 } 1820 UFS_WAPBL_END(mp); 1821 } 1822 #ifdef WAPBL 1823 KASSERT(!(mp->mnt_wapbl_replay && mp->mnt_wapbl)); 1824 if (mp->mnt_wapbl_replay) { 1825 KDASSERT(fs->fs_ronly); 1826 wapbl_replay_stop(mp->mnt_wapbl_replay); 1827 wapbl_replay_free(mp->mnt_wapbl_replay); 1828 mp->mnt_wapbl_replay = 0; 1829 } 1830 error = ffs_wapbl_stop(mp, doforce && (mntflags & MNT_FORCE)); 1831 if (error) { 1832 return error; 1833 } 1834 #endif /* WAPBL */ 1835 1836 if (ump->um_devvp->v_type != VBAD) 1837 spec_node_setmountedfs(ump->um_devvp, NULL); 1838 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 1839 (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD | FWRITE, 1840 NOCRED); 1841 vput(ump->um_devvp); 1842 1843 bsize = fs->fs_cssize; 1844 if (fs->fs_contigsumsize > 0) 1845 bsize += fs->fs_ncg * sizeof(int32_t); 1846 bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs); 1847 kmem_free(fs->fs_csp, bsize); 1848 1849 kmem_free(fs, fs->fs_sbsize); 1850 if (ump->um_oldfscompat != NULL) 1851 kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t)); 1852 mutex_destroy(&ump->um_lock); 1853 #ifndef FFS_NO_SNAPSHOT 1854 ffs_snapshot_fini(ump); 1855 #endif 1856 kmem_free(ump, sizeof(*ump)); 1857 mp->mnt_data = NULL; 1858 mp->mnt_flag &= ~MNT_LOCAL; 1859 return (0); 1860 } 1861 1862 /* 1863 * Flush out all the files in a filesystem. 1864 */ 1865 int 1866 ffs_flushfiles(struct mount *mp, int flags, struct lwp *l) 1867 { 1868 extern int doforce; 1869 struct ufsmount *ump; 1870 int error; 1871 1872 if (!doforce) 1873 flags &= ~FORCECLOSE; 1874 ump = VFSTOUFS(mp); 1875 #ifdef QUOTA 1876 if ((error = quota1_umount(mp, flags)) != 0) 1877 return (error); 1878 #endif 1879 #ifdef QUOTA2 1880 if ((error = quota2_umount(mp, flags)) != 0) 1881 return (error); 1882 #endif 1883 #ifdef UFS_EXTATTR 1884 if (ump->um_fstype == UFS1) { 1885 if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED) 1886 ufs_extattr_stop(mp, l); 1887 if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_INITIALIZED) 1888 ufs_extattr_uepm_destroy(&ump->um_extattr); 1889 mp->mnt_flag &= ~MNT_EXTATTR; 1890 } 1891 #endif 1892 if ((error = vflush(mp, 0, SKIPSYSTEM | flags)) != 0) 1893 return (error); 1894 #ifndef FFS_NO_SNAPSHOT 1895 ffs_snapshot_unmount(mp); 1896 #endif 1897 /* 1898 * Flush all the files. 1899 */ 1900 error = vflush(mp, NULLVP, flags); 1901 if (error) 1902 return (error); 1903 /* 1904 * Flush filesystem metadata. 1905 */ 1906 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 1907 error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0); 1908 VOP_UNLOCK(ump->um_devvp); 1909 if (flags & FORCECLOSE) /* XXXDBJ */ 1910 error = 0; 1911 1912 #ifdef WAPBL 1913 if (error) 1914 return error; 1915 if (mp->mnt_wapbl) { 1916 error = wapbl_flush(mp->mnt_wapbl, 1); 1917 if (flags & FORCECLOSE) 1918 error = 0; 1919 } 1920 #endif 1921 1922 return (error); 1923 } 1924 1925 /* 1926 * Get file system statistics. 1927 */ 1928 int 1929 ffs_statvfs(struct mount *mp, struct statvfs *sbp) 1930 { 1931 struct ufsmount *ump; 1932 struct fs *fs; 1933 1934 ump = VFSTOUFS(mp); 1935 fs = ump->um_fs; 1936 mutex_enter(&ump->um_lock); 1937 sbp->f_bsize = fs->fs_bsize; 1938 sbp->f_frsize = fs->fs_fsize; 1939 sbp->f_iosize = fs->fs_bsize; 1940 sbp->f_blocks = fs->fs_dsize; 1941 sbp->f_bfree = ffs_blkstofrags(fs, fs->fs_cstotal.cs_nbfree) + 1942 fs->fs_cstotal.cs_nffree + FFS_DBTOFSB(fs, fs->fs_pendingblocks); 1943 sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t) 1944 fs->fs_minfree) / (u_int64_t) 100; 1945 if (sbp->f_bfree > sbp->f_bresvd) 1946 sbp->f_bavail = sbp->f_bfree - sbp->f_bresvd; 1947 else 1948 sbp->f_bavail = 0; 1949 sbp->f_files = fs->fs_ncg * fs->fs_ipg - UFS_ROOTINO; 1950 sbp->f_ffree = fs->fs_cstotal.cs_nifree + fs->fs_pendinginodes; 1951 sbp->f_favail = sbp->f_ffree; 1952 sbp->f_fresvd = 0; 1953 mutex_exit(&ump->um_lock); 1954 copy_statvfs_info(sbp, mp); 1955 1956 return (0); 1957 } 1958 1959 struct ffs_sync_ctx { 1960 int waitfor; 1961 }; 1962 1963 static bool 1964 ffs_sync_selector(void *cl, struct vnode *vp) 1965 { 1966 struct ffs_sync_ctx *c = cl; 1967 struct inode *ip; 1968 1969 KASSERT(mutex_owned(vp->v_interlock)); 1970 1971 ip = VTOI(vp); 1972 /* 1973 * Skip the vnode/inode if inaccessible. 1974 */ 1975 if (ip == NULL || vp->v_type == VNON) 1976 return false; 1977 1978 /* 1979 * We deliberately update inode times here. This will 1980 * prevent a massive queue of updates accumulating, only 1981 * to be handled by a call to unmount. 1982 * 1983 * XXX It would be better to have the syncer trickle these 1984 * out. Adjustment needed to allow registering vnodes for 1985 * sync when the vnode is clean, but the inode dirty. Or 1986 * have ufs itself trickle out inode updates. 1987 * 1988 * If doing a lazy sync, we don't care about metadata or 1989 * data updates, because they are handled by each vnode's 1990 * synclist entry. In this case we are only interested in 1991 * writing back modified inodes. 1992 */ 1993 if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | 1994 IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) == 0 && 1995 (c->waitfor == MNT_LAZY || (LIST_EMPTY(&vp->v_dirtyblkhd) && 1996 (vp->v_iflag & VI_ONWORKLST) == 0))) 1997 return false; 1998 1999 return true; 2000 } 2001 2002 /* 2003 * Go through the disk queues to initiate sandbagged IO; 2004 * go through the inodes to write those that have been modified; 2005 * initiate the writing of the super block if it has been modified. 2006 */ 2007 int 2008 ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred) 2009 { 2010 struct vnode *vp; 2011 struct ufsmount *ump = VFSTOUFS(mp); 2012 struct fs *fs; 2013 struct vnode_iterator *marker; 2014 int error, allerror = 0; 2015 struct ffs_sync_ctx ctx; 2016 2017 fs = ump->um_fs; 2018 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */ 2019 panic("%s: rofs mod, fs=%s", __func__, fs->fs_fsmnt); 2020 } 2021 2022 /* 2023 * Write back each (modified) inode. 2024 */ 2025 vfs_vnode_iterator_init(mp, &marker); 2026 2027 ctx.waitfor = waitfor; 2028 while ((vp = vfs_vnode_iterator_next(marker, ffs_sync_selector, &ctx))) 2029 { 2030 error = vn_lock(vp, 2031 LK_EXCLUSIVE | (waitfor == MNT_LAZY ? LK_NOWAIT : 0)); 2032 if (error) { 2033 vrele(vp); 2034 continue; 2035 } 2036 if (waitfor == MNT_LAZY) { 2037 error = UFS_WAPBL_BEGIN(vp->v_mount); 2038 if (!error) { 2039 error = ffs_update(vp, NULL, NULL, 2040 UPDATE_CLOSE); 2041 UFS_WAPBL_END(vp->v_mount); 2042 } 2043 } else { 2044 error = VOP_FSYNC(vp, cred, FSYNC_NOLOG | 2045 (waitfor == MNT_WAIT ? FSYNC_WAIT : 0), 0, 0); 2046 } 2047 if (error) 2048 allerror = error; 2049 vput(vp); 2050 } 2051 vfs_vnode_iterator_destroy(marker); 2052 2053 /* 2054 * Force stale file system control information to be flushed. 2055 */ 2056 if (waitfor != MNT_LAZY) { 2057 bool need_devvp_fsync; 2058 2059 mutex_enter(ump->um_devvp->v_interlock); 2060 need_devvp_fsync = (ump->um_devvp->v_numoutput > 0 || 2061 !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd)); 2062 mutex_exit(ump->um_devvp->v_interlock); 2063 if (need_devvp_fsync) { 2064 int flags = FSYNC_NOLOG; 2065 2066 if (waitfor == MNT_WAIT) 2067 flags |= FSYNC_WAIT; 2068 2069 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 2070 if ((error = VOP_FSYNC(ump->um_devvp, cred, flags, 0, 2071 0)) != 0) 2072 allerror = error; 2073 VOP_UNLOCK(ump->um_devvp); 2074 } 2075 } 2076 #if defined(QUOTA) || defined(QUOTA2) 2077 qsync(mp); 2078 #endif 2079 /* 2080 * Write back modified superblock. 2081 */ 2082 error = UFS_WAPBL_BEGIN(mp); 2083 if (error) { 2084 allerror = error; 2085 } else { 2086 mutex_enter(&ump->um_lock); 2087 if (fs->fs_fmod != 0) { 2088 fs->fs_fmod = 0; 2089 fs->fs_time = time_second; 2090 mutex_exit(&ump->um_lock); 2091 if ((error = ffs_cgupdate(ump, waitfor))) 2092 allerror = error; 2093 } else { 2094 mutex_exit(&ump->um_lock); 2095 } 2096 UFS_WAPBL_END(mp); 2097 } 2098 2099 #ifdef WAPBL 2100 if (mp->mnt_wapbl) { 2101 error = wapbl_flush(mp->mnt_wapbl, (waitfor == MNT_WAIT)); 2102 if (error) 2103 allerror = error; 2104 } 2105 #endif 2106 2107 return (allerror); 2108 } 2109 2110 /* 2111 * Load inode from disk and initialize vnode. 2112 */ 2113 static int 2114 ffs_init_vnode(struct ufsmount *ump, struct vnode *vp, ino_t ino) 2115 { 2116 struct fs *fs; 2117 struct inode *ip; 2118 struct buf *bp; 2119 int error; 2120 2121 fs = ump->um_fs; 2122 2123 /* Read in the disk contents for the inode. */ 2124 error = bread(ump->um_devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ino)), 2125 (int)fs->fs_bsize, 0, &bp); 2126 if (error) 2127 return error; 2128 2129 /* Allocate and initialize inode. */ 2130 ip = pool_cache_get(ffs_inode_cache, PR_WAITOK); 2131 memset(ip, 0, sizeof(struct inode)); 2132 ip->i_ump = ump; 2133 ip->i_fs = fs; 2134 ip->i_dev = ump->um_dev; 2135 ip->i_number = ino; 2136 if (ump->um_fstype == UFS1) 2137 ip->i_din.ffs1_din = pool_cache_get(ffs_dinode1_cache, 2138 PR_WAITOK); 2139 else 2140 ip->i_din.ffs2_din = pool_cache_get(ffs_dinode2_cache, 2141 PR_WAITOK); 2142 ffs_load_inode(bp, ip, fs, ino); 2143 brelse(bp, 0); 2144 ip->i_vnode = vp; 2145 #if defined(QUOTA) || defined(QUOTA2) 2146 ufsquota_init(ip); 2147 #endif 2148 2149 /* Initialise vnode with this inode. */ 2150 vp->v_tag = VT_UFS; 2151 vp->v_op = ffs_vnodeop_p; 2152 vp->v_data = ip; 2153 2154 /* Initialize genfs node. */ 2155 genfs_node_init(vp, &ffs_genfsops); 2156 2157 return 0; 2158 } 2159 2160 /* 2161 * Undo ffs_init_vnode(). 2162 */ 2163 static void 2164 ffs_deinit_vnode(struct ufsmount *ump, struct vnode *vp) 2165 { 2166 struct inode *ip = VTOI(vp); 2167 2168 genfs_node_destroy(vp); 2169 vp->v_data = NULL; 2170 2171 if (ump->um_fstype == UFS1) 2172 pool_cache_put(ffs_dinode1_cache, ip->i_din.ffs1_din); 2173 else 2174 pool_cache_put(ffs_dinode2_cache, ip->i_din.ffs2_din); 2175 pool_cache_put(ffs_inode_cache, ip); 2176 } 2177 2178 /* 2179 * Read an inode from disk and initialize this vnode / inode pair. 2180 * Caller assures no other thread will try to load this inode. 2181 */ 2182 int 2183 ffs_loadvnode(struct mount *mp, struct vnode *vp, 2184 const void *key, size_t key_len, const void **new_key) 2185 { 2186 ino_t ino; 2187 struct fs *fs; 2188 struct inode *ip; 2189 struct ufsmount *ump; 2190 int error; 2191 2192 KASSERT(key_len == sizeof(ino)); 2193 memcpy(&ino, key, key_len); 2194 ump = VFSTOUFS(mp); 2195 fs = ump->um_fs; 2196 2197 error = ffs_init_vnode(ump, vp, ino); 2198 if (error) 2199 return error; 2200 2201 ip = VTOI(vp); 2202 if (ip->i_mode == 0) { 2203 ffs_deinit_vnode(ump, vp); 2204 2205 return ENOENT; 2206 } 2207 2208 /* Initialize the vnode from the inode. */ 2209 ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp); 2210 2211 /* Finish inode initialization. */ 2212 ip->i_devvp = ump->um_devvp; 2213 vref(ip->i_devvp); 2214 2215 /* 2216 * Ensure that uid and gid are correct. This is a temporary 2217 * fix until fsck has been changed to do the update. 2218 */ 2219 2220 if (fs->fs_magic == FS_UFS1_MAGIC && /* XXX */ 2221 fs->fs_old_inodefmt < FS_44INODEFMT) { /* XXX */ 2222 ip->i_uid = ip->i_ffs1_ouid; /* XXX */ 2223 ip->i_gid = ip->i_ffs1_ogid; /* XXX */ 2224 } /* XXX */ 2225 uvm_vnp_setsize(vp, ip->i_size); 2226 cache_enter_id(vp, ip->i_mode, ip->i_uid, ip->i_gid, !HAS_ACLS(ip)); 2227 *new_key = &ip->i_number; 2228 return 0; 2229 } 2230 2231 /* 2232 * Create a new inode on disk and initialize this vnode / inode pair. 2233 */ 2234 int 2235 ffs_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp, 2236 struct vattr *vap, kauth_cred_t cred, void *extra, 2237 size_t *key_len, const void **new_key) 2238 { 2239 ino_t ino; 2240 struct fs *fs; 2241 struct inode *ip; 2242 struct timespec ts; 2243 struct ufsmount *ump; 2244 int error, mode; 2245 2246 KASSERT(dvp->v_mount == mp); 2247 KASSERT(vap->va_type != VNON); 2248 2249 *key_len = sizeof(ino); 2250 ump = VFSTOUFS(mp); 2251 fs = ump->um_fs; 2252 mode = MAKEIMODE(vap->va_type, vap->va_mode); 2253 2254 /* Allocate fresh inode. */ 2255 error = ffs_valloc(dvp, mode, cred, &ino); 2256 if (error) 2257 return error; 2258 2259 /* Attach inode to vnode. */ 2260 error = ffs_init_vnode(ump, vp, ino); 2261 if (error) { 2262 if (UFS_WAPBL_BEGIN(mp) == 0) { 2263 ffs_vfree(dvp, ino, mode); 2264 UFS_WAPBL_END(mp); 2265 } 2266 return error; 2267 } 2268 2269 ip = VTOI(vp); 2270 if (ip->i_mode) { 2271 panic("%s: dup alloc ino=%" PRId64 " on %s: mode %o/%o " 2272 "gen %x/%x size %" PRIx64 " blocks %" PRIx64, 2273 __func__, ino, fs->fs_fsmnt, DIP(ip, mode), ip->i_mode, 2274 DIP(ip, gen), ip->i_gen, DIP(ip, size), DIP(ip, blocks)); 2275 } 2276 if (DIP(ip, size) || DIP(ip, blocks)) { 2277 printf("%s: ino=%" PRId64 " on %s: " 2278 "gen %x/%x has non zero blocks %" PRIx64 " or size %" 2279 PRIx64 "\n", 2280 __func__, ino, fs->fs_fsmnt, DIP(ip, gen), ip->i_gen, 2281 DIP(ip, blocks), DIP(ip, size)); 2282 if ((ip)->i_ump->um_fstype == UFS1) 2283 panic("%s: dirty filesystem?", __func__); 2284 DIP_ASSIGN(ip, blocks, 0); 2285 DIP_ASSIGN(ip, size, 0); 2286 } 2287 2288 /* Set uid / gid. */ 2289 if (cred == NOCRED || cred == FSCRED) { 2290 ip->i_gid = 0; 2291 ip->i_uid = 0; 2292 } else { 2293 ip->i_gid = VTOI(dvp)->i_gid; 2294 ip->i_uid = kauth_cred_geteuid(cred); 2295 } 2296 DIP_ASSIGN(ip, gid, ip->i_gid); 2297 DIP_ASSIGN(ip, uid, ip->i_uid); 2298 2299 #if defined(QUOTA) || defined(QUOTA2) 2300 error = UFS_WAPBL_BEGIN(mp); 2301 if (error) { 2302 ffs_deinit_vnode(ump, vp); 2303 2304 return error; 2305 } 2306 error = chkiq(ip, 1, cred, 0); 2307 if (error) { 2308 ffs_vfree(dvp, ino, mode); 2309 UFS_WAPBL_END(mp); 2310 ffs_deinit_vnode(ump, vp); 2311 2312 return error; 2313 } 2314 UFS_WAPBL_END(mp); 2315 #endif 2316 2317 /* Set type and finalize. */ 2318 ip->i_flags = 0; 2319 DIP_ASSIGN(ip, flags, 0); 2320 ip->i_mode = mode; 2321 DIP_ASSIGN(ip, mode, mode); 2322 if (vap->va_rdev != VNOVAL) { 2323 /* 2324 * Want to be able to use this to make badblock 2325 * inodes, so don't truncate the dev number. 2326 */ 2327 if (ump->um_fstype == UFS1) 2328 ip->i_ffs1_rdev = ufs_rw32(vap->va_rdev, 2329 UFS_MPNEEDSWAP(ump)); 2330 else 2331 ip->i_ffs2_rdev = ufs_rw64(vap->va_rdev, 2332 UFS_MPNEEDSWAP(ump)); 2333 } 2334 ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp); 2335 ip->i_devvp = ump->um_devvp; 2336 vref(ip->i_devvp); 2337 2338 /* Set up a new generation number for this inode. */ 2339 ip->i_gen++; 2340 DIP_ASSIGN(ip, gen, ip->i_gen); 2341 if (fs->fs_magic == FS_UFS2_MAGIC) { 2342 vfs_timestamp(&ts); 2343 ip->i_ffs2_birthtime = ts.tv_sec; 2344 ip->i_ffs2_birthnsec = ts.tv_nsec; 2345 } 2346 2347 uvm_vnp_setsize(vp, ip->i_size); 2348 cache_enter_id(vp, ip->i_mode, ip->i_uid, ip->i_gid, !HAS_ACLS(ip)); 2349 *new_key = &ip->i_number; 2350 return 0; 2351 } 2352 2353 /* 2354 * File handle to vnode 2355 * 2356 * Have to be really careful about stale file handles: 2357 * - check that the inode number is valid 2358 * - call ffs_vget() to get the locked inode 2359 * - check for an unallocated inode (i_mode == 0) 2360 * - check that the given client host has export rights and return 2361 * those rights via. exflagsp and credanonp 2362 */ 2363 int 2364 ffs_fhtovp(struct mount *mp, struct fid *fhp, int lktype, struct vnode **vpp) 2365 { 2366 struct ufid ufh; 2367 int error; 2368 2369 if (fhp->fid_len != sizeof(struct ufid)) 2370 return EINVAL; 2371 2372 memcpy(&ufh, fhp, sizeof(ufh)); 2373 if ((error = ffs_checkrange(mp, ufh.ufid_ino)) != 0) 2374 return error; 2375 2376 return (ufs_fhtovp(mp, &ufh, lktype, vpp)); 2377 } 2378 2379 /* 2380 * Vnode pointer to File handle 2381 */ 2382 /* ARGSUSED */ 2383 int 2384 ffs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) 2385 { 2386 struct inode *ip; 2387 struct ufid ufh; 2388 2389 if (*fh_size < sizeof(struct ufid)) { 2390 *fh_size = sizeof(struct ufid); 2391 return E2BIG; 2392 } 2393 ip = VTOI(vp); 2394 *fh_size = sizeof(struct ufid); 2395 memset(&ufh, 0, sizeof(ufh)); 2396 ufh.ufid_len = sizeof(struct ufid); 2397 ufh.ufid_ino = ip->i_number; 2398 ufh.ufid_gen = ip->i_gen; 2399 memcpy(fhp, &ufh, sizeof(ufh)); 2400 return (0); 2401 } 2402 2403 void 2404 ffs_init(void) 2405 { 2406 if (ffs_initcount++ > 0) 2407 return; 2408 2409 ffs_inode_cache = pool_cache_init(sizeof(struct inode), 0, 0, 0, 2410 "ffsino", NULL, IPL_NONE, NULL, NULL, NULL); 2411 ffs_dinode1_cache = pool_cache_init(sizeof(struct ufs1_dinode), 0, 0, 0, 2412 "ffsdino1", NULL, IPL_NONE, NULL, NULL, NULL); 2413 ffs_dinode2_cache = pool_cache_init(sizeof(struct ufs2_dinode), 0, 0, 0, 2414 "ffsdino2", NULL, IPL_NONE, NULL, NULL, NULL); 2415 ufs_init(); 2416 } 2417 2418 void 2419 ffs_reinit(void) 2420 { 2421 ufs_reinit(); 2422 } 2423 2424 void 2425 ffs_done(void) 2426 { 2427 if (--ffs_initcount > 0) 2428 return; 2429 2430 ufs_done(); 2431 pool_cache_destroy(ffs_dinode2_cache); 2432 pool_cache_destroy(ffs_dinode1_cache); 2433 pool_cache_destroy(ffs_inode_cache); 2434 } 2435 2436 /* 2437 * Write a superblock and associated information back to disk. 2438 */ 2439 int 2440 ffs_sbupdate(struct ufsmount *mp, int waitfor) 2441 { 2442 struct fs *fs = mp->um_fs; 2443 struct fs *bfs; 2444 struct buf *bp; 2445 int error; 2446 2447 error = ffs_getblk(mp->um_devvp, 2448 fs->fs_sblockloc / DEV_BSIZE, FFS_NOBLK, 2449 fs->fs_sbsize, false, &bp); 2450 if (error) 2451 return error; 2452 2453 mutex_enter(&mp->um_lock); 2454 memcpy(bp->b_data, fs, fs->fs_sbsize); 2455 mutex_exit(&mp->um_lock); 2456 2457 bfs = (struct fs *)bp->b_data; 2458 2459 bfs->fs_flags &= ~FS_INTERNAL; 2460 ffs_oldfscompat_write((struct fs *)bp->b_data, mp); 2461 if (mp->um_flags & UFS_EA) { 2462 KASSERT(bfs->fs_magic == FS_UFS2_MAGIC); 2463 bfs->fs_magic = FS_UFS2EA_MAGIC; 2464 } 2465 #ifdef FFS_EI 2466 if (mp->um_flags & UFS_NEEDSWAP) 2467 ffs_sb_swap(bfs, bfs); 2468 #endif 2469 2470 if (waitfor == MNT_WAIT) 2471 error = bwrite(bp); 2472 else 2473 bawrite(bp); 2474 return (error); 2475 } 2476 2477 int 2478 ffs_cgupdate(struct ufsmount *mp, int waitfor) 2479 { 2480 struct fs *fs = mp->um_fs; 2481 struct buf *bp; 2482 int blks; 2483 void *space; 2484 int i, size, error = 0, allerror = 0; 2485 2486 UFS_WAPBL_JLOCK_ASSERT(mp->um_mountp); 2487 2488 allerror = ffs_sbupdate(mp, waitfor); 2489 blks = howmany(fs->fs_cssize, fs->fs_fsize); 2490 space = fs->fs_csp; 2491 for (i = 0; i < blks; i += fs->fs_frag) { 2492 size = fs->fs_bsize; 2493 if (i + fs->fs_frag > blks) 2494 size = (blks - i) * fs->fs_fsize; 2495 error = ffs_getblk(mp->um_devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), 2496 FFS_NOBLK, size, false, &bp); 2497 if (error) 2498 break; 2499 #ifdef FFS_EI 2500 if (mp->um_flags & UFS_NEEDSWAP) 2501 ffs_csum_swap((struct csum*)space, 2502 (struct csum*)bp->b_data, size); 2503 else 2504 #endif 2505 memcpy(bp->b_data, space, (u_int)size); 2506 space = (char *)space + size; 2507 if (waitfor == MNT_WAIT) 2508 error = bwrite(bp); 2509 else 2510 bawrite(bp); 2511 } 2512 if (!allerror && error) 2513 allerror = error; 2514 return (allerror); 2515 } 2516 2517 int 2518 ffs_extattrctl(struct mount *mp, int cmd, struct vnode *vp, 2519 int attrnamespace, const char *attrname) 2520 { 2521 #ifdef UFS_EXTATTR 2522 /* 2523 * File-backed extended attributes are only supported on UFS1. 2524 * UFS2 has native extended attributes. 2525 */ 2526 if (VFSTOUFS(mp)->um_fstype == UFS1) 2527 return (ufs_extattrctl(mp, cmd, vp, attrnamespace, attrname)); 2528 #endif 2529 return (vfs_stdextattrctl(mp, cmd, vp, attrnamespace, attrname)); 2530 } 2531 2532 /* 2533 * Synch vnode for a mounted file system. 2534 */ 2535 static int 2536 ffs_vfs_fsync(vnode_t *vp, int flags) 2537 { 2538 int error, i, pflags; 2539 #ifdef WAPBL 2540 struct mount *mp; 2541 #endif 2542 2543 KASSERT(vp->v_type == VBLK); 2544 KASSERT(spec_node_getmountedfs(vp) != NULL); 2545 2546 /* 2547 * Flush all dirty data associated with the vnode. 2548 */ 2549 pflags = PGO_ALLPAGES | PGO_CLEANIT; 2550 if ((flags & FSYNC_WAIT) != 0) 2551 pflags |= PGO_SYNCIO; 2552 rw_enter(vp->v_uobj.vmobjlock, RW_WRITER); 2553 error = VOP_PUTPAGES(vp, 0, 0, pflags); 2554 if (error) 2555 return error; 2556 2557 #ifdef WAPBL 2558 mp = spec_node_getmountedfs(vp); 2559 if (mp && mp->mnt_wapbl) { 2560 /* 2561 * Don't bother writing out metadata if the syncer is 2562 * making the request. We will let the sync vnode 2563 * write it out in a single burst through a call to 2564 * VFS_SYNC(). 2565 */ 2566 if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY | FSYNC_NOLOG)) != 0) 2567 return 0; 2568 2569 /* 2570 * Don't flush the log if the vnode being flushed 2571 * contains no dirty buffers that could be in the log. 2572 */ 2573 if (!LIST_EMPTY(&vp->v_dirtyblkhd)) { 2574 error = wapbl_flush(mp->mnt_wapbl, 0); 2575 if (error) 2576 return error; 2577 } 2578 2579 if ((flags & FSYNC_WAIT) != 0) { 2580 mutex_enter(vp->v_interlock); 2581 while (vp->v_numoutput) 2582 cv_wait(&vp->v_cv, vp->v_interlock); 2583 mutex_exit(vp->v_interlock); 2584 } 2585 2586 return 0; 2587 } 2588 #endif /* WAPBL */ 2589 2590 error = vflushbuf(vp, flags); 2591 if (error == 0 && (flags & FSYNC_CACHE) != 0) { 2592 i = 1; 2593 (void)VOP_IOCTL(vp, DIOCCACHESYNC, &i, FWRITE, 2594 kauth_cred_get()); 2595 } 2596 2597 return error; 2598 } 2599