newfs->fs_ronly = fs->fs_ronly;
ffs_reload(mountp, cred, p)	register struct mount *mountp;	struct ucred *cred;	struct proc *p;{	register struct vnode *vp, *nvp, *devvp;	struct inode *ip;	caddr_t space;	struct buf *bp;	struct fs *fs, *newfs;	struct partinfo dpart;	int i, blks, size, error;	int32_t *lp;	if ((mountp->mnt_flag & MNT_RDONLY) == 0)		return (EINVAL);	/*	 * Step 1: invalidate all cached meta-data.	 */	devvp = VFSTOUFS(mountp)->um_devvp;	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);	error = vinvalbuf(devvp, 0, cred, p, 0, 0);	VOP_UNLOCK(devvp, 0, p);	if (error)		panic("ffs_reload: dirty1");	/*	 * Step 2: re-read superblock from disk.	 */	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)		size = DEV_BSIZE;	else		size = dpart.disklab->d_secsize;	error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp);	if (error)		return (error);	newfs = (struct fs *)bp->b_data;	if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||	    newfs->fs_bsize < sizeof(struct fs)) {		brelse(bp);		return (EIO);		/* XXX needs translation */	}	fs = VFSTOUFS(mountp)->um_fs;	/*	 * Copy pointer fields back into superblock before copying in	XXX	 * new superblock. These should really be in the ufsmount.	XXX	 * Note that important parameters (eg fs_ncg) are unchanged.	 */	newfs->fs_csp = fs->fs_csp;	newfs->fs_maxcluster = fs->fs_maxcluster;	bcopy(newfs, fs, (u_int)fs->fs_sbsize);	if (fs->fs_sbsize < SBSIZE)		bp->b_flags |= B_INVAL;	brelse(bp);	mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;	ffs_oldfscompat(fs);	(void)ffs_statfs(mountp, &mountp->mnt_stat, p);	/*	 * Step 3: re-read summary information from disk.	 */	blks = howmany(fs->fs_cssize, fs->fs_fsize);	space = (caddr_t)fs->fs_csp;	for (i = 0; i < blks; i += fs->fs_frag) {		size = fs->fs_bsize;		if (i + fs->fs_frag > blks)			size = (blks - i) * fs->fs_fsize;		error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,			      NOCRED, &bp);		if (error)			return (error);		bcopy(bp->b_data, space, (u_int)size);		space += size;		brelse(bp);	}	if ((fs->fs_flags & FS_DOSOFTDEP))		(void) softdep_mount(devvp, mountp, fs, cred);	/*	 * We no longer know anything about clusters per cylinder group.	 */	if (fs->fs_contigsumsize > 0) {		lp = fs->fs_maxcluster;		for (i = 0; i < fs->fs_ncg; i++)			*lp++ = fs->fs_contigsumsize;	}loop:	simple_lock(&mntvnode_slock);	for (vp = LIST_FIRST(&mountp->mnt_vnodelist); vp != NULL; vp = nvp) {		if (vp->v_mount != mountp) {			simple_unlock(&mntvnode_slock);			goto loop;		}		nvp = LIST_NEXT(vp, v_mntvnodes);		/*		 * Step 4: invalidate all inactive vnodes.		 */		if (vrecycle(vp, &mntvnode_slock, p))			goto loop;		/*		 * Step 5: invalidate all cached file data.		 */		simple_lock(&vp->v_interlock);		simple_unlock(&mntvnode_slock);		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))			goto loop;		if (vinvalbuf(vp, 0, cred, p, 0, 0))			panic("ffs_reload: dirty2");		/*		 * Step 6: re-read inode data for all active vnodes.		 */		ip = VTOI(vp);		error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),			      (int)fs->fs_bsize, NOCRED, &bp);		if (error) {			vput(vp);			return (error);		}		ip->i_din.ffs_din = *((struct dinode *)bp->b_data +		    ino_to_fsbo(fs, ip->i_number));		ip->i_effnlink = ip->i_ffs_nlink;		brelse(bp);		vput(vp);		simple_lock(&mntvnode_slock);	}	simple_unlock(&mntvnode_slock);	return (0);}