Deleted Added
full compact
pseudofs_vnops.c (77967) pseudofs_vnops.c (77998)
1/*-
2 * Copyright (c) 2001 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
1/*-
2 * Copyright (c) 2001 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/fs/pseudofs/pseudofs_vnops.c 77967 2001-06-10 10:42:55Z des $
28 * $FreeBSD: head/sys/fs/pseudofs/pseudofs_vnops.c 77998 2001-06-10 18:39:21Z des $
29 */
30
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/systm.h>
34#include <sys/ctype.h>
35#include <sys/dirent.h>
36#include <sys/mount.h>

--- 37 unchanged lines hidden (view full) ---

74
75/*
76 * Get file attributes
77 */
78static int
79pfs_getattr(struct vop_getattr_args *va)
80{
81 struct vnode *vn = va->a_vp;
29 */
30
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/systm.h>
34#include <sys/ctype.h>
35#include <sys/dirent.h>
36#include <sys/mount.h>

--- 37 unchanged lines hidden (view full) ---

74
75/*
76 * Get file attributes
77 */
78static int
79pfs_getattr(struct vop_getattr_args *va)
80{
81 struct vnode *vn = va->a_vp;
82 struct pfs_node *pn = (struct pfs_node *)vn->v_data;
82 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
83 struct pfs_node *pn = pvd->pvd_pn;
83 struct vattr *vap = va->a_vap;
84
85 VATTR_NULL(vap);
86 vap->va_type = vn->v_type;
87 vap->va_mode = pn->pn_mode;
88 vap->va_fileid = pn->pn_fileno;
89 vap->va_flags = 0;
90 vap->va_blocksize = PAGE_SIZE;

--- 9 unchanged lines hidden (view full) ---

100}
101
102/*
103 * Look up a file or directory
104 */
105static int
106pfs_lookup(struct vop_lookup_args *va)
107{
84 struct vattr *vap = va->a_vap;
85
86 VATTR_NULL(vap);
87 vap->va_type = vn->v_type;
88 vap->va_mode = pn->pn_mode;
89 vap->va_fileid = pn->pn_fileno;
90 vap->va_flags = 0;
91 vap->va_blocksize = PAGE_SIZE;

--- 9 unchanged lines hidden (view full) ---

101}
102
103/*
104 * Look up a file or directory
105 */
106static int
107pfs_lookup(struct vop_lookup_args *va)
108{
108 struct vnode *dvp = va->a_dvp;
109 struct vnode *vn = va->a_dvp;
109 struct vnode **vpp = va->a_vpp;
110 struct componentname *cnp = va->a_cnp;
110 struct vnode **vpp = va->a_vpp;
111 struct componentname *cnp = va->a_cnp;
111#if 0
112 struct pfs_info *pi = (struct pfs_info *)dvp->v_mount->mnt_data;
113#endif
114 struct pfs_node *pd = (struct pfs_node *)dvp->v_data, *pn;
115 struct proc *p;
112 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
113 struct pfs_node *pd = pvd->pvd_pn;
114 struct pfs_node *pn, *pdn = NULL;
115 pid_t pid = pvd->pvd_pid;
116 char *pname;
116 char *pname;
117 int error, i;
118 pid_t pid;
117 int error, i, namelen;
119
118
120 if (dvp->v_type != VDIR)
119 if (vn->v_type != VDIR)
121 return (ENOTDIR);
122
123 /* don't support CREATE, RENAME or DELETE */
124 if (cnp->cn_nameiop != LOOKUP)
125 return (EROFS);
126
127 /* shortcut */
128 if (cnp->cn_namelen >= PFS_NAMELEN)
129 return (ENOENT);
130
131 /* self */
120 return (ENOTDIR);
121
122 /* don't support CREATE, RENAME or DELETE */
123 if (cnp->cn_nameiop != LOOKUP)
124 return (EROFS);
125
126 /* shortcut */
127 if (cnp->cn_namelen >= PFS_NAMELEN)
128 return (ENOENT);
129
130 /* self */
131 namelen = cnp->cn_namelen;
132 pname = cnp->cn_nameptr;
132 pname = cnp->cn_nameptr;
133 if (cnp->cn_namelen == 1 && *pname == '.') {
133 if (namelen == 1 && *pname == '.') {
134 pn = pd;
134 pn = pd;
135 *vpp = dvp;
136 VREF(dvp);
135 *vpp = vn;
136 VREF(vn);
137 goto got_vnode;
138 }
139
140 /* parent */
141 if (cnp->cn_flags & ISDOTDOT) {
142 if (pd->pn_type == pfstype_root)
143 return (EIO);
144 KASSERT(pd->pn_parent, ("non-root directory has no parent"));
137 goto got_vnode;
138 }
139
140 /* parent */
141 if (cnp->cn_flags & ISDOTDOT) {
142 if (pd->pn_type == pfstype_root)
143 return (EIO);
144 KASSERT(pd->pn_parent, ("non-root directory has no parent"));
145 return pfs_vncache_alloc(dvp->v_mount, vpp, pd->pn_parent);
145 /*
146 * This one is tricky. Descendents of procdir nodes
147 * inherit their parent's process affinity, but
148 * there's no easy reverse mapping. For simplicity,
149 * we assume that if this node is a procdir, its
150 * parent isn't (which is correct as long as
151 * descendents of procdir nodes are never procdir
152 * nodes themselves)
153 */
154 if (pd->pn_type == pfstype_procdir)
155 pid = NO_PID;
156 return pfs_vncache_alloc(vn->v_mount, vpp, pd->pn_parent, pid);
146 }
147
157 }
158
148 /* process dependent */
149 for (i = 0, pid = 0; i < cnp->cn_namelen && isdigit(pname[i]); ++i)
150 pid = pid * 10 + pname[i] - '0';
151 /* XXX assume that 8 digits is the maximum safe length for a pid */
152 if (i == cnp->cn_namelen && i < 8) {
153 /* see if this directory has process-dependent children */
154 for (pn = pd->pn_nodes; pn->pn_type; ++pn)
155 if (pn->pn_type == pfstype_procdep)
156 break;
157 if (pn->pn_type) {
158 /* XXX pfind(0) should DTRT here */
159 p = pid ? pfind(pid) : &proc0;
160 if (p == NULL)
161 return (ENOENT);
162 if (p_can(cnp->cn_proc, p, P_CAN_SEE, NULL)) {
163 /* pretend it doesn't exist */
164 PROC_UNLOCK(p);
165 return (ENOENT);
166 }
167#if 0
168 if (!pn->pn_shadow)
169 pfs_create_shadow(pn, p);
170 pn = pn->pn_shadow;
171 PROC_UNLOCK(p);
159 /* named node */
160 for (pn = pd->pn_nodes; pn->pn_type; ++pn)
161 if (pn->pn_type == pfstype_procdir)
162 pdn = pn;
163 else if (pn->pn_name[namelen] == '\0'
164 && bcmp(pname, pn->pn_name, namelen) == 0)
172 goto got_pnode;
165 goto got_pnode;
173#else
174 /* not yet implemented */
175 PROC_UNLOCK(p);
176 return (EIO);
177#endif
178 }
179 }
180
181 /* something else */
182 for (pn = pd->pn_nodes; pn->pn_type; ++pn) {
183 for (i = 0; i < cnp->cn_namelen && pn->pn_name[i]; ++i)
184 if (pname[i] != pn->pn_name[i])
166
167 /* process dependent node */
168 if ((pn = pdn) != NULL) {
169 pid = 0;
170 for (pid = 0, i = 0; i < namelen && isdigit(pname[i]); ++i)
171 if ((pid = pid * 10 + pname[i] - '0') > PID_MAX)
185 break;
186 if (i == cnp->cn_namelen)
187 goto got_pnode;
188 }
172 break;
173 if (i == cnp->cn_namelen)
174 goto got_pnode;
175 }
189
176
190 return (ENOENT);
191 got_pnode:
192 if (!pn->pn_parent)
193 pn->pn_parent = pd;
177 return (ENOENT);
178 got_pnode:
179 if (!pn->pn_parent)
180 pn->pn_parent = pd;
194 error = pfs_vncache_alloc(dvp->v_mount, vpp, pn);
181 error = pfs_vncache_alloc(vn->v_mount, vpp, pn, pid);
195 if (error)
196 return error;
197 got_vnode:
198 if (cnp->cn_flags & MAKEENTRY)
182 if (error)
183 return error;
184 got_vnode:
185 if (cnp->cn_flags & MAKEENTRY)
199 cache_enter(dvp, *vpp, cnp);
186 cache_enter(vn, *vpp, cnp);
200 return (0);
201}
202
203/*
204 * Open a file or directory.
205 */
206static int
207pfs_open(struct vop_open_args *va)

--- 4 unchanged lines hidden (view full) ---

212
213/*
214 * Read from a file
215 */
216static int
217pfs_read(struct vop_read_args *va)
218{
219 struct vnode *vn = va->a_vp;
187 return (0);
188}
189
190/*
191 * Open a file or directory.
192 */
193static int
194pfs_open(struct vop_open_args *va)

--- 4 unchanged lines hidden (view full) ---

199
200/*
201 * Read from a file
202 */
203static int
204pfs_read(struct vop_read_args *va)
205{
206 struct vnode *vn = va->a_vp;
220 struct pfs_node *pn = vn->v_data;
207 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
208 struct pfs_node *pn = pvd->pvd_pn;
221 struct uio *uio = va->a_uio;
209 struct uio *uio = va->a_uio;
210 struct proc *proc = NULL;
222 struct sbuf *sb = NULL;
223 char *ps;
224 int error, xlen;
225
226 if (vn->v_type != VREG)
227 return (EINVAL);
228
211 struct sbuf *sb = NULL;
212 char *ps;
213 int error, xlen;
214
215 if (vn->v_type != VREG)
216 return (EINVAL);
217
218 if (pvd->pvd_pid != NO_PID) {
219 if ((proc = pfind(pvd->pvd_pid)) == NULL)
220 return (EIO);
221 _PHOLD(proc);
222 PROC_UNLOCK(proc);
223 }
224
229 sb = sbuf_new(sb, NULL, uio->uio_offset + uio->uio_resid, 0);
225 sb = sbuf_new(sb, NULL, uio->uio_offset + uio->uio_resid, 0);
230 if (sb == NULL)
226 if (sb == NULL) {
227 if (proc != NULL)
228 PRELE(proc);
231 return (EIO);
229 return (EIO);
230 }
232
231
233 error = (pn->pn_func)(pn, curproc, sb);
232 error = (pn->pn_func)(curproc, proc, pn, sb);
233
234 if (proc != NULL)
235 PRELE(proc);
234
235 /* XXX we should possibly detect and handle overflows */
236 sbuf_finish(sb);
237 ps = sbuf_data(sb) + uio->uio_offset;
238 xlen = sbuf_len(sb) - uio->uio_offset;
239 xlen = imin(xlen, uio->uio_resid);
240 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
241 sbuf_delete(sb);
242 return (error);
243}
244
245/*
236
237 /* XXX we should possibly detect and handle overflows */
238 sbuf_finish(sb);
239 ps = sbuf_data(sb) + uio->uio_offset;
240 xlen = sbuf_len(sb) - uio->uio_offset;
241 xlen = imin(xlen, uio->uio_resid);
242 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
243 sbuf_delete(sb);
244 return (error);
245}
246
247/*
248 * Iterate through directory entries
249 */
250static int
251pfs_iterate(struct pfs_info *pi, struct pfs_node **pn, struct proc **p)
252{
253 if ((*pn)->pn_type == pfstype_none)
254 return (-1);
255
256 if ((*pn)->pn_type != pfstype_procdir)
257 ++*pn;
258
259 while ((*pn)->pn_type == pfstype_procdir) {
260 if (*p == NULL)
261 *p = LIST_FIRST(&allproc);
262 else
263 *p = LIST_NEXT(*p, p_list);
264 if (*p != NULL)
265 return (0);
266 ++*pn;
267 }
268
269 if ((*pn)->pn_type == pfstype_none)
270 return (-1);
271
272 return (0);
273}
274
275/*
246 * Return directory entries.
247 */
248static int
249pfs_readdir(struct vop_readdir_args *va)
250{
251 struct vnode *vn = va->a_vp;
276 * Return directory entries.
277 */
278static int
279pfs_readdir(struct vop_readdir_args *va)
280{
281 struct vnode *vn = va->a_vp;
252 struct pfs_info *pi;
253 struct pfs_node *pd, *pn;
282 struct pfs_info *pi = (struct pfs_info *)vn->v_mount->mnt_data;
283 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
284 struct pfs_node *pd = pvd->pvd_pn;
285 struct pfs_node *pn;
254 struct dirent entry;
255 struct uio *uio;
286 struct dirent entry;
287 struct uio *uio;
256#if 0
257 struct proc *p;
288 struct proc *p;
258#endif
259 off_t offset;
260 int error, i, resid;
261
262 if (vn->v_type != VDIR)
263 return (ENOTDIR);
289 off_t offset;
290 int error, i, resid;
291
292 if (vn->v_type != VDIR)
293 return (ENOTDIR);
264 pi = (struct pfs_info *)vn->v_mount->mnt_data;
265 pd = (struct pfs_node *)vn->v_data;
266 pn = pd->pn_nodes;
267 uio = va->a_uio;
268
269 /* only allow reading entire entries */
270 offset = uio->uio_offset;
271 resid = uio->uio_resid;
272 if (offset < 0 || offset % PFS_DELEN != 0 || resid < PFS_DELEN)
273 return (EINVAL);
274
275 /* skip unwanted entries */
294 uio = va->a_uio;
295
296 /* only allow reading entire entries */
297 offset = uio->uio_offset;
298 resid = uio->uio_resid;
299 if (offset < 0 || offset % PFS_DELEN != 0 || resid < PFS_DELEN)
300 return (EINVAL);
301
302 /* skip unwanted entries */
276 for (; pn->pn_type && offset > 0; ++pn, offset -= PFS_DELEN)
277 /* nothing */ ;
278
303 sx_slock(&allproc_lock);
304 for (pn = pd->pn_nodes, p = NULL; offset > 0; offset -= PFS_DELEN)
305 if (pfs_iterate(pi, &pn, &p) == -1)
306 break;
307
279 /* fill in entries */
280 entry.d_reclen = PFS_DELEN;
308 /* fill in entries */
309 entry.d_reclen = PFS_DELEN;
281 for (; pn->pn_type && resid > 0; ++pn) {
310 while (pfs_iterate(pi, &pn, &p) != -1 && resid > 0) {
282 if (!pn->pn_parent)
283 pn->pn_parent = pd;
284 if (!pn->pn_fileno)
285 pfs_fileno_alloc(pi, pn);
311 if (!pn->pn_parent)
312 pn->pn_parent = pd;
313 if (!pn->pn_fileno)
314 pfs_fileno_alloc(pi, pn);
286 entry.d_fileno = pn->pn_fileno;
315 if (pvd->pvd_pid != NO_PID)
316 entry.d_fileno = pn->pn_fileno * NO_PID + pvd->pvd_pid;
317 else
318 entry.d_fileno = pn->pn_fileno;
287 /* PFS_DELEN was picked to fit PFS_NAMLEN */
288 for (i = 0; i < PFS_NAMELEN - 1 && pn->pn_name[i] != '\0'; ++i)
289 entry.d_name[i] = pn->pn_name[i];
290 entry.d_name[i] = 0;
291 entry.d_namlen = i;
292 switch (pn->pn_type) {
319 /* PFS_DELEN was picked to fit PFS_NAMLEN */
320 for (i = 0; i < PFS_NAMELEN - 1 && pn->pn_name[i] != '\0'; ++i)
321 entry.d_name[i] = pn->pn_name[i];
322 entry.d_name[i] = 0;
323 entry.d_namlen = i;
324 switch (pn->pn_type) {
325 case pfstype_procdir:
326 KASSERT(p != NULL,
327 ("reached procdir node with p == NULL"));
328 entry.d_fileno = pn->pn_fileno * NO_PID + p->p_pid;
329 entry.d_namlen = snprintf(entry.d_name,
330 PFS_NAMELEN, "%d", p->p_pid);
331 /* fall through */
293 case pfstype_root:
294 case pfstype_dir:
295 case pfstype_this:
296 case pfstype_parent:
297 entry.d_type = DT_DIR;
298 break;
299 case pfstype_file:
300 entry.d_type = DT_REG;
301 break;
302 case pfstype_symlink:
303 entry.d_type = DT_LNK;
304 break;
332 case pfstype_root:
333 case pfstype_dir:
334 case pfstype_this:
335 case pfstype_parent:
336 entry.d_type = DT_DIR;
337 break;
338 case pfstype_file:
339 entry.d_type = DT_REG;
340 break;
341 case pfstype_symlink:
342 entry.d_type = DT_LNK;
343 break;
305 case pfstype_procdep:
306 /* don't handle process-dependent nodes here */
307 continue;
308 default:
344 default:
345 sx_sunlock(&allproc_lock);
309 panic("%s has unexpected node type: %d", pn->pn_name, pn->pn_type);
310 }
346 panic("%s has unexpected node type: %d", pn->pn_name, pn->pn_type);
347 }
311 if ((error = uiomove((caddr_t)&entry, PFS_DELEN, uio)))
348 if ((error = uiomove((caddr_t)&entry, PFS_DELEN, uio))) {
349 sx_sunlock(&allproc_lock);
312 return (error);
350 return (error);
351 }
313 offset += PFS_DELEN;
314 resid -= PFS_DELEN;
315 }
352 offset += PFS_DELEN;
353 resid -= PFS_DELEN;
354 }
316#if 0
317 for (pn = pd->pn_nodes; pn->pn_type && resid > 0; ++pn) {
318 if (pn->pn_type != pfstype_procdep)
319 continue;
320
321 sx_slock(&allproc_lock);
322 p = LIST_FIRST(&allproc);
323
324 sx_sunlock(&allproc_lock);
325 offset += PFS_DELEN;
326 resid -= PFS_DELEN;
327 break;
328 }
329#endif
330
355
356 sx_sunlock(&allproc_lock);
331 uio->uio_offset += offset;
332 return (0);
333}
334
335/*
336 * Read a symbolic link
337 */
338static int
339pfs_readlink(struct vop_readlink_args *va)
340{
341 struct vnode *vn = va->a_vp;
357 uio->uio_offset += offset;
358 return (0);
359}
360
361/*
362 * Read a symbolic link
363 */
364static int
365pfs_readlink(struct vop_readlink_args *va)
366{
367 struct vnode *vn = va->a_vp;
342 struct pfs_node *pn = vn->v_data;
368 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
369 struct pfs_node *pn = pvd->pvd_pn;
343 struct uio *uio = va->a_uio;
370 struct uio *uio = va->a_uio;
371 struct proc *proc = NULL;
344 char buf[MAXPATHLEN], *ps;
345 struct sbuf sb;
346 int error, xlen;
347
348 if (vn->v_type != VLNK)
349 return (EINVAL);
350
372 char buf[MAXPATHLEN], *ps;
373 struct sbuf sb;
374 int error, xlen;
375
376 if (vn->v_type != VLNK)
377 return (EINVAL);
378
379 if (pvd->pvd_pid != NO_PID) {
380 if ((proc = pfind(pvd->pvd_pid)) == NULL)
381 return (EIO);
382 _PHOLD(proc);
383 PROC_UNLOCK(proc);
384 }
385
351 /* sbuf_new() can't fail with a static buffer */
352 sbuf_new(&sb, buf, sizeof buf, 0);
353
386 /* sbuf_new() can't fail with a static buffer */
387 sbuf_new(&sb, buf, sizeof buf, 0);
388
354 error = (pn->pn_func)(pn, curproc, &sb);
389 error = (pn->pn_func)(curproc, proc, pn, &sb);
390
391 if (proc != NULL)
392 PRELE(proc);
355
356 /* XXX we should detect and handle overflows */
357 sbuf_finish(&sb);
358 ps = sbuf_data(&sb) + uio->uio_offset;
359 xlen = sbuf_len(&sb) - uio->uio_offset;
360 xlen = imin(xlen, uio->uio_resid);
361 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
362 sbuf_delete(&sb);

--- 10 unchanged lines hidden (view full) ---

373}
374
375/*
376 * Set attributes
377 */
378static int
379pfs_setattr(struct vop_setattr_args *va)
380{
393
394 /* XXX we should detect and handle overflows */
395 sbuf_finish(&sb);
396 ps = sbuf_data(&sb) + uio->uio_offset;
397 xlen = sbuf_len(&sb) - uio->uio_offset;
398 xlen = imin(xlen, uio->uio_resid);
399 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
400 sbuf_delete(&sb);

--- 10 unchanged lines hidden (view full) ---

411}
412
413/*
414 * Set attributes
415 */
416static int
417pfs_setattr(struct vop_setattr_args *va)
418{
381 if (va->a_vap->va_flags != VNOVAL)
419 if (va->a_vap->va_flags != (u_long)VNOVAL)
382 return (EOPNOTSUPP);
420 return (EOPNOTSUPP);
421 /* XXX it's a bit more complex than that, really... */
383 return (0);
384}
385
386/*
387 * Dummy operations
388 */
389static int pfs_erofs(void *va) { return (EROFS); }
390static int pfs_null(void *va) { return (0); }

--- 34 unchanged lines hidden ---
422 return (0);
423}
424
425/*
426 * Dummy operations
427 */
428static int pfs_erofs(void *va) { return (EROFS); }
429static int pfs_null(void *va) { return (0); }

--- 34 unchanged lines hidden ---