10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 280Sstevel@tonic-gate /* All Rights Reserved */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate /* 310Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 320Sstevel@tonic-gate * The Regents of the University of California 330Sstevel@tonic-gate * All Rights Reserved 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 360Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 370Sstevel@tonic-gate * contributors. 380Sstevel@tonic-gate */ 390Sstevel@tonic-gate 400Sstevel@tonic-gate 410Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 420Sstevel@tonic-gate 430Sstevel@tonic-gate #include <sys/types.h> 440Sstevel@tonic-gate #include <sys/t_lock.h> 450Sstevel@tonic-gate #include <sys/param.h> 460Sstevel@tonic-gate #include <sys/systm.h> 470Sstevel@tonic-gate #include <sys/bitmap.h> 480Sstevel@tonic-gate #include <sys/sysmacros.h> 490Sstevel@tonic-gate #include <sys/kmem.h> 500Sstevel@tonic-gate #include <sys/signal.h> 510Sstevel@tonic-gate #include <sys/user.h> 520Sstevel@tonic-gate #include <sys/proc.h> 530Sstevel@tonic-gate #include <sys/disp.h> 540Sstevel@tonic-gate #include <sys/buf.h> 550Sstevel@tonic-gate #include <sys/pathname.h> 560Sstevel@tonic-gate #include <sys/vfs.h> 570Sstevel@tonic-gate #include <sys/vnode.h> 580Sstevel@tonic-gate #include <sys/file.h> 59329Saguzovsk #include <sys/atomic.h> 600Sstevel@tonic-gate #include <sys/uio.h> 610Sstevel@tonic-gate #include <sys/dkio.h> 620Sstevel@tonic-gate #include <sys/cred.h> 630Sstevel@tonic-gate #include <sys/conf.h> 640Sstevel@tonic-gate #include <sys/dnlc.h> 650Sstevel@tonic-gate #include <sys/kstat.h> 660Sstevel@tonic-gate #include <sys/acl.h> 670Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h> 680Sstevel@tonic-gate #include <sys/fs/ufs_fs.h> 690Sstevel@tonic-gate #include <sys/fs/ufs_inode.h> 700Sstevel@tonic-gate #include <sys/fs/ufs_mount.h> 710Sstevel@tonic-gate #include <sys/fs/ufs_acl.h> 720Sstevel@tonic-gate #include <sys/fs/ufs_panic.h> 730Sstevel@tonic-gate #include <sys/fs/ufs_bio.h> 740Sstevel@tonic-gate #include <sys/fs/ufs_quota.h> 750Sstevel@tonic-gate #include <sys/fs/ufs_log.h> 760Sstevel@tonic-gate #undef NFS 770Sstevel@tonic-gate #include <sys/statvfs.h> 780Sstevel@tonic-gate #include <sys/mount.h> 790Sstevel@tonic-gate #include <sys/mntent.h> 800Sstevel@tonic-gate #include <sys/swap.h> 810Sstevel@tonic-gate #include <sys/errno.h> 820Sstevel@tonic-gate #include <sys/debug.h> 830Sstevel@tonic-gate #include "fs/fs_subr.h" 840Sstevel@tonic-gate #include <sys/cmn_err.h> 850Sstevel@tonic-gate #include <sys/dnlc.h> 860Sstevel@tonic-gate #include <sys/fssnap_if.h> 870Sstevel@tonic-gate #include <sys/sunddi.h> 880Sstevel@tonic-gate #include <sys/bootconf.h> 890Sstevel@tonic-gate #include <sys/policy.h> 900Sstevel@tonic-gate #include <sys/zone.h> 910Sstevel@tonic-gate 920Sstevel@tonic-gate /* 930Sstevel@tonic-gate * This is the loadable module wrapper. 940Sstevel@tonic-gate */ 950Sstevel@tonic-gate #include <sys/modctl.h> 960Sstevel@tonic-gate 970Sstevel@tonic-gate int ufsfstype; 980Sstevel@tonic-gate vfsops_t *ufs_vfsops; 990Sstevel@tonic-gate static int ufsinit(int, char *); 1000Sstevel@tonic-gate static int mountfs(); 1010Sstevel@tonic-gate extern int highbit(); 1020Sstevel@tonic-gate extern struct instats ins; 1030Sstevel@tonic-gate extern struct vnode *common_specvp(struct vnode *vp); 1040Sstevel@tonic-gate extern vfs_t EIO_vfs; 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate struct dquot *dquot, *dquotNDQUOT; 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate /* 1090Sstevel@tonic-gate * Cylinder group summary information handling tunable. 1100Sstevel@tonic-gate * This defines when these deltas get logged. 1110Sstevel@tonic-gate * If the number of cylinders in the file system is over the 1120Sstevel@tonic-gate * tunable then we log csum updates. Otherwise the updates are only 1130Sstevel@tonic-gate * done for performance on unmount. After a panic they can be 1140Sstevel@tonic-gate * quickly constructed during mounting. See ufs_construct_si() 1150Sstevel@tonic-gate * called from ufs_getsummaryinfo(). 1160Sstevel@tonic-gate * 1170Sstevel@tonic-gate * This performance feature can of course be disabled by setting 1180Sstevel@tonic-gate * ufs_ncg_log to 0, and fully enabled by setting it to 0xffffffff. 1190Sstevel@tonic-gate */ 1200Sstevel@tonic-gate #define UFS_LOG_NCG_DEFAULT 10000 1210Sstevel@tonic-gate uint32_t ufs_ncg_log = UFS_LOG_NCG_DEFAULT; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate /* 1240Sstevel@tonic-gate * ufs_clean_root indicates whether the root fs went down cleanly 1250Sstevel@tonic-gate */ 1260Sstevel@tonic-gate static int ufs_clean_root = 0; 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* 1290Sstevel@tonic-gate * UFS Mount options table 1300Sstevel@tonic-gate */ 1310Sstevel@tonic-gate static char *intr_cancel[] = { MNTOPT_NOINTR, NULL }; 1320Sstevel@tonic-gate static char *nointr_cancel[] = { MNTOPT_INTR, NULL }; 1330Sstevel@tonic-gate static char *forcedirectio_cancel[] = { MNTOPT_NOFORCEDIRECTIO, NULL }; 1340Sstevel@tonic-gate static char *noforcedirectio_cancel[] = { MNTOPT_FORCEDIRECTIO, NULL }; 1350Sstevel@tonic-gate static char *largefiles_cancel[] = { MNTOPT_NOLARGEFILES, NULL }; 1360Sstevel@tonic-gate static char *nolargefiles_cancel[] = { MNTOPT_LARGEFILES, NULL }; 1370Sstevel@tonic-gate static char *logging_cancel[] = { MNTOPT_NOLOGGING, NULL }; 1380Sstevel@tonic-gate static char *nologging_cancel[] = { MNTOPT_LOGGING, NULL }; 1390Sstevel@tonic-gate static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL }; 1400Sstevel@tonic-gate static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL }; 1410Sstevel@tonic-gate static char *quota_cancel[] = { MNTOPT_NOQUOTA, NULL }; 1420Sstevel@tonic-gate static char *noquota_cancel[] = { MNTOPT_QUOTA, NULL }; 1430Sstevel@tonic-gate static char *dfratime_cancel[] = { MNTOPT_NODFRATIME, NULL }; 1440Sstevel@tonic-gate static char *nodfratime_cancel[] = { MNTOPT_DFRATIME, NULL }; 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate static mntopt_t mntopts[] = { 1470Sstevel@tonic-gate /* 1480Sstevel@tonic-gate * option name cancel option default arg flags 1490Sstevel@tonic-gate * ufs arg flag 1500Sstevel@tonic-gate */ 1510Sstevel@tonic-gate { MNTOPT_INTR, intr_cancel, NULL, MO_DEFAULT, 1520Sstevel@tonic-gate (void *)0 }, 1530Sstevel@tonic-gate { MNTOPT_NOINTR, nointr_cancel, NULL, 0, 1540Sstevel@tonic-gate (void *)UFSMNT_NOINTR }, 1550Sstevel@tonic-gate { MNTOPT_SYNCDIR, NULL, NULL, 0, 1560Sstevel@tonic-gate (void *)UFSMNT_SYNCDIR }, 1570Sstevel@tonic-gate { MNTOPT_FORCEDIRECTIO, forcedirectio_cancel, NULL, 0, 1580Sstevel@tonic-gate (void *)UFSMNT_FORCEDIRECTIO }, 1590Sstevel@tonic-gate { MNTOPT_NOFORCEDIRECTIO, noforcedirectio_cancel, NULL, 0, 1600Sstevel@tonic-gate (void *)UFSMNT_NOFORCEDIRECTIO }, 1610Sstevel@tonic-gate { MNTOPT_NOSETSEC, NULL, NULL, 0, 1620Sstevel@tonic-gate (void *)UFSMNT_NOSETSEC }, 1630Sstevel@tonic-gate { MNTOPT_LARGEFILES, largefiles_cancel, NULL, MO_DEFAULT, 1640Sstevel@tonic-gate (void *)UFSMNT_LARGEFILES }, 1650Sstevel@tonic-gate { MNTOPT_NOLARGEFILES, nolargefiles_cancel, NULL, 0, 1660Sstevel@tonic-gate (void *)0 }, 1670Sstevel@tonic-gate { MNTOPT_LOGGING, logging_cancel, NULL, MO_TAG, 1680Sstevel@tonic-gate (void *)UFSMNT_LOGGING }, 1690Sstevel@tonic-gate { MNTOPT_NOLOGGING, nologging_cancel, NULL, 1700Sstevel@tonic-gate MO_NODISPLAY|MO_DEFAULT|MO_TAG, (void *)0 }, 1710Sstevel@tonic-gate { MNTOPT_QUOTA, quota_cancel, NULL, MO_IGNORE, 1720Sstevel@tonic-gate (void *)0 }, 1730Sstevel@tonic-gate { MNTOPT_NOQUOTA, noquota_cancel, NULL, 1740Sstevel@tonic-gate MO_NODISPLAY|MO_DEFAULT, (void *)0 }, 1750Sstevel@tonic-gate { MNTOPT_GLOBAL, NULL, NULL, 0, 1760Sstevel@tonic-gate (void *)0 }, 1770Sstevel@tonic-gate { MNTOPT_XATTR, xattr_cancel, NULL, MO_DEFAULT, 1780Sstevel@tonic-gate (void *)0 }, 1790Sstevel@tonic-gate { MNTOPT_NOXATTR, noxattr_cancel, NULL, 0, 1800Sstevel@tonic-gate (void *)0 }, 1810Sstevel@tonic-gate { MNTOPT_NOATIME, NULL, NULL, 0, 1820Sstevel@tonic-gate (void *)UFSMNT_NOATIME }, 1830Sstevel@tonic-gate { MNTOPT_DFRATIME, dfratime_cancel, NULL, 0, 1840Sstevel@tonic-gate (void *)0 }, 1850Sstevel@tonic-gate { MNTOPT_NODFRATIME, nodfratime_cancel, NULL, 1860Sstevel@tonic-gate MO_NODISPLAY|MO_DEFAULT, (void *)UFSMNT_NODFRATIME }, 1870Sstevel@tonic-gate { MNTOPT_ONERROR, NULL, UFSMNT_ONERROR_PANIC_STR, 1880Sstevel@tonic-gate MO_DEFAULT|MO_HASVALUE, (void *)0 }, 1890Sstevel@tonic-gate }; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate static mntopts_t ufs_mntopts = { 1920Sstevel@tonic-gate sizeof (mntopts) / sizeof (mntopt_t), 1930Sstevel@tonic-gate mntopts 1940Sstevel@tonic-gate }; 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate static vfsdef_t vfw = { 1970Sstevel@tonic-gate VFSDEF_VERSION, 1980Sstevel@tonic-gate "ufs", 1990Sstevel@tonic-gate ufsinit, 2000Sstevel@tonic-gate VSW_HASPROTO|VSW_CANREMOUNT, 2010Sstevel@tonic-gate &ufs_mntopts 2020Sstevel@tonic-gate }; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate /* 2050Sstevel@tonic-gate * Module linkage information for the kernel. 2060Sstevel@tonic-gate */ 2070Sstevel@tonic-gate extern struct mod_ops mod_fsops; 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate static struct modlfs modlfs = { 2100Sstevel@tonic-gate &mod_fsops, "filesystem for ufs", &vfw 2110Sstevel@tonic-gate }; 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate static struct modlinkage modlinkage = { 2140Sstevel@tonic-gate MODREV_1, (void *)&modlfs, NULL 2150Sstevel@tonic-gate }; 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate /* 2180Sstevel@tonic-gate * An attempt has been made to make this module unloadable. In order to 2190Sstevel@tonic-gate * test it, we need a system in which the root fs is NOT ufs. THIS HAS NOT 2200Sstevel@tonic-gate * BEEN DONE 2210Sstevel@tonic-gate */ 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate extern kstat_t *ufs_inode_kstat; 2240Sstevel@tonic-gate extern uint_t ufs_lockfs_key; 2250Sstevel@tonic-gate extern void ufs_lockfs_tsd_destructor(void *); 2260Sstevel@tonic-gate extern uint_t bypass_snapshot_throttle_key; 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate int 2290Sstevel@tonic-gate _init(void) 2300Sstevel@tonic-gate { 2310Sstevel@tonic-gate /* 2320Sstevel@tonic-gate * Create an index into the per thread array so that any thread doing 2330Sstevel@tonic-gate * VOP will have a lockfs mark on it. 2340Sstevel@tonic-gate */ 2350Sstevel@tonic-gate tsd_create(&ufs_lockfs_key, ufs_lockfs_tsd_destructor); 2360Sstevel@tonic-gate tsd_create(&bypass_snapshot_throttle_key, NULL); 2370Sstevel@tonic-gate return (mod_install(&modlinkage)); 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate int 2410Sstevel@tonic-gate _fini(void) 2420Sstevel@tonic-gate { 2430Sstevel@tonic-gate return (EBUSY); 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate int 2470Sstevel@tonic-gate _info(struct modinfo *modinfop) 2480Sstevel@tonic-gate { 2490Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate extern struct vnode *makespecvp(dev_t dev, vtype_t type); 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate extern kmutex_t ufs_scan_lock; 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate static int mountfs(struct vfs *, enum whymountroot, struct vnode *, char *, 2570Sstevel@tonic-gate struct cred *, int, void *, int); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate static int 2610Sstevel@tonic-gate ufs_mount(struct vfs *vfsp, struct vnode *mvp, struct mounta *uap, 2620Sstevel@tonic-gate struct cred *cr) 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate { 2650Sstevel@tonic-gate char *data = uap->dataptr; 2660Sstevel@tonic-gate int datalen = uap->datalen; 2670Sstevel@tonic-gate dev_t dev; 2680Sstevel@tonic-gate struct vnode *bvp; 2690Sstevel@tonic-gate struct pathname dpn; 2700Sstevel@tonic-gate int error; 2710Sstevel@tonic-gate enum whymountroot why = ROOT_INIT; 2720Sstevel@tonic-gate struct ufs_args args; 2730Sstevel@tonic-gate int oflag, aflag; 2740Sstevel@tonic-gate int fromspace = (uap->flags & MS_SYSSPACE) ? 2750Sstevel@tonic-gate UIO_SYSSPACE : UIO_USERSPACE; 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) 2780Sstevel@tonic-gate return (error); 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate if (mvp->v_type != VDIR) 2810Sstevel@tonic-gate return (ENOTDIR); 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate mutex_enter(&mvp->v_lock); 2840Sstevel@tonic-gate if ((uap->flags & MS_REMOUNT) == 0 && 2850Sstevel@tonic-gate (uap->flags & MS_OVERLAY) == 0 && 2860Sstevel@tonic-gate (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { 2870Sstevel@tonic-gate mutex_exit(&mvp->v_lock); 2880Sstevel@tonic-gate return (EBUSY); 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate mutex_exit(&mvp->v_lock); 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * Get arguments 2940Sstevel@tonic-gate */ 2950Sstevel@tonic-gate bzero(&args, sizeof (args)); 2960Sstevel@tonic-gate if ((uap->flags & MS_DATA) && data != NULL && datalen != 0) { 2970Sstevel@tonic-gate int copy_result = 0; 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate if (datalen > sizeof (args)) 3000Sstevel@tonic-gate return (EINVAL); 3010Sstevel@tonic-gate if (uap->flags & MS_SYSSPACE) 3020Sstevel@tonic-gate bcopy(data, &args, datalen); 3030Sstevel@tonic-gate else 3040Sstevel@tonic-gate copy_result = copyin(data, &args, datalen); 3050Sstevel@tonic-gate if (copy_result) 3060Sstevel@tonic-gate return (EFAULT); 3070Sstevel@tonic-gate datalen = sizeof (struct ufs_args); 3080Sstevel@tonic-gate } else { 3090Sstevel@tonic-gate datalen = 0; 3100Sstevel@tonic-gate } 3110Sstevel@tonic-gate /* 3120Sstevel@tonic-gate * Read in the mount point pathname 3130Sstevel@tonic-gate * (so we can record the directory the file system was last mounted on). 3140Sstevel@tonic-gate */ 3150Sstevel@tonic-gate if (error = pn_get(uap->dir, fromspace, &dpn)) 3160Sstevel@tonic-gate return (error); 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate /* 3190Sstevel@tonic-gate * Resolve path name of special file being mounted. 3200Sstevel@tonic-gate */ 3210Sstevel@tonic-gate if (error = lookupname(uap->spec, fromspace, FOLLOW, NULL, &bvp)) { 3220Sstevel@tonic-gate pn_free(&dpn); 3230Sstevel@tonic-gate return (error); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate if (bvp->v_type != VBLK) { 3260Sstevel@tonic-gate VN_RELE(bvp); 3270Sstevel@tonic-gate pn_free(&dpn); 3280Sstevel@tonic-gate return (ENOTBLK); 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate dev = bvp->v_rdev; 3310Sstevel@tonic-gate if (getmajor(dev) >= devcnt) { 3320Sstevel@tonic-gate pn_free(&dpn); 3330Sstevel@tonic-gate VN_RELE(bvp); 3340Sstevel@tonic-gate return (ENXIO); 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate if (uap->flags & MS_REMOUNT) 3370Sstevel@tonic-gate why = ROOT_REMOUNT; 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate /* 3400Sstevel@tonic-gate * In SunCluster, requests to a global device are satisfied by 3410Sstevel@tonic-gate * a local device. We substitute the global pxfs node with a 3420Sstevel@tonic-gate * local spec node here. 3430Sstevel@tonic-gate */ 3440Sstevel@tonic-gate if (IS_PXFSVP(bvp)) { 3450Sstevel@tonic-gate VN_RELE(bvp); 3460Sstevel@tonic-gate bvp = makespecvp(dev, VBLK); 3470Sstevel@tonic-gate } 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate /* 3500Sstevel@tonic-gate * Open block device mounted on. We need this to 3510Sstevel@tonic-gate * check whether the caller has sufficient rights to 3520Sstevel@tonic-gate * access the device in question. 3530Sstevel@tonic-gate * When bio is fixed for vnodes this can all be vnode 3540Sstevel@tonic-gate * operations. 3550Sstevel@tonic-gate */ 3560Sstevel@tonic-gate if ((vfsp->vfs_flag & VFS_RDONLY) != 0 || 3570Sstevel@tonic-gate (uap->flags & MS_RDONLY) != 0) { 3580Sstevel@tonic-gate oflag = FREAD; 3590Sstevel@tonic-gate aflag = VREAD; 3600Sstevel@tonic-gate } else { 3610Sstevel@tonic-gate oflag = FREAD | FWRITE; 3620Sstevel@tonic-gate aflag = VREAD | VWRITE; 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate if ((error = VOP_ACCESS(bvp, aflag, 0, cr)) != 0 || 3650Sstevel@tonic-gate (error = secpolicy_spec_open(cr, bvp, oflag)) != 0) { 3660Sstevel@tonic-gate pn_free(&dpn); 3670Sstevel@tonic-gate VN_RELE(bvp); 3680Sstevel@tonic-gate return (error); 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate /* 3720Sstevel@tonic-gate * Ensure that this device isn't already mounted or in progress on a 3730Sstevel@tonic-gate * mount unless this is a REMOUNT request or we are told to suppress 3740Sstevel@tonic-gate * mount checks. Global mounts require special handling. 3750Sstevel@tonic-gate */ 3760Sstevel@tonic-gate if ((uap->flags & MS_NOCHECK) == 0) { 3770Sstevel@tonic-gate if ((uap->flags & MS_GLOBAL) == 0 && 3780Sstevel@tonic-gate vfs_devmounting(dev, vfsp)) { 3790Sstevel@tonic-gate pn_free(&dpn); 3800Sstevel@tonic-gate VN_RELE(bvp); 3810Sstevel@tonic-gate return (EBUSY); 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate if (vfs_devismounted(dev)) { 3840Sstevel@tonic-gate if ((uap->flags & MS_REMOUNT) == 0) { 3850Sstevel@tonic-gate pn_free(&dpn); 3860Sstevel@tonic-gate VN_RELE(bvp); 3870Sstevel@tonic-gate return (EBUSY); 3880Sstevel@tonic-gate } 3890Sstevel@tonic-gate } 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate /* 3930Sstevel@tonic-gate * If the device is a tape, mount it read only 3940Sstevel@tonic-gate */ 3950Sstevel@tonic-gate if (devopsp[getmajor(dev)]->devo_cb_ops->cb_flag & D_TAPE) { 3960Sstevel@tonic-gate vfsp->vfs_flag |= VFS_RDONLY; 3970Sstevel@tonic-gate vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0); 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate if (uap->flags & MS_RDONLY) 4000Sstevel@tonic-gate vfsp->vfs_flag |= VFS_RDONLY; 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate /* 4030Sstevel@tonic-gate * Mount the filesystem, free the device vnode on error. 4040Sstevel@tonic-gate */ 4050Sstevel@tonic-gate error = mountfs(vfsp, why, bvp, dpn.pn_path, cr, 0, &args, datalen); 4060Sstevel@tonic-gate pn_free(&dpn); 4070Sstevel@tonic-gate if (error) { 4080Sstevel@tonic-gate VN_RELE(bvp); 4090Sstevel@tonic-gate } 4100Sstevel@tonic-gate return (error); 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate /* 4130Sstevel@tonic-gate * Mount root file system. 4140Sstevel@tonic-gate * "why" is ROOT_INIT on initial call ROOT_REMOUNT if called to 4150Sstevel@tonic-gate * remount the root file system, and ROOT_UNMOUNT if called to 4160Sstevel@tonic-gate * unmount the root (e.g., as part of a system shutdown). 4170Sstevel@tonic-gate * 4180Sstevel@tonic-gate * XXX - this may be partially machine-dependent; it, along with the VFS_SWAPVP 4190Sstevel@tonic-gate * operation, goes along with auto-configuration. A mechanism should be 4200Sstevel@tonic-gate * provided by which machine-INdependent code in the kernel can say "get me the 4210Sstevel@tonic-gate * right root file system" and "get me the right initial swap area", and have 4220Sstevel@tonic-gate * that done in what may well be a machine-dependent fashion. 4230Sstevel@tonic-gate * Unfortunately, it is also file-system-type dependent (NFS gets it via 4240Sstevel@tonic-gate * bootparams calls, UFS gets it from various and sundry machine-dependent 4250Sstevel@tonic-gate * mechanisms, as SPECFS does for swap). 4260Sstevel@tonic-gate */ 4270Sstevel@tonic-gate static int 4280Sstevel@tonic-gate ufs_mountroot(struct vfs *vfsp, enum whymountroot why) 4290Sstevel@tonic-gate { 4300Sstevel@tonic-gate struct fs *fsp; 4310Sstevel@tonic-gate int error; 4320Sstevel@tonic-gate static int ufsrootdone = 0; 4330Sstevel@tonic-gate dev_t rootdev; 4340Sstevel@tonic-gate struct vnode *vp; 4350Sstevel@tonic-gate struct vnode *devvp = 0; 4360Sstevel@tonic-gate int ovflags; 4370Sstevel@tonic-gate int doclkset; 4380Sstevel@tonic-gate ufsvfs_t *ufsvfsp; 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate if (why == ROOT_INIT) { 4410Sstevel@tonic-gate if (ufsrootdone++) 4420Sstevel@tonic-gate return (EBUSY); 4430Sstevel@tonic-gate rootdev = getrootdev(); 4440Sstevel@tonic-gate if (rootdev == (dev_t)NODEV) 4450Sstevel@tonic-gate return (ENODEV); 4460Sstevel@tonic-gate vfsp->vfs_dev = rootdev; 4470Sstevel@tonic-gate vfsp->vfs_flag |= VFS_RDONLY; 4480Sstevel@tonic-gate } else if (why == ROOT_REMOUNT) { 4490Sstevel@tonic-gate vp = ((struct ufsvfs *)vfsp->vfs_data)->vfs_devvp; 4500Sstevel@tonic-gate (void) dnlc_purge_vfsp(vfsp, 0); 4510Sstevel@tonic-gate vp = common_specvp(vp); 4520Sstevel@tonic-gate (void) VOP_PUTPAGE(vp, (offset_t)0, (size_t)0, B_INVAL, CRED()); 4530Sstevel@tonic-gate (void) bfinval(vfsp->vfs_dev, 0); 4540Sstevel@tonic-gate fsp = getfs(vfsp); 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate ovflags = vfsp->vfs_flag; 4570Sstevel@tonic-gate vfsp->vfs_flag &= ~VFS_RDONLY; 4580Sstevel@tonic-gate vfsp->vfs_flag |= VFS_REMOUNT; 4590Sstevel@tonic-gate rootdev = vfsp->vfs_dev; 4600Sstevel@tonic-gate } else if (why == ROOT_UNMOUNT) { 4610Sstevel@tonic-gate if (vfs_lock(vfsp) == 0) { 4620Sstevel@tonic-gate (void) ufs_flush(vfsp); 4630Sstevel@tonic-gate /* 4640Sstevel@tonic-gate * Mark the log as fully rolled 4650Sstevel@tonic-gate */ 4660Sstevel@tonic-gate ufsvfsp = (ufsvfs_t *)vfsp->vfs_data; 4670Sstevel@tonic-gate fsp = ufsvfsp->vfs_fs; 4680Sstevel@tonic-gate if (TRANS_ISTRANS(ufsvfsp) && 4690Sstevel@tonic-gate !TRANS_ISERROR(ufsvfsp) && 4700Sstevel@tonic-gate (fsp->fs_rolled == FS_NEED_ROLL)) { 4710Sstevel@tonic-gate ml_unit_t *ul = ufsvfsp->vfs_log; 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate error = ufs_putsummaryinfo(ul->un_dev, 4740Sstevel@tonic-gate ufsvfsp, fsp); 4750Sstevel@tonic-gate if (error == 0) { 4760Sstevel@tonic-gate fsp->fs_rolled = FS_ALL_ROLLED; 4770Sstevel@tonic-gate UFS_BWRITE2(NULL, ufsvfsp->vfs_bufp); 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate vfs_unlock(vfsp); 4810Sstevel@tonic-gate } else { 4820Sstevel@tonic-gate ufs_update(0); 4830Sstevel@tonic-gate } 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate vp = ((struct ufsvfs *)vfsp->vfs_data)->vfs_devvp; 4860Sstevel@tonic-gate (void) VOP_CLOSE(vp, FREAD|FWRITE, 1, 4870Sstevel@tonic-gate (offset_t)0, CRED()); 4880Sstevel@tonic-gate return (0); 4890Sstevel@tonic-gate } 4900Sstevel@tonic-gate error = vfs_lock(vfsp); 4910Sstevel@tonic-gate if (error) 4920Sstevel@tonic-gate return (error); 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate devvp = makespecvp(rootdev, VBLK); 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate /* If RO media, don't call clkset() (see below) */ 4970Sstevel@tonic-gate doclkset = 1; 4980Sstevel@tonic-gate if (why == ROOT_INIT) { 4990Sstevel@tonic-gate error = VOP_OPEN(&devvp, FREAD|FWRITE, CRED()); 5000Sstevel@tonic-gate if (error == 0) { 5010Sstevel@tonic-gate (void) VOP_CLOSE(devvp, FREAD|FWRITE, 1, 5020Sstevel@tonic-gate (offset_t)0, CRED()); 5030Sstevel@tonic-gate } else { 5040Sstevel@tonic-gate doclkset = 0; 5050Sstevel@tonic-gate } 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate error = mountfs(vfsp, why, devvp, "/", CRED(), 1, NULL, 0); 5090Sstevel@tonic-gate /* 5100Sstevel@tonic-gate * XXX - assumes root device is not indirect, because we don't set 5110Sstevel@tonic-gate * rootvp. Is rootvp used for anything? If so, make another arg 5120Sstevel@tonic-gate * to mountfs. 5130Sstevel@tonic-gate */ 5140Sstevel@tonic-gate if (error) { 5150Sstevel@tonic-gate vfs_unlock(vfsp); 5160Sstevel@tonic-gate if (why == ROOT_REMOUNT) 5170Sstevel@tonic-gate vfsp->vfs_flag = ovflags; 5180Sstevel@tonic-gate if (rootvp) { 5190Sstevel@tonic-gate VN_RELE(rootvp); 5200Sstevel@tonic-gate rootvp = (struct vnode *)0; 5210Sstevel@tonic-gate } 5220Sstevel@tonic-gate VN_RELE(devvp); 5230Sstevel@tonic-gate return (error); 5240Sstevel@tonic-gate } 5250Sstevel@tonic-gate if (why == ROOT_INIT) 5260Sstevel@tonic-gate vfs_add((struct vnode *)0, vfsp, 5270Sstevel@tonic-gate (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0); 5280Sstevel@tonic-gate vfs_unlock(vfsp); 5290Sstevel@tonic-gate fsp = getfs(vfsp); 5300Sstevel@tonic-gate clkset(doclkset ? fsp->fs_time : -1); 5310Sstevel@tonic-gate ufsvfsp = (ufsvfs_t *)vfsp->vfs_data; 5320Sstevel@tonic-gate if (ufsvfsp->vfs_log) { 5330Sstevel@tonic-gate vfs_setmntopt(vfsp, MNTOPT_LOGGING, NULL, 0); 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate return (0); 5360Sstevel@tonic-gate } 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate static int 5390Sstevel@tonic-gate remountfs(struct vfs *vfsp, dev_t dev, void *raw_argsp, int args_len) 5400Sstevel@tonic-gate { 5410Sstevel@tonic-gate struct ufsvfs *ufsvfsp = (struct ufsvfs *)vfsp->vfs_data; 5420Sstevel@tonic-gate struct ulockfs *ulp = &ufsvfsp->vfs_ulockfs; 5430Sstevel@tonic-gate struct buf *bp = ufsvfsp->vfs_bufp; 5440Sstevel@tonic-gate struct fs *fsp = (struct fs *)bp->b_un.b_addr; 5450Sstevel@tonic-gate struct fs *fspt; 5460Sstevel@tonic-gate struct buf *tpt = 0; 5470Sstevel@tonic-gate int error = 0; 5480Sstevel@tonic-gate int flags = 0; 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate if (args_len == sizeof (struct ufs_args) && raw_argsp) 5510Sstevel@tonic-gate flags = ((struct ufs_args *)raw_argsp)->flags; 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate /* cannot remount to RDONLY */ 5540Sstevel@tonic-gate if (vfsp->vfs_flag & VFS_RDONLY) 555*1107Ssjelinek return (ENOTSUP); 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate /* whoops, wrong dev */ 5580Sstevel@tonic-gate if (vfsp->vfs_dev != dev) 5590Sstevel@tonic-gate return (EINVAL); 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate /* 5620Sstevel@tonic-gate * synchronize w/ufs ioctls 5630Sstevel@tonic-gate */ 5640Sstevel@tonic-gate mutex_enter(&ulp->ul_lock); 565329Saguzovsk atomic_add_long(&ufs_quiesce_pend, 1); 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate /* 5680Sstevel@tonic-gate * reset options 5690Sstevel@tonic-gate */ 5700Sstevel@tonic-gate ufsvfsp->vfs_nointr = flags & UFSMNT_NOINTR; 5710Sstevel@tonic-gate ufsvfsp->vfs_syncdir = flags & UFSMNT_SYNCDIR; 5720Sstevel@tonic-gate ufsvfsp->vfs_nosetsec = flags & UFSMNT_NOSETSEC; 5730Sstevel@tonic-gate ufsvfsp->vfs_noatime = flags & UFSMNT_NOATIME; 5740Sstevel@tonic-gate if ((flags & UFSMNT_NODFRATIME) || ufsvfsp->vfs_noatime) 5750Sstevel@tonic-gate ufsvfsp->vfs_dfritime &= ~UFS_DFRATIME; 5760Sstevel@tonic-gate else /* dfratime, default behavior */ 5770Sstevel@tonic-gate ufsvfsp->vfs_dfritime |= UFS_DFRATIME; 5780Sstevel@tonic-gate if (flags & UFSMNT_FORCEDIRECTIO) 5790Sstevel@tonic-gate ufsvfsp->vfs_forcedirectio = 1; 5800Sstevel@tonic-gate else /* default is no direct I/O */ 5810Sstevel@tonic-gate ufsvfsp->vfs_forcedirectio = 0; 5820Sstevel@tonic-gate ufsvfsp->vfs_iotstamp = lbolt; 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate /* 5850Sstevel@tonic-gate * set largefiles flag in ufsvfs equal to the 5860Sstevel@tonic-gate * value passed in by the mount command. If 5870Sstevel@tonic-gate * it is "nolargefiles", and the flag is set 5880Sstevel@tonic-gate * in the superblock, the mount fails. 5890Sstevel@tonic-gate */ 5900Sstevel@tonic-gate if (!(flags & UFSMNT_LARGEFILES)) { /* "nolargefiles" */ 5910Sstevel@tonic-gate if (fsp->fs_flags & FSLARGEFILES) { 5920Sstevel@tonic-gate error = EFBIG; 5930Sstevel@tonic-gate goto remounterr; 5940Sstevel@tonic-gate } 5950Sstevel@tonic-gate ufsvfsp->vfs_lfflags &= ~UFS_LARGEFILES; 5960Sstevel@tonic-gate } else /* "largefiles" */ 5970Sstevel@tonic-gate ufsvfsp->vfs_lfflags |= UFS_LARGEFILES; 5980Sstevel@tonic-gate /* 5990Sstevel@tonic-gate * read/write to read/write; all done 6000Sstevel@tonic-gate */ 6010Sstevel@tonic-gate if (fsp->fs_ronly == 0) 6020Sstevel@tonic-gate goto remounterr; 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate /* 6050Sstevel@tonic-gate * fix-on-panic assumes RO->RW remount implies system-critical fs 6060Sstevel@tonic-gate * if it is shortly after boot; so, don't attempt to lock and fix 6070Sstevel@tonic-gate * (unless the user explicitly asked for another action on error) 6080Sstevel@tonic-gate * XXX UFSMNT_ONERROR_RDONLY rather than UFSMNT_ONERROR_PANIC 6090Sstevel@tonic-gate */ 6100Sstevel@tonic-gate #define BOOT_TIME_LIMIT (180*hz) 6110Sstevel@tonic-gate if (!(flags & UFSMNT_ONERROR_FLGMASK) && lbolt < BOOT_TIME_LIMIT) { 6120Sstevel@tonic-gate cmn_err(CE_WARN, "%s is required to be mounted onerror=%s", 6130Sstevel@tonic-gate ufsvfsp->vfs_fs->fs_fsmnt, UFSMNT_ONERROR_PANIC_STR); 6140Sstevel@tonic-gate flags |= UFSMNT_ONERROR_PANIC; 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate if ((error = ufsfx_mount(ufsvfsp, flags)) != 0) 6180Sstevel@tonic-gate goto remounterr; 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate /* 621921Sbatschul * quiesce the file system 6220Sstevel@tonic-gate */ 6230Sstevel@tonic-gate error = ufs_quiesce(ulp); 6240Sstevel@tonic-gate if (error) 6250Sstevel@tonic-gate goto remounterr; 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate tpt = UFS_BREAD(ufsvfsp, ufsvfsp->vfs_dev, SBLOCK, SBSIZE); 6280Sstevel@tonic-gate if (tpt->b_flags & B_ERROR) { 6290Sstevel@tonic-gate error = EIO; 6300Sstevel@tonic-gate goto remounterr; 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate fspt = (struct fs *)tpt->b_un.b_addr; 6330Sstevel@tonic-gate if (((fspt->fs_magic != FS_MAGIC) && 6340Sstevel@tonic-gate (fspt->fs_magic != MTB_UFS_MAGIC)) || 635757Svsakar (fspt->fs_magic == FS_MAGIC && 636757Svsakar (fspt->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 637757Svsakar fspt->fs_version != UFS_VERSION_MIN)) || 6380Sstevel@tonic-gate (fspt->fs_magic == MTB_UFS_MAGIC && 6390Sstevel@tonic-gate (fspt->fs_version > MTB_UFS_VERSION_1 || 6400Sstevel@tonic-gate fspt->fs_version < MTB_UFS_VERSION_MIN)) || 6410Sstevel@tonic-gate fspt->fs_bsize > MAXBSIZE || fspt->fs_frag > MAXFRAG || 6420Sstevel@tonic-gate fspt->fs_bsize < sizeof (struct fs) || fspt->fs_bsize < PAGESIZE) { 6430Sstevel@tonic-gate tpt->b_flags |= B_STALE | B_AGE; 6440Sstevel@tonic-gate error = EINVAL; 6450Sstevel@tonic-gate goto remounterr; 6460Sstevel@tonic-gate } 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate if (ufsvfsp->vfs_log && (ufsvfsp->vfs_log->un_flags & LDL_NOROLL)) { 6490Sstevel@tonic-gate ufsvfsp->vfs_log->un_flags &= ~LDL_NOROLL; 6500Sstevel@tonic-gate logmap_start_roll(ufsvfsp->vfs_log); 6510Sstevel@tonic-gate } 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate if (TRANS_ISERROR(ufsvfsp)) 6540Sstevel@tonic-gate goto remounterr; 6550Sstevel@tonic-gate TRANS_DOMATAMAP(ufsvfsp); 6560Sstevel@tonic-gate 6570Sstevel@tonic-gate if ((fspt->fs_state + fspt->fs_time == FSOKAY) && 6580Sstevel@tonic-gate fspt->fs_clean == FSLOG && !TRANS_ISTRANS(ufsvfsp)) { 6590Sstevel@tonic-gate ufsvfsp->vfs_log = NULL; 6600Sstevel@tonic-gate ufsvfsp->vfs_domatamap = 0; 6610Sstevel@tonic-gate error = ENOSPC; 6620Sstevel@tonic-gate goto remounterr; 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate if (fspt->fs_state + fspt->fs_time == FSOKAY && 6660Sstevel@tonic-gate (fspt->fs_clean == FSCLEAN || 6670Sstevel@tonic-gate fspt->fs_clean == FSSTABLE || 6680Sstevel@tonic-gate fspt->fs_clean == FSLOG)) { 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate /* 6710Sstevel@tonic-gate * Ensure that ufs_getsummaryinfo doesn't reconstruct 6720Sstevel@tonic-gate * the summary info. 6730Sstevel@tonic-gate */ 6740Sstevel@tonic-gate error = ufs_getsummaryinfo(vfsp->vfs_dev, ufsvfsp, fspt); 6750Sstevel@tonic-gate if (error) 6760Sstevel@tonic-gate goto remounterr; 6770Sstevel@tonic-gate 6780Sstevel@tonic-gate /* preserve mount name */ 6790Sstevel@tonic-gate (void) strncpy(fspt->fs_fsmnt, fsp->fs_fsmnt, MAXMNTLEN); 6800Sstevel@tonic-gate /* free the old cg space */ 6810Sstevel@tonic-gate kmem_free(fsp->fs_u.fs_csp, fsp->fs_cssize); 6820Sstevel@tonic-gate /* switch in the new superblock */ 6830Sstevel@tonic-gate fspt->fs_rolled = FS_NEED_ROLL; 6840Sstevel@tonic-gate bcopy(tpt->b_un.b_addr, bp->b_un.b_addr, fspt->fs_sbsize); 6850Sstevel@tonic-gate 6860Sstevel@tonic-gate fsp->fs_clean = FSSTABLE; 6870Sstevel@tonic-gate } /* superblock updated in memory */ 6880Sstevel@tonic-gate tpt->b_flags |= B_STALE | B_AGE; 6890Sstevel@tonic-gate brelse(tpt); 6900Sstevel@tonic-gate tpt = 0; 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate if (fsp->fs_clean != FSSTABLE) { 6930Sstevel@tonic-gate error = ENOSPC; 6940Sstevel@tonic-gate goto remounterr; 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate if (TRANS_ISTRANS(ufsvfsp)) { 6990Sstevel@tonic-gate fsp->fs_clean = FSLOG; 7000Sstevel@tonic-gate ufsvfsp->vfs_dio = 0; 7010Sstevel@tonic-gate } else 7020Sstevel@tonic-gate if (ufsvfsp->vfs_dio) 7030Sstevel@tonic-gate fsp->fs_clean = FSSUSPEND; 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate TRANS_MATA_MOUNT(ufsvfsp); 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate fsp->fs_fmod = 0; 7080Sstevel@tonic-gate fsp->fs_ronly = 0; 7090Sstevel@tonic-gate 710329Saguzovsk atomic_add_long(&ufs_quiesce_pend, -1); 7110Sstevel@tonic-gate cv_broadcast(&ulp->ul_cv); 7120Sstevel@tonic-gate mutex_exit(&ulp->ul_lock); 7130Sstevel@tonic-gate 7140Sstevel@tonic-gate if (TRANS_ISTRANS(ufsvfsp)) { 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate /* 7170Sstevel@tonic-gate * start the delete thread 7180Sstevel@tonic-gate */ 7190Sstevel@tonic-gate ufs_thread_start(&ufsvfsp->vfs_delete, ufs_thread_delete, vfsp); 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate /* 7220Sstevel@tonic-gate * start the reclaim thread 7230Sstevel@tonic-gate */ 7240Sstevel@tonic-gate if (fsp->fs_reclaim & (FS_RECLAIM|FS_RECLAIMING)) { 7250Sstevel@tonic-gate fsp->fs_reclaim &= ~FS_RECLAIM; 7260Sstevel@tonic-gate fsp->fs_reclaim |= FS_RECLAIMING; 7270Sstevel@tonic-gate ufs_thread_start(&ufsvfsp->vfs_reclaim, 7280Sstevel@tonic-gate ufs_thread_reclaim, vfsp); 7290Sstevel@tonic-gate } 7300Sstevel@tonic-gate } 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate TRANS_SBWRITE(ufsvfsp, TOP_MOUNT); 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate return (0); 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate remounterr: 7370Sstevel@tonic-gate if (tpt) 7380Sstevel@tonic-gate brelse(tpt); 739329Saguzovsk atomic_add_long(&ufs_quiesce_pend, -1); 7400Sstevel@tonic-gate cv_broadcast(&ulp->ul_cv); 7410Sstevel@tonic-gate mutex_exit(&ulp->ul_lock); 7420Sstevel@tonic-gate return (error); 7430Sstevel@tonic-gate } 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate /* 7460Sstevel@tonic-gate * If the device maxtransfer size is not available, we use ufs_maxmaxphys 7470Sstevel@tonic-gate * along with the system value for maxphys to determine the value for 7480Sstevel@tonic-gate * maxtransfer. 7490Sstevel@tonic-gate */ 7500Sstevel@tonic-gate int ufs_maxmaxphys = (1024 * 1024); 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate #include <sys/ddi.h> /* for delay(9f) */ 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate int ufs_mount_error_delay = 20; /* default to 20ms */ 755*1107Ssjelinek int ufs_mount_timeout = 60000; /* default to 1 minute */ 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate static int 7580Sstevel@tonic-gate mountfs(struct vfs *vfsp, enum whymountroot why, struct vnode *devvp, 7590Sstevel@tonic-gate char *path, cred_t *cr, int isroot, void *raw_argsp, int args_len) 7600Sstevel@tonic-gate { 7610Sstevel@tonic-gate dev_t dev = devvp->v_rdev; 7620Sstevel@tonic-gate struct fs *fsp; 7630Sstevel@tonic-gate struct ufsvfs *ufsvfsp = 0; 7640Sstevel@tonic-gate struct buf *bp = 0; 7650Sstevel@tonic-gate struct buf *tp = 0; 7660Sstevel@tonic-gate struct dk_cinfo ci; 7670Sstevel@tonic-gate int error = 0; 7680Sstevel@tonic-gate size_t len; 7690Sstevel@tonic-gate int needclose = 0; 7700Sstevel@tonic-gate int needtrans = 0; 7710Sstevel@tonic-gate struct inode *rip; 7720Sstevel@tonic-gate struct vnode *rvp = NULL; 7730Sstevel@tonic-gate int flags = 0; 7740Sstevel@tonic-gate kmutex_t *ihm; 7750Sstevel@tonic-gate int elapsed; 7760Sstevel@tonic-gate int status; 7770Sstevel@tonic-gate extern int maxphys; 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate if (args_len == sizeof (struct ufs_args) && raw_argsp) 7800Sstevel@tonic-gate flags = ((struct ufs_args *)raw_argsp)->flags; 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate ASSERT(vfs_lock_held(vfsp)); 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate if (why == ROOT_INIT) { 7850Sstevel@tonic-gate /* 7860Sstevel@tonic-gate * Open block device mounted on. 7870Sstevel@tonic-gate * When bio is fixed for vnodes this can all be vnode 7880Sstevel@tonic-gate * operations. 7890Sstevel@tonic-gate */ 7900Sstevel@tonic-gate error = VOP_OPEN(&devvp, 7910Sstevel@tonic-gate (vfsp->vfs_flag & VFS_RDONLY) ? FREAD : FREAD|FWRITE, cr); 7920Sstevel@tonic-gate if (error) 7930Sstevel@tonic-gate goto out; 7940Sstevel@tonic-gate needclose = 1; 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate /* 7970Sstevel@tonic-gate * Refuse to go any further if this 7980Sstevel@tonic-gate * device is being used for swapping. 7990Sstevel@tonic-gate */ 8000Sstevel@tonic-gate if (IS_SWAPVP(devvp)) { 8010Sstevel@tonic-gate error = EBUSY; 8020Sstevel@tonic-gate goto out; 8030Sstevel@tonic-gate } 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate /* 8070Sstevel@tonic-gate * check for dev already mounted on 8080Sstevel@tonic-gate */ 8090Sstevel@tonic-gate if (vfsp->vfs_flag & VFS_REMOUNT) { 8100Sstevel@tonic-gate error = remountfs(vfsp, dev, raw_argsp, args_len); 8110Sstevel@tonic-gate if (error == 0) 8120Sstevel@tonic-gate VN_RELE(devvp); 8130Sstevel@tonic-gate return (error); 8140Sstevel@tonic-gate } 8150Sstevel@tonic-gate 8160Sstevel@tonic-gate ASSERT(devvp != 0); 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate /* 8190Sstevel@tonic-gate * Flush back any dirty pages on the block device to 8200Sstevel@tonic-gate * try and keep the buffer cache in sync with the page 8210Sstevel@tonic-gate * cache if someone is trying to use block devices when 8220Sstevel@tonic-gate * they really should be using the raw device. 8230Sstevel@tonic-gate */ 8240Sstevel@tonic-gate (void) VOP_PUTPAGE(common_specvp(devvp), (offset_t)0, 8250Sstevel@tonic-gate (size_t)0, B_INVAL, cr); 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate /* 8280Sstevel@tonic-gate * read in superblock 8290Sstevel@tonic-gate */ 8300Sstevel@tonic-gate ufsvfsp = kmem_zalloc(sizeof (struct ufsvfs), KM_SLEEP); 8310Sstevel@tonic-gate tp = UFS_BREAD(ufsvfsp, dev, SBLOCK, SBSIZE); 8320Sstevel@tonic-gate if (tp->b_flags & B_ERROR) 8330Sstevel@tonic-gate goto out; 8340Sstevel@tonic-gate fsp = (struct fs *)tp->b_un.b_addr; 835757Svsakar 8360Sstevel@tonic-gate if ((fsp->fs_magic != FS_MAGIC) && (fsp->fs_magic != MTB_UFS_MAGIC)) { 837757Svsakar cmn_err(CE_NOTE, 838757Svsakar "mount: not a UFS magic number (0x%x)", fsp->fs_magic); 839757Svsakar error = EINVAL; 840757Svsakar goto out; 841757Svsakar } 842757Svsakar 843757Svsakar if ((fsp->fs_magic == FS_MAGIC) && 844757Svsakar (fsp->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 845757Svsakar fsp->fs_version != UFS_VERSION_MIN)) { 846757Svsakar cmn_err(CE_NOTE, 847757Svsakar "mount: unrecognized version of UFS on-disk format: %d", 848757Svsakar fsp->fs_version); 8490Sstevel@tonic-gate error = EINVAL; 8500Sstevel@tonic-gate goto out; 8510Sstevel@tonic-gate } 8520Sstevel@tonic-gate 8530Sstevel@tonic-gate if ((fsp->fs_magic == MTB_UFS_MAGIC) && 8540Sstevel@tonic-gate (fsp->fs_version > MTB_UFS_VERSION_1 || 8550Sstevel@tonic-gate fsp->fs_version < MTB_UFS_VERSION_MIN)) { 8560Sstevel@tonic-gate cmn_err(CE_NOTE, 8570Sstevel@tonic-gate "mount: unrecognized version of UFS on-disk format: %d", 8580Sstevel@tonic-gate fsp->fs_version); 8590Sstevel@tonic-gate error = EINVAL; 8600Sstevel@tonic-gate goto out; 8610Sstevel@tonic-gate } 8620Sstevel@tonic-gate 863757Svsakar #ifndef _LP64 8640Sstevel@tonic-gate if (fsp->fs_magic == MTB_UFS_MAGIC) { 8650Sstevel@tonic-gate /* 8660Sstevel@tonic-gate * Find the size of the device in sectors. If the 8670Sstevel@tonic-gate * the size in sectors is greater than INT_MAX, it's 8680Sstevel@tonic-gate * a multi-terabyte file system, which can't be 8690Sstevel@tonic-gate * mounted by a 32-bit kernel. We can't use the 8700Sstevel@tonic-gate * fsbtodb() macro in the next line because the macro 8710Sstevel@tonic-gate * casts the intermediate values to daddr_t, which is 8720Sstevel@tonic-gate * a 32-bit quantity in a 32-bit kernel. Here we 8730Sstevel@tonic-gate * really do need the intermediate values to be held 8740Sstevel@tonic-gate * in 64-bit quantities because we're checking for 8750Sstevel@tonic-gate * overflow of a 32-bit field. 8760Sstevel@tonic-gate */ 8770Sstevel@tonic-gate if ((((diskaddr_t)(fsp->fs_size)) << fsp->fs_fsbtodb) 8780Sstevel@tonic-gate > INT_MAX) { 8790Sstevel@tonic-gate cmn_err(CE_NOTE, 8800Sstevel@tonic-gate "mount: multi-terabyte UFS cannot be" 8810Sstevel@tonic-gate " mounted by a 32-bit kernel"); 8820Sstevel@tonic-gate error = EINVAL; 8830Sstevel@tonic-gate goto out; 8840Sstevel@tonic-gate } 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate } 887757Svsakar #endif 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate if (fsp->fs_bsize > MAXBSIZE || fsp->fs_frag > MAXFRAG || 8900Sstevel@tonic-gate fsp->fs_bsize < sizeof (struct fs) || fsp->fs_bsize < PAGESIZE) { 8910Sstevel@tonic-gate error = EINVAL; /* also needs translation */ 8920Sstevel@tonic-gate goto out; 8930Sstevel@tonic-gate } 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate /* 8960Sstevel@tonic-gate * Allocate VFS private data. 8970Sstevel@tonic-gate */ 8980Sstevel@tonic-gate vfsp->vfs_bcount = 0; 8990Sstevel@tonic-gate vfsp->vfs_data = (caddr_t)ufsvfsp; 9000Sstevel@tonic-gate vfsp->vfs_fstype = ufsfstype; 9010Sstevel@tonic-gate vfsp->vfs_dev = dev; 9020Sstevel@tonic-gate vfsp->vfs_flag |= VFS_NOTRUNC; 9030Sstevel@tonic-gate vfs_make_fsid(&vfsp->vfs_fsid, dev, ufsfstype); 9040Sstevel@tonic-gate ufsvfsp->vfs_devvp = devvp; 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate /* 9070Sstevel@tonic-gate * Cross-link with vfs and add to instance list. 9080Sstevel@tonic-gate */ 9090Sstevel@tonic-gate ufsvfsp->vfs_vfs = vfsp; 9100Sstevel@tonic-gate ufs_vfs_add(ufsvfsp); 9110Sstevel@tonic-gate 9120Sstevel@tonic-gate ufsvfsp->vfs_dev = dev; 9130Sstevel@tonic-gate ufsvfsp->vfs_bufp = tp; 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate ufsvfsp->vfs_dirsize = INODESIZE + (4 * ALLOCSIZE) + fsp->fs_fsize; 9160Sstevel@tonic-gate ufsvfsp->vfs_minfrags = (int)((int64_t)fsp->fs_dsize * 9170Sstevel@tonic-gate fsp->fs_minfree / 100); 9180Sstevel@tonic-gate /* 9190Sstevel@tonic-gate * if mount allows largefiles, indicate so in ufsvfs 9200Sstevel@tonic-gate */ 9210Sstevel@tonic-gate if (flags & UFSMNT_LARGEFILES) 9220Sstevel@tonic-gate ufsvfsp->vfs_lfflags |= UFS_LARGEFILES; 9230Sstevel@tonic-gate /* 9240Sstevel@tonic-gate * Initialize threads 9250Sstevel@tonic-gate */ 926512Sjkennedy ufs_delete_init(ufsvfsp, 1); 9270Sstevel@tonic-gate ufs_thread_init(&ufsvfsp->vfs_reclaim, 0); 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate /* 9300Sstevel@tonic-gate * Chicken and egg problem. The superblock may have deltas 9310Sstevel@tonic-gate * in the log. So after the log is scanned we reread the 9320Sstevel@tonic-gate * superblock. We guarantee that the fields needed to 9330Sstevel@tonic-gate * scan the log will not be in the log. 9340Sstevel@tonic-gate */ 9350Sstevel@tonic-gate if (fsp->fs_logbno && fsp->fs_clean == FSLOG && 9360Sstevel@tonic-gate (fsp->fs_state + fsp->fs_time == FSOKAY)) { 9370Sstevel@tonic-gate error = lufs_snarf(ufsvfsp, fsp, (vfsp->vfs_flag & VFS_RDONLY)); 9380Sstevel@tonic-gate if (error) { 9390Sstevel@tonic-gate /* 9400Sstevel@tonic-gate * Allow a ro mount to continue even if the 9410Sstevel@tonic-gate * log cannot be processed - yet. 9420Sstevel@tonic-gate */ 9430Sstevel@tonic-gate if (!(vfsp->vfs_flag & VFS_RDONLY)) { 9440Sstevel@tonic-gate cmn_err(CE_WARN, "Error accessing ufs " 9450Sstevel@tonic-gate "log for %s; Please run fsck(1M)", 9460Sstevel@tonic-gate path); 9470Sstevel@tonic-gate goto out; 9480Sstevel@tonic-gate } 9490Sstevel@tonic-gate } 9500Sstevel@tonic-gate tp->b_flags |= (B_AGE | B_STALE); 9510Sstevel@tonic-gate brelse(tp); 9520Sstevel@tonic-gate tp = UFS_BREAD(ufsvfsp, dev, SBLOCK, SBSIZE); 9530Sstevel@tonic-gate fsp = (struct fs *)tp->b_un.b_addr; 9540Sstevel@tonic-gate ufsvfsp->vfs_bufp = tp; 9550Sstevel@tonic-gate if (tp->b_flags & B_ERROR) 9560Sstevel@tonic-gate goto out; 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate /* 9600Sstevel@tonic-gate * Set logging mounted flag used by lockfs 9610Sstevel@tonic-gate */ 9620Sstevel@tonic-gate ufsvfsp->vfs_validfs = UT_MOUNTED; 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate /* 9650Sstevel@tonic-gate * Copy the super block into a buffer in its native size. 9660Sstevel@tonic-gate * Use ngeteblk to allocate the buffer 9670Sstevel@tonic-gate */ 9680Sstevel@tonic-gate bp = ngeteblk(fsp->fs_bsize); 9690Sstevel@tonic-gate ufsvfsp->vfs_bufp = bp; 9700Sstevel@tonic-gate bp->b_edev = dev; 9710Sstevel@tonic-gate bp->b_dev = cmpdev(dev); 9720Sstevel@tonic-gate bp->b_blkno = SBLOCK; 9730Sstevel@tonic-gate bp->b_bcount = fsp->fs_sbsize; 9740Sstevel@tonic-gate bcopy(tp->b_un.b_addr, bp->b_un.b_addr, fsp->fs_sbsize); 9750Sstevel@tonic-gate tp->b_flags |= B_STALE | B_AGE; 9760Sstevel@tonic-gate brelse(tp); 9770Sstevel@tonic-gate tp = 0; 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate fsp = (struct fs *)bp->b_un.b_addr; 9800Sstevel@tonic-gate /* 9810Sstevel@tonic-gate * Mount fails if superblock flag indicates presence of large 9820Sstevel@tonic-gate * files and filesystem is attempted to be mounted 'nolargefiles'. 9830Sstevel@tonic-gate * The exception is for a read only mount of root, which we 9840Sstevel@tonic-gate * always want to succeed, so fsck can fix potential problems. 9850Sstevel@tonic-gate * The assumption is that we will remount root at some point, 9860Sstevel@tonic-gate * and the remount will enforce the mount option. 9870Sstevel@tonic-gate */ 9880Sstevel@tonic-gate if (!(isroot & (vfsp->vfs_flag & VFS_RDONLY)) && 9890Sstevel@tonic-gate (fsp->fs_flags & FSLARGEFILES) && 9900Sstevel@tonic-gate !(flags & UFSMNT_LARGEFILES)) { 9910Sstevel@tonic-gate error = EFBIG; 9920Sstevel@tonic-gate goto out; 9930Sstevel@tonic-gate } 9940Sstevel@tonic-gate 9950Sstevel@tonic-gate if (vfsp->vfs_flag & VFS_RDONLY) { 9960Sstevel@tonic-gate fsp->fs_ronly = 1; 9970Sstevel@tonic-gate fsp->fs_fmod = 0; 9980Sstevel@tonic-gate if (((fsp->fs_state + fsp->fs_time) == FSOKAY) && 9990Sstevel@tonic-gate ((fsp->fs_clean == FSCLEAN) || 10000Sstevel@tonic-gate (fsp->fs_clean == FSSTABLE) || 10010Sstevel@tonic-gate (fsp->fs_clean == FSLOG))) { 10020Sstevel@tonic-gate if (isroot) { 10030Sstevel@tonic-gate if (fsp->fs_clean == FSLOG) { 10040Sstevel@tonic-gate if (fsp->fs_rolled == FS_ALL_ROLLED) { 10050Sstevel@tonic-gate ufs_clean_root = 1; 10060Sstevel@tonic-gate } 10070Sstevel@tonic-gate } else { 10080Sstevel@tonic-gate ufs_clean_root = 1; 10090Sstevel@tonic-gate } 10100Sstevel@tonic-gate } 10110Sstevel@tonic-gate fsp->fs_clean = FSSTABLE; 10120Sstevel@tonic-gate } else { 10130Sstevel@tonic-gate fsp->fs_clean = FSBAD; 10140Sstevel@tonic-gate } 10150Sstevel@tonic-gate } else { 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate fsp->fs_fmod = 0; 10180Sstevel@tonic-gate fsp->fs_ronly = 0; 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate TRANS_DOMATAMAP(ufsvfsp); 10210Sstevel@tonic-gate 10220Sstevel@tonic-gate if ((TRANS_ISERROR(ufsvfsp)) || 10230Sstevel@tonic-gate (((fsp->fs_state + fsp->fs_time) == FSOKAY) && 10240Sstevel@tonic-gate fsp->fs_clean == FSLOG && !TRANS_ISTRANS(ufsvfsp))) { 10250Sstevel@tonic-gate ufsvfsp->vfs_log = NULL; 10260Sstevel@tonic-gate ufsvfsp->vfs_domatamap = 0; 10270Sstevel@tonic-gate error = ENOSPC; 10280Sstevel@tonic-gate goto out; 10290Sstevel@tonic-gate } 10300Sstevel@tonic-gate 10310Sstevel@tonic-gate if (((fsp->fs_state + fsp->fs_time) == FSOKAY) && 10320Sstevel@tonic-gate (fsp->fs_clean == FSCLEAN || 10330Sstevel@tonic-gate fsp->fs_clean == FSSTABLE || 10340Sstevel@tonic-gate fsp->fs_clean == FSLOG)) 10350Sstevel@tonic-gate fsp->fs_clean = FSSTABLE; 10360Sstevel@tonic-gate else { 10370Sstevel@tonic-gate if (isroot) { 10380Sstevel@tonic-gate /* 10390Sstevel@tonic-gate * allow root partition to be mounted even 10400Sstevel@tonic-gate * when fs_state is not ok 10410Sstevel@tonic-gate * will be fixed later by a remount root 10420Sstevel@tonic-gate */ 10430Sstevel@tonic-gate fsp->fs_clean = FSBAD; 10440Sstevel@tonic-gate ufsvfsp->vfs_log = NULL; 10450Sstevel@tonic-gate ufsvfsp->vfs_domatamap = 0; 10460Sstevel@tonic-gate } else { 10470Sstevel@tonic-gate error = ENOSPC; 10480Sstevel@tonic-gate goto out; 10490Sstevel@tonic-gate } 10500Sstevel@tonic-gate } 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate if (fsp->fs_clean == FSSTABLE && TRANS_ISTRANS(ufsvfsp)) 10530Sstevel@tonic-gate fsp->fs_clean = FSLOG; 10540Sstevel@tonic-gate } 10550Sstevel@tonic-gate TRANS_MATA_MOUNT(ufsvfsp); 10560Sstevel@tonic-gate needtrans = 1; 10570Sstevel@tonic-gate 10580Sstevel@tonic-gate vfsp->vfs_bsize = fsp->fs_bsize; 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate /* 10610Sstevel@tonic-gate * Read in summary info 10620Sstevel@tonic-gate */ 10630Sstevel@tonic-gate if (error = ufs_getsummaryinfo(dev, ufsvfsp, fsp)) 10640Sstevel@tonic-gate goto out; 10650Sstevel@tonic-gate 10660Sstevel@tonic-gate /* 10670Sstevel@tonic-gate * lastwhinetime is set to zero rather than lbolt, so that after 10680Sstevel@tonic-gate * mounting if the filesystem is found to be full, then immediately the 10690Sstevel@tonic-gate * "file system message" will be logged. 10700Sstevel@tonic-gate */ 10710Sstevel@tonic-gate ufsvfsp->vfs_lastwhinetime = 0L; 10720Sstevel@tonic-gate 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate mutex_init(&ufsvfsp->vfs_lock, NULL, MUTEX_DEFAULT, NULL); 10750Sstevel@tonic-gate (void) copystr(path, fsp->fs_fsmnt, sizeof (fsp->fs_fsmnt) - 1, &len); 10760Sstevel@tonic-gate bzero(fsp->fs_fsmnt + len, sizeof (fsp->fs_fsmnt) - len); 10770Sstevel@tonic-gate 10780Sstevel@tonic-gate /* 10790Sstevel@tonic-gate * Sanity checks for old file systems 10800Sstevel@tonic-gate */ 10810Sstevel@tonic-gate if (fsp->fs_postblformat == FS_42POSTBLFMT) 10820Sstevel@tonic-gate ufsvfsp->vfs_nrpos = 8; 10830Sstevel@tonic-gate else 10840Sstevel@tonic-gate ufsvfsp->vfs_nrpos = fsp->fs_nrpos; 10850Sstevel@tonic-gate 10860Sstevel@tonic-gate /* 10870Sstevel@tonic-gate * Initialize lockfs structure to support file system locking 10880Sstevel@tonic-gate */ 10890Sstevel@tonic-gate bzero(&ufsvfsp->vfs_ulockfs.ul_lockfs, 10900Sstevel@tonic-gate sizeof (struct lockfs)); 10910Sstevel@tonic-gate ufsvfsp->vfs_ulockfs.ul_fs_lock = ULOCKFS_ULOCK; 10920Sstevel@tonic-gate mutex_init(&ufsvfsp->vfs_ulockfs.ul_lock, NULL, 10930Sstevel@tonic-gate MUTEX_DEFAULT, NULL); 10940Sstevel@tonic-gate cv_init(&ufsvfsp->vfs_ulockfs.ul_cv, NULL, CV_DEFAULT, NULL); 10950Sstevel@tonic-gate 10960Sstevel@tonic-gate /* 10970Sstevel@tonic-gate * We don't need to grab vfs_dqrwlock for this ufs_iget() call. 10980Sstevel@tonic-gate * We are in the process of mounting the file system so there 10990Sstevel@tonic-gate * is no need to grab the quota lock. If a quota applies to the 11000Sstevel@tonic-gate * root inode, then it will be updated when quotas are enabled. 11010Sstevel@tonic-gate * 11020Sstevel@tonic-gate * However, we have an ASSERT(RW_LOCK_HELD(&ufsvfsp->vfs_dqrwlock)) 11030Sstevel@tonic-gate * in getinoquota() that we want to keep so grab it anyway. 11040Sstevel@tonic-gate */ 11050Sstevel@tonic-gate rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER); 11060Sstevel@tonic-gate 11070Sstevel@tonic-gate error = ufs_iget_alloced(vfsp, UFSROOTINO, &rip, cr); 11080Sstevel@tonic-gate 11090Sstevel@tonic-gate rw_exit(&ufsvfsp->vfs_dqrwlock); 11100Sstevel@tonic-gate 11110Sstevel@tonic-gate if (error) 11120Sstevel@tonic-gate goto out; 11130Sstevel@tonic-gate 11140Sstevel@tonic-gate /* 11150Sstevel@tonic-gate * make sure root inode is a directory. Returning ENOTDIR might 11160Sstevel@tonic-gate * be confused with the mount point not being a directory, so 11170Sstevel@tonic-gate * we use EIO instead. 11180Sstevel@tonic-gate */ 11190Sstevel@tonic-gate if ((rip->i_mode & IFMT) != IFDIR) { 11200Sstevel@tonic-gate /* 11210Sstevel@tonic-gate * Mark this inode as subject for cleanup 11220Sstevel@tonic-gate * to avoid stray inodes in the cache. 11230Sstevel@tonic-gate */ 11240Sstevel@tonic-gate rvp = ITOV(rip); 11250Sstevel@tonic-gate error = EIO; 11260Sstevel@tonic-gate goto out; 11270Sstevel@tonic-gate } 11280Sstevel@tonic-gate 11290Sstevel@tonic-gate rvp = ITOV(rip); 11300Sstevel@tonic-gate mutex_enter(&rvp->v_lock); 11310Sstevel@tonic-gate rvp->v_flag |= VROOT; 11320Sstevel@tonic-gate mutex_exit(&rvp->v_lock); 11330Sstevel@tonic-gate ufsvfsp->vfs_root = rvp; 11340Sstevel@tonic-gate /* The buffer for the root inode does not contain a valid b_vp */ 11350Sstevel@tonic-gate (void) bfinval(dev, 0); 11360Sstevel@tonic-gate 11370Sstevel@tonic-gate /* options */ 11380Sstevel@tonic-gate ufsvfsp->vfs_nosetsec = flags & UFSMNT_NOSETSEC; 11390Sstevel@tonic-gate ufsvfsp->vfs_nointr = flags & UFSMNT_NOINTR; 11400Sstevel@tonic-gate ufsvfsp->vfs_syncdir = flags & UFSMNT_SYNCDIR; 11410Sstevel@tonic-gate ufsvfsp->vfs_noatime = flags & UFSMNT_NOATIME; 11420Sstevel@tonic-gate if ((flags & UFSMNT_NODFRATIME) || ufsvfsp->vfs_noatime) 11430Sstevel@tonic-gate ufsvfsp->vfs_dfritime &= ~UFS_DFRATIME; 11440Sstevel@tonic-gate else /* dfratime, default behavior */ 11450Sstevel@tonic-gate ufsvfsp->vfs_dfritime |= UFS_DFRATIME; 11460Sstevel@tonic-gate if (flags & UFSMNT_FORCEDIRECTIO) 11470Sstevel@tonic-gate ufsvfsp->vfs_forcedirectio = 1; 11480Sstevel@tonic-gate else if (flags & UFSMNT_NOFORCEDIRECTIO) 11490Sstevel@tonic-gate ufsvfsp->vfs_forcedirectio = 0; 11500Sstevel@tonic-gate ufsvfsp->vfs_iotstamp = lbolt; 11510Sstevel@tonic-gate 11520Sstevel@tonic-gate ufsvfsp->vfs_nindiroffset = fsp->fs_nindir - 1; 11530Sstevel@tonic-gate ufsvfsp->vfs_nindirshift = highbit(ufsvfsp->vfs_nindiroffset); 11540Sstevel@tonic-gate ufsvfsp->vfs_ioclustsz = fsp->fs_bsize * fsp->fs_maxcontig; 11550Sstevel@tonic-gate 11560Sstevel@tonic-gate if (cdev_ioctl(dev, DKIOCINFO, (intptr_t)&ci, 11570Sstevel@tonic-gate FKIOCTL|FNATIVE|FREAD, CRED(), &status) == 0) { 11580Sstevel@tonic-gate ufsvfsp->vfs_iotransz = ci.dki_maxtransfer * DEV_BSIZE; 11590Sstevel@tonic-gate } else { 11600Sstevel@tonic-gate ufsvfsp->vfs_iotransz = MIN(maxphys, ufs_maxmaxphys); 11610Sstevel@tonic-gate } 11620Sstevel@tonic-gate 11630Sstevel@tonic-gate if (ufsvfsp->vfs_iotransz <= 0) { 11640Sstevel@tonic-gate ufsvfsp->vfs_iotransz = MIN(maxphys, ufs_maxmaxphys); 11650Sstevel@tonic-gate } 11660Sstevel@tonic-gate 11670Sstevel@tonic-gate /* 11680Sstevel@tonic-gate * When logging, used to reserve log space for writes and truncs 11690Sstevel@tonic-gate */ 11700Sstevel@tonic-gate ufsvfsp->vfs_avgbfree = fsp->fs_cstotal.cs_nbfree / fsp->fs_ncg; 11710Sstevel@tonic-gate 11720Sstevel@tonic-gate /* 11730Sstevel@tonic-gate * Determine whether to log cylinder group summary info. 11740Sstevel@tonic-gate */ 11750Sstevel@tonic-gate ufsvfsp->vfs_nolog_si = (fsp->fs_ncg < ufs_ncg_log); 11760Sstevel@tonic-gate 11770Sstevel@tonic-gate if (TRANS_ISTRANS(ufsvfsp)) { 11780Sstevel@tonic-gate /* 11790Sstevel@tonic-gate * start the delete thread 11800Sstevel@tonic-gate */ 11810Sstevel@tonic-gate ufs_thread_start(&ufsvfsp->vfs_delete, ufs_thread_delete, vfsp); 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate /* 11840Sstevel@tonic-gate * start reclaim thread if the filesystem was not mounted 11850Sstevel@tonic-gate * read only. 11860Sstevel@tonic-gate */ 11870Sstevel@tonic-gate if (!fsp->fs_ronly && (fsp->fs_reclaim & 11880Sstevel@tonic-gate (FS_RECLAIM|FS_RECLAIMING))) { 11890Sstevel@tonic-gate fsp->fs_reclaim &= ~FS_RECLAIM; 11900Sstevel@tonic-gate fsp->fs_reclaim |= FS_RECLAIMING; 11910Sstevel@tonic-gate ufs_thread_start(&ufsvfsp->vfs_reclaim, 11920Sstevel@tonic-gate ufs_thread_reclaim, vfsp); 11930Sstevel@tonic-gate } 11940Sstevel@tonic-gate 11950Sstevel@tonic-gate /* Mark the fs as unrolled */ 11960Sstevel@tonic-gate fsp->fs_rolled = FS_NEED_ROLL; 11970Sstevel@tonic-gate } else if (!fsp->fs_ronly && (fsp->fs_reclaim & 11980Sstevel@tonic-gate (FS_RECLAIM|FS_RECLAIMING))) { 11990Sstevel@tonic-gate /* 12000Sstevel@tonic-gate * If a file system that is mounted nologging, after 12010Sstevel@tonic-gate * having previously been mounted logging, becomes 12020Sstevel@tonic-gate * unmounted whilst the reclaim thread is in the throes 12030Sstevel@tonic-gate * of reclaiming open/deleted inodes, a subsequent mount 12040Sstevel@tonic-gate * of such a file system with logging disabled could lead 12050Sstevel@tonic-gate * to inodes becoming lost. So, start reclaim now, even 12060Sstevel@tonic-gate * though logging was disabled for the previous mount, to 12070Sstevel@tonic-gate * tidy things up. 12080Sstevel@tonic-gate */ 12090Sstevel@tonic-gate fsp->fs_reclaim &= ~FS_RECLAIM; 12100Sstevel@tonic-gate fsp->fs_reclaim |= FS_RECLAIMING; 12110Sstevel@tonic-gate ufs_thread_start(&ufsvfsp->vfs_reclaim, 12120Sstevel@tonic-gate ufs_thread_reclaim, vfsp); 12130Sstevel@tonic-gate } 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate if (!fsp->fs_ronly) { 12160Sstevel@tonic-gate TRANS_SBWRITE(ufsvfsp, TOP_MOUNT); 12170Sstevel@tonic-gate if (error = geterror(ufsvfsp->vfs_bufp)) 12180Sstevel@tonic-gate goto out; 12190Sstevel@tonic-gate } 12200Sstevel@tonic-gate 12210Sstevel@tonic-gate /* fix-on-panic initialization */ 12220Sstevel@tonic-gate if (isroot && !(flags & UFSMNT_ONERROR_FLGMASK)) 12230Sstevel@tonic-gate flags |= UFSMNT_ONERROR_PANIC; /* XXX ..._RDONLY */ 12240Sstevel@tonic-gate 12250Sstevel@tonic-gate if ((error = ufsfx_mount(ufsvfsp, flags)) != 0) 12260Sstevel@tonic-gate goto out; 12270Sstevel@tonic-gate 12280Sstevel@tonic-gate if (why == ROOT_INIT && isroot) 12290Sstevel@tonic-gate rootvp = devvp; 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate return (0); 12320Sstevel@tonic-gate out: 12330Sstevel@tonic-gate if (error == 0) 12340Sstevel@tonic-gate error = EIO; 12350Sstevel@tonic-gate if (rvp) { 12360Sstevel@tonic-gate /* the following sequence is similar to ufs_unmount() */ 12370Sstevel@tonic-gate 12380Sstevel@tonic-gate /* 12390Sstevel@tonic-gate * There's a problem that ufs_iget() puts inodes into 12400Sstevel@tonic-gate * the inode cache before it returns them. If someone 12410Sstevel@tonic-gate * traverses that cache and gets a reference to our 12420Sstevel@tonic-gate * inode, there's a chance they'll still be using it 12430Sstevel@tonic-gate * after we've destroyed it. This is a hard race to 12440Sstevel@tonic-gate * hit, but it's happened (putting in a medium delay 12450Sstevel@tonic-gate * here, and a large delay in ufs_scan_inodes() for 12460Sstevel@tonic-gate * inodes on the device we're bailing out on, makes 12470Sstevel@tonic-gate * the race easy to demonstrate). The symptom is some 12480Sstevel@tonic-gate * other part of UFS faulting on bad inode contents, 12490Sstevel@tonic-gate * or when grabbing one of the locks inside the inode, 12500Sstevel@tonic-gate * etc. The usual victim is ufs_scan_inodes() or 12510Sstevel@tonic-gate * someone called by it. 12520Sstevel@tonic-gate */ 12530Sstevel@tonic-gate 12540Sstevel@tonic-gate /* 12550Sstevel@tonic-gate * First, isolate it so that no new references can be 12560Sstevel@tonic-gate * gotten via the inode cache. 12570Sstevel@tonic-gate */ 12580Sstevel@tonic-gate ihm = &ih_lock[INOHASH(UFSROOTINO)]; 12590Sstevel@tonic-gate mutex_enter(ihm); 12600Sstevel@tonic-gate remque(rip); 12610Sstevel@tonic-gate mutex_exit(ihm); 12620Sstevel@tonic-gate 12630Sstevel@tonic-gate /* 12640Sstevel@tonic-gate * Now wait for all outstanding references except our 12650Sstevel@tonic-gate * own to drain. This could, in theory, take forever, 12660Sstevel@tonic-gate * so don't wait *too* long. If we time out, mark 12670Sstevel@tonic-gate * it stale and leak it, so we don't hit the problem 12680Sstevel@tonic-gate * described above. 12690Sstevel@tonic-gate * 12700Sstevel@tonic-gate * Note that v_count is an int, which means we can read 12710Sstevel@tonic-gate * it in one operation. Thus, there's no need to lock 12720Sstevel@tonic-gate * around our tests. 12730Sstevel@tonic-gate */ 12740Sstevel@tonic-gate elapsed = 0; 12750Sstevel@tonic-gate while ((rvp->v_count > 1) && (elapsed < ufs_mount_timeout)) { 12760Sstevel@tonic-gate delay(ufs_mount_error_delay * drv_usectohz(1000)); 12770Sstevel@tonic-gate elapsed += ufs_mount_error_delay; 12780Sstevel@tonic-gate } 12790Sstevel@tonic-gate 12800Sstevel@tonic-gate if (rvp->v_count > 1) { 12810Sstevel@tonic-gate mutex_enter(&rip->i_tlock); 12820Sstevel@tonic-gate rip->i_flag |= ISTALE; 12830Sstevel@tonic-gate mutex_exit(&rip->i_tlock); 12840Sstevel@tonic-gate cmn_err(CE_WARN, 12850Sstevel@tonic-gate "Timed out while cleaning up after failed mount of %s", 12860Sstevel@tonic-gate path); 12870Sstevel@tonic-gate } else { 12880Sstevel@tonic-gate 12890Sstevel@tonic-gate /* 12900Sstevel@tonic-gate * Now we're the only one with a handle left, so tear 12910Sstevel@tonic-gate * it down the rest of the way. 12920Sstevel@tonic-gate */ 12930Sstevel@tonic-gate if (ufs_rmidle(rip)) 12940Sstevel@tonic-gate VN_RELE(rvp); 12950Sstevel@tonic-gate ufs_si_del(rip); 12960Sstevel@tonic-gate rip->i_ufsvfs = NULL; 12970Sstevel@tonic-gate rvp->v_vfsp = NULL; 12980Sstevel@tonic-gate rvp->v_type = VBAD; 12990Sstevel@tonic-gate VN_RELE(rvp); 13000Sstevel@tonic-gate } 13010Sstevel@tonic-gate } 13020Sstevel@tonic-gate if (needtrans) { 13030Sstevel@tonic-gate TRANS_MATA_UMOUNT(ufsvfsp); 13040Sstevel@tonic-gate } 13050Sstevel@tonic-gate if (ufsvfsp) { 13060Sstevel@tonic-gate ufs_vfs_remove(ufsvfsp); 13070Sstevel@tonic-gate ufs_thread_exit(&ufsvfsp->vfs_delete); 13080Sstevel@tonic-gate ufs_thread_exit(&ufsvfsp->vfs_reclaim); 13090Sstevel@tonic-gate mutex_destroy(&ufsvfsp->vfs_lock); 13100Sstevel@tonic-gate if (ufsvfsp->vfs_log) { 13110Sstevel@tonic-gate lufs_unsnarf(ufsvfsp); 13120Sstevel@tonic-gate } 13130Sstevel@tonic-gate kmem_free(ufsvfsp, sizeof (struct ufsvfs)); 13140Sstevel@tonic-gate } 13150Sstevel@tonic-gate if (bp) { 13160Sstevel@tonic-gate bp->b_flags |= (B_STALE|B_AGE); 13170Sstevel@tonic-gate brelse(bp); 13180Sstevel@tonic-gate } 13190Sstevel@tonic-gate if (tp) { 13200Sstevel@tonic-gate tp->b_flags |= (B_STALE|B_AGE); 13210Sstevel@tonic-gate brelse(tp); 13220Sstevel@tonic-gate } 13230Sstevel@tonic-gate if (needclose) { 13240Sstevel@tonic-gate (void) VOP_CLOSE(devvp, (vfsp->vfs_flag & VFS_RDONLY) ? 13250Sstevel@tonic-gate FREAD : FREAD|FWRITE, 1, (offset_t)0, cr); 13260Sstevel@tonic-gate bflush(dev); 13270Sstevel@tonic-gate (void) bfinval(dev, 1); 13280Sstevel@tonic-gate } 13290Sstevel@tonic-gate return (error); 13300Sstevel@tonic-gate } 13310Sstevel@tonic-gate 13320Sstevel@tonic-gate /* 13330Sstevel@tonic-gate * vfs operations 13340Sstevel@tonic-gate */ 13350Sstevel@tonic-gate static int 13360Sstevel@tonic-gate ufs_unmount(struct vfs *vfsp, int fflag, struct cred *cr) 13370Sstevel@tonic-gate { 13380Sstevel@tonic-gate dev_t dev = vfsp->vfs_dev; 13390Sstevel@tonic-gate struct ufsvfs *ufsvfsp = (struct ufsvfs *)vfsp->vfs_data; 13400Sstevel@tonic-gate struct fs *fs = ufsvfsp->vfs_fs; 13410Sstevel@tonic-gate struct ulockfs *ulp = &ufsvfsp->vfs_ulockfs; 13420Sstevel@tonic-gate struct vnode *bvp, *vp; 13430Sstevel@tonic-gate struct buf *bp; 13440Sstevel@tonic-gate struct inode *ip, *inext, *rip; 13450Sstevel@tonic-gate union ihead *ih; 13460Sstevel@tonic-gate int error, flag, i; 13470Sstevel@tonic-gate struct lockfs lockfs; 13480Sstevel@tonic-gate int poll_events = POLLPRI; 13490Sstevel@tonic-gate extern struct pollhead ufs_pollhd; 13500Sstevel@tonic-gate refstr_t *mountpoint; 13510Sstevel@tonic-gate 13520Sstevel@tonic-gate ASSERT(vfs_lock_held(vfsp)); 13530Sstevel@tonic-gate 13540Sstevel@tonic-gate if (secpolicy_fs_unmount(cr, vfsp) != 0) 13550Sstevel@tonic-gate return (EPERM); 13560Sstevel@tonic-gate /* 13570Sstevel@tonic-gate * Forced unmount is now supported through the 13580Sstevel@tonic-gate * lockfs protocol. 13590Sstevel@tonic-gate */ 13600Sstevel@tonic-gate if (fflag & MS_FORCE) { 13610Sstevel@tonic-gate /* 13620Sstevel@tonic-gate * Mark the filesystem as being unmounted now in 13630Sstevel@tonic-gate * case of a forcible umount before we take any 13640Sstevel@tonic-gate * locks inside UFS to prevent racing with a VFS_VGET() 13650Sstevel@tonic-gate * request. Throw these VFS_VGET() requests away for 13660Sstevel@tonic-gate * the duration of the forcible umount so they won't 13670Sstevel@tonic-gate * use stale or even freed data later on when we're done. 13680Sstevel@tonic-gate * It may happen that the VFS has had a additional hold 13690Sstevel@tonic-gate * placed on it by someone other than UFS and thus will 13700Sstevel@tonic-gate * not get freed immediately once we're done with the 13710Sstevel@tonic-gate * umount by dounmount() - use VFS_UNMOUNTED to inform 13720Sstevel@tonic-gate * users of this still-alive VFS that its corresponding 13730Sstevel@tonic-gate * filesystem being gone so they can detect that and error 13740Sstevel@tonic-gate * out. 13750Sstevel@tonic-gate */ 13760Sstevel@tonic-gate vfsp->vfs_flag |= VFS_UNMOUNTED; 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate ufs_thread_suspend(&ufsvfsp->vfs_delete); 13790Sstevel@tonic-gate mutex_enter(&ulp->ul_lock); 13800Sstevel@tonic-gate /* 13810Sstevel@tonic-gate * If file system is already hard locked, 13820Sstevel@tonic-gate * unmount the file system, otherwise 13830Sstevel@tonic-gate * hard lock it before unmounting. 13840Sstevel@tonic-gate */ 13850Sstevel@tonic-gate if (!ULOCKFS_IS_HLOCK(ulp)) { 1386329Saguzovsk atomic_add_long(&ufs_quiesce_pend, 1); 13870Sstevel@tonic-gate lockfs.lf_lock = LOCKFS_HLOCK; 13880Sstevel@tonic-gate lockfs.lf_flags = 0; 13890Sstevel@tonic-gate lockfs.lf_key = ulp->ul_lockfs.lf_key + 1; 13900Sstevel@tonic-gate lockfs.lf_comlen = 0; 13910Sstevel@tonic-gate lockfs.lf_comment = NULL; 13920Sstevel@tonic-gate ufs_freeze(ulp, &lockfs); 13930Sstevel@tonic-gate ULOCKFS_SET_BUSY(ulp); 13940Sstevel@tonic-gate LOCKFS_SET_BUSY(&ulp->ul_lockfs); 13950Sstevel@tonic-gate (void) ufs_quiesce(ulp); 13960Sstevel@tonic-gate (void) ufs_flush(vfsp); 13970Sstevel@tonic-gate (void) ufs_thaw(vfsp, ufsvfsp, ulp); 1398329Saguzovsk atomic_add_long(&ufs_quiesce_pend, -1); 13990Sstevel@tonic-gate ULOCKFS_CLR_BUSY(ulp); 14000Sstevel@tonic-gate LOCKFS_CLR_BUSY(&ulp->ul_lockfs); 14010Sstevel@tonic-gate poll_events |= POLLERR; 14020Sstevel@tonic-gate pollwakeup(&ufs_pollhd, poll_events); 14030Sstevel@tonic-gate } 14040Sstevel@tonic-gate ufs_thread_continue(&ufsvfsp->vfs_delete); 14050Sstevel@tonic-gate mutex_exit(&ulp->ul_lock); 14060Sstevel@tonic-gate } 14070Sstevel@tonic-gate 14080Sstevel@tonic-gate /* let all types of writes go through */ 14090Sstevel@tonic-gate ufsvfsp->vfs_iotstamp = lbolt; 14100Sstevel@tonic-gate 14110Sstevel@tonic-gate /* coordinate with global hlock thread */ 14120Sstevel@tonic-gate if (TRANS_ISTRANS(ufsvfsp) && (ufsvfsp->vfs_validfs == UT_HLOCKING)) { 14130Sstevel@tonic-gate /* 14140Sstevel@tonic-gate * last possibility for a forced umount to fail hence clear 14150Sstevel@tonic-gate * VFS_UNMOUNTED if appropriate. 14160Sstevel@tonic-gate */ 14170Sstevel@tonic-gate if (fflag & MS_FORCE) 14180Sstevel@tonic-gate vfsp->vfs_flag &= ~VFS_UNMOUNTED; 14190Sstevel@tonic-gate return (EAGAIN); 14200Sstevel@tonic-gate } 14210Sstevel@tonic-gate 14220Sstevel@tonic-gate ufsvfsp->vfs_validfs = UT_UNMOUNTED; 14230Sstevel@tonic-gate 14240Sstevel@tonic-gate /* kill the reclaim thread */ 14250Sstevel@tonic-gate ufs_thread_exit(&ufsvfsp->vfs_reclaim); 14260Sstevel@tonic-gate 14270Sstevel@tonic-gate /* suspend the delete thread */ 14280Sstevel@tonic-gate ufs_thread_suspend(&ufsvfsp->vfs_delete); 14290Sstevel@tonic-gate 14300Sstevel@tonic-gate /* 14310Sstevel@tonic-gate * drain the delete and idle queues 14320Sstevel@tonic-gate */ 14330Sstevel@tonic-gate ufs_delete_drain(vfsp, -1, 1); 14340Sstevel@tonic-gate ufs_idle_drain(vfsp); 14350Sstevel@tonic-gate 14360Sstevel@tonic-gate /* 14370Sstevel@tonic-gate * use the lockfs protocol to prevent new ops from starting 14380Sstevel@tonic-gate * a forcible umount can not fail beyond this point as 14390Sstevel@tonic-gate * we hard-locked the filesystem and drained all current consumers 14400Sstevel@tonic-gate * before. 14410Sstevel@tonic-gate */ 14420Sstevel@tonic-gate mutex_enter(&ulp->ul_lock); 14430Sstevel@tonic-gate 14440Sstevel@tonic-gate /* 14450Sstevel@tonic-gate * if the file system is busy; return EBUSY 14460Sstevel@tonic-gate */ 1447923Ssdebnath if (ulp->ul_vnops_cnt || ulp->ul_falloc_cnt || ULOCKFS_IS_SLOCK(ulp)) { 14480Sstevel@tonic-gate error = EBUSY; 14490Sstevel@tonic-gate goto out; 14500Sstevel@tonic-gate } 14510Sstevel@tonic-gate 14520Sstevel@tonic-gate /* 14530Sstevel@tonic-gate * if this is not a forced unmount (!hard/error locked), then 14540Sstevel@tonic-gate * get rid of every inode except the root and quota inodes 14550Sstevel@tonic-gate * also, commit any outstanding transactions 14560Sstevel@tonic-gate */ 14570Sstevel@tonic-gate if (!ULOCKFS_IS_HLOCK(ulp) && !ULOCKFS_IS_ELOCK(ulp)) 14580Sstevel@tonic-gate if (error = ufs_flush(vfsp)) 14590Sstevel@tonic-gate goto out; 14600Sstevel@tonic-gate 14610Sstevel@tonic-gate /* 14620Sstevel@tonic-gate * ignore inodes in the cache if fs is hard locked or error locked 14630Sstevel@tonic-gate */ 14640Sstevel@tonic-gate rip = VTOI(ufsvfsp->vfs_root); 14650Sstevel@tonic-gate if (!ULOCKFS_IS_HLOCK(ulp) && !ULOCKFS_IS_ELOCK(ulp)) { 14660Sstevel@tonic-gate /* 14670Sstevel@tonic-gate * Otherwise, only the quota and root inodes are in the cache. 14680Sstevel@tonic-gate * 14690Sstevel@tonic-gate * Avoid racing with ufs_update() and ufs_sync(). 14700Sstevel@tonic-gate */ 14710Sstevel@tonic-gate mutex_enter(&ufs_scan_lock); 14720Sstevel@tonic-gate 14730Sstevel@tonic-gate for (i = 0, ih = ihead; i < inohsz; i++, ih++) { 14740Sstevel@tonic-gate mutex_enter(&ih_lock[i]); 14750Sstevel@tonic-gate for (ip = ih->ih_chain[0]; 14760Sstevel@tonic-gate ip != (struct inode *)ih; 14770Sstevel@tonic-gate ip = ip->i_forw) { 14780Sstevel@tonic-gate if (ip->i_ufsvfs != ufsvfsp) 14790Sstevel@tonic-gate continue; 14800Sstevel@tonic-gate if (ip == ufsvfsp->vfs_qinod) 14810Sstevel@tonic-gate continue; 14820Sstevel@tonic-gate if (ip == rip && ITOV(ip)->v_count == 1) 14830Sstevel@tonic-gate continue; 14840Sstevel@tonic-gate mutex_exit(&ih_lock[i]); 14850Sstevel@tonic-gate mutex_exit(&ufs_scan_lock); 14860Sstevel@tonic-gate error = EBUSY; 14870Sstevel@tonic-gate goto out; 14880Sstevel@tonic-gate } 14890Sstevel@tonic-gate mutex_exit(&ih_lock[i]); 14900Sstevel@tonic-gate } 14910Sstevel@tonic-gate mutex_exit(&ufs_scan_lock); 14920Sstevel@tonic-gate } 14930Sstevel@tonic-gate 14940Sstevel@tonic-gate /* 14950Sstevel@tonic-gate * if a snapshot exists and this is a forced unmount, then delete 14960Sstevel@tonic-gate * the snapshot. Otherwise return EBUSY. This will insure the 14970Sstevel@tonic-gate * snapshot always belongs to a valid file system. 14980Sstevel@tonic-gate */ 14990Sstevel@tonic-gate if (ufsvfsp->vfs_snapshot) { 15000Sstevel@tonic-gate if (ULOCKFS_IS_HLOCK(ulp) || ULOCKFS_IS_ELOCK(ulp)) { 15010Sstevel@tonic-gate (void) fssnap_delete(&ufsvfsp->vfs_snapshot); 15020Sstevel@tonic-gate } else { 15030Sstevel@tonic-gate error = EBUSY; 15040Sstevel@tonic-gate goto out; 15050Sstevel@tonic-gate } 15060Sstevel@tonic-gate } 15070Sstevel@tonic-gate 15080Sstevel@tonic-gate /* 15090Sstevel@tonic-gate * Close the quota file and invalidate anything left in the quota 15100Sstevel@tonic-gate * cache for this file system. Pass kcred to allow all quota 15110Sstevel@tonic-gate * manipulations. 15120Sstevel@tonic-gate */ 15130Sstevel@tonic-gate (void) closedq(ufsvfsp, kcred); 15140Sstevel@tonic-gate invalidatedq(ufsvfsp); 15150Sstevel@tonic-gate /* 15160Sstevel@tonic-gate * drain the delete and idle queues 15170Sstevel@tonic-gate */ 15180Sstevel@tonic-gate ufs_delete_drain(vfsp, -1, 0); 15190Sstevel@tonic-gate ufs_idle_drain(vfsp); 15200Sstevel@tonic-gate 15210Sstevel@tonic-gate /* 15220Sstevel@tonic-gate * discard the inodes for this fs (including root, shadow, and quota) 15230Sstevel@tonic-gate */ 15240Sstevel@tonic-gate for (i = 0, ih = ihead; i < inohsz; i++, ih++) { 15250Sstevel@tonic-gate mutex_enter(&ih_lock[i]); 15260Sstevel@tonic-gate for (inext = 0, ip = ih->ih_chain[0]; 15270Sstevel@tonic-gate ip != (struct inode *)ih; 15280Sstevel@tonic-gate ip = inext) { 15290Sstevel@tonic-gate inext = ip->i_forw; 15300Sstevel@tonic-gate if (ip->i_ufsvfs != ufsvfsp) 15310Sstevel@tonic-gate continue; 15320Sstevel@tonic-gate vp = ITOV(ip); 15330Sstevel@tonic-gate VN_HOLD(vp) 15340Sstevel@tonic-gate remque(ip); 15350Sstevel@tonic-gate if (ufs_rmidle(ip)) 15360Sstevel@tonic-gate VN_RELE(vp); 15370Sstevel@tonic-gate ufs_si_del(ip); 15380Sstevel@tonic-gate /* 15390Sstevel@tonic-gate * rip->i_ufsvfsp is needed by bflush() 15400Sstevel@tonic-gate */ 15410Sstevel@tonic-gate if (ip != rip) 15420Sstevel@tonic-gate ip->i_ufsvfs = NULL; 15430Sstevel@tonic-gate /* 15440Sstevel@tonic-gate * Set vnode's vfsops to dummy ops, which return 15450Sstevel@tonic-gate * EIO. This is needed to forced unmounts to work 15460Sstevel@tonic-gate * with lofs/nfs properly. 15470Sstevel@tonic-gate */ 15480Sstevel@tonic-gate if (ULOCKFS_IS_HLOCK(ulp) || ULOCKFS_IS_ELOCK(ulp)) 15490Sstevel@tonic-gate vp->v_vfsp = &EIO_vfs; 15500Sstevel@tonic-gate else 15510Sstevel@tonic-gate vp->v_vfsp = NULL; 15520Sstevel@tonic-gate vp->v_type = VBAD; 15530Sstevel@tonic-gate VN_RELE(vp); 15540Sstevel@tonic-gate } 15550Sstevel@tonic-gate mutex_exit(&ih_lock[i]); 15560Sstevel@tonic-gate } 15570Sstevel@tonic-gate ufs_si_cache_flush(dev); 15580Sstevel@tonic-gate 15590Sstevel@tonic-gate /* 15600Sstevel@tonic-gate * kill the delete thread and drain the idle queue 15610Sstevel@tonic-gate */ 15620Sstevel@tonic-gate ufs_thread_exit(&ufsvfsp->vfs_delete); 15630Sstevel@tonic-gate ufs_idle_drain(vfsp); 15640Sstevel@tonic-gate 15650Sstevel@tonic-gate bp = ufsvfsp->vfs_bufp; 15660Sstevel@tonic-gate bvp = ufsvfsp->vfs_devvp; 15670Sstevel@tonic-gate flag = !fs->fs_ronly; 15680Sstevel@tonic-gate if (flag) { 15690Sstevel@tonic-gate bflush(dev); 15700Sstevel@tonic-gate if (fs->fs_clean != FSBAD) { 15710Sstevel@tonic-gate if (fs->fs_clean == FSSTABLE) 15720Sstevel@tonic-gate fs->fs_clean = FSCLEAN; 15730Sstevel@tonic-gate fs->fs_reclaim &= ~FS_RECLAIM; 15740Sstevel@tonic-gate } 15750Sstevel@tonic-gate if (TRANS_ISTRANS(ufsvfsp) && 15760Sstevel@tonic-gate !TRANS_ISERROR(ufsvfsp) && 15770Sstevel@tonic-gate !ULOCKFS_IS_HLOCK(ulp) && 15780Sstevel@tonic-gate (fs->fs_rolled == FS_NEED_ROLL)) { 15790Sstevel@tonic-gate /* 15800Sstevel@tonic-gate * ufs_flush() above has flushed the last Moby. 15810Sstevel@tonic-gate * This is needed to ensure the following superblock 15820Sstevel@tonic-gate * update really is the last metadata update 15830Sstevel@tonic-gate */ 15840Sstevel@tonic-gate error = ufs_putsummaryinfo(dev, ufsvfsp, fs); 15850Sstevel@tonic-gate if (error == 0) { 15860Sstevel@tonic-gate fs->fs_rolled = FS_ALL_ROLLED; 15870Sstevel@tonic-gate } 15880Sstevel@tonic-gate } 15890Sstevel@tonic-gate TRANS_SBUPDATE(ufsvfsp, vfsp, TOP_SBUPDATE_UNMOUNT); 15900Sstevel@tonic-gate /* 15910Sstevel@tonic-gate * push this last transaction 15920Sstevel@tonic-gate */ 15930Sstevel@tonic-gate curthread->t_flag |= T_DONTBLOCK; 15940Sstevel@tonic-gate TRANS_BEGIN_SYNC(ufsvfsp, TOP_COMMIT_UNMOUNT, TOP_COMMIT_SIZE, 15950Sstevel@tonic-gate error); 15960Sstevel@tonic-gate if (!error) 15970Sstevel@tonic-gate TRANS_END_SYNC(ufsvfsp, error, TOP_COMMIT_UNMOUNT, 15980Sstevel@tonic-gate TOP_COMMIT_SIZE); 15990Sstevel@tonic-gate curthread->t_flag &= ~T_DONTBLOCK; 16000Sstevel@tonic-gate } 16010Sstevel@tonic-gate 16020Sstevel@tonic-gate TRANS_MATA_UMOUNT(ufsvfsp); 16030Sstevel@tonic-gate lufs_unsnarf(ufsvfsp); /* Release the in-memory structs */ 16040Sstevel@tonic-gate ufsfx_unmount(ufsvfsp); /* fix-on-panic bookkeeping */ 16050Sstevel@tonic-gate kmem_free(fs->fs_u.fs_csp, fs->fs_cssize); 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate bp->b_flags |= B_STALE|B_AGE; 16080Sstevel@tonic-gate ufsvfsp->vfs_bufp = NULL; /* don't point at freed buf */ 16090Sstevel@tonic-gate brelse(bp); /* free the superblock buf */ 16100Sstevel@tonic-gate 16110Sstevel@tonic-gate (void) VOP_PUTPAGE(common_specvp(bvp), (offset_t)0, (size_t)0, 16120Sstevel@tonic-gate B_INVAL, cr); 16130Sstevel@tonic-gate (void) VOP_CLOSE(bvp, flag, 1, (offset_t)0, cr); 16140Sstevel@tonic-gate bflush(dev); 16150Sstevel@tonic-gate (void) bfinval(dev, 1); 16160Sstevel@tonic-gate VN_RELE(bvp); 16170Sstevel@tonic-gate 16180Sstevel@tonic-gate /* 16190Sstevel@tonic-gate * It is now safe to NULL out the ufsvfs pointer and discard 16200Sstevel@tonic-gate * the root inode. 16210Sstevel@tonic-gate */ 16220Sstevel@tonic-gate rip->i_ufsvfs = NULL; 16230Sstevel@tonic-gate VN_RELE(ITOV(rip)); 16240Sstevel@tonic-gate 16250Sstevel@tonic-gate /* free up lockfs comment structure, if any */ 16260Sstevel@tonic-gate if (ulp->ul_lockfs.lf_comlen && ulp->ul_lockfs.lf_comment) 16270Sstevel@tonic-gate kmem_free(ulp->ul_lockfs.lf_comment, ulp->ul_lockfs.lf_comlen); 16280Sstevel@tonic-gate 16290Sstevel@tonic-gate /* 16300Sstevel@tonic-gate * Remove from instance list. 16310Sstevel@tonic-gate */ 16320Sstevel@tonic-gate ufs_vfs_remove(ufsvfsp); 16330Sstevel@tonic-gate 16340Sstevel@tonic-gate /* 16350Sstevel@tonic-gate * For a forcible unmount, threads may be asleep in 16360Sstevel@tonic-gate * ufs_lockfs_begin/ufs_check_lockfs. These threads will need 16370Sstevel@tonic-gate * the ufsvfs structure so we don't free it, yet. ufs_update 16380Sstevel@tonic-gate * will free it up after awhile. 16390Sstevel@tonic-gate */ 16400Sstevel@tonic-gate if (ULOCKFS_IS_HLOCK(ulp) || ULOCKFS_IS_ELOCK(ulp)) { 16410Sstevel@tonic-gate extern kmutex_t ufsvfs_mutex; 16420Sstevel@tonic-gate extern struct ufsvfs *ufsvfslist; 16430Sstevel@tonic-gate 16440Sstevel@tonic-gate mutex_enter(&ufsvfs_mutex); 16450Sstevel@tonic-gate ufsvfsp->vfs_dontblock = 1; 16460Sstevel@tonic-gate ufsvfsp->vfs_next = ufsvfslist; 16470Sstevel@tonic-gate ufsvfslist = ufsvfsp; 16480Sstevel@tonic-gate mutex_exit(&ufsvfs_mutex); 16490Sstevel@tonic-gate /* wakeup any suspended threads */ 16500Sstevel@tonic-gate cv_broadcast(&ulp->ul_cv); 16510Sstevel@tonic-gate mutex_exit(&ulp->ul_lock); 16520Sstevel@tonic-gate } else { 16530Sstevel@tonic-gate mutex_destroy(&ufsvfsp->vfs_lock); 16540Sstevel@tonic-gate kmem_free(ufsvfsp, sizeof (struct ufsvfs)); 16550Sstevel@tonic-gate } 16560Sstevel@tonic-gate 16570Sstevel@tonic-gate /* 16580Sstevel@tonic-gate * Now mark the filesystem as unmounted since we're done with it. 16590Sstevel@tonic-gate */ 16600Sstevel@tonic-gate vfsp->vfs_flag |= VFS_UNMOUNTED; 16610Sstevel@tonic-gate 16620Sstevel@tonic-gate return (0); 16630Sstevel@tonic-gate out: 16640Sstevel@tonic-gate /* open the fs to new ops */ 16650Sstevel@tonic-gate cv_broadcast(&ulp->ul_cv); 16660Sstevel@tonic-gate mutex_exit(&ulp->ul_lock); 16670Sstevel@tonic-gate 16680Sstevel@tonic-gate if (TRANS_ISTRANS(ufsvfsp)) { 16690Sstevel@tonic-gate /* allow the delete thread to continue */ 16700Sstevel@tonic-gate ufs_thread_continue(&ufsvfsp->vfs_delete); 16710Sstevel@tonic-gate /* restart the reclaim thread */ 16720Sstevel@tonic-gate ufs_thread_start(&ufsvfsp->vfs_reclaim, ufs_thread_reclaim, 16730Sstevel@tonic-gate vfsp); 16740Sstevel@tonic-gate /* coordinate with global hlock thread */ 16750Sstevel@tonic-gate ufsvfsp->vfs_validfs = UT_MOUNTED; 16760Sstevel@tonic-gate /* check for trans errors during umount */ 16770Sstevel@tonic-gate ufs_trans_onerror(); 16780Sstevel@tonic-gate 16790Sstevel@tonic-gate /* 16800Sstevel@tonic-gate * if we have a seperate /usr it will never unmount 16810Sstevel@tonic-gate * when halting. In order to not re-read all the 16820Sstevel@tonic-gate * cylinder group summary info on mounting after 16830Sstevel@tonic-gate * reboot the logging of summary info is re-enabled 16840Sstevel@tonic-gate * and the super block written out. 16850Sstevel@tonic-gate */ 16860Sstevel@tonic-gate mountpoint = vfs_getmntpoint(vfsp); 16870Sstevel@tonic-gate if ((fs->fs_si == FS_SI_OK) && 16880Sstevel@tonic-gate (strcmp("/usr", refstr_value(mountpoint)) == 0)) { 16890Sstevel@tonic-gate ufsvfsp->vfs_nolog_si = 0; 16900Sstevel@tonic-gate UFS_BWRITE2(NULL, ufsvfsp->vfs_bufp); 16910Sstevel@tonic-gate } 16920Sstevel@tonic-gate refstr_rele(mountpoint); 16930Sstevel@tonic-gate } 16940Sstevel@tonic-gate 16950Sstevel@tonic-gate return (error); 16960Sstevel@tonic-gate } 16970Sstevel@tonic-gate 16980Sstevel@tonic-gate static int 16990Sstevel@tonic-gate ufs_root(struct vfs *vfsp, struct vnode **vpp) 17000Sstevel@tonic-gate { 17010Sstevel@tonic-gate struct ufsvfs *ufsvfsp; 17020Sstevel@tonic-gate struct vnode *vp; 17030Sstevel@tonic-gate 17040Sstevel@tonic-gate if (!vfsp) 17050Sstevel@tonic-gate return (EIO); 17060Sstevel@tonic-gate 17070Sstevel@tonic-gate ufsvfsp = (struct ufsvfs *)vfsp->vfs_data; 17080Sstevel@tonic-gate if (!ufsvfsp || !ufsvfsp->vfs_root) 17090Sstevel@tonic-gate return (EIO); /* forced unmount */ 17100Sstevel@tonic-gate 17110Sstevel@tonic-gate vp = ufsvfsp->vfs_root; 17120Sstevel@tonic-gate VN_HOLD(vp); 17130Sstevel@tonic-gate *vpp = vp; 17140Sstevel@tonic-gate return (0); 17150Sstevel@tonic-gate } 17160Sstevel@tonic-gate 17170Sstevel@tonic-gate /* 17180Sstevel@tonic-gate * Get file system statistics. 17190Sstevel@tonic-gate */ 17200Sstevel@tonic-gate static int 17210Sstevel@tonic-gate ufs_statvfs(struct vfs *vfsp, struct statvfs64 *sp) 17220Sstevel@tonic-gate { 17230Sstevel@tonic-gate struct fs *fsp; 17240Sstevel@tonic-gate struct ufsvfs *ufsvfsp; 17250Sstevel@tonic-gate int blk, i; 17260Sstevel@tonic-gate long max_avail, used; 17270Sstevel@tonic-gate dev32_t d32; 17280Sstevel@tonic-gate 17290Sstevel@tonic-gate if (vfsp->vfs_flag & VFS_UNMOUNTED) 17300Sstevel@tonic-gate return (EIO); 17310Sstevel@tonic-gate 17320Sstevel@tonic-gate ufsvfsp = (struct ufsvfs *)vfsp->vfs_data; 17330Sstevel@tonic-gate fsp = ufsvfsp->vfs_fs; 17340Sstevel@tonic-gate if ((fsp->fs_magic != FS_MAGIC) && (fsp->fs_magic != MTB_UFS_MAGIC)) 17350Sstevel@tonic-gate return (EINVAL); 1736757Svsakar if (fsp->fs_magic == FS_MAGIC && 1737757Svsakar (fsp->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 1738757Svsakar fsp->fs_version != UFS_VERSION_MIN)) 1739757Svsakar return (EINVAL); 17400Sstevel@tonic-gate if (fsp->fs_magic == MTB_UFS_MAGIC && 17410Sstevel@tonic-gate (fsp->fs_version > MTB_UFS_VERSION_1 || 17420Sstevel@tonic-gate fsp->fs_version < MTB_UFS_VERSION_MIN)) 17430Sstevel@tonic-gate return (EINVAL); 17440Sstevel@tonic-gate 17450Sstevel@tonic-gate /* 17460Sstevel@tonic-gate * get the basic numbers 17470Sstevel@tonic-gate */ 17480Sstevel@tonic-gate (void) bzero(sp, sizeof (*sp)); 17490Sstevel@tonic-gate 17500Sstevel@tonic-gate sp->f_bsize = fsp->fs_bsize; 17510Sstevel@tonic-gate sp->f_frsize = fsp->fs_fsize; 17520Sstevel@tonic-gate sp->f_blocks = (fsblkcnt64_t)fsp->fs_dsize; 17530Sstevel@tonic-gate sp->f_bfree = (fsblkcnt64_t)fsp->fs_cstotal.cs_nbfree * fsp->fs_frag + 17540Sstevel@tonic-gate fsp->fs_cstotal.cs_nffree; 17550Sstevel@tonic-gate 17560Sstevel@tonic-gate sp->f_files = (fsfilcnt64_t)fsp->fs_ncg * fsp->fs_ipg; 17570Sstevel@tonic-gate sp->f_ffree = (fsfilcnt64_t)fsp->fs_cstotal.cs_nifree; 17580Sstevel@tonic-gate 17590Sstevel@tonic-gate /* 17600Sstevel@tonic-gate * Adjust the numbers based on things waiting to be deleted. 17610Sstevel@tonic-gate * modifies f_bfree and f_ffree. Afterwards, everything we 17620Sstevel@tonic-gate * come up with will be self-consistent. By definition, this 17630Sstevel@tonic-gate * is a point-in-time snapshot, so the fact that the delete 17640Sstevel@tonic-gate * thread's probably already invalidated the results is not a 1765512Sjkennedy * problem. Note that if the delete thread is ever extended to 1766512Sjkennedy * non-logging ufs, this adjustment must always be made. 17670Sstevel@tonic-gate */ 1768512Sjkennedy if (TRANS_ISTRANS(ufsvfsp)) 1769512Sjkennedy ufs_delete_adjust_stats(ufsvfsp, sp); 17700Sstevel@tonic-gate 17710Sstevel@tonic-gate /* 17720Sstevel@tonic-gate * avail = MAX(max_avail - used, 0) 17730Sstevel@tonic-gate */ 17740Sstevel@tonic-gate max_avail = fsp->fs_dsize - ufsvfsp->vfs_minfrags; 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate used = (fsp->fs_dsize - sp->f_bfree); 17770Sstevel@tonic-gate 17780Sstevel@tonic-gate if (max_avail > used) 17790Sstevel@tonic-gate sp->f_bavail = (fsblkcnt64_t)max_avail - used; 17800Sstevel@tonic-gate else 17810Sstevel@tonic-gate sp->f_bavail = (fsblkcnt64_t)0; 17820Sstevel@tonic-gate 17830Sstevel@tonic-gate sp->f_favail = sp->f_ffree; 17840Sstevel@tonic-gate (void) cmpldev(&d32, vfsp->vfs_dev); 17850Sstevel@tonic-gate sp->f_fsid = d32; 17860Sstevel@tonic-gate (void) strcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 17870Sstevel@tonic-gate sp->f_flag = vf_to_stf(vfsp->vfs_flag); 17880Sstevel@tonic-gate 17890Sstevel@tonic-gate /* keep coordinated with ufs_l_pathconf() */ 17900Sstevel@tonic-gate sp->f_namemax = MAXNAMLEN; 17910Sstevel@tonic-gate 17920Sstevel@tonic-gate if (fsp->fs_cpc == 0) { 17930Sstevel@tonic-gate bzero(sp->f_fstr, 14); 17940Sstevel@tonic-gate return (0); 17950Sstevel@tonic-gate } 17960Sstevel@tonic-gate blk = fsp->fs_spc * fsp->fs_cpc / NSPF(fsp); 17970Sstevel@tonic-gate for (i = 0; i < blk; i += fsp->fs_frag) /* CSTYLED */ 17980Sstevel@tonic-gate /* void */; 17990Sstevel@tonic-gate i -= fsp->fs_frag; 18000Sstevel@tonic-gate blk = i / fsp->fs_frag; 18010Sstevel@tonic-gate bcopy(&(fs_rotbl(fsp)[blk]), sp->f_fstr, 14); 18020Sstevel@tonic-gate return (0); 18030Sstevel@tonic-gate } 18040Sstevel@tonic-gate 18050Sstevel@tonic-gate /* 18060Sstevel@tonic-gate * Flush any pending I/O to file system vfsp. 18070Sstevel@tonic-gate * The ufs_update() routine will only flush *all* ufs files. 18080Sstevel@tonic-gate * If vfsp is non-NULL, only sync this ufs (in preparation 18090Sstevel@tonic-gate * for a umount). 18100Sstevel@tonic-gate */ 18110Sstevel@tonic-gate /*ARGSUSED*/ 18120Sstevel@tonic-gate static int 18130Sstevel@tonic-gate ufs_sync(struct vfs *vfsp, short flag, struct cred *cr) 18140Sstevel@tonic-gate { 18150Sstevel@tonic-gate struct ufsvfs *ufsvfsp; 18160Sstevel@tonic-gate struct fs *fs; 18170Sstevel@tonic-gate int cheap = flag & SYNC_ATTR; 18180Sstevel@tonic-gate int error; 18190Sstevel@tonic-gate 18200Sstevel@tonic-gate /* 18210Sstevel@tonic-gate * SYNC_CLOSE means we're rebooting. Toss everything 18220Sstevel@tonic-gate * on the idle queue so we don't have to slog through 18230Sstevel@tonic-gate * a bunch of uninteresting inodes over and over again. 18240Sstevel@tonic-gate */ 18250Sstevel@tonic-gate if (flag & SYNC_CLOSE) 18260Sstevel@tonic-gate ufs_idle_drain(NULL); 18270Sstevel@tonic-gate 18280Sstevel@tonic-gate if (vfsp == NULL) { 18290Sstevel@tonic-gate ufs_update(flag); 18300Sstevel@tonic-gate return (0); 18310Sstevel@tonic-gate } 18320Sstevel@tonic-gate 18330Sstevel@tonic-gate /* Flush a single ufs */ 18340Sstevel@tonic-gate if (!vfs_matchops(vfsp, ufs_vfsops) || vfs_lock(vfsp) != 0) 18350Sstevel@tonic-gate return (0); 18360Sstevel@tonic-gate 18370Sstevel@tonic-gate ufsvfsp = (struct ufsvfs *)vfsp->vfs_data; 18380Sstevel@tonic-gate if (!ufsvfsp) 18390Sstevel@tonic-gate return (EIO); 18400Sstevel@tonic-gate fs = ufsvfsp->vfs_fs; 18410Sstevel@tonic-gate mutex_enter(&ufsvfsp->vfs_lock); 18420Sstevel@tonic-gate 18430Sstevel@tonic-gate if (ufsvfsp->vfs_dio && 18440Sstevel@tonic-gate fs->fs_ronly == 0 && 18450Sstevel@tonic-gate fs->fs_clean != FSBAD && 18460Sstevel@tonic-gate fs->fs_clean != FSLOG) { 18470Sstevel@tonic-gate /* turn off fast-io on unmount, so no fsck needed (4029401) */ 18480Sstevel@tonic-gate ufsvfsp->vfs_dio = 0; 18490Sstevel@tonic-gate fs->fs_clean = FSACTIVE; 18500Sstevel@tonic-gate fs->fs_fmod = 1; 18510Sstevel@tonic-gate } 18520Sstevel@tonic-gate 18530Sstevel@tonic-gate /* Write back modified superblock */ 18540Sstevel@tonic-gate if (fs->fs_fmod == 0) { 18550Sstevel@tonic-gate mutex_exit(&ufsvfsp->vfs_lock); 18560Sstevel@tonic-gate } else { 18570Sstevel@tonic-gate if (fs->fs_ronly != 0) { 18580Sstevel@tonic-gate mutex_exit(&ufsvfsp->vfs_lock); 18590Sstevel@tonic-gate vfs_unlock(vfsp); 18600Sstevel@tonic-gate return (ufs_fault(ufsvfsp->vfs_root, 18610Sstevel@tonic-gate "fs = %s update: ro fs mod\n", 18620Sstevel@tonic-gate fs->fs_fsmnt)); 18630Sstevel@tonic-gate } 18640Sstevel@tonic-gate fs->fs_fmod = 0; 18650Sstevel@tonic-gate mutex_exit(&ufsvfsp->vfs_lock); 18660Sstevel@tonic-gate 18670Sstevel@tonic-gate TRANS_SBUPDATE(ufsvfsp, vfsp, TOP_SBUPDATE_UPDATE); 18680Sstevel@tonic-gate } 18690Sstevel@tonic-gate vfs_unlock(vfsp); 18700Sstevel@tonic-gate 18710Sstevel@tonic-gate /* 18720Sstevel@tonic-gate * Avoid racing with ufs_update() and ufs_unmount(). 18730Sstevel@tonic-gate * 18740Sstevel@tonic-gate */ 18750Sstevel@tonic-gate mutex_enter(&ufs_scan_lock); 18760Sstevel@tonic-gate 18770Sstevel@tonic-gate (void) ufs_scan_inodes(1, ufs_sync_inode, 18780Sstevel@tonic-gate (void *)(uintptr_t)cheap, ufsvfsp); 18790Sstevel@tonic-gate 18800Sstevel@tonic-gate mutex_exit(&ufs_scan_lock); 18810Sstevel@tonic-gate 18820Sstevel@tonic-gate bflush((dev_t)vfsp->vfs_dev); 18830Sstevel@tonic-gate 18840Sstevel@tonic-gate /* 18850Sstevel@tonic-gate * commit any outstanding async transactions 18860Sstevel@tonic-gate */ 18870Sstevel@tonic-gate curthread->t_flag |= T_DONTBLOCK; 18880Sstevel@tonic-gate TRANS_BEGIN_SYNC(ufsvfsp, TOP_COMMIT_UPDATE, TOP_COMMIT_SIZE, error); 18890Sstevel@tonic-gate if (!error) { 18900Sstevel@tonic-gate TRANS_END_SYNC(ufsvfsp, error, TOP_COMMIT_UPDATE, 18910Sstevel@tonic-gate TOP_COMMIT_SIZE); 18920Sstevel@tonic-gate } 18930Sstevel@tonic-gate curthread->t_flag &= ~T_DONTBLOCK; 18940Sstevel@tonic-gate 18950Sstevel@tonic-gate return (0); 18960Sstevel@tonic-gate } 18970Sstevel@tonic-gate 18980Sstevel@tonic-gate 18990Sstevel@tonic-gate void 19000Sstevel@tonic-gate sbupdate(struct vfs *vfsp) 19010Sstevel@tonic-gate { 19020Sstevel@tonic-gate struct ufsvfs *ufsvfsp = (struct ufsvfs *)vfsp->vfs_data; 19030Sstevel@tonic-gate struct fs *fs = ufsvfsp->vfs_fs; 19040Sstevel@tonic-gate struct buf *bp; 19050Sstevel@tonic-gate int blks; 19060Sstevel@tonic-gate caddr_t space; 19070Sstevel@tonic-gate int i; 19080Sstevel@tonic-gate size_t size; 19090Sstevel@tonic-gate 19100Sstevel@tonic-gate /* 19110Sstevel@tonic-gate * for ulockfs processing, limit the superblock writes 19120Sstevel@tonic-gate */ 19130Sstevel@tonic-gate if ((ufsvfsp->vfs_ulockfs.ul_sbowner) && 19140Sstevel@tonic-gate (curthread != ufsvfsp->vfs_ulockfs.ul_sbowner)) { 19150Sstevel@tonic-gate /* process later */ 19160Sstevel@tonic-gate fs->fs_fmod = 1; 19170Sstevel@tonic-gate return; 19180Sstevel@tonic-gate } 19190Sstevel@tonic-gate ULOCKFS_SET_MOD((&ufsvfsp->vfs_ulockfs)); 19200Sstevel@tonic-gate 19210Sstevel@tonic-gate if (TRANS_ISTRANS(ufsvfsp)) { 19220Sstevel@tonic-gate mutex_enter(&ufsvfsp->vfs_lock); 19230Sstevel@tonic-gate ufs_sbwrite(ufsvfsp); 19240Sstevel@tonic-gate mutex_exit(&ufsvfsp->vfs_lock); 19250Sstevel@tonic-gate return; 19260Sstevel@tonic-gate } 19270Sstevel@tonic-gate 19280Sstevel@tonic-gate blks = howmany(fs->fs_cssize, fs->fs_fsize); 19290Sstevel@tonic-gate space = (caddr_t)fs->fs_u.fs_csp; 19300Sstevel@tonic-gate for (i = 0; i < blks; i += fs->fs_frag) { 19310Sstevel@tonic-gate size = fs->fs_bsize; 19320Sstevel@tonic-gate if (i + fs->fs_frag > blks) 19330Sstevel@tonic-gate size = (blks - i) * fs->fs_fsize; 19340Sstevel@tonic-gate bp = UFS_GETBLK(ufsvfsp, ufsvfsp->vfs_dev, 19350Sstevel@tonic-gate (daddr_t)(fsbtodb(fs, fs->fs_csaddr + i)), 19360Sstevel@tonic-gate fs->fs_bsize); 19370Sstevel@tonic-gate bcopy(space, bp->b_un.b_addr, size); 19380Sstevel@tonic-gate space += size; 19390Sstevel@tonic-gate bp->b_bcount = size; 19400Sstevel@tonic-gate UFS_BRWRITE(ufsvfsp, bp); 19410Sstevel@tonic-gate } 19420Sstevel@tonic-gate mutex_enter(&ufsvfsp->vfs_lock); 19430Sstevel@tonic-gate ufs_sbwrite(ufsvfsp); 19440Sstevel@tonic-gate mutex_exit(&ufsvfsp->vfs_lock); 19450Sstevel@tonic-gate } 19460Sstevel@tonic-gate 19470Sstevel@tonic-gate int ufs_vget_idle_count = 2; /* Number of inodes to idle each time */ 19480Sstevel@tonic-gate static int 19490Sstevel@tonic-gate ufs_vget(struct vfs *vfsp, struct vnode **vpp, struct fid *fidp) 19500Sstevel@tonic-gate { 19510Sstevel@tonic-gate int error = 0; 19520Sstevel@tonic-gate struct ufid *ufid; 19530Sstevel@tonic-gate struct inode *ip; 19540Sstevel@tonic-gate struct ufsvfs *ufsvfsp = (struct ufsvfs *)vfsp->vfs_data; 19550Sstevel@tonic-gate struct ulockfs *ulp; 19560Sstevel@tonic-gate 19570Sstevel@tonic-gate /* 19580Sstevel@tonic-gate * Check for unmounted filesystem. 19590Sstevel@tonic-gate */ 19600Sstevel@tonic-gate if (vfsp->vfs_flag & VFS_UNMOUNTED) { 19610Sstevel@tonic-gate error = EIO; 19620Sstevel@tonic-gate goto errout; 19630Sstevel@tonic-gate } 19640Sstevel@tonic-gate 19650Sstevel@tonic-gate /* 19660Sstevel@tonic-gate * Keep the idle queue from getting too long by 19670Sstevel@tonic-gate * idling an inode before attempting to allocate another. 19680Sstevel@tonic-gate * This operation must be performed before entering 19690Sstevel@tonic-gate * lockfs or a transaction. 19700Sstevel@tonic-gate */ 19710Sstevel@tonic-gate if (ufs_idle_q.uq_ne > ufs_idle_q.uq_hiwat) 19720Sstevel@tonic-gate if ((curthread->t_flag & T_DONTBLOCK) == 0) { 19730Sstevel@tonic-gate ins.in_vidles.value.ul += ufs_vget_idle_count; 19740Sstevel@tonic-gate ufs_idle_some(ufs_vget_idle_count); 19750Sstevel@tonic-gate } 19760Sstevel@tonic-gate 19770Sstevel@tonic-gate ufid = (struct ufid *)fidp; 19780Sstevel@tonic-gate 19790Sstevel@tonic-gate if (error = ufs_lockfs_begin(ufsvfsp, &ulp, ULOCKFS_VGET_MASK)) 19800Sstevel@tonic-gate goto errout; 19810Sstevel@tonic-gate 19820Sstevel@tonic-gate rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER); 19830Sstevel@tonic-gate 19840Sstevel@tonic-gate error = ufs_iget(vfsp, ufid->ufid_ino, &ip, CRED()); 19850Sstevel@tonic-gate 19860Sstevel@tonic-gate rw_exit(&ufsvfsp->vfs_dqrwlock); 19870Sstevel@tonic-gate 19880Sstevel@tonic-gate ufs_lockfs_end(ulp); 19890Sstevel@tonic-gate 19900Sstevel@tonic-gate if (error) 19910Sstevel@tonic-gate goto errout; 19920Sstevel@tonic-gate 19930Sstevel@tonic-gate /* 19940Sstevel@tonic-gate * Check if the inode has been deleted or freed or is in transient state 19950Sstevel@tonic-gate * since the last VFS_VGET() request for it, release it and don't return 19960Sstevel@tonic-gate * it to the caller, presumably NFS, as it's no longer valid. 19970Sstevel@tonic-gate */ 19980Sstevel@tonic-gate if (ip->i_gen != ufid->ufid_gen || ip->i_mode == 0 || 19990Sstevel@tonic-gate (ip->i_flag & IDEL)) { 20000Sstevel@tonic-gate VN_RELE(ITOV(ip)); 20010Sstevel@tonic-gate error = EINVAL; 20020Sstevel@tonic-gate goto errout; 20030Sstevel@tonic-gate } 20040Sstevel@tonic-gate 20050Sstevel@tonic-gate *vpp = ITOV(ip); 20060Sstevel@tonic-gate return (0); 20070Sstevel@tonic-gate 20080Sstevel@tonic-gate errout: 20090Sstevel@tonic-gate *vpp = NULL; 20100Sstevel@tonic-gate return (error); 20110Sstevel@tonic-gate } 20120Sstevel@tonic-gate 20130Sstevel@tonic-gate static int 20140Sstevel@tonic-gate ufsinit(int fstype, char *name) 20150Sstevel@tonic-gate { 20160Sstevel@tonic-gate static const fs_operation_def_t ufs_vfsops_template[] = { 20170Sstevel@tonic-gate VFSNAME_MOUNT, ufs_mount, 20180Sstevel@tonic-gate VFSNAME_UNMOUNT, ufs_unmount, 20190Sstevel@tonic-gate VFSNAME_ROOT, ufs_root, 20200Sstevel@tonic-gate VFSNAME_STATVFS, ufs_statvfs, 20210Sstevel@tonic-gate VFSNAME_SYNC, (fs_generic_func_p) ufs_sync, 20220Sstevel@tonic-gate VFSNAME_VGET, ufs_vget, 20230Sstevel@tonic-gate VFSNAME_MOUNTROOT, ufs_mountroot, 20240Sstevel@tonic-gate NULL, NULL 20250Sstevel@tonic-gate }; 20260Sstevel@tonic-gate int error; 20270Sstevel@tonic-gate 20280Sstevel@tonic-gate ufsfstype = fstype; 20290Sstevel@tonic-gate 20300Sstevel@tonic-gate error = vfs_setfsops(fstype, ufs_vfsops_template, &ufs_vfsops); 20310Sstevel@tonic-gate if (error != 0) { 20320Sstevel@tonic-gate cmn_err(CE_WARN, "ufsinit: bad vfs ops template"); 20330Sstevel@tonic-gate return (error); 20340Sstevel@tonic-gate } 20350Sstevel@tonic-gate 20360Sstevel@tonic-gate error = vn_make_ops(name, ufs_vnodeops_template, &ufs_vnodeops); 20370Sstevel@tonic-gate if (error != 0) { 20380Sstevel@tonic-gate (void) vfs_freevfsops_by_type(fstype); 20390Sstevel@tonic-gate cmn_err(CE_WARN, "ufsinit: bad vnode ops template"); 20400Sstevel@tonic-gate return (error); 20410Sstevel@tonic-gate } 20420Sstevel@tonic-gate 20430Sstevel@tonic-gate ufs_iinit(); 20440Sstevel@tonic-gate return (0); 20450Sstevel@tonic-gate } 20460Sstevel@tonic-gate 20470Sstevel@tonic-gate #ifdef __sparc 20480Sstevel@tonic-gate 20490Sstevel@tonic-gate /* 20500Sstevel@tonic-gate * Mounting a mirrored SVM volume is only supported on ufs, 20510Sstevel@tonic-gate * this is special-case boot code to support that configuration. 20520Sstevel@tonic-gate * At this point, we have booted and mounted root on a 20530Sstevel@tonic-gate * single component of the mirror. Complete the boot 20540Sstevel@tonic-gate * by configuring SVM and converting the root to the 20550Sstevel@tonic-gate * dev_t of the mirrored root device. This dev_t conversion 20560Sstevel@tonic-gate * only works because the underlying device doesn't change. 20570Sstevel@tonic-gate */ 20580Sstevel@tonic-gate int 20590Sstevel@tonic-gate ufs_remountroot(struct vfs *vfsp) 20600Sstevel@tonic-gate { 20610Sstevel@tonic-gate struct ufsvfs *ufsvfsp; 20620Sstevel@tonic-gate struct ulockfs *ulp; 20630Sstevel@tonic-gate dev_t new_rootdev; 20640Sstevel@tonic-gate dev_t old_rootdev; 20650Sstevel@tonic-gate struct vnode *old_rootvp; 20660Sstevel@tonic-gate struct vnode *new_rootvp; 20670Sstevel@tonic-gate int error, sberror = 0; 20680Sstevel@tonic-gate struct inode *ip; 20690Sstevel@tonic-gate union ihead *ih; 20700Sstevel@tonic-gate struct buf *bp; 20710Sstevel@tonic-gate int i; 20720Sstevel@tonic-gate 20730Sstevel@tonic-gate old_rootdev = rootdev; 20740Sstevel@tonic-gate old_rootvp = rootvp; 20750Sstevel@tonic-gate 20760Sstevel@tonic-gate new_rootdev = getrootdev(); 20770Sstevel@tonic-gate if (new_rootdev == (dev_t)NODEV) { 20780Sstevel@tonic-gate return (ENODEV); 20790Sstevel@tonic-gate } 20800Sstevel@tonic-gate 20810Sstevel@tonic-gate new_rootvp = makespecvp(new_rootdev, VBLK); 20820Sstevel@tonic-gate 20830Sstevel@tonic-gate error = VOP_OPEN(&new_rootvp, 20840Sstevel@tonic-gate (vfsp->vfs_flag & VFS_RDONLY) ? FREAD : FREAD|FWRITE, CRED()); 20850Sstevel@tonic-gate if (error) { 20860Sstevel@tonic-gate cmn_err(CE_CONT, 20870Sstevel@tonic-gate "Cannot open mirrored root device, error %d\n", error); 20880Sstevel@tonic-gate return (error); 20890Sstevel@tonic-gate } 20900Sstevel@tonic-gate 20910Sstevel@tonic-gate if (vfs_lock(vfsp) != 0) { 20920Sstevel@tonic-gate return (EBUSY); 20930Sstevel@tonic-gate } 20940Sstevel@tonic-gate 20950Sstevel@tonic-gate ufsvfsp = (struct ufsvfs *)vfsp->vfs_data; 20960Sstevel@tonic-gate ulp = &ufsvfsp->vfs_ulockfs; 20970Sstevel@tonic-gate 20980Sstevel@tonic-gate mutex_enter(&ulp->ul_lock); 2099329Saguzovsk atomic_add_long(&ufs_quiesce_pend, 1); 21000Sstevel@tonic-gate 21010Sstevel@tonic-gate (void) ufs_quiesce(ulp); 21020Sstevel@tonic-gate (void) ufs_flush(vfsp); 21030Sstevel@tonic-gate 21040Sstevel@tonic-gate /* 21050Sstevel@tonic-gate * Convert root vfs to new dev_t, including vfs hash 21060Sstevel@tonic-gate * table and fs id. 21070Sstevel@tonic-gate */ 21080Sstevel@tonic-gate vfs_root_redev(vfsp, new_rootdev, ufsfstype); 21090Sstevel@tonic-gate 21100Sstevel@tonic-gate ufsvfsp->vfs_devvp = new_rootvp; 21110Sstevel@tonic-gate ufsvfsp->vfs_dev = new_rootdev; 21120Sstevel@tonic-gate 21130Sstevel@tonic-gate bp = ufsvfsp->vfs_bufp; 21140Sstevel@tonic-gate bp->b_edev = new_rootdev; 21150Sstevel@tonic-gate bp->b_dev = cmpdev(new_rootdev); 21160Sstevel@tonic-gate 21170Sstevel@tonic-gate /* 21180Sstevel@tonic-gate * The buffer for the root inode does not contain a valid b_vp 21190Sstevel@tonic-gate */ 21200Sstevel@tonic-gate (void) bfinval(new_rootdev, 0); 21210Sstevel@tonic-gate 21220Sstevel@tonic-gate /* 21230Sstevel@tonic-gate * Here we hand-craft inodes with old root device 21240Sstevel@tonic-gate * references to refer to the new device instead. 21250Sstevel@tonic-gate */ 21260Sstevel@tonic-gate mutex_enter(&ufs_scan_lock); 21270Sstevel@tonic-gate 21280Sstevel@tonic-gate for (i = 0, ih = ihead; i < inohsz; i++, ih++) { 21290Sstevel@tonic-gate mutex_enter(&ih_lock[i]); 21300Sstevel@tonic-gate for (ip = ih->ih_chain[0]; 21310Sstevel@tonic-gate ip != (struct inode *)ih; 21320Sstevel@tonic-gate ip = ip->i_forw) { 21330Sstevel@tonic-gate if (ip->i_ufsvfs != ufsvfsp) 21340Sstevel@tonic-gate continue; 21350Sstevel@tonic-gate if (ip == ufsvfsp->vfs_qinod) 21360Sstevel@tonic-gate continue; 21370Sstevel@tonic-gate if (ip->i_dev == old_rootdev) { 21380Sstevel@tonic-gate ip->i_dev = new_rootdev; 21390Sstevel@tonic-gate } 21400Sstevel@tonic-gate 21410Sstevel@tonic-gate if (ip->i_devvp == old_rootvp) { 21420Sstevel@tonic-gate ip->i_devvp = new_rootvp; 21430Sstevel@tonic-gate } 21440Sstevel@tonic-gate } 21450Sstevel@tonic-gate mutex_exit(&ih_lock[i]); 21460Sstevel@tonic-gate } 21470Sstevel@tonic-gate 21480Sstevel@tonic-gate mutex_exit(&ufs_scan_lock); 21490Sstevel@tonic-gate 21500Sstevel@tonic-gate /* 21510Sstevel@tonic-gate * Make Sure logging structures are using the new device 21520Sstevel@tonic-gate * if logging is enabled. Also start any logging thread that 21530Sstevel@tonic-gate * needs to write to the device and couldn't earlier. 21540Sstevel@tonic-gate */ 21550Sstevel@tonic-gate if (ufsvfsp->vfs_log) { 21560Sstevel@tonic-gate buf_t *bp, *tbp; 21570Sstevel@tonic-gate ml_unit_t *ul = ufsvfsp->vfs_log; 21580Sstevel@tonic-gate struct fs *fsp = ufsvfsp->vfs_fs; 21590Sstevel@tonic-gate 21600Sstevel@tonic-gate /* 21610Sstevel@tonic-gate * Update the main logging structure. 21620Sstevel@tonic-gate */ 21630Sstevel@tonic-gate ul->un_dev = new_rootdev; 21640Sstevel@tonic-gate 21650Sstevel@tonic-gate /* 21660Sstevel@tonic-gate * Get a new bp for the on disk structures. 21670Sstevel@tonic-gate */ 21680Sstevel@tonic-gate bp = ul->un_bp; 21690Sstevel@tonic-gate tbp = ngeteblk(dbtob(LS_SECTORS)); 21700Sstevel@tonic-gate tbp->b_edev = new_rootdev; 21710Sstevel@tonic-gate tbp->b_dev = cmpdev(new_rootdev); 21720Sstevel@tonic-gate tbp->b_blkno = bp->b_blkno; 21730Sstevel@tonic-gate bcopy(bp->b_un.b_addr, tbp->b_un.b_addr, DEV_BSIZE); 21740Sstevel@tonic-gate bcopy(bp->b_un.b_addr, tbp->b_un.b_addr + DEV_BSIZE, DEV_BSIZE); 21750Sstevel@tonic-gate bp->b_flags |= (B_STALE | B_AGE); 21760Sstevel@tonic-gate brelse(bp); 21770Sstevel@tonic-gate ul->un_bp = tbp; 21780Sstevel@tonic-gate 21790Sstevel@tonic-gate /* 21800Sstevel@tonic-gate * Allocate new circular buffers. 21810Sstevel@tonic-gate */ 21820Sstevel@tonic-gate alloc_rdbuf(&ul->un_rdbuf, MAPBLOCKSIZE, MAPBLOCKSIZE); 21830Sstevel@tonic-gate alloc_wrbuf(&ul->un_wrbuf, ldl_bufsize(ul)); 21840Sstevel@tonic-gate 21850Sstevel@tonic-gate /* 21860Sstevel@tonic-gate * Clear the noroll bit which indicates that logging 2187921Sbatschul * can't roll the log yet and start the logmap roll thread 2188921Sbatschul * unless the filesystem is still read-only in which case 2189921Sbatschul * remountfs() will do it when going to read-write. 21900Sstevel@tonic-gate */ 21910Sstevel@tonic-gate ASSERT(ul->un_flags & LDL_NOROLL); 21920Sstevel@tonic-gate 2193921Sbatschul if (!fsp->fs_ronly) { 2194921Sbatschul ul->un_flags &= ~LDL_NOROLL; 2195921Sbatschul logmap_start_roll(ul); 2196921Sbatschul } 21970Sstevel@tonic-gate 21980Sstevel@tonic-gate /* 21990Sstevel@tonic-gate * Start the reclaim thread if needed. 22000Sstevel@tonic-gate */ 22010Sstevel@tonic-gate if (!fsp->fs_ronly && (fsp->fs_reclaim & 22020Sstevel@tonic-gate (FS_RECLAIM|FS_RECLAIMING))) { 22030Sstevel@tonic-gate fsp->fs_reclaim &= ~FS_RECLAIM; 22040Sstevel@tonic-gate fsp->fs_reclaim |= FS_RECLAIMING; 22050Sstevel@tonic-gate ufs_thread_start(&ufsvfsp->vfs_reclaim, 22060Sstevel@tonic-gate ufs_thread_reclaim, vfsp); 22070Sstevel@tonic-gate TRANS_SBWRITE(ufsvfsp, TOP_SBUPDATE_UPDATE); 22080Sstevel@tonic-gate if (sberror = geterror(ufsvfsp->vfs_bufp)) { 22090Sstevel@tonic-gate refstr_t *mntpt; 22100Sstevel@tonic-gate mntpt = vfs_getmntpoint(vfsp); 22110Sstevel@tonic-gate cmn_err(CE_WARN, 22120Sstevel@tonic-gate "Remountroot failed to update Reclaim" 22130Sstevel@tonic-gate "state for filesystem %s " 22140Sstevel@tonic-gate "Error writing SuperBlock %d", 22150Sstevel@tonic-gate refstr_value(mntpt), error); 22160Sstevel@tonic-gate refstr_rele(mntpt); 22170Sstevel@tonic-gate } 22180Sstevel@tonic-gate } 22190Sstevel@tonic-gate } 22200Sstevel@tonic-gate 22210Sstevel@tonic-gate rootdev = new_rootdev; 22220Sstevel@tonic-gate rootvp = new_rootvp; 22230Sstevel@tonic-gate 2224329Saguzovsk atomic_add_long(&ufs_quiesce_pend, -1); 22250Sstevel@tonic-gate cv_broadcast(&ulp->ul_cv); 22260Sstevel@tonic-gate mutex_exit(&ulp->ul_lock); 22270Sstevel@tonic-gate 22280Sstevel@tonic-gate vfs_unlock(vfsp); 22290Sstevel@tonic-gate 22300Sstevel@tonic-gate error = VOP_CLOSE(old_rootvp, FREAD, 1, (offset_t)0, CRED()); 22310Sstevel@tonic-gate if (error) { 22320Sstevel@tonic-gate cmn_err(CE_CONT, 22330Sstevel@tonic-gate "close of root device component failed, error %d\n", 22340Sstevel@tonic-gate error); 22350Sstevel@tonic-gate } 22360Sstevel@tonic-gate VN_RELE(old_rootvp); 22370Sstevel@tonic-gate 22380Sstevel@tonic-gate return (sberror ? sberror : error); 22390Sstevel@tonic-gate } 22400Sstevel@tonic-gate 22410Sstevel@tonic-gate #endif /* __sparc */ 2242