Commit | Line | Data |
---|---|---|
1c281610 | 1 | /* lfs_vfsops.c 6.4 84/06/26 */ |
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 | ||
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; | |
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 | ||
71e4e98b SL |
51 | /* this routine has races if running twice */ |
52 | struct fs * | |
53 | mountfs(dev, ronly, ip) | |
54 | dev_t dev; | |
55 | int ronly; | |
56 | struct inode *ip; | |
57 | { | |
58 | register struct mount *mp = 0; | |
59 | struct buf *tp = 0; | |
60 | register struct buf *bp = 0; | |
61 | register struct fs *fs; | |
62 | int blks; | |
63 | caddr_t space; | |
64 | int i, size; | |
1c281610 | 65 | register error; |
71e4e98b | 66 | |
1c281610 | 67 | error = |
71e4e98b | 68 | (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE); |
1c281610 | 69 | if (error) |
71e4e98b | 70 | goto out; |
71e4e98b SL |
71 | tp = bread(dev, SBLOCK, SBSIZE); |
72 | if (tp->b_flags & B_ERROR) | |
73 | goto out; | |
74 | for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) | |
75 | if (mp->m_bufp != 0 && dev == mp->m_dev) { | |
76 | mp = 0; | |
1c281610 | 77 | error = EBUSY; |
71e4e98b SL |
78 | goto out; |
79 | } | |
80 | for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) | |
81 | if (mp->m_bufp == 0) | |
82 | goto found; | |
83 | mp = 0; | |
1c281610 | 84 | error = EMFILE; /* needs translation */ |
71e4e98b SL |
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; | |
1c281610 MK |
90 | if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE |
91 | || fs->fs_bsize < sizeof(struct fs)) { | |
92 | error = EINVAL; /* also needs translation */ | |
93 | goto out; | |
94 | } | |
71e4e98b SL |
95 | bp = geteblk((int)fs->fs_sbsize); |
96 | mp->m_bufp = bp; | |
97 | bcopy((caddr_t)tp->b_un.b_addr, (caddr_t)bp->b_un.b_addr, | |
98 | (u_int)fs->fs_sbsize); | |
99 | brelse(tp); | |
100 | tp = 0; | |
101 | fs = bp->b_un.b_fs; | |
71e4e98b SL |
102 | fs->fs_ronly = (ronly != 0); |
103 | if (ronly == 0) | |
104 | fs->fs_fmod = 1; | |
105 | blks = howmany(fs->fs_cssize, fs->fs_fsize); | |
106 | space = wmemall(vmemall, (int)fs->fs_cssize); | |
1c281610 MK |
107 | if (space == 0) { |
108 | error = ENOMEM; | |
71e4e98b | 109 | goto out; |
1c281610 | 110 | } |
71e4e98b SL |
111 | for (i = 0; i < blks; i += fs->fs_frag) { |
112 | size = fs->fs_bsize; | |
113 | if (i + fs->fs_frag > blks) | |
114 | size = (blks - i) * fs->fs_fsize; | |
115 | tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size); | |
116 | if (tp->b_flags&B_ERROR) { | |
117 | wmemfree(space, (int)fs->fs_cssize); | |
118 | goto out; | |
119 | } | |
120 | bcopy((caddr_t)tp->b_un.b_addr, space, (u_int)size); | |
121 | fs->fs_csp[i / fs->fs_frag] = (struct csum *)space; | |
122 | space += size; | |
123 | brelse(tp); | |
124 | tp = 0; | |
125 | } | |
126 | mp->m_inodp = ip; | |
127 | mp->m_dev = dev; | |
128 | if (ip) { | |
129 | ip->i_flag |= IMOUNT; | |
130 | iunlock(ip); | |
131 | } | |
132 | return (fs); | |
133 | out: | |
1c281610 MK |
134 | if (error == 0) |
135 | error = EIO; | |
71e4e98b SL |
136 | if (ip) |
137 | iput(ip); | |
138 | if (mp) | |
139 | mp->m_bufp = 0; | |
140 | if (bp) | |
141 | brelse(bp); | |
142 | if (tp) | |
143 | brelse(tp); | |
1c281610 | 144 | u.u_error = error; |
71e4e98b SL |
145 | return (0); |
146 | } | |
147 | ||
148 | umount() | |
149 | { | |
150 | struct a { | |
151 | char *fspec; | |
152 | }; | |
153 | ||
154 | u.u_error = unmount1(0); | |
155 | } | |
156 | ||
157 | unmount1(forcibly) | |
158 | int forcibly; | |
159 | { | |
160 | dev_t dev; | |
161 | register struct mount *mp; | |
162 | int stillopen, flag, error; | |
163 | register struct inode *ip; | |
164 | register struct fs *fs; | |
165 | ||
166 | error = getmdev(&dev); | |
167 | if (error) | |
168 | return (error); | |
169 | for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) | |
170 | if (mp->m_bufp != NULL && dev == mp->m_dev) | |
171 | goto found; | |
172 | return (EINVAL); | |
173 | found: | |
174 | xumount(dev); /* remove unused sticky files from text table */ | |
f93197fc | 175 | nchinval(dev); /* flush the name cache */ |
71e4e98b SL |
176 | update(); |
177 | #ifdef QUOTA | |
178 | if ((stillopen = iflush(dev, mp->m_qinod)) < 0 && !forcibly) | |
179 | #else | |
180 | if ((stillopen = iflush(dev)) < 0 && !forcibly) | |
181 | #endif | |
182 | return (EBUSY); | |
183 | if (stillopen < 0) | |
184 | return (EBUSY); /* XXX */ | |
185 | #ifdef QUOTA | |
186 | closedq(mp); | |
187 | /* | |
188 | * Here we have to iflush again to get rid of the quota inode. | |
189 | * A drag, but it would be ugly to cheat, & this doesn't happen often | |
190 | */ | |
191 | (void)iflush(dev, (struct inode *)NULL); | |
192 | #endif | |
193 | ip = mp->m_inodp; | |
194 | ip->i_flag &= ~IMOUNT; | |
195 | irele(ip); | |
196 | fs = mp->m_bufp->b_un.b_fs; | |
197 | wmemfree((caddr_t)fs->fs_csp[0], (int)fs->fs_cssize); | |
198 | flag = !fs->fs_ronly; | |
199 | brelse(mp->m_bufp); | |
200 | mp->m_bufp = 0; | |
201 | mp->m_dev = 0; | |
202 | mpurge(mp - &mount[0]); | |
203 | if (!stillopen) { | |
204 | (*bdevsw[major(dev)].d_close)(dev, flag); | |
205 | binval(dev); | |
206 | } | |
207 | return (0); | |
208 | } | |
209 | ||
210 | sbupdate(mp) | |
211 | struct mount *mp; | |
212 | { | |
213 | register struct fs *fs = mp->m_bufp->b_un.b_fs; | |
214 | register struct buf *bp; | |
215 | int blks; | |
216 | caddr_t space; | |
217 | int i, size; | |
218 | ||
219 | bp = getblk(mp->m_dev, SBLOCK, (int)fs->fs_sbsize); | |
220 | bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); | |
221 | bwrite(bp); | |
222 | blks = howmany(fs->fs_cssize, fs->fs_fsize); | |
223 | space = (caddr_t)fs->fs_csp[0]; | |
224 | for (i = 0; i < blks; i += fs->fs_frag) { | |
225 | size = fs->fs_bsize; | |
226 | if (i + fs->fs_frag > blks) | |
227 | size = (blks - i) * fs->fs_fsize; | |
228 | bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size); | |
229 | bcopy(space, bp->b_un.b_addr, (u_int)size); | |
230 | space += size; | |
231 | bwrite(bp); | |
232 | } | |
233 | } | |
234 | ||
235 | /* | |
236 | * Common code for mount and umount. | |
237 | * Check that the user's argument is a reasonable | |
238 | * thing on which to mount, and return the device number if so. | |
239 | */ | |
240 | getmdev(pdev) | |
241 | dev_t *pdev; | |
242 | { | |
243 | dev_t dev; | |
244 | register struct inode *ip; | |
245 | ||
246 | if (!suser()) | |
247 | return (u.u_error); | |
248 | ip = namei(uchar, LOOKUP, 1); | |
249 | if (ip == NULL) | |
250 | return (u.u_error); | |
e95cdf5c MK |
251 | if ((ip->i_mode&IFMT) != IFBLK) { |
252 | iput(ip); | |
71e4e98b | 253 | return (ENOTBLK); |
e95cdf5c | 254 | } |
71e4e98b | 255 | dev = (dev_t)ip->i_rdev; |
e95cdf5c | 256 | iput(ip); |
71e4e98b SL |
257 | if (major(dev) >= nblkdev) |
258 | return (ENXIO); | |
71e4e98b SL |
259 | *pdev = dev; |
260 | return (0); | |
261 | } |