Commit | Line | Data |
---|---|---|
6764856a JSP |
1 | /* |
2 | * Copyright (c) 1992 The Regents of the University of California | |
3 | * Copyright (c) 1990, 1992 Jan-Simon Pendry | |
4 | * All rights reserved. | |
5 | * | |
6 | * This code is derived from software donated to Berkeley by | |
7 | * Jan-Simon Pendry. | |
8 | * | |
9 | * %sccs.include.redist.c% | |
10 | * | |
6681df29 | 11 | * @(#)lofs_vfsops.c 7.1 (Berkeley) %G% |
6764856a JSP |
12 | * |
13 | * $Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp jsp $ | |
14 | */ | |
15 | ||
16 | /* | |
17 | * Loopback Filesystem | |
18 | */ | |
19 | ||
20 | #include <sys/param.h> | |
21 | #include <sys/systm.h> | |
22 | #include <sys/time.h> | |
23 | #include <sys/types.h> | |
24 | #include <sys/vnode.h> | |
25 | #include <sys/mount.h> | |
26 | #include <sys/namei.h> | |
27 | #include <sys/malloc.h> | |
6681df29 | 28 | #include <miscfs/lofs/lofs.h> |
6764856a JSP |
29 | |
30 | /* | |
31 | * Mount loopback copy of existing name space | |
32 | */ | |
33 | lofs_mount(mp, path, data, ndp, p) | |
34 | struct mount *mp; | |
35 | char *path; | |
36 | caddr_t data; | |
37 | struct nameidata *ndp; | |
38 | struct proc *p; | |
39 | { | |
6764856a JSP |
40 | int error = 0; |
41 | struct lofs_args args; | |
42 | struct vnode *vp; | |
43 | struct vnode *rootvp; | |
44 | struct lofsmount *amp; | |
45 | u_int size; | |
46 | ||
47 | #ifdef LOFS_DIAGNOSTIC | |
48 | printf("lofs_mount(mp = %x)\n", mp); | |
49 | #endif | |
50 | ||
51 | /* | |
52 | * Update is a no-op | |
53 | */ | |
54 | if (mp->mnt_flag & MNT_UPDATE) { | |
55 | return (EOPNOTSUPP); | |
56 | /* return VFS_MOUNT(VFSTOLOFS(mp)->looped_vfs, path, data, ndp, p);*/ | |
57 | } | |
58 | ||
59 | /* | |
60 | * Get argument | |
61 | */ | |
62 | if (error = copyin(data, (caddr_t)&args, sizeof(struct lofs_args))) | |
63 | return (error); | |
64 | ||
65 | /* | |
66 | * Find target node | |
67 | */ | |
68 | NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, | |
69 | UIO_USERSPACE, args.target, p); | |
70 | if (error = namei(ndp)) | |
71 | return (error); | |
72 | ||
73 | /* | |
74 | * Sanity check on target vnode | |
75 | */ | |
76 | vp = ndp->ni_vp; | |
77 | #ifdef LOFS_DIAGNOSTIC | |
78 | printf("vp = %x, check for VDIR...\n", vp); | |
79 | #endif | |
80 | vrele(ndp->ni_dvp); | |
81 | ndp->ni_dvp = 0; | |
82 | ||
83 | if (vp->v_type != VDIR) { | |
84 | vput(vp); | |
85 | return (EINVAL); | |
86 | } | |
87 | ||
88 | #ifdef LOFS_DIAGNOSTIC | |
89 | printf("mp = %x\n", mp); | |
90 | #endif | |
91 | ||
92 | amp = (struct lofsmount *) malloc(sizeof(struct lofsmount), | |
93 | M_UFSMNT, M_WAITOK); /* XXX */ | |
94 | ||
95 | /* | |
96 | * Save reference to underlying target FS | |
97 | */ | |
98 | amp->looped_vfs = vp->v_mount; | |
99 | ||
100 | /* | |
101 | * Save reference. Each mount also holds | |
102 | * a reference on the root vnode. | |
103 | */ | |
104 | error = make_lofs(mp, &vp); | |
105 | /* | |
106 | * Unlock the node (either the target or the alias) | |
107 | */ | |
108 | VOP_UNLOCK(vp); | |
109 | /* | |
110 | * Make sure the node alias worked | |
111 | */ | |
112 | if (error) { | |
113 | vrele(vp); | |
114 | free(amp, M_UFSMNT); /* XXX */ | |
115 | return (error); | |
116 | } | |
117 | ||
118 | /* | |
119 | * Keep a held reference to the root vnode. | |
120 | * It is vrele'd in lofs_unmount. | |
121 | */ | |
122 | rootvp = vp; | |
123 | rootvp->v_flag |= VROOT; | |
124 | amp->rootvp = rootvp; | |
125 | if (LOFSVP(rootvp)->v_mount->mnt_flag & MNT_LOCAL) | |
126 | mp->mnt_flag |= MNT_LOCAL; | |
127 | mp->mnt_data = (qaddr_t) amp; | |
128 | getnewfsid(mp, MOUNT_LOFS); | |
129 | ||
130 | (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); | |
131 | bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); | |
132 | (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, | |
133 | &size); | |
134 | bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); | |
135 | #ifdef LOFS_DIAGNOSTIC | |
136 | printf("lofs_mount: target %s, alias at %s\n", | |
137 | mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); | |
138 | #endif | |
139 | return (0); | |
140 | } | |
141 | ||
142 | /* | |
143 | * VFS start. Nothing needed here - the start routine | |
144 | * on the underlying filesystem will have been called | |
145 | * when that filesystem was mounted. | |
146 | */ | |
147 | lofs_start(mp, flags, p) | |
148 | struct mount *mp; | |
149 | int flags; | |
150 | struct proc *p; | |
151 | { | |
152 | return (0); | |
153 | /* return VFS_START(VFSTOLOFS(mp)->looped_vfs, flags, p); */ | |
154 | } | |
155 | ||
156 | /* | |
157 | * Free reference to looped FS | |
158 | */ | |
159 | lofs_unmount(mp, mntflags, p) | |
160 | struct mount *mp; | |
161 | int mntflags; | |
162 | struct proc *p; | |
163 | { | |
164 | struct vnode *rootvp = VFSTOLOFS(mp)->rootvp; | |
165 | int error; | |
166 | int flags = 0; | |
167 | extern int doforce; | |
168 | ||
169 | #ifdef LOFS_DIAGNOSTIC | |
170 | printf("lofs_unmount(mp = %x)\n", mp); | |
171 | #endif | |
172 | ||
173 | if (mntflags & MNT_FORCE) { | |
174 | /* lofs can never be rootfs so don't check for it */ | |
175 | if (!doforce) | |
176 | return (EINVAL); | |
177 | flags |= FORCECLOSE; | |
178 | } | |
179 | ||
180 | /* | |
181 | * Clear out buffer cache. I don't think we | |
182 | * ever get anything cached at this level at the | |
183 | * moment, but who knows... | |
184 | */ | |
6764856a JSP |
185 | if (rootvp->v_usecount > 1) |
186 | return (EBUSY); | |
187 | if (error = vflush(mp, rootvp, flags)) | |
188 | return (error); | |
189 | ||
190 | #ifdef LOFS_DIAGNOSTIC | |
191 | /* | |
192 | * Flush any remaining vnode references | |
193 | */ | |
194 | lofs_flushmp(mp); | |
195 | #endif | |
196 | ||
197 | #ifdef LOFS_DIAGNOSTIC | |
198 | vprint("alias root of target", rootvp); | |
199 | #endif | |
200 | /* | |
201 | * Release reference on underlying root vnode | |
202 | */ | |
203 | vrele(rootvp); | |
204 | /* | |
205 | * And blow it away for future re-use | |
206 | */ | |
207 | vgone(rootvp); | |
208 | /* | |
209 | * Finally, throw away the lofsmount structure | |
210 | */ | |
211 | free(mp->mnt_data, M_UFSMNT); /* XXX */ | |
212 | mp->mnt_data = 0; | |
213 | return 0; | |
214 | } | |
215 | ||
216 | lofs_root(mp, vpp) | |
217 | struct mount *mp; | |
218 | struct vnode **vpp; | |
219 | { | |
6764856a JSP |
220 | struct vnode *vp; |
221 | ||
222 | #ifdef LOFS_DIAGNOSTIC | |
223 | printf("lofs_root(mp = %x, vp = %x->%x)\n", mp, | |
224 | VFSTOLOFS(mp)->rootvp, | |
225 | LOFSVP(VFSTOLOFS(mp)->rootvp) | |
226 | ); | |
227 | #endif | |
228 | ||
229 | /* | |
230 | * Return locked reference to root. | |
231 | */ | |
232 | vp = VFSTOLOFS(mp)->rootvp; | |
233 | VREF(vp); | |
234 | VOP_LOCK(vp); | |
235 | *vpp = vp; | |
236 | return 0; | |
237 | } | |
238 | ||
239 | lofs_quotactl(mp, cmd, uid, arg, p) | |
240 | struct mount *mp; | |
241 | int cmd; | |
242 | uid_t uid; | |
243 | caddr_t arg; | |
244 | struct proc *p; | |
245 | { | |
246 | return VFS_QUOTACTL(VFSTOLOFS(mp)->looped_vfs, cmd, uid, arg, p); | |
247 | } | |
248 | ||
249 | lofs_statfs(mp, sbp, p) | |
250 | struct mount *mp; | |
251 | struct statfs *sbp; | |
252 | struct proc *p; | |
253 | { | |
254 | int error; | |
255 | struct statfs mstat; | |
256 | ||
257 | #ifdef LOFS_DIAGNOSTIC | |
258 | printf("lofs_statfs(mp = %x, vp = %x->%x)\n", mp, | |
259 | VFSTOLOFS(mp)->rootvp, | |
260 | LOFSVP(VFSTOLOFS(mp)->rootvp) | |
261 | ); | |
262 | #endif | |
263 | ||
264 | bzero(&mstat, sizeof(mstat)); | |
265 | ||
266 | error = VFS_STATFS(VFSTOLOFS(mp)->looped_vfs, &mstat, p); | |
267 | if (error) | |
268 | return (error); | |
269 | ||
270 | /* now copy across the "interesting" information and fake the rest */ | |
271 | sbp->f_type = mstat.f_type; | |
272 | sbp->f_flags = mstat.f_flags; | |
273 | sbp->f_bsize = mstat.f_bsize; | |
274 | sbp->f_iosize = mstat.f_iosize; | |
275 | sbp->f_blocks = mstat.f_blocks; | |
276 | sbp->f_bfree = mstat.f_bfree; | |
277 | sbp->f_bavail = mstat.f_bavail; | |
278 | sbp->f_files = mstat.f_files; | |
279 | sbp->f_ffree = mstat.f_ffree; | |
280 | if (sbp != &mp->mnt_stat) { | |
281 | bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); | |
282 | bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); | |
283 | bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); | |
284 | } | |
285 | return (0); | |
286 | } | |
287 | ||
288 | lofs_sync(mp, waitfor) | |
289 | struct mount *mp; | |
290 | int waitfor; | |
291 | { | |
279e0ea4 | 292 | return (0); |
6764856a JSP |
293 | } |
294 | ||
e28b0770 JSP |
295 | /* |
296 | * LOFS flat namespace lookup. | |
297 | * Currently unsupported. | |
298 | */ | |
299 | lofs_vget(mp, ino, vpp) | |
6764856a | 300 | struct mount *mp; |
e28b0770 JSP |
301 | ino_t ino; |
302 | struct vnode **vpp; | |
303 | { | |
304 | ||
305 | return (EOPNOTSUPP); | |
306 | } | |
307 | ||
308 | lofs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) | |
309 | register struct mount *mp; | |
6764856a | 310 | struct fid *fhp; |
e28b0770 | 311 | struct mbuf *nam; |
6764856a | 312 | struct vnode **vpp; |
e28b0770 JSP |
313 | int *exflagsp; |
314 | struct ucred **credanonp; | |
6764856a | 315 | { |
e28b0770 | 316 | return VFS_FHTOVP(VFSTOLOFS(mp)->looped_vfs, fhp, nam, vpp, exflagsp, credanonp); |
6764856a JSP |
317 | } |
318 | ||
319 | lofs_vptofh(vp, fhp) | |
320 | struct vnode *vp; | |
321 | struct fid *fhp; | |
322 | { | |
323 | return VFS_VPTOFH(LOFSVP(vp), fhp); | |
324 | } | |
325 | ||
326 | int lofs_init __P((void)); | |
327 | ||
328 | struct vfsops lofs_vfsops = { | |
329 | lofs_mount, | |
330 | lofs_start, | |
331 | lofs_unmount, | |
332 | lofs_root, | |
333 | lofs_quotactl, | |
334 | lofs_statfs, | |
335 | lofs_sync, | |
e28b0770 | 336 | lofs_vget, |
6764856a JSP |
337 | lofs_fhtovp, |
338 | lofs_vptofh, | |
339 | lofs_init, | |
340 | }; |