xref: /csrg-svn/sys/ufs/lfs/lfs_vfsops.c (revision 15800)
1*15800Smckusick /*	lfs_vfsops.c	6.2	84/01/03	*/
212795Ssam 
312795Ssam #include "../h/param.h"
412795Ssam #include "../h/systm.h"
512795Ssam #include "../h/dir.h"
612795Ssam #include "../h/user.h"
712795Ssam #include "../h/inode.h"
812795Ssam #include "../h/proc.h"
912795Ssam #include "../h/fs.h"
1012795Ssam #include "../h/buf.h"
1112795Ssam #include "../h/mount.h"
1212795Ssam #include "../h/file.h"
1312795Ssam #include "../h/nami.h"
1412795Ssam #include "../h/conf.h"
1512795Ssam 
1612795Ssam smount()
1712795Ssam {
1812795Ssam 	register struct a {
1912795Ssam 		char	*fspec;
2012795Ssam 		char	*freg;
2112795Ssam 		int	ronly;
2212795Ssam 	} *uap;
2312795Ssam 	dev_t dev;
2412795Ssam 	register struct inode *ip;
2512795Ssam 	register struct fs *fs;
2612795Ssam 	register char *cp;
2712795Ssam 
2812795Ssam 	uap = (struct a *)u.u_ap;
2912795Ssam 	u.u_error = getmdev(&dev);
3012795Ssam 	if (u.u_error)
3112795Ssam 		return;
3212795Ssam 	u.u_dirp = (caddr_t)uap->freg;
33*15800Smckusick 	ip = namei(uchar, LOOKUP | NOCACHE, 1);
3412795Ssam 	if (ip == NULL)
3512795Ssam 		return;
3612795Ssam 	if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) {
3712795Ssam 		iput(ip);
3812795Ssam 		u.u_error = EBUSY;
3912795Ssam 		return;
4012795Ssam 	}
4112795Ssam 	fs = mountfs(dev, uap->ronly, ip);
4212795Ssam 	if (fs == 0)
4312795Ssam 		return;
4412795Ssam 	u.u_dirp = uap->freg;
4512795Ssam 	for (cp = fs->fs_fsmnt; cp < &fs->fs_fsmnt[sizeof(fs->fs_fsmnt) - 2]; )
4612795Ssam 		if ((*cp++ = uchar()) == 0)
4712795Ssam 			u.u_dirp--;		/* get 0 again */
4812795Ssam 	*cp = 0;
4912795Ssam }
5012795Ssam 
5112795Ssam /* this routine has lousy error codes */
5212795Ssam /* this routine has races if running twice */
5312795Ssam struct fs *
5412795Ssam mountfs(dev, ronly, ip)
5512795Ssam 	dev_t dev;
5612795Ssam 	int ronly;
5712795Ssam 	struct inode *ip;
5812795Ssam {
5912795Ssam 	register struct mount *mp = 0;
6012795Ssam 	struct buf *tp = 0;
6112795Ssam 	register struct buf *bp = 0;
6212795Ssam 	register struct fs *fs;
6312795Ssam 	int blks;
6412795Ssam 	caddr_t space;
6512795Ssam 	int i, size;
6612795Ssam 
6712795Ssam 	u.u_error =
6812795Ssam 	    (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE);
6912795Ssam 	if (u.u_error) {
7012795Ssam 		u.u_error = EIO;
7112795Ssam 		goto out;
7212795Ssam 	}
7312795Ssam 	tp = bread(dev, SBLOCK, SBSIZE);
7412795Ssam 	if (tp->b_flags & B_ERROR)
7512795Ssam 		goto out;
7612795Ssam 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
7712795Ssam 		if (mp->m_bufp != 0 && dev == mp->m_dev) {
7812795Ssam 			mp = 0;
7912795Ssam 			goto out;
8012795Ssam 		}
8112795Ssam 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
8212795Ssam 		if (mp->m_bufp == 0)
8312795Ssam 			goto found;
8412795Ssam 	mp = 0;
8512795Ssam 	goto out;
8612795Ssam found:
8712795Ssam 	mp->m_bufp = tp;	/* just to reserve this slot */
8812795Ssam 	mp->m_dev = NODEV;
8912795Ssam 	fs = tp->b_un.b_fs;
9012795Ssam 	bp = geteblk((int)fs->fs_sbsize);
9112795Ssam 	mp->m_bufp = bp;
9212795Ssam 	bcopy((caddr_t)tp->b_un.b_addr, (caddr_t)bp->b_un.b_addr,
9312795Ssam 	   (u_int)fs->fs_sbsize);
9412795Ssam 	brelse(tp);
9512795Ssam 	tp = 0;
9612795Ssam 	fs = bp->b_un.b_fs;
9712795Ssam 	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE)
9812795Ssam 		goto out;
9912795Ssam 	fs->fs_ronly = (ronly != 0);
10012795Ssam 	if (ronly == 0)
10112795Ssam 		fs->fs_fmod = 1;
10212795Ssam 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
10312795Ssam 	space = wmemall(vmemall, (int)fs->fs_cssize);
10412795Ssam 	if (space == 0)
10512795Ssam 		goto out;
10612795Ssam 	for (i = 0; i < blks; i += fs->fs_frag) {
10712795Ssam 		size = fs->fs_bsize;
10812795Ssam 		if (i + fs->fs_frag > blks)
10912795Ssam 			size = (blks - i) * fs->fs_fsize;
11012795Ssam 		tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size);
11112795Ssam 		if (tp->b_flags&B_ERROR) {
11212795Ssam 			wmemfree(space, (int)fs->fs_cssize);
11312795Ssam 			goto out;
11412795Ssam 		}
11512795Ssam 		bcopy((caddr_t)tp->b_un.b_addr, space, (u_int)size);
11612795Ssam 		fs->fs_csp[i / fs->fs_frag] = (struct csum *)space;
11712795Ssam 		space += size;
11812795Ssam 		brelse(tp);
11912795Ssam 		tp = 0;
12012795Ssam 	}
12112795Ssam 	mp->m_inodp = ip;
12212795Ssam 	mp->m_dev = dev;
12312795Ssam 	if (ip) {
12412795Ssam 		ip->i_flag |= IMOUNT;
12512795Ssam 		iunlock(ip);
12612795Ssam 	}
12712795Ssam 	return (fs);
12812795Ssam out:
12912795Ssam 	u.u_error = EBUSY;
13012795Ssam 	if (ip)
13112795Ssam 		iput(ip);
13212795Ssam 	if (mp)
13312795Ssam 		mp->m_bufp = 0;
13412795Ssam 	if (bp)
13512795Ssam 		brelse(bp);
13612795Ssam 	if (tp)
13712795Ssam 		brelse(tp);
13812795Ssam 	return (0);
13912795Ssam }
14012795Ssam 
14112795Ssam umount()
14212795Ssam {
14312795Ssam 	struct a {
14412795Ssam 		char	*fspec;
14512795Ssam 	};
14612795Ssam 
14712795Ssam 	u.u_error = unmount1(0);
14812795Ssam }
14912795Ssam 
15012795Ssam unmount1(forcibly)
15112795Ssam 	int forcibly;
15212795Ssam {
15312795Ssam 	dev_t dev;
15412795Ssam 	register struct mount *mp;
15512795Ssam 	int stillopen, flag, error;
15612795Ssam 	register struct inode *ip;
15712795Ssam 	register struct fs *fs;
15812795Ssam 
15912795Ssam 	error = getmdev(&dev);
16012795Ssam 	if (error)
16112795Ssam 		return (error);
16212795Ssam 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
16312795Ssam 		if (mp->m_bufp != NULL && dev == mp->m_dev)
16412795Ssam 			goto found;
16512795Ssam 	return (EINVAL);
16612795Ssam found:
16712795Ssam 	xumount(dev);	/* remove unused sticky files from text table */
168*15800Smckusick 	nchinval(dev);	/* flush the name cache */
16912795Ssam 	update();
17012795Ssam #ifdef QUOTA
17112795Ssam 	if ((stillopen = iflush(dev, mp->m_qinod)) < 0 && !forcibly)
17212795Ssam #else
17312795Ssam 	if ((stillopen = iflush(dev)) < 0 && !forcibly)
17412795Ssam #endif
17512795Ssam 		return (EBUSY);
17612795Ssam 	if (stillopen < 0)
17712795Ssam 		return (EBUSY);			/* XXX */
17812795Ssam #ifdef QUOTA
17912795Ssam 	closedq(mp);
18012795Ssam 	/*
18112795Ssam 	 * Here we have to iflush again to get rid of the quota inode.
18212795Ssam 	 * A drag, but it would be ugly to cheat, & this doesn't happen often
18312795Ssam 	 */
18412795Ssam 	(void)iflush(dev, (struct inode *)NULL);
18512795Ssam #endif
18612795Ssam 	ip = mp->m_inodp;
18712795Ssam 	ip->i_flag &= ~IMOUNT;
18812795Ssam 	irele(ip);
18912795Ssam 	fs = mp->m_bufp->b_un.b_fs;
19012795Ssam 	wmemfree((caddr_t)fs->fs_csp[0], (int)fs->fs_cssize);
19112795Ssam 	flag = !fs->fs_ronly;
19212795Ssam 	brelse(mp->m_bufp);
19312795Ssam 	mp->m_bufp = 0;
19412795Ssam 	mp->m_dev = 0;
19512795Ssam 	mpurge(mp - &mount[0]);
19612795Ssam 	if (!stillopen) {
19712795Ssam 		(*bdevsw[major(dev)].d_close)(dev, flag);
19812795Ssam 		binval(dev);
19912795Ssam 	}
20012795Ssam 	return (0);
20112795Ssam }
20212795Ssam 
20312795Ssam sbupdate(mp)
20412795Ssam 	struct mount *mp;
20512795Ssam {
20612795Ssam 	register struct fs *fs = mp->m_bufp->b_un.b_fs;
20712795Ssam 	register struct buf *bp;
20812795Ssam 	int blks;
20912795Ssam 	caddr_t space;
21012795Ssam 	int i, size;
21112795Ssam 
21212795Ssam 	bp = getblk(mp->m_dev, SBLOCK, (int)fs->fs_sbsize);
21312795Ssam 	bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
21412795Ssam 	bwrite(bp);
21512795Ssam 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
21612795Ssam 	space = (caddr_t)fs->fs_csp[0];
21712795Ssam 	for (i = 0; i < blks; i += fs->fs_frag) {
21812795Ssam 		size = fs->fs_bsize;
21912795Ssam 		if (i + fs->fs_frag > blks)
22012795Ssam 			size = (blks - i) * fs->fs_fsize;
22112795Ssam 		bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size);
22212795Ssam 		bcopy(space, bp->b_un.b_addr, (u_int)size);
22312795Ssam 		space += size;
22412795Ssam 		bwrite(bp);
22512795Ssam 	}
22612795Ssam }
22712795Ssam 
22812795Ssam /*
22912795Ssam  * Common code for mount and umount.
23012795Ssam  * Check that the user's argument is a reasonable
23112795Ssam  * thing on which to mount, and return the device number if so.
23212795Ssam  */
23312795Ssam getmdev(pdev)
23412795Ssam 	dev_t *pdev;
23512795Ssam {
23612795Ssam 	dev_t dev;
23712795Ssam 	register struct inode *ip;
23812795Ssam 
23912795Ssam 	if (!suser())
24012795Ssam 		return (u.u_error);
24112795Ssam 	ip = namei(uchar, LOOKUP, 1);
24212795Ssam 	if (ip == NULL)
24312795Ssam 		return (u.u_error);
24412795Ssam 	if ((ip->i_mode&IFMT) != IFBLK)
24512795Ssam 		return (ENOTBLK);
24612795Ssam 	dev = (dev_t)ip->i_rdev;
24712795Ssam 	if (major(dev) >= nblkdev)
24812795Ssam 		return (ENXIO);
24912795Ssam 	iput(ip);
25012795Ssam 	*pdev = dev;
25112795Ssam 	return (0);
25212795Ssam }
253