xref: /csrg-svn/sys/ufs/ffs/ffs_vfsops.c (revision 12795)
1*12795Ssam /*	ffs_vfsops.c	4.1	83/05/27	*/
2*12795Ssam 
3*12795Ssam #include "../h/param.h"
4*12795Ssam #include "../h/systm.h"
5*12795Ssam #include "../h/dir.h"
6*12795Ssam #include "../h/user.h"
7*12795Ssam #include "../h/inode.h"
8*12795Ssam #include "../h/proc.h"
9*12795Ssam #include "../h/fs.h"
10*12795Ssam #include "../h/buf.h"
11*12795Ssam #include "../h/mount.h"
12*12795Ssam #include "../h/file.h"
13*12795Ssam #include "../h/nami.h"
14*12795Ssam #include "../h/conf.h"
15*12795Ssam 
16*12795Ssam smount()
17*12795Ssam {
18*12795Ssam 	register struct a {
19*12795Ssam 		char	*fspec;
20*12795Ssam 		char	*freg;
21*12795Ssam 		int	ronly;
22*12795Ssam 	} *uap;
23*12795Ssam 	dev_t dev;
24*12795Ssam 	register struct inode *ip;
25*12795Ssam 	register struct fs *fs;
26*12795Ssam 	register char *cp;
27*12795Ssam 
28*12795Ssam 	uap = (struct a *)u.u_ap;
29*12795Ssam 	u.u_error = getmdev(&dev);
30*12795Ssam 	if (u.u_error)
31*12795Ssam 		return;
32*12795Ssam 	u.u_dirp = (caddr_t)uap->freg;
33*12795Ssam 	ip = namei(uchar, LOOKUP, 1);
34*12795Ssam 	if (ip == NULL)
35*12795Ssam 		return;
36*12795Ssam 	if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) {
37*12795Ssam 		iput(ip);
38*12795Ssam 		u.u_error = EBUSY;
39*12795Ssam 		return;
40*12795Ssam 	}
41*12795Ssam 	fs = mountfs(dev, uap->ronly, ip);
42*12795Ssam 	if (fs == 0)
43*12795Ssam 		return;
44*12795Ssam 	u.u_dirp = uap->freg;
45*12795Ssam 	for (cp = fs->fs_fsmnt; cp < &fs->fs_fsmnt[sizeof(fs->fs_fsmnt) - 2]; )
46*12795Ssam 		if ((*cp++ = uchar()) == 0)
47*12795Ssam 			u.u_dirp--;		/* get 0 again */
48*12795Ssam 	*cp = 0;
49*12795Ssam }
50*12795Ssam 
51*12795Ssam /* this routine has lousy error codes */
52*12795Ssam /* this routine has races if running twice */
53*12795Ssam struct fs *
54*12795Ssam mountfs(dev, ronly, ip)
55*12795Ssam 	dev_t dev;
56*12795Ssam 	int ronly;
57*12795Ssam 	struct inode *ip;
58*12795Ssam {
59*12795Ssam 	register struct mount *mp = 0;
60*12795Ssam 	struct buf *tp = 0;
61*12795Ssam 	register struct buf *bp = 0;
62*12795Ssam 	register struct fs *fs;
63*12795Ssam 	int blks;
64*12795Ssam 	caddr_t space;
65*12795Ssam 	int i, size;
66*12795Ssam 
67*12795Ssam 	u.u_error =
68*12795Ssam 	    (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE);
69*12795Ssam 	if (u.u_error) {
70*12795Ssam 		u.u_error = EIO;
71*12795Ssam 		goto out;
72*12795Ssam 	}
73*12795Ssam 	tp = bread(dev, SBLOCK, SBSIZE);
74*12795Ssam 	if (tp->b_flags & B_ERROR)
75*12795Ssam 		goto out;
76*12795Ssam 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
77*12795Ssam 		if (mp->m_bufp != 0 && dev == mp->m_dev) {
78*12795Ssam 			mp = 0;
79*12795Ssam 			goto out;
80*12795Ssam 		}
81*12795Ssam 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
82*12795Ssam 		if (mp->m_bufp == 0)
83*12795Ssam 			goto found;
84*12795Ssam 	mp = 0;
85*12795Ssam 	goto out;
86*12795Ssam found:
87*12795Ssam 	mp->m_bufp = tp;	/* just to reserve this slot */
88*12795Ssam 	mp->m_dev = NODEV;
89*12795Ssam 	fs = tp->b_un.b_fs;
90*12795Ssam 	bp = geteblk((int)fs->fs_sbsize);
91*12795Ssam 	mp->m_bufp = bp;
92*12795Ssam 	bcopy((caddr_t)tp->b_un.b_addr, (caddr_t)bp->b_un.b_addr,
93*12795Ssam 	   (u_int)fs->fs_sbsize);
94*12795Ssam 	brelse(tp);
95*12795Ssam 	tp = 0;
96*12795Ssam 	fs = bp->b_un.b_fs;
97*12795Ssam 	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE)
98*12795Ssam 		goto out;
99*12795Ssam 	fs->fs_ronly = (ronly != 0);
100*12795Ssam 	if (ronly == 0)
101*12795Ssam 		fs->fs_fmod = 1;
102*12795Ssam 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
103*12795Ssam 	space = wmemall(vmemall, (int)fs->fs_cssize);
104*12795Ssam 	if (space == 0)
105*12795Ssam 		goto out;
106*12795Ssam 	for (i = 0; i < blks; i += fs->fs_frag) {
107*12795Ssam 		size = fs->fs_bsize;
108*12795Ssam 		if (i + fs->fs_frag > blks)
109*12795Ssam 			size = (blks - i) * fs->fs_fsize;
110*12795Ssam 		tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size);
111*12795Ssam 		if (tp->b_flags&B_ERROR) {
112*12795Ssam 			wmemfree(space, (int)fs->fs_cssize);
113*12795Ssam 			goto out;
114*12795Ssam 		}
115*12795Ssam 		bcopy((caddr_t)tp->b_un.b_addr, space, (u_int)size);
116*12795Ssam 		fs->fs_csp[i / fs->fs_frag] = (struct csum *)space;
117*12795Ssam 		space += size;
118*12795Ssam 		brelse(tp);
119*12795Ssam 		tp = 0;
120*12795Ssam 	}
121*12795Ssam 	mp->m_inodp = ip;
122*12795Ssam 	mp->m_dev = dev;
123*12795Ssam 	if (ip) {
124*12795Ssam 		ip->i_flag |= IMOUNT;
125*12795Ssam 		iunlock(ip);
126*12795Ssam 	}
127*12795Ssam 	return (fs);
128*12795Ssam out:
129*12795Ssam 	u.u_error = EBUSY;
130*12795Ssam 	if (ip)
131*12795Ssam 		iput(ip);
132*12795Ssam 	if (mp)
133*12795Ssam 		mp->m_bufp = 0;
134*12795Ssam 	if (bp)
135*12795Ssam 		brelse(bp);
136*12795Ssam 	if (tp)
137*12795Ssam 		brelse(tp);
138*12795Ssam 	return (0);
139*12795Ssam }
140*12795Ssam 
141*12795Ssam umount()
142*12795Ssam {
143*12795Ssam 	struct a {
144*12795Ssam 		char	*fspec;
145*12795Ssam 	};
146*12795Ssam 
147*12795Ssam 	u.u_error = unmount1(0);
148*12795Ssam }
149*12795Ssam 
150*12795Ssam unmount1(forcibly)
151*12795Ssam 	int forcibly;
152*12795Ssam {
153*12795Ssam 	dev_t dev;
154*12795Ssam 	register struct mount *mp;
155*12795Ssam 	int stillopen, flag, error;
156*12795Ssam 	register struct inode *ip;
157*12795Ssam 	register struct fs *fs;
158*12795Ssam 
159*12795Ssam 	error = getmdev(&dev);
160*12795Ssam 	if (error)
161*12795Ssam 		return (error);
162*12795Ssam 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
163*12795Ssam 		if (mp->m_bufp != NULL && dev == mp->m_dev)
164*12795Ssam 			goto found;
165*12795Ssam 	return (EINVAL);
166*12795Ssam found:
167*12795Ssam 	xumount(dev);	/* remove unused sticky files from text table */
168*12795Ssam 	update();
169*12795Ssam #ifdef QUOTA
170*12795Ssam 	if ((stillopen = iflush(dev, mp->m_qinod)) < 0 && !forcibly)
171*12795Ssam #else
172*12795Ssam 	if ((stillopen = iflush(dev)) < 0 && !forcibly)
173*12795Ssam #endif
174*12795Ssam 		return (EBUSY);
175*12795Ssam 	if (stillopen < 0)
176*12795Ssam 		return (EBUSY);			/* XXX */
177*12795Ssam #ifdef QUOTA
178*12795Ssam 	closedq(mp);
179*12795Ssam 	/*
180*12795Ssam 	 * Here we have to iflush again to get rid of the quota inode.
181*12795Ssam 	 * A drag, but it would be ugly to cheat, & this doesn't happen often
182*12795Ssam 	 */
183*12795Ssam 	(void)iflush(dev, (struct inode *)NULL);
184*12795Ssam #endif
185*12795Ssam 	ip = mp->m_inodp;
186*12795Ssam 	ip->i_flag &= ~IMOUNT;
187*12795Ssam 	irele(ip);
188*12795Ssam 	fs = mp->m_bufp->b_un.b_fs;
189*12795Ssam 	wmemfree((caddr_t)fs->fs_csp[0], (int)fs->fs_cssize);
190*12795Ssam 	flag = !fs->fs_ronly;
191*12795Ssam 	brelse(mp->m_bufp);
192*12795Ssam 	mp->m_bufp = 0;
193*12795Ssam 	mp->m_dev = 0;
194*12795Ssam 	mpurge(mp - &mount[0]);
195*12795Ssam 	if (!stillopen) {
196*12795Ssam 		(*bdevsw[major(dev)].d_close)(dev, flag);
197*12795Ssam 		binval(dev);
198*12795Ssam 	}
199*12795Ssam 	return (0);
200*12795Ssam }
201*12795Ssam 
202*12795Ssam sbupdate(mp)
203*12795Ssam 	struct mount *mp;
204*12795Ssam {
205*12795Ssam 	register struct fs *fs = mp->m_bufp->b_un.b_fs;
206*12795Ssam 	register struct buf *bp;
207*12795Ssam 	int blks;
208*12795Ssam 	caddr_t space;
209*12795Ssam 	int i, size;
210*12795Ssam 
211*12795Ssam 	bp = getblk(mp->m_dev, SBLOCK, (int)fs->fs_sbsize);
212*12795Ssam 	bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
213*12795Ssam 	bwrite(bp);
214*12795Ssam 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
215*12795Ssam 	space = (caddr_t)fs->fs_csp[0];
216*12795Ssam 	for (i = 0; i < blks; i += fs->fs_frag) {
217*12795Ssam 		size = fs->fs_bsize;
218*12795Ssam 		if (i + fs->fs_frag > blks)
219*12795Ssam 			size = (blks - i) * fs->fs_fsize;
220*12795Ssam 		bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size);
221*12795Ssam 		bcopy(space, bp->b_un.b_addr, (u_int)size);
222*12795Ssam 		space += size;
223*12795Ssam 		bwrite(bp);
224*12795Ssam 	}
225*12795Ssam }
226*12795Ssam 
227*12795Ssam /*
228*12795Ssam  * Common code for mount and umount.
229*12795Ssam  * Check that the user's argument is a reasonable
230*12795Ssam  * thing on which to mount, and return the device number if so.
231*12795Ssam  */
232*12795Ssam getmdev(pdev)
233*12795Ssam 	dev_t *pdev;
234*12795Ssam {
235*12795Ssam 	dev_t dev;
236*12795Ssam 	register struct inode *ip;
237*12795Ssam 
238*12795Ssam 	if (!suser())
239*12795Ssam 		return (u.u_error);
240*12795Ssam 	ip = namei(uchar, LOOKUP, 1);
241*12795Ssam 	if (ip == NULL)
242*12795Ssam 		return (u.u_error);
243*12795Ssam 	if ((ip->i_mode&IFMT) != IFBLK)
244*12795Ssam 		return (ENOTBLK);
245*12795Ssam 	dev = (dev_t)ip->i_rdev;
246*12795Ssam 	if (major(dev) >= nblkdev)
247*12795Ssam 		return (ENXIO);
248*12795Ssam 	iput(ip);
249*12795Ssam 	*pdev = dev;
250*12795Ssam 	return (0);
251*12795Ssam }
252