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