Commit | Line | Data |
---|---|---|
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 | ||
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 | ||
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 */ | |
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 | ||
203 | sbupdate(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 | */ | |
233 | getmdev(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 | } |