/*ARGSUSED*/ static int mod_infofs(struct modlfs *modl, struct modlinkage *modlp, int *p0) { struct vfssw *vswp; RLOCK_VFSSW(); if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL) *p0 = -1; else { *p0 = vswp - vfssw; vfs_unrefvfssw(vswp); } RUNLOCK_VFSSW(); return (0); }
/* * As part of file system hardening, this daemon is awakened * every second to flush cached data which includes the * buffer cache, the inode cache and mapped pages. */ void fsflush() { struct buf *bp, *dwp; struct hbuf *hp; int autoup; unsigned int ix, icount, count = 0; callb_cpr_t cprinfo; uint_t bcount; kmutex_t *hmp; struct vfssw *vswp; proc_fsflush = ttoproc(curthread); proc_fsflush->p_cstime = 0; proc_fsflush->p_stime = 0; proc_fsflush->p_cutime = 0; proc_fsflush->p_utime = 0; bcopy("fsflush", curproc->p_user.u_psargs, 8); bcopy("fsflush", curproc->p_user.u_comm, 7); mutex_init(&fsflush_lock, NULL, MUTEX_DEFAULT, NULL); sema_init(&fsflush_sema, 0, NULL, SEMA_DEFAULT, NULL); /* * Setup page coalescing. */ fsf_npgsz = page_num_pagesizes(); ASSERT(fsf_npgsz < MAX_PAGESIZES); for (ix = 0; ix < fsf_npgsz - 1; ++ix) { fsf_pgcnt[ix] = page_get_pagesize(ix + 1) / page_get_pagesize(ix); fsf_mask[ix] = page_get_pagecnt(ix + 1) - 1; } autoup = v.v_autoup * hz; icount = v.v_autoup / tune.t_fsflushr; CALLB_CPR_INIT(&cprinfo, &fsflush_lock, callb_generic_cpr, "fsflush"); loop: sema_v(&fsflush_sema); mutex_enter(&fsflush_lock); CALLB_CPR_SAFE_BEGIN(&cprinfo); cv_wait(&fsflush_cv, &fsflush_lock); /* wait for clock */ CALLB_CPR_SAFE_END(&cprinfo, &fsflush_lock); mutex_exit(&fsflush_lock); sema_p(&fsflush_sema); /* * Write back all old B_DELWRI buffers on the freelist. */ bcount = 0; for (ix = 0; ix < v.v_hbuf; ix++) { hp = &hbuf[ix]; dwp = (struct buf *)&dwbuf[ix]; bcount += (hp->b_length); if (dwp->av_forw == dwp) { continue; } hmp = &hbuf[ix].b_lock; mutex_enter(hmp); bp = dwp->av_forw; /* * Go down only on the delayed write lists. */ while (bp != dwp) { ASSERT(bp->b_flags & B_DELWRI); if ((bp->b_flags & B_DELWRI) && (ddi_get_lbolt() - bp->b_start >= autoup) && sema_tryp(&bp->b_sem)) { bp->b_flags |= B_ASYNC; hp->b_length--; notavail(bp); mutex_exit(hmp); if (bp->b_vp == NULL) { BWRITE(bp); } else { UFS_BWRITE(VTOI(bp->b_vp)->i_ufsvfs, bp); } mutex_enter(hmp); bp = dwp->av_forw; } else { bp = bp->av_forw; } } mutex_exit(hmp); } /* * * There is no need to wakeup any thread waiting on bio_mem_cv * since brelse will wake them up as soon as IO is complete. */ bfreelist.b_bcount = bcount; if (dopageflush) fsflush_do_pages(); if (!doiflush) goto loop; /* * If the system was not booted to single user mode, skip the * inode flushing until after fsflush_iflush_delay secs have elapsed. */ if ((boothowto & RB_SINGLE) == 0 && (ddi_get_lbolt64() / hz) < fsflush_iflush_delay) goto loop; /* * Flush cached attribute information (e.g. inodes). */ if (++count >= icount) { count = 0; /* * Sync back cached data. */ RLOCK_VFSSW(); for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) { if (ALLOCATED_VFSSW(vswp) && VFS_INSTALLED(vswp)) { vfs_refvfssw(vswp); RUNLOCK_VFSSW(); (void) fsop_sync_by_kind(vswp - vfssw, SYNC_ATTR, kcred); vfs_unrefvfssw(vswp); RLOCK_VFSSW(); } } RUNLOCK_VFSSW(); } goto loop; }
/* * Configure root file system. */ int rootconf(void) { int error; struct vfssw *vsw; extern void pm_init(void); BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype)); BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name)); BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags)); BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath)); /* * Install cluster modules that were only loaded during * loadrootmodules(). */ if (error = clboot_rootconf()) return (error); if (root_is_svm) { (void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME); BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name)); BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath)); } /* * Run _init on the root filesystem (we already loaded it * but we've been waiting until now to _init it) which will * have the side-effect of running vsw_init() on this vfs. * Because all the nfs filesystems are lumped into one * module we need to special case it. */ if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { if (modload("fs", "nfs") == -1) { cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", rootfs.bo_fstype); return (ENXIO); } } else { if (modload("fs", rootfs.bo_fstype) == -1) { cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", rootfs.bo_fstype); return (ENXIO); } } RLOCK_VFSSW(); vsw = vfs_getvfsswbyname(rootfs.bo_fstype); RUNLOCK_VFSSW(); VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0); VFS_HOLD(rootvfs); if (root_is_svm) { rootvfs->vfs_flag |= VFS_RDONLY; } /* * This pm-releated call has to occur before root is mounted since we * need to power up all devices. It is placed after VFS_INIT() such * that opening a device via ddi_lyr_ interface just before root has * been mounted would work. */ pm_init(); if (netboot) { if ((error = strplumb()) != 0) { cmn_err(CE_CONT, "Cannot plumb network device\n"); return (error); } } /* * ufs_mountroot() ends up calling getrootdev() * (below) which actually triggers the _init, identify, * probe and attach of the drivers that make up root device * bush; these are also quietly waiting in memory. */ BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype)); error = VFS_MOUNTROOT(rootvfs, ROOT_INIT); vfs_unrefvfssw(vsw); rootdev = rootvfs->vfs_dev; if (error) cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n", rootfs.bo_name, rootfs.bo_fstype); else cmn_err(CE_CONT, "?root on %s fstype %s\n", rootfs.bo_name, rootfs.bo_fstype); return (error); }