missing iput's on errors
[unix-history] / usr / src / sys / ufs / lfs / lfs_vfsops.c
CommitLineData
e95cdf5c 1/* lfs_vfsops.c 6.3 84/02/07 */
71e4e98b
SL
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
16smount()
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;
f93197fc 33 ip = namei(uchar, LOOKUP | NOCACHE, 1);
71e4e98b
SL
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 */
53struct fs *
54mountfs(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;
86found:
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);
128out:
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
141umount()
142{
143 struct a {
144 char *fspec;
145 };
146
147 u.u_error = unmount1(0);
148}
149
150unmount1(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);
166found:
167 xumount(dev); /* remove unused sticky files from text table */
f93197fc 168 nchinval(dev); /* flush the name cache */
71e4e98b
SL
169 update();
170#ifdef QUOTA
171 if ((stillopen = iflush(dev, mp->m_qinod)) < 0 && !forcibly)
172#else
173 if ((stillopen = iflush(dev)) < 0 && !forcibly)
174#endif
175 return (EBUSY);
176 if (stillopen < 0)
177 return (EBUSY); /* XXX */
178#ifdef QUOTA
179 closedq(mp);
180 /*
181 * Here we have to iflush again to get rid of the quota inode.
182 * A drag, but it would be ugly to cheat, & this doesn't happen often
183 */
184 (void)iflush(dev, (struct inode *)NULL);
185#endif
186 ip = mp->m_inodp;
187 ip->i_flag &= ~IMOUNT;
188 irele(ip);
189 fs = mp->m_bufp->b_un.b_fs;
190 wmemfree((caddr_t)fs->fs_csp[0], (int)fs->fs_cssize);
191 flag = !fs->fs_ronly;
192 brelse(mp->m_bufp);
193 mp->m_bufp = 0;
194 mp->m_dev = 0;
195 mpurge(mp - &mount[0]);
196 if (!stillopen) {
197 (*bdevsw[major(dev)].d_close)(dev, flag);
198 binval(dev);
199 }
200 return (0);
201}
202
203sbupdate(mp)
204 struct mount *mp;
205{
206 register struct fs *fs = mp->m_bufp->b_un.b_fs;
207 register struct buf *bp;
208 int blks;
209 caddr_t space;
210 int i, size;
211
212 bp = getblk(mp->m_dev, SBLOCK, (int)fs->fs_sbsize);
213 bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
214 bwrite(bp);
215 blks = howmany(fs->fs_cssize, fs->fs_fsize);
216 space = (caddr_t)fs->fs_csp[0];
217 for (i = 0; i < blks; i += fs->fs_frag) {
218 size = fs->fs_bsize;
219 if (i + fs->fs_frag > blks)
220 size = (blks - i) * fs->fs_fsize;
221 bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size);
222 bcopy(space, bp->b_un.b_addr, (u_int)size);
223 space += size;
224 bwrite(bp);
225 }
226}
227
228/*
229 * Common code for mount and umount.
230 * Check that the user's argument is a reasonable
231 * thing on which to mount, and return the device number if so.
232 */
233getmdev(pdev)
234 dev_t *pdev;
235{
236 dev_t dev;
237 register struct inode *ip;
238
239 if (!suser())
240 return (u.u_error);
241 ip = namei(uchar, LOOKUP, 1);
242 if (ip == NULL)
243 return (u.u_error);
e95cdf5c
MK
244 if ((ip->i_mode&IFMT) != IFBLK) {
245 iput(ip);
71e4e98b 246 return (ENOTBLK);
e95cdf5c 247 }
71e4e98b 248 dev = (dev_t)ip->i_rdev;
e95cdf5c 249 iput(ip);
71e4e98b
SL
250 if (major(dev) >= nblkdev)
251 return (ENXIO);
71e4e98b
SL
252 *pdev = dev;
253 return (0);
254}