19733a808SDag-Erling Smørgrav /*- 2d63027b6SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3d63027b6SPedro F. Giffuni * 4*e738085bSDag-Erling Smørgrav * Copyright (c) 2001 Dag-Erling Smørgrav 59733a808SDag-Erling Smørgrav * All rights reserved. 69733a808SDag-Erling Smørgrav * 79733a808SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 89733a808SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 99733a808SDag-Erling Smørgrav * are met: 109733a808SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 119733a808SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer 129733a808SDag-Erling Smørgrav * in this position and unchanged. 139733a808SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 149733a808SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 159733a808SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 169733a808SDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote products 179733a808SDag-Erling Smørgrav * derived from this software without specific prior written permission. 189733a808SDag-Erling Smørgrav * 199733a808SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 209733a808SDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 219733a808SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 229733a808SDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 239733a808SDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 249733a808SDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 259733a808SDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 269733a808SDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 279733a808SDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 289733a808SDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 299733a808SDag-Erling Smørgrav */ 309733a808SDag-Erling Smørgrav 319733a808SDag-Erling Smørgrav #ifndef _PSEUDOFS_H_INCLUDED 329733a808SDag-Erling Smørgrav #define _PSEUDOFS_H_INCLUDED 339733a808SDag-Erling Smørgrav 3441c0675eSMartin Matuska #include <sys/jail.h> 3541c0675eSMartin Matuska 369733a808SDag-Erling Smørgrav /* 3741aa8697SDag-Erling Smørgrav * Opaque structures 3841aa8697SDag-Erling Smørgrav */ 39c9ad8a67SKelly Yancey struct mntarg; 4041aa8697SDag-Erling Smørgrav struct mount; 4141aa8697SDag-Erling Smørgrav struct nameidata; 4241aa8697SDag-Erling Smørgrav struct proc; 4341aa8697SDag-Erling Smørgrav struct sbuf; 4441aa8697SDag-Erling Smørgrav struct statfs; 4541aa8697SDag-Erling Smørgrav struct thread; 4641aa8697SDag-Erling Smørgrav struct uio; 4741aa8697SDag-Erling Smørgrav struct vfsconf; 4841aa8697SDag-Erling Smørgrav struct vnode; 4941aa8697SDag-Erling Smørgrav 5041aa8697SDag-Erling Smørgrav /* 519733a808SDag-Erling Smørgrav * Limits and constants 529733a808SDag-Erling Smørgrav */ 5381167243SMatt Macy #define PFS_NAMELEN 128 5441aa8697SDag-Erling Smørgrav #define PFS_FSNAMELEN 16 /* equal to MFSNAMELEN */ 550a7c8d30SDmitry Chagin #define PFS_DELEN (offsetof(struct dirent, d_name) + PFS_NAMELEN) 569733a808SDag-Erling Smørgrav 579733a808SDag-Erling Smørgrav typedef enum { 589733a808SDag-Erling Smørgrav pfstype_none = 0, 599733a808SDag-Erling Smørgrav pfstype_root, 609733a808SDag-Erling Smørgrav pfstype_dir, 619733a808SDag-Erling Smørgrav pfstype_this, 629733a808SDag-Erling Smørgrav pfstype_parent, 639733a808SDag-Erling Smørgrav pfstype_file, 649733a808SDag-Erling Smørgrav pfstype_symlink, 65649ad985SDag-Erling Smørgrav pfstype_procdir 669733a808SDag-Erling Smørgrav } pfs_type_t; 679733a808SDag-Erling Smørgrav 689733a808SDag-Erling Smørgrav /* 698712e867SDag-Erling Smørgrav * Flags 708712e867SDag-Erling Smørgrav */ 717d8f809fSDag-Erling Smørgrav #define PFS_RD 0x0001 /* readable */ 727d8f809fSDag-Erling Smørgrav #define PFS_WR 0x0002 /* writeable */ 737d8f809fSDag-Erling Smørgrav #define PFS_RDWR (PFS_RD|PFS_WR) 748712e867SDag-Erling Smørgrav #define PFS_RAWRD 0x0004 /* raw reader */ 758712e867SDag-Erling Smørgrav #define PFS_RAWWR 0x0008 /* raw writer */ 767d8f809fSDag-Erling Smørgrav #define PFS_RAW (PFS_RAWRD|PFS_RAWWR) 7733802b9eSDag-Erling Smørgrav #define PFS_PROCDEP 0x0010 /* process-dependent */ 7881167243SMatt Macy #define PFS_NOWAIT 0x0020 /* allow malloc to fail */ 7920172854SConrad Meyer #define PFS_AUTODRAIN 0x0040 /* sbuf_print can sleep to drain */ 808712e867SDag-Erling Smørgrav 818712e867SDag-Erling Smørgrav /* 829733a808SDag-Erling Smørgrav * Data structures 839733a808SDag-Erling Smørgrav */ 849733a808SDag-Erling Smørgrav struct pfs_info; 859733a808SDag-Erling Smørgrav struct pfs_node; 869733a808SDag-Erling Smørgrav 8780a3cef8SDag-Erling Smørgrav /* 8833802b9eSDag-Erling Smørgrav * Init / uninit callback 8933802b9eSDag-Erling Smørgrav */ 9033802b9eSDag-Erling Smørgrav #define PFS_INIT_ARGS \ 9133802b9eSDag-Erling Smørgrav struct pfs_info *pi, struct vfsconf *vfc 92388596dfSDag-Erling Smørgrav #define PFS_INIT_ARGNAMES \ 93388596dfSDag-Erling Smørgrav pi, vfc 9433802b9eSDag-Erling Smørgrav #define PFS_INIT_PROTO(name) \ 9533802b9eSDag-Erling Smørgrav int name(PFS_INIT_ARGS); 9633802b9eSDag-Erling Smørgrav typedef int (*pfs_init_t)(PFS_INIT_ARGS); 9733802b9eSDag-Erling Smørgrav 9833802b9eSDag-Erling Smørgrav /* 9980a3cef8SDag-Erling Smørgrav * Filler callback 100388596dfSDag-Erling Smørgrav * Called with proc held but unlocked 10180a3cef8SDag-Erling Smørgrav */ 102649ad985SDag-Erling Smørgrav #define PFS_FILL_ARGS \ 1038712e867SDag-Erling Smørgrav struct thread *td, struct proc *p, struct pfs_node *pn, \ 1048712e867SDag-Erling Smørgrav struct sbuf *sb, struct uio *uio 105388596dfSDag-Erling Smørgrav #define PFS_FILL_ARGNAMES \ 106388596dfSDag-Erling Smørgrav td, p, pn, sb, uio 107649ad985SDag-Erling Smørgrav #define PFS_FILL_PROTO(name) \ 108649ad985SDag-Erling Smørgrav int name(PFS_FILL_ARGS); 109649ad985SDag-Erling Smørgrav typedef int (*pfs_fill_t)(PFS_FILL_ARGS); 1109733a808SDag-Erling Smørgrav 11180a3cef8SDag-Erling Smørgrav /* 11280a3cef8SDag-Erling Smørgrav * Attribute callback 113388596dfSDag-Erling Smørgrav * Called with proc locked 11480a3cef8SDag-Erling Smørgrav */ 11580a3cef8SDag-Erling Smørgrav struct vattr; 11680a3cef8SDag-Erling Smørgrav #define PFS_ATTR_ARGS \ 11780a3cef8SDag-Erling Smørgrav struct thread *td, struct proc *p, struct pfs_node *pn, \ 11880a3cef8SDag-Erling Smørgrav struct vattr *vap 119388596dfSDag-Erling Smørgrav #define PFS_ATTR_ARGNAMES \ 120388596dfSDag-Erling Smørgrav td, p, pn, vap 12180a3cef8SDag-Erling Smørgrav #define PFS_ATTR_PROTO(name) \ 12280a3cef8SDag-Erling Smørgrav int name(PFS_ATTR_ARGS); 12380a3cef8SDag-Erling Smørgrav typedef int (*pfs_attr_t)(PFS_ATTR_ARGS); 12480a3cef8SDag-Erling Smørgrav 1259733a808SDag-Erling Smørgrav /* 126198bc14bSDag-Erling Smørgrav * Visibility callback 127388596dfSDag-Erling Smørgrav * Called with proc locked 128198bc14bSDag-Erling Smørgrav */ 129198bc14bSDag-Erling Smørgrav #define PFS_VIS_ARGS \ 130198bc14bSDag-Erling Smørgrav struct thread *td, struct proc *p, struct pfs_node *pn 131388596dfSDag-Erling Smørgrav #define PFS_VIS_ARGNAMES \ 132388596dfSDag-Erling Smørgrav td, p, pn 133198bc14bSDag-Erling Smørgrav #define PFS_VIS_PROTO(name) \ 134198bc14bSDag-Erling Smørgrav int name(PFS_VIS_ARGS); 135198bc14bSDag-Erling Smørgrav typedef int (*pfs_vis_t)(PFS_VIS_ARGS); 136198bc14bSDag-Erling Smørgrav 137198bc14bSDag-Erling Smørgrav /* 13818319000SDag-Erling Smørgrav * Ioctl callback 139388596dfSDag-Erling Smørgrav * Called with proc locked 14018319000SDag-Erling Smørgrav */ 14118319000SDag-Erling Smørgrav #define PFS_IOCTL_ARGS \ 14218319000SDag-Erling Smørgrav struct thread *td, struct proc *p, struct pfs_node *pn, \ 1437b726be3SDag-Erling Smørgrav unsigned long cmd, void *data 144388596dfSDag-Erling Smørgrav #define PFS_IOCTL_ARGNAMES \ 145388596dfSDag-Erling Smørgrav td, p, pn, cmd, data 14618319000SDag-Erling Smørgrav #define PFS_IOCTL_PROTO(name) \ 14718319000SDag-Erling Smørgrav int name(PFS_IOCTL_ARGS); 14818319000SDag-Erling Smørgrav typedef int (*pfs_ioctl_t)(PFS_IOCTL_ARGS); 14918319000SDag-Erling Smørgrav 15018319000SDag-Erling Smørgrav /* 15141a35633SBrian Feldman * Getextattr callback 152388596dfSDag-Erling Smørgrav * Called with proc locked 15341a35633SBrian Feldman */ 15441a35633SBrian Feldman #define PFS_GETEXTATTR_ARGS \ 15541a35633SBrian Feldman struct thread *td, struct proc *p, struct pfs_node *pn, \ 15641a35633SBrian Feldman int attrnamespace, const char *name, struct uio *uio, \ 15774237f55SRobert Watson size_t *size, struct ucred *cred 158388596dfSDag-Erling Smørgrav #define PFS_GETEXTATTR_ARGNAMES \ 159388596dfSDag-Erling Smørgrav td, p, pn, attrnamespace, name, uio, size, cred 16041a35633SBrian Feldman #define PFS_GETEXTATTR_PROTO(name) \ 16141a35633SBrian Feldman int name(PFS_GETEXTATTR_ARGS); 16241a35633SBrian Feldman struct ucred; 16341a35633SBrian Feldman typedef int (*pfs_getextattr_t)(PFS_GETEXTATTR_ARGS); 16441a35633SBrian Feldman 16541a35633SBrian Feldman /* 16698c7e22cSDag-Erling Smørgrav * Last-close callback 167388596dfSDag-Erling Smørgrav * Called with proc locked 16898c7e22cSDag-Erling Smørgrav */ 16998c7e22cSDag-Erling Smørgrav #define PFS_CLOSE_ARGS \ 17098c7e22cSDag-Erling Smørgrav struct thread *td, struct proc *p, struct pfs_node *pn 171388596dfSDag-Erling Smørgrav #define PFS_CLOSE_ARGNAMES \ 172388596dfSDag-Erling Smørgrav td, p, pn 17398c7e22cSDag-Erling Smørgrav #define PFS_CLOSE_PROTO(name) \ 17498c7e22cSDag-Erling Smørgrav int name(PFS_CLOSE_ARGS); 17598c7e22cSDag-Erling Smørgrav typedef int (*pfs_close_t)(PFS_CLOSE_ARGS); 17698c7e22cSDag-Erling Smørgrav 17798c7e22cSDag-Erling Smørgrav /* 178771709ebSDag-Erling Smørgrav * Destroy callback 179771709ebSDag-Erling Smørgrav */ 180771709ebSDag-Erling Smørgrav #define PFS_DESTROY_ARGS \ 181771709ebSDag-Erling Smørgrav struct pfs_node *pn 182388596dfSDag-Erling Smørgrav #define PFS_DESTROY_ARGNAMES \ 183388596dfSDag-Erling Smørgrav pn 184771709ebSDag-Erling Smørgrav #define PFS_DESTROY_PROTO(name) \ 185771709ebSDag-Erling Smørgrav int name(PFS_DESTROY_ARGS); 186771709ebSDag-Erling Smørgrav typedef int (*pfs_destroy_t)(PFS_DESTROY_ARGS); 187771709ebSDag-Erling Smørgrav 188771709ebSDag-Erling Smørgrav /* 1899733a808SDag-Erling Smørgrav * pfs_info: describes a pseudofs instance 190f61bc4eaSDag-Erling Smørgrav * 19129ffb32cSKonstantin Belousov * The pi_mutex is only used to avoid using the global subr_unit lock 19229ffb32cSKonstantin Belousov * for unrhdr. The rest of struct pfs_info is only modified during 19329ffb32cSKonstantin Belousov * vfs_init() and vfs_uninit() of the consumer filesystem. 1949733a808SDag-Erling Smørgrav */ 1959733a808SDag-Erling Smørgrav struct pfs_info { 19641aa8697SDag-Erling Smørgrav char pi_name[PFS_FSNAMELEN]; 19733802b9eSDag-Erling Smørgrav pfs_init_t pi_init; 19833802b9eSDag-Erling Smørgrav pfs_init_t pi_uninit; 199f61bc4eaSDag-Erling Smørgrav 200f61bc4eaSDag-Erling Smørgrav /* members below this line are initialized at run time */ 20133802b9eSDag-Erling Smørgrav struct pfs_node *pi_root; 2029733a808SDag-Erling Smørgrav struct mtx pi_mutex; 2037f661c6bSPoul-Henning Kamp struct unrhdr *pi_unrhdr; 2049733a808SDag-Erling Smørgrav }; 2059733a808SDag-Erling Smørgrav 2069733a808SDag-Erling Smørgrav /* 2079733a808SDag-Erling Smørgrav * pfs_node: describes a node (file or directory) within a pseudofs 208388596dfSDag-Erling Smørgrav * 209388596dfSDag-Erling Smørgrav * - Fields marked (o) are protected by the node's own mutex. 210388596dfSDag-Erling Smørgrav * - Fields marked (p) are protected by the node's parent's mutex. 211388596dfSDag-Erling Smørgrav * - Remaining fields are not protected by any lock and are assumed to be 212388596dfSDag-Erling Smørgrav * immutable once the node has been created. 213388596dfSDag-Erling Smørgrav * 214388596dfSDag-Erling Smørgrav * To prevent deadlocks, if a node's mutex is to be held at the same time 215388596dfSDag-Erling Smørgrav * as its parent's (e.g. when adding or removing nodes to a directory), 216388596dfSDag-Erling Smørgrav * the parent's mutex must always be acquired first. Unfortunately, this 217388596dfSDag-Erling Smørgrav * is not enforcable by WITNESS. 2189733a808SDag-Erling Smørgrav */ 2199733a808SDag-Erling Smørgrav struct pfs_node { 2209733a808SDag-Erling Smørgrav pfs_type_t pn_type; 221388596dfSDag-Erling Smørgrav int pn_flags; 222388596dfSDag-Erling Smørgrav struct mtx pn_mutex; 223388596dfSDag-Erling Smørgrav void *pn_data; /* (o) */ 224388596dfSDag-Erling Smørgrav 225388596dfSDag-Erling Smørgrav pfs_fill_t pn_fill; 22618319000SDag-Erling Smørgrav pfs_ioctl_t pn_ioctl; 22798c7e22cSDag-Erling Smørgrav pfs_close_t pn_close; 22880a3cef8SDag-Erling Smørgrav pfs_attr_t pn_attr; 229198bc14bSDag-Erling Smørgrav pfs_vis_t pn_vis; 23041a35633SBrian Feldman pfs_getextattr_t pn_getextattr; 231771709ebSDag-Erling Smørgrav pfs_destroy_t pn_destroy; 23233802b9eSDag-Erling Smørgrav 23333802b9eSDag-Erling Smørgrav struct pfs_info *pn_info; 234388596dfSDag-Erling Smørgrav u_int32_t pn_fileno; /* (o) */ 235388596dfSDag-Erling Smørgrav 236388596dfSDag-Erling Smørgrav struct pfs_node *pn_parent; /* (o) */ 237388596dfSDag-Erling Smørgrav struct pfs_node *pn_nodes; /* (o) */ 238cf389852SEdward Tomasz Napierala struct pfs_node *pn_last_node; /* (o) */ 239388596dfSDag-Erling Smørgrav struct pfs_node *pn_next; /* (p) */ 2407f723243SDmitry Chagin char pn_name[]; /* Keep it last */ 2419733a808SDag-Erling Smørgrav }; 2429733a808SDag-Erling Smørgrav 2439733a808SDag-Erling Smørgrav /* 2449733a808SDag-Erling Smørgrav * VFS interface 2459733a808SDag-Erling Smørgrav */ 246dfd233edSAttilio Rao int pfs_mount (struct pfs_info *pi, struct mount *mp); 247cc672d35SKirk McKusick int pfs_cmount (struct mntarg *ma, void *data, uint64_t flags); 248dfd233edSAttilio Rao int pfs_unmount (struct mount *mp, int mntflags); 249d9b2d9f7SJeff Roberson int pfs_root (struct mount *mp, int flags, 250dfd233edSAttilio Rao struct vnode **vpp); 251dfd233edSAttilio Rao int pfs_statfs (struct mount *mp, struct statfs *sbp); 2529733a808SDag-Erling Smørgrav int pfs_init (struct pfs_info *pi, struct vfsconf *vfc); 2539733a808SDag-Erling Smørgrav int pfs_uninit (struct pfs_info *pi, struct vfsconf *vfc); 2549733a808SDag-Erling Smørgrav 2559733a808SDag-Erling Smørgrav /* 25633802b9eSDag-Erling Smørgrav * Directory structure construction and manipulation 257b84ce334SDag-Erling Smørgrav */ 258b331ec01SDag-Erling Smørgrav struct pfs_node *pfs_create_dir (struct pfs_node *parent, const char *name, 259771709ebSDag-Erling Smørgrav pfs_attr_t attr, pfs_vis_t vis, 260771709ebSDag-Erling Smørgrav pfs_destroy_t destroy, int flags); 261b331ec01SDag-Erling Smørgrav struct pfs_node *pfs_create_file(struct pfs_node *parent, const char *name, 26233802b9eSDag-Erling Smørgrav pfs_fill_t fill, pfs_attr_t attr, 263771709ebSDag-Erling Smørgrav pfs_vis_t vis, pfs_destroy_t destroy, 264771709ebSDag-Erling Smørgrav int flags); 265b331ec01SDag-Erling Smørgrav struct pfs_node *pfs_create_link(struct pfs_node *parent, const char *name, 26633802b9eSDag-Erling Smørgrav pfs_fill_t fill, pfs_attr_t attr, 267771709ebSDag-Erling Smørgrav pfs_vis_t vis, pfs_destroy_t destroy, 268771709ebSDag-Erling Smørgrav int flags); 269b331ec01SDag-Erling Smørgrav struct pfs_node *pfs_find_node (struct pfs_node *parent, const char *name); 27015bad11fSDag-Erling Smørgrav void pfs_purge (struct pfs_node *pn); 27133802b9eSDag-Erling Smørgrav int pfs_destroy (struct pfs_node *pn); 272b84ce334SDag-Erling Smørgrav 273b84ce334SDag-Erling Smørgrav /* 2749733a808SDag-Erling Smørgrav * Now for some initialization magic... 2759733a808SDag-Erling Smørgrav */ 2760e5c6bd4SJamie Gritton #define PSEUDOFS(name, version, flags) \ 2779733a808SDag-Erling Smørgrav \ 2789733a808SDag-Erling Smørgrav static struct pfs_info name##_info = { \ 2799733a808SDag-Erling Smørgrav #name, \ 280ce2fb577SPoul-Henning Kamp name##_init, \ 281ce2fb577SPoul-Henning Kamp name##_uninit, \ 2829733a808SDag-Erling Smørgrav }; \ 2839733a808SDag-Erling Smørgrav \ 2849733a808SDag-Erling Smørgrav static int \ 285dfd233edSAttilio Rao _##name##_mount(struct mount *mp) { \ 2866828ba63SKonstantin Belousov return (pfs_mount(&name##_info, mp)); \ 2879733a808SDag-Erling Smørgrav } \ 2889733a808SDag-Erling Smørgrav \ 2899733a808SDag-Erling Smørgrav static int \ 2909733a808SDag-Erling Smørgrav _##name##_init(struct vfsconf *vfc) { \ 2916828ba63SKonstantin Belousov return (pfs_init(&name##_info, vfc)); \ 2929733a808SDag-Erling Smørgrav } \ 2939733a808SDag-Erling Smørgrav \ 2949733a808SDag-Erling Smørgrav static int \ 2959733a808SDag-Erling Smørgrav _##name##_uninit(struct vfsconf *vfc) { \ 2966828ba63SKonstantin Belousov return (pfs_uninit(&name##_info, vfc)); \ 2979733a808SDag-Erling Smørgrav } \ 2989733a808SDag-Erling Smørgrav \ 2997005ce8aSDag-Erling Smørgrav static struct vfsops name##_vfsops = { \ 300c9ad8a67SKelly Yancey .vfs_cmount = pfs_cmount, \ 3017652131bSPoul-Henning Kamp .vfs_init = _##name##_init, \ 3025e8c582aSPoul-Henning Kamp .vfs_mount = _##name##_mount, \ 3037652131bSPoul-Henning Kamp .vfs_root = pfs_root, \ 3047652131bSPoul-Henning Kamp .vfs_statfs = pfs_statfs, \ 3057652131bSPoul-Henning Kamp .vfs_uninit = _##name##_uninit, \ 3067652131bSPoul-Henning Kamp .vfs_unmount = pfs_unmount, \ 3079733a808SDag-Erling Smørgrav }; \ 3080e5c6bd4SJamie Gritton VFS_SET(name##_vfsops, name, VFCF_SYNTHETIC | flags); \ 3098712e867SDag-Erling Smørgrav MODULE_VERSION(name, version); \ 31098c7e22cSDag-Erling Smørgrav MODULE_DEPEND(name, pseudofs, 1, 1, 1); 3119733a808SDag-Erling Smørgrav 3129733a808SDag-Erling Smørgrav #endif 313