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