]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/pseudofs/pseudofs_vnops.c
MFV: zstd 1.5.2
[FreeBSD/FreeBSD.git] / sys / fs / pseudofs / pseudofs_vnops.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2001 Dag-Erling Coïdan Smørgrav
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer
12  *    in this position and unchanged.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "opt_pseudofs.h"
35
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/systm.h>
39 #include <sys/ctype.h>
40 #include <sys/dirent.h>
41 #include <sys/fcntl.h>
42 #include <sys/limits.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/mount.h>
46 #include <sys/mutex.h>
47 #include <sys/namei.h>
48 #include <sys/proc.h>
49 #include <sys/sbuf.h>
50 #include <sys/sx.h>
51 #include <sys/sysctl.h>
52 #include <sys/vnode.h>
53
54 #include <fs/pseudofs/pseudofs.h>
55 #include <fs/pseudofs/pseudofs_internal.h>
56
57 #define KASSERT_PN_IS_DIR(pn)                                           \
58         KASSERT((pn)->pn_type == pfstype_root ||                        \
59             (pn)->pn_type == pfstype_dir ||                             \
60             (pn)->pn_type == pfstype_procdir,                           \
61             ("%s(): VDIR vnode refers to non-directory pfs_node", __func__))
62
63 #define KASSERT_PN_IS_FILE(pn)                                          \
64         KASSERT((pn)->pn_type == pfstype_file,                          \
65             ("%s(): VREG vnode refers to non-file pfs_node", __func__))
66
67 #define KASSERT_PN_IS_LINK(pn)                                          \
68         KASSERT((pn)->pn_type == pfstype_symlink,                       \
69             ("%s(): VLNK vnode refers to non-link pfs_node", __func__))
70
71 #define PFS_MAXBUFSIZ           1024 * 1024
72
73 /*
74  * Returns the fileno, adjusted for target pid
75  */
76 static uint32_t
77 pn_fileno(struct pfs_node *pn, pid_t pid)
78 {
79
80         KASSERT(pn->pn_fileno > 0,
81             ("%s(): no fileno allocated", __func__));
82         if (pid != NO_PID)
83                 return (pn->pn_fileno * NO_PID + pid);
84         return (pn->pn_fileno);
85 }
86
87 /*
88  * Returns non-zero if given file is visible to given thread.
89  */
90 static int
91 pfs_visible_proc(struct thread *td, struct pfs_node *pn, struct proc *proc)
92 {
93         int visible;
94
95         if (proc == NULL)
96                 return (0);
97
98         PROC_LOCK_ASSERT(proc, MA_OWNED);
99
100         visible = ((proc->p_flag & P_WEXIT) == 0);
101         if (visible)
102                 visible = (p_cansee(td, proc) == 0);
103         if (visible && pn->pn_vis != NULL)
104                 visible = pn_vis(td, proc, pn);
105         if (!visible)
106                 return (0);
107         return (1);
108 }
109
110 static int
111 pfs_visible(struct thread *td, struct pfs_node *pn, pid_t pid,
112     struct proc **p)
113 {
114         struct proc *proc;
115
116         PFS_TRACE(("%s (pid: %d, req: %d)",
117             pn->pn_name, pid, td->td_proc->p_pid));
118
119         if (p)
120                 *p = NULL;
121         if (pid == NO_PID)
122                 PFS_RETURN (1);
123         proc = pfind(pid);
124         if (proc == NULL)
125                 PFS_RETURN (0);
126         if (pfs_visible_proc(td, pn, proc)) {
127                 if (p)
128                         *p = proc;
129                 else
130                         PROC_UNLOCK(proc);
131                 PFS_RETURN (1);
132         }
133         PROC_UNLOCK(proc);
134         PFS_RETURN (0);
135 }
136
137 static int
138 pfs_lookup_proc(pid_t pid, struct proc **p)
139 {
140         struct proc *proc;
141
142         proc = pfind(pid);
143         if (proc == NULL)
144                 return (0);
145         if ((proc->p_flag & P_WEXIT) != 0) {
146                 PROC_UNLOCK(proc);
147                 return (0);
148         }
149         _PHOLD(proc);
150         PROC_UNLOCK(proc);
151         *p = proc;
152         return (1);
153 }
154
155 /*
156  * Verify permissions
157  */
158 static int
159 pfs_access(struct vop_access_args *va)
160 {
161         struct vnode *vn = va->a_vp;
162         struct pfs_vdata *pvd = vn->v_data;
163         struct vattr vattr;
164         int error;
165
166         PFS_TRACE(("%s", pvd->pvd_pn->pn_name));
167         (void)pvd;
168
169         error = VOP_GETATTR(vn, &vattr, va->a_cred);
170         if (error)
171                 PFS_RETURN (error);
172         error = vaccess(vn->v_type, vattr.va_mode, vattr.va_uid, vattr.va_gid,
173             va->a_accmode, va->a_cred);
174         PFS_RETURN (error);
175 }
176
177 /*
178  * Close a file or directory
179  */
180 static int
181 pfs_close(struct vop_close_args *va)
182 {
183         struct vnode *vn = va->a_vp;
184         struct pfs_vdata *pvd = vn->v_data;
185         struct pfs_node *pn = pvd->pvd_pn;
186         struct proc *proc;
187         int error;
188
189         PFS_TRACE(("%s", pn->pn_name));
190         pfs_assert_not_owned(pn);
191
192         /*
193          * Do nothing unless this is the last close and the node has a
194          * last-close handler.
195          */
196         if (vrefcnt(vn) > 1 || pn->pn_close == NULL)
197                 PFS_RETURN (0);
198
199         if (pvd->pvd_pid != NO_PID) {
200                 proc = pfind(pvd->pvd_pid);
201         } else {
202                 proc = NULL;
203         }
204
205         error = pn_close(va->a_td, proc, pn);
206
207         if (proc != NULL)
208                 PROC_UNLOCK(proc);
209
210         PFS_RETURN (error);
211 }
212
213 /*
214  * Get file attributes
215  */
216 static int
217 pfs_getattr(struct vop_getattr_args *va)
218 {
219         struct vnode *vn = va->a_vp;
220         struct pfs_vdata *pvd = vn->v_data;
221         struct pfs_node *pn = pvd->pvd_pn;
222         struct vattr *vap = va->a_vap;
223         struct proc *proc;
224         int error = 0;
225
226         PFS_TRACE(("%s", pn->pn_name));
227         pfs_assert_not_owned(pn);
228
229         if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc))
230                 PFS_RETURN (ENOENT);
231
232         vap->va_type = vn->v_type;
233         vap->va_fileid = pn_fileno(pn, pvd->pvd_pid);
234         vap->va_flags = 0;
235         vap->va_blocksize = PAGE_SIZE;
236         vap->va_bytes = vap->va_size = 0;
237         vap->va_filerev = 0;
238         vap->va_fsid = vn->v_mount->mnt_stat.f_fsid.val[0];
239         vap->va_nlink = 1;
240         nanotime(&vap->va_ctime);
241         vap->va_atime = vap->va_mtime = vap->va_ctime;
242
243         switch (pn->pn_type) {
244         case pfstype_procdir:
245         case pfstype_root:
246         case pfstype_dir:
247 #if 0
248                 pfs_lock(pn);
249                 /* compute link count */
250                 pfs_unlock(pn);
251 #endif
252                 vap->va_mode = 0555;
253                 break;
254         case pfstype_file:
255         case pfstype_symlink:
256                 vap->va_mode = 0444;
257                 break;
258         default:
259                 printf("shouldn't be here!\n");
260                 vap->va_mode = 0;
261                 break;
262         }
263
264         if (proc != NULL) {
265                 vap->va_uid = proc->p_ucred->cr_ruid;
266                 vap->va_gid = proc->p_ucred->cr_rgid;
267         } else {
268                 vap->va_uid = 0;
269                 vap->va_gid = 0;
270         }
271
272         if (pn->pn_attr != NULL)
273                 error = pn_attr(curthread, proc, pn, vap);
274
275         if(proc != NULL)
276                 PROC_UNLOCK(proc);
277
278         PFS_RETURN (error);
279 }
280
281 /*
282  * Perform an ioctl
283  */
284 static int
285 pfs_ioctl(struct vop_ioctl_args *va)
286 {
287         struct vnode *vn;
288         struct pfs_vdata *pvd;
289         struct pfs_node *pn;
290         struct proc *proc;
291         int error;
292
293         vn = va->a_vp;
294         vn_lock(vn, LK_SHARED | LK_RETRY);
295         if (VN_IS_DOOMED(vn)) {
296                 VOP_UNLOCK(vn);
297                 return (EBADF);
298         }
299         pvd = vn->v_data;
300         pn = pvd->pvd_pn;
301
302         PFS_TRACE(("%s: %lx", pn->pn_name, va->a_command));
303         pfs_assert_not_owned(pn);
304
305         if (vn->v_type != VREG) {
306                 VOP_UNLOCK(vn);
307                 PFS_RETURN (EINVAL);
308         }
309         KASSERT_PN_IS_FILE(pn);
310
311         if (pn->pn_ioctl == NULL) {
312                 VOP_UNLOCK(vn);
313                 PFS_RETURN (ENOTTY);
314         }
315
316         /*
317          * This is necessary because process' privileges may
318          * have changed since the open() call.
319          */
320         if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) {
321                 VOP_UNLOCK(vn);
322                 PFS_RETURN (EIO);
323         }
324
325         error = pn_ioctl(curthread, proc, pn, va->a_command, va->a_data);
326
327         if (proc != NULL)
328                 PROC_UNLOCK(proc);
329
330         VOP_UNLOCK(vn);
331         PFS_RETURN (error);
332 }
333
334 /*
335  * Perform getextattr
336  */
337 static int
338 pfs_getextattr(struct vop_getextattr_args *va)
339 {
340         struct vnode *vn = va->a_vp;
341         struct pfs_vdata *pvd = vn->v_data;
342         struct pfs_node *pn = pvd->pvd_pn;
343         struct proc *proc;
344         int error;
345
346         PFS_TRACE(("%s", pn->pn_name));
347         pfs_assert_not_owned(pn);
348
349         /*
350          * This is necessary because either process' privileges may
351          * have changed since the open() call.
352          */
353         if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc))
354                 PFS_RETURN (EIO);
355
356         if (pn->pn_getextattr == NULL)
357                 error = EOPNOTSUPP;
358         else
359                 error = pn_getextattr(curthread, proc, pn,
360                     va->a_attrnamespace, va->a_name, va->a_uio,
361                     va->a_size, va->a_cred);
362
363         if (proc != NULL)
364                 PROC_UNLOCK(proc);
365
366         PFS_RETURN (error);
367 }
368
369 /*
370  * Convert a vnode to its component name
371  */
372 static int
373 pfs_vptocnp(struct vop_vptocnp_args *ap)
374 {
375         struct vnode *vp = ap->a_vp;
376         struct vnode **dvp = ap->a_vpp;
377         struct pfs_vdata *pvd = vp->v_data;
378         struct pfs_node *pd = pvd->pvd_pn;
379         struct pfs_node *pn;
380         struct mount *mp;
381         char *buf = ap->a_buf;
382         size_t *buflen = ap->a_buflen;
383         char pidbuf[PFS_NAMELEN];
384         pid_t pid = pvd->pvd_pid;
385         int len, i, error, locked;
386
387         i = *buflen;
388         error = 0;
389
390         pfs_lock(pd);
391
392         if (vp->v_type == VDIR && pd->pn_type == pfstype_root) {
393                 *dvp = vp;
394                 vhold(*dvp);
395                 pfs_unlock(pd);
396                 PFS_RETURN (0);
397         } else if (vp->v_type == VDIR && pd->pn_type == pfstype_procdir) {
398                 len = snprintf(pidbuf, sizeof(pidbuf), "%d", pid);
399                 i -= len;
400                 if (i < 0) {
401                         error = ENOMEM;
402                         goto failed;
403                 }
404                 bcopy(pidbuf, buf + i, len);
405         } else {
406                 len = strlen(pd->pn_name);
407                 i -= len;
408                 if (i < 0) {
409                         error = ENOMEM;
410                         goto failed;
411                 }
412                 bcopy(pd->pn_name, buf + i, len);
413         }
414
415         pn = pd->pn_parent;
416         pfs_unlock(pd);
417
418         mp = vp->v_mount;
419         error = vfs_busy(mp, 0);
420         if (error)
421                 return (error);
422
423         /*
424          * vp is held by caller.
425          */
426         locked = VOP_ISLOCKED(vp);
427         VOP_UNLOCK(vp);
428
429         error = pfs_vncache_alloc(mp, dvp, pn, pid);
430         if (error) {
431                 vn_lock(vp, locked | LK_RETRY);
432                 vfs_unbusy(mp);
433                 PFS_RETURN(error);
434         }
435
436         *buflen = i;
437         VOP_UNLOCK(*dvp);
438         vn_lock(vp, locked | LK_RETRY);
439         vfs_unbusy(mp);
440
441         PFS_RETURN (0);
442 failed:
443         pfs_unlock(pd);
444         PFS_RETURN(error);
445 }
446
447 /*
448  * Look up a file or directory
449  */
450 static int
451 pfs_lookup(struct vop_cachedlookup_args *va)
452 {
453         struct vnode *vn = va->a_dvp;
454         struct vnode **vpp = va->a_vpp;
455         struct componentname *cnp = va->a_cnp;
456         struct pfs_vdata *pvd = vn->v_data;
457         struct pfs_node *pd = pvd->pvd_pn;
458         struct pfs_node *pn, *pdn = NULL;
459         struct mount *mp;
460         pid_t pid = pvd->pvd_pid;
461         char *pname;
462         int error, i, namelen, visible;
463
464         PFS_TRACE(("%.*s", (int)cnp->cn_namelen, cnp->cn_nameptr));
465         pfs_assert_not_owned(pd);
466
467         if (vn->v_type != VDIR)
468                 PFS_RETURN (ENOTDIR);
469         KASSERT_PN_IS_DIR(pd);
470
471         /*
472          * Don't support DELETE or RENAME.  CREATE is supported so
473          * that O_CREAT will work, but the lookup will still fail if
474          * the file does not exist.
475          */
476         if ((cnp->cn_flags & ISLASTCN) &&
477             (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
478                 PFS_RETURN (EOPNOTSUPP);
479
480         /* shortcut: check if the name is too long */
481         if (cnp->cn_namelen >= PFS_NAMELEN)
482                 PFS_RETURN (ENOENT);
483
484         /* check that parent directory is visible... */
485         if (!pfs_visible(curthread, pd, pvd->pvd_pid, NULL))
486                 PFS_RETURN (ENOENT);
487
488         /* self */
489         namelen = cnp->cn_namelen;
490         pname = cnp->cn_nameptr;
491         if (namelen == 1 && pname[0] == '.') {
492                 pn = pd;
493                 *vpp = vn;
494                 VREF(vn);
495                 PFS_RETURN (0);
496         }
497
498         mp = vn->v_mount;
499
500         /* parent */
501         if (cnp->cn_flags & ISDOTDOT) {
502                 if (pd->pn_type == pfstype_root)
503                         PFS_RETURN (EIO);
504                 error = vfs_busy(mp, MBF_NOWAIT);
505                 if (error != 0) {
506                         vfs_ref(mp);
507                         VOP_UNLOCK(vn);
508                         error = vfs_busy(mp, 0);
509                         vn_lock(vn, LK_EXCLUSIVE | LK_RETRY);
510                         vfs_rel(mp);
511                         if (error != 0)
512                                 PFS_RETURN(ENOENT);
513                         if (VN_IS_DOOMED(vn)) {
514                                 vfs_unbusy(mp);
515                                 PFS_RETURN(ENOENT);
516                         }
517                 }
518                 VOP_UNLOCK(vn);
519                 KASSERT(pd->pn_parent != NULL,
520                     ("%s(): non-root directory has no parent", __func__));
521                 /*
522                  * This one is tricky.  Descendents of procdir nodes
523                  * inherit their parent's process affinity, but
524                  * there's no easy reverse mapping.  For simplicity,
525                  * we assume that if this node is a procdir, its
526                  * parent isn't (which is correct as long as
527                  * descendents of procdir nodes are never procdir
528                  * nodes themselves)
529                  */
530                 if (pd->pn_type == pfstype_procdir)
531                         pid = NO_PID;
532                 pfs_lock(pd);
533                 pn = pd->pn_parent;
534                 pfs_unlock(pd);
535                 goto got_pnode;
536         }
537
538         pfs_lock(pd);
539
540         /* named node */
541         for (pn = pd->pn_nodes; pn != NULL; pn = pn->pn_next)
542                 if (pn->pn_type == pfstype_procdir)
543                         pdn = pn;
544                 else if (pn->pn_name[namelen] == '\0' &&
545                     bcmp(pname, pn->pn_name, namelen) == 0) {
546                         pfs_unlock(pd);
547                         goto got_pnode;
548                 }
549
550         /* process dependent node */
551         if ((pn = pdn) != NULL) {
552                 pid = 0;
553                 for (pid = 0, i = 0; i < namelen && isdigit(pname[i]); ++i)
554                         if ((pid = pid * 10 + pname[i] - '0') > PID_MAX)
555                                 break;
556                 if (i == cnp->cn_namelen) {
557                         pfs_unlock(pd);
558                         goto got_pnode;
559                 }
560         }
561
562         pfs_unlock(pd);
563
564         PFS_RETURN (ENOENT);
565
566  got_pnode:
567         pfs_assert_not_owned(pd);
568         pfs_assert_not_owned(pn);
569         visible = pfs_visible(curthread, pn, pid, NULL);
570         if (!visible) {
571                 error = ENOENT;
572                 goto failed;
573         }
574
575         error = pfs_vncache_alloc(mp, vpp, pn, pid);
576         if (error)
577                 goto failed;
578
579         if (cnp->cn_flags & ISDOTDOT) {
580                 vfs_unbusy(mp);
581                 vn_lock(vn, LK_EXCLUSIVE | LK_RETRY);
582                 if (VN_IS_DOOMED(vn)) {
583                         vput(*vpp);
584                         *vpp = NULL;
585                         PFS_RETURN(ENOENT);
586                 }
587         }
588         if (cnp->cn_flags & MAKEENTRY && !VN_IS_DOOMED(vn))
589                 cache_enter(vn, *vpp, cnp);
590         PFS_RETURN (0);
591  failed:
592         if (cnp->cn_flags & ISDOTDOT) {
593                 vfs_unbusy(mp);
594                 vn_lock(vn, LK_EXCLUSIVE | LK_RETRY);
595                 *vpp = NULL;
596         }
597         PFS_RETURN(error);
598 }
599
600 /*
601  * Open a file or directory.
602  */
603 static int
604 pfs_open(struct vop_open_args *va)
605 {
606         struct vnode *vn = va->a_vp;
607         struct pfs_vdata *pvd = vn->v_data;
608         struct pfs_node *pn = pvd->pvd_pn;
609         int mode = va->a_mode;
610
611         PFS_TRACE(("%s (mode 0x%x)", pn->pn_name, mode));
612         pfs_assert_not_owned(pn);
613
614         /* check if the requested mode is permitted */
615         if (((mode & FREAD) && !(mode & PFS_RD)) ||
616             ((mode & FWRITE) && !(mode & PFS_WR)))
617                 PFS_RETURN (EPERM);
618
619         /* we don't support locking */
620         if ((mode & O_SHLOCK) || (mode & O_EXLOCK))
621                 PFS_RETURN (EOPNOTSUPP);
622
623         PFS_RETURN (0);
624 }
625
626 struct sbuf_seek_helper {
627         off_t           skip_bytes;
628         struct uio      *uio;
629 };
630
631 static int
632 pfs_sbuf_uio_drain(void *arg, const char *data, int len)
633 {
634         struct sbuf_seek_helper *ssh;
635         struct uio *uio;
636         int error, skipped;
637
638         ssh = arg;
639         uio = ssh->uio;
640         skipped = 0;
641
642         /* Need to discard first uio_offset bytes. */
643         if (ssh->skip_bytes > 0) {
644                 if (ssh->skip_bytes >= len) {
645                         ssh->skip_bytes -= len;
646                         return (len);
647                 }
648
649                 data += ssh->skip_bytes;
650                 len -= ssh->skip_bytes;
651                 skipped = ssh->skip_bytes;
652                 ssh->skip_bytes = 0;
653         }
654
655         error = uiomove(__DECONST(void *, data), len, uio);
656         if (error != 0)
657                 return (-error);
658
659         /*
660          * The fill function has more to emit, but the reader is finished.
661          * This is similar to the truncated read case for non-draining PFS
662          * sbufs, and should be handled appropriately in fill-routines.
663          */
664         if (uio->uio_resid == 0)
665                 return (-ENOBUFS);
666
667         return (skipped + len);
668 }
669
670 /*
671  * Read from a file
672  */
673 static int
674 pfs_read(struct vop_read_args *va)
675 {
676         struct vnode *vn = va->a_vp;
677         struct pfs_vdata *pvd = vn->v_data;
678         struct pfs_node *pn = pvd->pvd_pn;
679         struct uio *uio = va->a_uio;
680         struct proc *proc;
681         struct sbuf *sb = NULL;
682         int error, locked;
683         off_t buflen, buflim;
684         struct sbuf_seek_helper ssh;
685
686         PFS_TRACE(("%s", pn->pn_name));
687         pfs_assert_not_owned(pn);
688
689         if (vn->v_type != VREG)
690                 PFS_RETURN (EINVAL);
691         KASSERT_PN_IS_FILE(pn);
692
693         if (!(pn->pn_flags & PFS_RD))
694                 PFS_RETURN (EBADF);
695
696         if (pn->pn_fill == NULL)
697                 PFS_RETURN (EIO);
698
699         /*
700          * This is necessary because either process' privileges may
701          * have changed since the open() call.
702          */
703         if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc))
704                 PFS_RETURN (EIO);
705         if (proc != NULL) {
706                 _PHOLD(proc);
707                 PROC_UNLOCK(proc);
708         }
709
710         vhold(vn);
711         locked = VOP_ISLOCKED(vn);
712         VOP_UNLOCK(vn);
713
714         if (pn->pn_flags & PFS_RAWRD) {
715                 PFS_TRACE(("%zd resid", uio->uio_resid));
716                 error = pn_fill(curthread, proc, pn, NULL, uio);
717                 PFS_TRACE(("%zd resid", uio->uio_resid));
718                 goto ret;
719         }
720
721         if (uio->uio_resid < 0 || uio->uio_offset < 0 ||
722             uio->uio_resid > OFF_MAX - uio->uio_offset) {
723                 error = EINVAL;
724                 goto ret;
725         }
726         buflen = uio->uio_offset + uio->uio_resid + 1;
727         if (pn->pn_flags & PFS_AUTODRAIN)
728                 /*
729                  * We can use a smaller buffer if we can stream output to the
730                  * consumer.
731                  */
732                 buflim = PAGE_SIZE;
733         else
734                 buflim = PFS_MAXBUFSIZ;
735         if (buflen > buflim)
736                 buflen = buflim;
737
738         sb = sbuf_new(sb, NULL, buflen, 0);
739         if (sb == NULL) {
740                 error = EIO;
741                 goto ret;
742         }
743
744         if (pn->pn_flags & PFS_AUTODRAIN) {
745                 ssh.skip_bytes = uio->uio_offset;
746                 ssh.uio = uio;
747                 sbuf_set_drain(sb, pfs_sbuf_uio_drain, &ssh);
748         }
749
750         error = pn_fill(curthread, proc, pn, sb, uio);
751
752         if (error) {
753                 sbuf_delete(sb);
754                 goto ret;
755         }
756
757         /*
758          * XXX: If the buffer overflowed, sbuf_len() will not return
759          * the data length. Then just use the full length because an
760          * overflowed sbuf must be full.
761          */
762         error = sbuf_finish(sb);
763         if ((pn->pn_flags & PFS_AUTODRAIN)) {
764                 /*
765                  * ENOBUFS just indicates early termination of the fill
766                  * function as the caller's buffer was already filled.  Squash
767                  * to zero.
768                  */
769                 if (uio->uio_resid == 0 && error == ENOBUFS)
770                         error = 0;
771         } else {
772                 if (error == 0)
773                         buflen = sbuf_len(sb);
774                 else
775                         /* The trailing byte is not valid. */
776                         buflen--;
777                 error = uiomove_frombuf(sbuf_data(sb), buflen, uio);
778         }
779         sbuf_delete(sb);
780 ret:
781         vn_lock(vn, locked | LK_RETRY);
782         vdrop(vn);
783         if (proc != NULL)
784                 PRELE(proc);
785         PFS_RETURN (error);
786 }
787
788 /*
789  * Iterate through directory entries
790  */
791 static int
792 pfs_iterate(struct thread *td, struct proc *proc, struct pfs_node *pd,
793             struct pfs_node **pn, struct proc **p)
794 {
795         int visible;
796
797         sx_assert(&allproc_lock, SX_SLOCKED);
798         pfs_assert_owned(pd);
799  again:
800         if (*pn == NULL) {
801                 /* first node */
802                 *pn = pd->pn_nodes;
803         } else if ((*pn)->pn_type != pfstype_procdir) {
804                 /* next node */
805                 *pn = (*pn)->pn_next;
806         }
807         if (*pn != NULL && (*pn)->pn_type == pfstype_procdir) {
808                 /* next process */
809                 if (*p == NULL)
810                         *p = LIST_FIRST(&allproc);
811                 else
812                         *p = LIST_NEXT(*p, p_list);
813                 /* out of processes: next node */
814                 if (*p == NULL)
815                         *pn = (*pn)->pn_next;
816                 else
817                         PROC_LOCK(*p);
818         }
819
820         if ((*pn) == NULL)
821                 return (-1);
822
823         if (*p != NULL) {
824                 visible = pfs_visible_proc(td, *pn, *p);
825                 PROC_UNLOCK(*p);
826         } else if (proc != NULL) {
827                 visible = pfs_visible_proc(td, *pn, proc);
828         } else {
829                 visible = 1;
830         }
831         if (!visible)
832                 goto again;
833
834         return (0);
835 }
836
837 /* Directory entry list */
838 struct pfsentry {
839         STAILQ_ENTRY(pfsentry)  link;
840         struct dirent           entry;
841 };
842 STAILQ_HEAD(pfsdirentlist, pfsentry);
843
844 /*
845  * Return directory entries.
846  */
847 static int
848 pfs_readdir(struct vop_readdir_args *va)
849 {
850         struct vnode *vn = va->a_vp;
851         struct pfs_vdata *pvd = vn->v_data;
852         struct pfs_node *pd = pvd->pvd_pn;
853         pid_t pid = pvd->pvd_pid;
854         struct proc *p, *proc;
855         struct pfs_node *pn;
856         struct uio *uio;
857         struct pfsentry *pfsent, *pfsent2;
858         struct pfsdirentlist lst;
859         off_t offset;
860         int error, i, resid;
861
862         STAILQ_INIT(&lst);
863         error = 0;
864         KASSERT(pd->pn_info == vn->v_mount->mnt_data,
865             ("%s(): pn_info does not match mountpoint", __func__));
866         PFS_TRACE(("%s pid %lu", pd->pn_name, (unsigned long)pid));
867         pfs_assert_not_owned(pd);
868
869         if (vn->v_type != VDIR)
870                 PFS_RETURN (ENOTDIR);
871         KASSERT_PN_IS_DIR(pd);
872         uio = va->a_uio;
873
874         /* only allow reading entire entries */
875         offset = uio->uio_offset;
876         resid = uio->uio_resid;
877         if (offset < 0 || offset % PFS_DELEN != 0 ||
878             (resid && resid < PFS_DELEN))
879                 PFS_RETURN (EINVAL);
880         if (resid == 0)
881                 PFS_RETURN (0);
882
883         proc = NULL;
884         if (pid != NO_PID && !pfs_lookup_proc(pid, &proc))
885                 PFS_RETURN (ENOENT);
886
887         sx_slock(&allproc_lock);
888         pfs_lock(pd);
889
890         KASSERT(pid == NO_PID || proc != NULL,
891             ("%s(): no process for pid %lu", __func__, (unsigned long)pid));
892
893         if (pid != NO_PID) {
894                 PROC_LOCK(proc);
895
896                 /* check if the directory is visible to the caller */
897                 if (!pfs_visible_proc(curthread, pd, proc)) {
898                         _PRELE(proc);
899                         PROC_UNLOCK(proc);
900                         sx_sunlock(&allproc_lock);
901                         pfs_unlock(pd);
902                         PFS_RETURN (ENOENT);
903                 }
904         }
905
906         /* skip unwanted entries */
907         for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN) {
908                 if (pfs_iterate(curthread, proc, pd, &pn, &p) == -1) {
909                         /* nothing left... */
910                         if (proc != NULL) {
911                                 _PRELE(proc);
912                                 PROC_UNLOCK(proc);
913                         }
914                         pfs_unlock(pd);
915                         sx_sunlock(&allproc_lock);
916                         PFS_RETURN (0);
917                 }
918         }
919
920         /* fill in entries */
921         while (pfs_iterate(curthread, proc, pd, &pn, &p) != -1 &&
922             resid >= PFS_DELEN) {
923                 if ((pfsent = malloc(sizeof(struct pfsentry), M_IOV,
924                     M_NOWAIT | M_ZERO)) == NULL) {
925                         error = ENOMEM;
926                         break;
927                 }
928                 pfsent->entry.d_reclen = PFS_DELEN;
929                 pfsent->entry.d_fileno = pn_fileno(pn, pid);
930                 /* PFS_DELEN was picked to fit PFS_NAMLEN */
931                 for (i = 0; i < PFS_NAMELEN - 1 && pn->pn_name[i] != '\0'; ++i)
932                         pfsent->entry.d_name[i] = pn->pn_name[i];
933                 pfsent->entry.d_namlen = i;
934                 /* NOTE: d_off is the offset of the *next* entry. */
935                 pfsent->entry.d_off = offset + PFS_DELEN;
936                 switch (pn->pn_type) {
937                 case pfstype_procdir:
938                         KASSERT(p != NULL,
939                             ("reached procdir node with p == NULL"));
940                         pfsent->entry.d_namlen = snprintf(pfsent->entry.d_name,
941                             PFS_NAMELEN, "%d", p->p_pid);
942                         /* fall through */
943                 case pfstype_root:
944                 case pfstype_dir:
945                 case pfstype_this:
946                 case pfstype_parent:
947                         pfsent->entry.d_type = DT_DIR;
948                         break;
949                 case pfstype_file:
950                         pfsent->entry.d_type = DT_REG;
951                         break;
952                 case pfstype_symlink:
953                         pfsent->entry.d_type = DT_LNK;
954                         break;
955                 default:
956                         panic("%s has unexpected node type: %d", pn->pn_name, pn->pn_type);
957                 }
958                 PFS_TRACE(("%s", pfsent->entry.d_name));
959                 dirent_terminate(&pfsent->entry);
960                 STAILQ_INSERT_TAIL(&lst, pfsent, link);
961                 offset += PFS_DELEN;
962                 resid -= PFS_DELEN;
963         }
964         if (proc != NULL) {
965                 _PRELE(proc);
966                 PROC_UNLOCK(proc);
967         }
968         pfs_unlock(pd);
969         sx_sunlock(&allproc_lock);
970         i = 0;
971         STAILQ_FOREACH_SAFE(pfsent, &lst, link, pfsent2) {
972                 if (error == 0)
973                         error = uiomove(&pfsent->entry, PFS_DELEN, uio);
974                 free(pfsent, M_IOV);
975                 i++;
976         }
977         PFS_TRACE(("%ju bytes", (uintmax_t)(i * PFS_DELEN)));
978         PFS_RETURN (error);
979 }
980
981 /*
982  * Read a symbolic link
983  */
984 static int
985 pfs_readlink(struct vop_readlink_args *va)
986 {
987         struct vnode *vn = va->a_vp;
988         struct pfs_vdata *pvd = vn->v_data;
989         struct pfs_node *pn = pvd->pvd_pn;
990         struct uio *uio = va->a_uio;
991         struct proc *proc = NULL;
992         char buf[PATH_MAX];
993         struct sbuf sb;
994         int error, locked;
995
996         PFS_TRACE(("%s", pn->pn_name));
997         pfs_assert_not_owned(pn);
998
999         if (vn->v_type != VLNK)
1000                 PFS_RETURN (EINVAL);
1001         KASSERT_PN_IS_LINK(pn);
1002
1003         if (pn->pn_fill == NULL)
1004                 PFS_RETURN (EIO);
1005
1006         if (pvd->pvd_pid != NO_PID) {
1007                 if ((proc = pfind(pvd->pvd_pid)) == NULL)
1008                         PFS_RETURN (EIO);
1009                 if (proc->p_flag & P_WEXIT) {
1010                         PROC_UNLOCK(proc);
1011                         PFS_RETURN (EIO);
1012                 }
1013                 _PHOLD(proc);
1014                 PROC_UNLOCK(proc);
1015         }
1016         vhold(vn);
1017         locked = VOP_ISLOCKED(vn);
1018         VOP_UNLOCK(vn);
1019
1020         /* sbuf_new() can't fail with a static buffer */
1021         sbuf_new(&sb, buf, sizeof buf, 0);
1022
1023         error = pn_fill(curthread, proc, pn, &sb, NULL);
1024
1025         if (proc != NULL)
1026                 PRELE(proc);
1027         vn_lock(vn, locked | LK_RETRY);
1028         vdrop(vn);
1029
1030         if (error) {
1031                 sbuf_delete(&sb);
1032                 PFS_RETURN (error);
1033         }
1034
1035         if (sbuf_finish(&sb) != 0) {
1036                 sbuf_delete(&sb);
1037                 PFS_RETURN (ENAMETOOLONG);
1038         }
1039
1040         error = uiomove_frombuf(sbuf_data(&sb), sbuf_len(&sb), uio);
1041         sbuf_delete(&sb);
1042         PFS_RETURN (error);
1043 }
1044
1045 /*
1046  * Reclaim a vnode
1047  */
1048 static int
1049 pfs_reclaim(struct vop_reclaim_args *va)
1050 {
1051         struct vnode *vn = va->a_vp;
1052         struct pfs_vdata *pvd = vn->v_data;
1053         struct pfs_node *pn = pvd->pvd_pn;
1054
1055         PFS_TRACE(("%s", pn->pn_name));
1056         pfs_assert_not_owned(pn);
1057
1058         return (pfs_vncache_free(va->a_vp));
1059 }
1060
1061 /*
1062  * Set attributes
1063  */
1064 static int
1065 pfs_setattr(struct vop_setattr_args *va)
1066 {
1067         struct vnode *vn = va->a_vp;
1068         struct pfs_vdata *pvd = vn->v_data;
1069         struct pfs_node *pn = pvd->pvd_pn;
1070
1071         PFS_TRACE(("%s", pn->pn_name));
1072         pfs_assert_not_owned(pn);
1073
1074         /* Silently ignore unchangeable attributes. */
1075         PFS_RETURN (0);
1076 }
1077
1078 /*
1079  * Write to a file
1080  */
1081 static int
1082 pfs_write(struct vop_write_args *va)
1083 {
1084         struct vnode *vn = va->a_vp;
1085         struct pfs_vdata *pvd = vn->v_data;
1086         struct pfs_node *pn = pvd->pvd_pn;
1087         struct uio *uio = va->a_uio;
1088         struct proc *proc;
1089         struct sbuf sb;
1090         int error;
1091
1092         PFS_TRACE(("%s", pn->pn_name));
1093         pfs_assert_not_owned(pn);
1094
1095         if (vn->v_type != VREG)
1096                 PFS_RETURN (EINVAL);
1097         KASSERT_PN_IS_FILE(pn);
1098
1099         if (!(pn->pn_flags & PFS_WR))
1100                 PFS_RETURN (EBADF);
1101
1102         if (pn->pn_fill == NULL)
1103                 PFS_RETURN (EIO);
1104
1105         if (uio->uio_resid > PFS_MAXBUFSIZ)
1106                 PFS_RETURN (EIO);
1107
1108         /*
1109          * This is necessary because either process' privileges may
1110          * have changed since the open() call.
1111          */
1112         if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc))
1113                 PFS_RETURN (EIO);
1114         if (proc != NULL) {
1115                 _PHOLD(proc);
1116                 PROC_UNLOCK(proc);
1117         }
1118
1119         if (pn->pn_flags & PFS_RAWWR) {
1120                 error = pn_fill(curthread, proc, pn, NULL, uio);
1121                 if (proc != NULL)
1122                         PRELE(proc);
1123                 PFS_RETURN (error);
1124         }
1125
1126         sbuf_uionew(&sb, uio, &error);
1127         if (error) {
1128                 if (proc != NULL)
1129                         PRELE(proc);
1130                 PFS_RETURN (error);
1131         }
1132
1133         error = pn_fill(curthread, proc, pn, &sb, uio);
1134
1135         sbuf_delete(&sb);
1136         if (proc != NULL)
1137                 PRELE(proc);
1138         PFS_RETURN (error);
1139 }
1140
1141 /*
1142  * Vnode operations
1143  */
1144 struct vop_vector pfs_vnodeops = {
1145         .vop_default =          &default_vnodeops,
1146
1147         .vop_access =           pfs_access,
1148         .vop_cachedlookup =     pfs_lookup,
1149         .vop_close =            pfs_close,
1150         .vop_create =           VOP_EOPNOTSUPP,
1151         .vop_getattr =          pfs_getattr,
1152         .vop_getextattr =       pfs_getextattr,
1153         .vop_ioctl =            pfs_ioctl,
1154         .vop_link =             VOP_EOPNOTSUPP,
1155         .vop_lookup =           vfs_cache_lookup,
1156         .vop_mkdir =            VOP_EOPNOTSUPP,
1157         .vop_mknod =            VOP_EOPNOTSUPP,
1158         .vop_open =             pfs_open,
1159         .vop_read =             pfs_read,
1160         .vop_readdir =          pfs_readdir,
1161         .vop_readlink =         pfs_readlink,
1162         .vop_reclaim =          pfs_reclaim,
1163         .vop_remove =           VOP_EOPNOTSUPP,
1164         .vop_rename =           VOP_EOPNOTSUPP,
1165         .vop_rmdir =            VOP_EOPNOTSUPP,
1166         .vop_setattr =          pfs_setattr,
1167         .vop_symlink =          VOP_EOPNOTSUPP,
1168         .vop_vptocnp =          pfs_vptocnp,
1169         .vop_write =            pfs_write,
1170         .vop_add_writecount =   vop_stdadd_writecount_nomsync,
1171         /* XXX I've probably forgotten a few that need VOP_EOPNOTSUPP */
1172 };
1173 VFS_VOP_VECTOR_REGISTER(pfs_vnodeops);