xref: /freebsd/sys/fs/pseudofs/pseudofs.c (revision def91cf2674d10fb1fa5e71d531927b9137372db)
19733a808SDag-Erling Smørgrav /*-
29733a808SDag-Erling Smørgrav  * Copyright (c) 2001 Dag-Erling Co�dan Sm�rgrav
39733a808SDag-Erling Smørgrav  * All rights reserved.
49733a808SDag-Erling Smørgrav  *
59733a808SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
69733a808SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
79733a808SDag-Erling Smørgrav  * are met:
89733a808SDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
99733a808SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer
109733a808SDag-Erling Smørgrav  *    in this position and unchanged.
119733a808SDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
129733a808SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
139733a808SDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
149733a808SDag-Erling Smørgrav  * 3. The name of the author may not be used to endorse or promote products
159733a808SDag-Erling Smørgrav  *    derived from this software without specific prior written permission.
169733a808SDag-Erling Smørgrav  *
179733a808SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
189733a808SDag-Erling Smørgrav  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
199733a808SDag-Erling Smørgrav  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
209733a808SDag-Erling Smørgrav  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
219733a808SDag-Erling Smørgrav  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
229733a808SDag-Erling Smørgrav  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239733a808SDag-Erling Smørgrav  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249733a808SDag-Erling Smørgrav  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259733a808SDag-Erling Smørgrav  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
269733a808SDag-Erling Smørgrav  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279733a808SDag-Erling Smørgrav  *
289733a808SDag-Erling Smørgrav  *	$FreeBSD$
299733a808SDag-Erling Smørgrav  */
309733a808SDag-Erling Smørgrav 
319733a808SDag-Erling Smørgrav #include <sys/param.h>
329733a808SDag-Erling Smørgrav #include <sys/kernel.h>
339733a808SDag-Erling Smørgrav #include <sys/systm.h>
347106ca0dSJohn Baldwin #include <sys/lock.h>
359733a808SDag-Erling Smørgrav #include <sys/malloc.h>
369733a808SDag-Erling Smørgrav #include <sys/module.h>
379733a808SDag-Erling Smørgrav #include <sys/mount.h>
3849fa664fSDag-Erling Smørgrav #include <sys/mutex.h>
399733a808SDag-Erling Smørgrav #include <sys/proc.h>
409733a808SDag-Erling Smørgrav #include <sys/sbuf.h>
419733a808SDag-Erling Smørgrav #include <sys/sysctl.h>
429733a808SDag-Erling Smørgrav #include <sys/vnode.h>
439733a808SDag-Erling Smørgrav 
449733a808SDag-Erling Smørgrav #include <fs/pseudofs/pseudofs.h>
459733a808SDag-Erling Smørgrav #include <fs/pseudofs/pseudofs_internal.h>
469733a808SDag-Erling Smørgrav 
4733802b9eSDag-Erling Smørgrav static MALLOC_DEFINE(M_PFSNODES, "pfs_nodes", "pseudofs nodes");
4833802b9eSDag-Erling Smørgrav 
499733a808SDag-Erling Smørgrav SYSCTL_NODE(_vfs, OID_AUTO, pfs, CTLFLAG_RW, 0,
509733a808SDag-Erling Smørgrav     "pseudofs");
519733a808SDag-Erling Smørgrav 
5241aa8697SDag-Erling Smørgrav #if PFS_FSNAMELEN != MFSNAMELEN
5341aa8697SDag-Erling Smørgrav #error "PFS_FSNAMELEN is not equal to MFSNAMELEN"
5441aa8697SDag-Erling Smørgrav #endif
5541aa8697SDag-Erling Smørgrav 
569733a808SDag-Erling Smørgrav /*
5733802b9eSDag-Erling Smørgrav  * Add a node to a directory
5833802b9eSDag-Erling Smørgrav  */
5933802b9eSDag-Erling Smørgrav static int
6033802b9eSDag-Erling Smørgrav _pfs_add_node(struct pfs_node *parent, struct pfs_node *node)
6133802b9eSDag-Erling Smørgrav {
6233802b9eSDag-Erling Smørgrav 	KASSERT(parent != NULL,
636e551fb6SDavid E. O'Brien 	    ("%s(): parent is NULL", __func__));
6433802b9eSDag-Erling Smørgrav 	KASSERT(parent->pn_info != NULL,
656e551fb6SDavid E. O'Brien 	    ("%s(): parent has no pn_info", __func__));
6633802b9eSDag-Erling Smørgrav 	KASSERT(parent->pn_type == pfstype_dir ||
6733802b9eSDag-Erling Smørgrav 	    parent->pn_type == pfstype_procdir ||
6833802b9eSDag-Erling Smørgrav 	    parent->pn_type == pfstype_root,
696e551fb6SDavid E. O'Brien 	    ("%s(): parent is not a directory", __func__));
7033802b9eSDag-Erling Smørgrav 
7133802b9eSDag-Erling Smørgrav 	/* XXX should check for duplicate names etc. */
7233802b9eSDag-Erling Smørgrav 
7333802b9eSDag-Erling Smørgrav 	mtx_lock(&parent->pn_info->pi_mutex);
7433802b9eSDag-Erling Smørgrav 	node->pn_info = parent->pn_info;
7533802b9eSDag-Erling Smørgrav 	node->pn_parent = parent;
7633802b9eSDag-Erling Smørgrav 	node->pn_next = parent->pn_nodes;
7733802b9eSDag-Erling Smørgrav 	parent->pn_nodes = node;
7806be2aaaSNate Lawson 	/* Propagate flag to all child nodes (and thus their vnodes) */
7906be2aaaSNate Lawson 	if ((parent->pn_flags & PFS_PROCDEP) != 0)
8006be2aaaSNate Lawson 		node->pn_flags |= PFS_PROCDEP;
8133802b9eSDag-Erling Smørgrav 	mtx_unlock(&parent->pn_info->pi_mutex);
8233802b9eSDag-Erling Smørgrav 
8333802b9eSDag-Erling Smørgrav 	return (0);
8433802b9eSDag-Erling Smørgrav }
8533802b9eSDag-Erling Smørgrav 
8633802b9eSDag-Erling Smørgrav /*
8733802b9eSDag-Erling Smørgrav  * Add . and .. to a directory
8833802b9eSDag-Erling Smørgrav  */
8933802b9eSDag-Erling Smørgrav static int
9033802b9eSDag-Erling Smørgrav _pfs_fixup_dir(struct pfs_node *parent)
9133802b9eSDag-Erling Smørgrav {
9233802b9eSDag-Erling Smørgrav 	struct pfs_node *dir;
9333802b9eSDag-Erling Smørgrav 
9433802b9eSDag-Erling Smørgrav 	MALLOC(dir, struct pfs_node *, sizeof *dir,
95a163d034SWarner Losh 	    M_PFSNODES, M_WAITOK|M_ZERO);
9633802b9eSDag-Erling Smørgrav 	dir->pn_name[0] = '.';
9733802b9eSDag-Erling Smørgrav 	dir->pn_type = pfstype_this;
9833802b9eSDag-Erling Smørgrav 
9933802b9eSDag-Erling Smørgrav 	if (_pfs_add_node(parent, dir) != 0) {
10033802b9eSDag-Erling Smørgrav 		FREE(dir, M_PFSNODES);
10133802b9eSDag-Erling Smørgrav 		return (-1);
10233802b9eSDag-Erling Smørgrav 	}
10333802b9eSDag-Erling Smørgrav 
10433802b9eSDag-Erling Smørgrav 	MALLOC(dir, struct pfs_node *, sizeof *dir,
105a163d034SWarner Losh 	    M_PFSNODES, M_WAITOK|M_ZERO);
10633802b9eSDag-Erling Smørgrav 	dir->pn_name[0] = dir->pn_name[1] = '.';
10733802b9eSDag-Erling Smørgrav 	dir->pn_type = pfstype_parent;
10833802b9eSDag-Erling Smørgrav 
10933802b9eSDag-Erling Smørgrav 	if (_pfs_add_node(parent, dir) != 0) {
11033802b9eSDag-Erling Smørgrav 		FREE(dir, M_PFSNODES);
11133802b9eSDag-Erling Smørgrav 		return (-1);
11233802b9eSDag-Erling Smørgrav 	}
11333802b9eSDag-Erling Smørgrav 
11433802b9eSDag-Erling Smørgrav 	return (0);
11533802b9eSDag-Erling Smørgrav }
11633802b9eSDag-Erling Smørgrav 
11733802b9eSDag-Erling Smørgrav /*
11833802b9eSDag-Erling Smørgrav  * Create a directory
11933802b9eSDag-Erling Smørgrav  */
12033802b9eSDag-Erling Smørgrav struct pfs_node	*
121b331ec01SDag-Erling Smørgrav pfs_create_dir(struct pfs_node *parent, const char *name,
12233802b9eSDag-Erling Smørgrav 	       pfs_attr_t attr, pfs_vis_t vis, int flags)
12333802b9eSDag-Erling Smørgrav {
12433802b9eSDag-Erling Smørgrav 	struct pfs_node *dir;
12533802b9eSDag-Erling Smørgrav 
12633802b9eSDag-Erling Smørgrav 	KASSERT(strlen(name) < PFS_NAMELEN,
1276e551fb6SDavid E. O'Brien 	    ("%s(): node name is too long", __func__));
12833802b9eSDag-Erling Smørgrav 
12933802b9eSDag-Erling Smørgrav 	MALLOC(dir, struct pfs_node *, sizeof *dir,
130a163d034SWarner Losh 	    M_PFSNODES, M_WAITOK|M_ZERO);
13133802b9eSDag-Erling Smørgrav 	strcpy(dir->pn_name, name);
13233802b9eSDag-Erling Smørgrav 	dir->pn_type = (flags & PFS_PROCDEP) ? pfstype_procdir : pfstype_dir;
13333802b9eSDag-Erling Smørgrav 	dir->pn_attr = attr;
13433802b9eSDag-Erling Smørgrav 	dir->pn_vis = vis;
13506be2aaaSNate Lawson 	dir->pn_flags = flags;
13633802b9eSDag-Erling Smørgrav 
13733802b9eSDag-Erling Smørgrav 	if (_pfs_add_node(parent, dir) != 0) {
13833802b9eSDag-Erling Smørgrav 		FREE(dir, M_PFSNODES);
13933802b9eSDag-Erling Smørgrav 		return (NULL);
14033802b9eSDag-Erling Smørgrav 	}
14133802b9eSDag-Erling Smørgrav 
14233802b9eSDag-Erling Smørgrav 	if (_pfs_fixup_dir(dir) != 0) {
14333802b9eSDag-Erling Smørgrav 		pfs_destroy(dir);
14433802b9eSDag-Erling Smørgrav 		return (NULL);
14533802b9eSDag-Erling Smørgrav 	}
14633802b9eSDag-Erling Smørgrav 
14733802b9eSDag-Erling Smørgrav 	return (dir);
14833802b9eSDag-Erling Smørgrav }
14933802b9eSDag-Erling Smørgrav 
15033802b9eSDag-Erling Smørgrav /*
15133802b9eSDag-Erling Smørgrav  * Create a file
15233802b9eSDag-Erling Smørgrav  */
15333802b9eSDag-Erling Smørgrav struct pfs_node	*
154b331ec01SDag-Erling Smørgrav pfs_create_file(struct pfs_node *parent, const char *name, pfs_fill_t fill,
15533802b9eSDag-Erling Smørgrav 		pfs_attr_t attr, pfs_vis_t vis, int flags)
15633802b9eSDag-Erling Smørgrav {
15733802b9eSDag-Erling Smørgrav 	struct pfs_node *node;
15833802b9eSDag-Erling Smørgrav 
15933802b9eSDag-Erling Smørgrav 	KASSERT(strlen(name) < PFS_NAMELEN,
1606e551fb6SDavid E. O'Brien 	    ("%s(): node name is too long", __func__));
16133802b9eSDag-Erling Smørgrav 
16233802b9eSDag-Erling Smørgrav 	MALLOC(node, struct pfs_node *, sizeof *node,
163a163d034SWarner Losh 	    M_PFSNODES, M_WAITOK|M_ZERO);
16433802b9eSDag-Erling Smørgrav 	strcpy(node->pn_name, name);
16533802b9eSDag-Erling Smørgrav 	node->pn_type = pfstype_file;
16633802b9eSDag-Erling Smørgrav 	node->pn_func = fill;
16733802b9eSDag-Erling Smørgrav 	node->pn_attr = attr;
16833802b9eSDag-Erling Smørgrav 	node->pn_vis = vis;
16933802b9eSDag-Erling Smørgrav 	node->pn_flags = flags;
17033802b9eSDag-Erling Smørgrav 
17133802b9eSDag-Erling Smørgrav 	if (_pfs_add_node(parent, node) != 0) {
17233802b9eSDag-Erling Smørgrav 		FREE(node, M_PFSNODES);
17333802b9eSDag-Erling Smørgrav 		return (NULL);
17433802b9eSDag-Erling Smørgrav 	}
17533802b9eSDag-Erling Smørgrav 
17633802b9eSDag-Erling Smørgrav 	return (node);
17733802b9eSDag-Erling Smørgrav }
17833802b9eSDag-Erling Smørgrav 
17933802b9eSDag-Erling Smørgrav /*
18033802b9eSDag-Erling Smørgrav  * Create a symlink
18133802b9eSDag-Erling Smørgrav  */
18233802b9eSDag-Erling Smørgrav struct pfs_node	*
183b331ec01SDag-Erling Smørgrav pfs_create_link(struct pfs_node *parent, const char *name, pfs_fill_t fill,
18433802b9eSDag-Erling Smørgrav 		pfs_attr_t attr, pfs_vis_t vis, int flags)
18533802b9eSDag-Erling Smørgrav {
18633802b9eSDag-Erling Smørgrav 	struct pfs_node *node;
18733802b9eSDag-Erling Smørgrav 
18833802b9eSDag-Erling Smørgrav 	node = pfs_create_file(parent, name, fill, attr, vis, flags);
18933802b9eSDag-Erling Smørgrav 	if (node == NULL)
19033802b9eSDag-Erling Smørgrav 		return (NULL);
19133802b9eSDag-Erling Smørgrav 	node->pn_type = pfstype_symlink;
19233802b9eSDag-Erling Smørgrav 	return (node);
19333802b9eSDag-Erling Smørgrav }
19433802b9eSDag-Erling Smørgrav 
19533802b9eSDag-Erling Smørgrav /*
196b331ec01SDag-Erling Smørgrav  * Locate a node by name
197b331ec01SDag-Erling Smørgrav  */
198b331ec01SDag-Erling Smørgrav struct pfs_node *
199b331ec01SDag-Erling Smørgrav pfs_find_node(struct pfs_node *parent, const char *name)
200b331ec01SDag-Erling Smørgrav {
201b331ec01SDag-Erling Smørgrav 	struct pfs_node *node;
202b331ec01SDag-Erling Smørgrav 
203b331ec01SDag-Erling Smørgrav 	for (node = parent->pn_nodes; node != NULL; node = node->pn_next)
204b331ec01SDag-Erling Smørgrav 		if (strcmp(node->pn_name, name) == 0)
205b331ec01SDag-Erling Smørgrav 			return (node);
206b331ec01SDag-Erling Smørgrav 	return (NULL);
207b331ec01SDag-Erling Smørgrav }
208b331ec01SDag-Erling Smørgrav 
209b331ec01SDag-Erling Smørgrav /*
21033802b9eSDag-Erling Smørgrav  * Destroy a node or a tree of nodes
21133802b9eSDag-Erling Smørgrav  */
21233802b9eSDag-Erling Smørgrav int
21333802b9eSDag-Erling Smørgrav pfs_destroy(struct pfs_node *node)
21433802b9eSDag-Erling Smørgrav {
21533802b9eSDag-Erling Smørgrav 	struct pfs_node *parent, *rover;
21633802b9eSDag-Erling Smørgrav 
21733802b9eSDag-Erling Smørgrav 	KASSERT(node != NULL,
2186e551fb6SDavid E. O'Brien 	    ("%s(): node is NULL", __func__));
21933802b9eSDag-Erling Smørgrav 	KASSERT(node->pn_info != NULL,
2206e551fb6SDavid E. O'Brien 	    ("%s(): node has no pn_info", __func__));
22133802b9eSDag-Erling Smørgrav 
22233802b9eSDag-Erling Smørgrav 	/* destroy children */
22333802b9eSDag-Erling Smørgrav 	if (node->pn_type == pfstype_dir ||
22433802b9eSDag-Erling Smørgrav 	    node->pn_type == pfstype_procdir ||
22533802b9eSDag-Erling Smørgrav 	    node->pn_type == pfstype_root)
22633802b9eSDag-Erling Smørgrav 		while (node->pn_nodes != NULL)
22733802b9eSDag-Erling Smørgrav 			pfs_destroy(node->pn_nodes);
22833802b9eSDag-Erling Smørgrav 
22933802b9eSDag-Erling Smørgrav 	/* unlink from parent */
23033802b9eSDag-Erling Smørgrav 	if ((parent = node->pn_parent) != NULL) {
23133802b9eSDag-Erling Smørgrav 		KASSERT(parent->pn_info == node->pn_info,
2326e551fb6SDavid E. O'Brien 		    ("%s(): parent has different pn_info", __func__));
23333802b9eSDag-Erling Smørgrav 		mtx_lock(&node->pn_info->pi_mutex);
23433802b9eSDag-Erling Smørgrav 		if (parent->pn_nodes == node) {
23533802b9eSDag-Erling Smørgrav 			parent->pn_nodes = node->pn_next;
23633802b9eSDag-Erling Smørgrav 		} else {
23733802b9eSDag-Erling Smørgrav 			rover = parent->pn_nodes;
23833802b9eSDag-Erling Smørgrav 			while (rover->pn_next != NULL) {
23933802b9eSDag-Erling Smørgrav 				if (rover->pn_next == node) {
24033802b9eSDag-Erling Smørgrav 					rover->pn_next = node->pn_next;
24133802b9eSDag-Erling Smørgrav 					break;
24233802b9eSDag-Erling Smørgrav 				}
24333802b9eSDag-Erling Smørgrav 				rover = rover->pn_next;
24433802b9eSDag-Erling Smørgrav 			}
24533802b9eSDag-Erling Smørgrav 		}
24633802b9eSDag-Erling Smørgrav 		mtx_unlock(&node->pn_info->pi_mutex);
24733802b9eSDag-Erling Smørgrav 	}
24833802b9eSDag-Erling Smørgrav 
24933802b9eSDag-Erling Smørgrav 	/* revoke vnodes and release memory */
25033802b9eSDag-Erling Smørgrav 	pfs_disable(node);
25133802b9eSDag-Erling Smørgrav 	FREE(node, M_PFSNODES);
25233802b9eSDag-Erling Smørgrav 
25333802b9eSDag-Erling Smørgrav 	return (0);
25433802b9eSDag-Erling Smørgrav }
25533802b9eSDag-Erling Smørgrav 
25633802b9eSDag-Erling Smørgrav /*
2579733a808SDag-Erling Smørgrav  * Mount a pseudofs instance
2589733a808SDag-Erling Smørgrav  */
2599733a808SDag-Erling Smørgrav int
2605e8c582aSPoul-Henning Kamp pfs_mount(struct pfs_info *pi, struct mount *mp, struct thread *td)
2619733a808SDag-Erling Smørgrav {
2629733a808SDag-Erling Smørgrav 	struct statfs *sbp;
2639733a808SDag-Erling Smørgrav 
2649733a808SDag-Erling Smørgrav 	if (mp->mnt_flag & MNT_UPDATE)
2659733a808SDag-Erling Smørgrav 		return (EOPNOTSUPP);
2669733a808SDag-Erling Smørgrav 
2679733a808SDag-Erling Smørgrav 	mp->mnt_flag |= MNT_LOCAL;
2689733a808SDag-Erling Smørgrav 	mp->mnt_data = (qaddr_t)pi;
2699733a808SDag-Erling Smørgrav 	vfs_getnewfsid(mp);
2709733a808SDag-Erling Smørgrav 
2719733a808SDag-Erling Smørgrav 	sbp = &mp->mnt_stat;
272def91cf2SPoul-Henning Kamp 	vfs_mountedfrom(mp, pi->pi_name);
2739733a808SDag-Erling Smørgrav 	sbp->f_bsize = PAGE_SIZE;
2749733a808SDag-Erling Smørgrav 	sbp->f_iosize = PAGE_SIZE;
2759733a808SDag-Erling Smørgrav 	sbp->f_blocks = 1;
2769733a808SDag-Erling Smørgrav 	sbp->f_bfree = 0;
2779733a808SDag-Erling Smørgrav 	sbp->f_bavail = 0;
2789733a808SDag-Erling Smørgrav 	sbp->f_files = 1;
2799733a808SDag-Erling Smørgrav 	sbp->f_ffree = 0;
2809733a808SDag-Erling Smørgrav 
2819733a808SDag-Erling Smørgrav 	return (0);
2829733a808SDag-Erling Smørgrav }
2839733a808SDag-Erling Smørgrav 
2849733a808SDag-Erling Smørgrav /*
2859733a808SDag-Erling Smørgrav  * Unmount a pseudofs instance
2869733a808SDag-Erling Smørgrav  */
2879733a808SDag-Erling Smørgrav int
288b40ce416SJulian Elischer pfs_unmount(struct mount *mp, int mntflags, struct thread *td)
2899733a808SDag-Erling Smørgrav {
2909733a808SDag-Erling Smørgrav 	struct pfs_info *pi;
2919733a808SDag-Erling Smørgrav 	int error;
2929733a808SDag-Erling Smørgrav 
2939733a808SDag-Erling Smørgrav 	pi = (struct pfs_info *)mp->mnt_data;
2949733a808SDag-Erling Smørgrav 
2959733a808SDag-Erling Smørgrav 	/* XXX do stuff with pi... */
2969733a808SDag-Erling Smørgrav 
297f257b7a5SAlfred Perlstein 	error = vflush(mp, 0, (mntflags & MNT_FORCE) ?  FORCECLOSE : 0, td);
2989733a808SDag-Erling Smørgrav 	return (error);
2999733a808SDag-Erling Smørgrav }
3009733a808SDag-Erling Smørgrav 
3019733a808SDag-Erling Smørgrav /*
3029733a808SDag-Erling Smørgrav  * Return a root vnode
3039733a808SDag-Erling Smørgrav  */
3049733a808SDag-Erling Smørgrav int
305f257b7a5SAlfred Perlstein pfs_root(struct mount *mp, struct vnode **vpp, struct thread *td)
3069733a808SDag-Erling Smørgrav {
3079733a808SDag-Erling Smørgrav 	struct pfs_info *pi;
3089733a808SDag-Erling Smørgrav 
3099733a808SDag-Erling Smørgrav 	pi = (struct pfs_info *)mp->mnt_data;
310649ad985SDag-Erling Smørgrav 	return pfs_vncache_alloc(mp, vpp, pi->pi_root, NO_PID);
3119733a808SDag-Erling Smørgrav }
3129733a808SDag-Erling Smørgrav 
3139733a808SDag-Erling Smørgrav /*
3149733a808SDag-Erling Smørgrav  * Return filesystem stats
3159733a808SDag-Erling Smørgrav  */
3169733a808SDag-Erling Smørgrav int
317b40ce416SJulian Elischer pfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
3189733a808SDag-Erling Smørgrav {
319def91cf2SPoul-Henning Kamp 	/* no-op:  always called with mp->mnt_stat */
3209733a808SDag-Erling Smørgrav 	return (0);
3219733a808SDag-Erling Smørgrav }
3229733a808SDag-Erling Smørgrav 
3239733a808SDag-Erling Smørgrav /*
3249733a808SDag-Erling Smørgrav  * Initialize a pseudofs instance
3259733a808SDag-Erling Smørgrav  */
3269733a808SDag-Erling Smørgrav int
3279733a808SDag-Erling Smørgrav pfs_init(struct pfs_info *pi, struct vfsconf *vfc)
3289733a808SDag-Erling Smørgrav {
32933802b9eSDag-Erling Smørgrav 	struct pfs_node *root;
33033802b9eSDag-Erling Smørgrav 	int error;
33133802b9eSDag-Erling Smørgrav 
3326008862bSJohn Baldwin 	mtx_init(&pi->pi_mutex, "pseudofs", NULL, MTX_DEF);
33333802b9eSDag-Erling Smørgrav 
33433802b9eSDag-Erling Smørgrav 	/* set up the root diretory */
33533802b9eSDag-Erling Smørgrav 	MALLOC(root, struct pfs_node *, sizeof *root,
336a163d034SWarner Losh 	    M_PFSNODES, M_WAITOK|M_ZERO);
33733802b9eSDag-Erling Smørgrav 	root->pn_type = pfstype_root;
33833802b9eSDag-Erling Smørgrav 	root->pn_name[0] = '/';
33933802b9eSDag-Erling Smørgrav 	root->pn_info = pi;
34033802b9eSDag-Erling Smørgrav 	if (_pfs_fixup_dir(root) != 0) {
34133802b9eSDag-Erling Smørgrav 		FREE(root, M_PFSNODES);
34233802b9eSDag-Erling Smørgrav 		return (ENODEV); /* XXX not really the right errno */
34333802b9eSDag-Erling Smørgrav 	}
34433802b9eSDag-Erling Smørgrav 	pi->pi_root = root;
34533802b9eSDag-Erling Smørgrav 
34633802b9eSDag-Erling Smørgrav 	/* construct file hierarchy */
34733802b9eSDag-Erling Smørgrav 	error = (pi->pi_init)(pi, vfc);
34833802b9eSDag-Erling Smørgrav 	if (error) {
34933802b9eSDag-Erling Smørgrav 		pfs_destroy(root);
35033802b9eSDag-Erling Smørgrav 		pi->pi_root = NULL;
35133802b9eSDag-Erling Smørgrav 		mtx_destroy(&pi->pi_mutex);
35233802b9eSDag-Erling Smørgrav 		return (error);
35333802b9eSDag-Erling Smørgrav 	}
35433802b9eSDag-Erling Smørgrav 
3559733a808SDag-Erling Smørgrav 	pfs_fileno_init(pi);
356b7004390SDag-Erling Smørgrav 	if (bootverbose)
3579733a808SDag-Erling Smørgrav 		printf("%s registered\n", pi->pi_name);
3589733a808SDag-Erling Smørgrav 	return (0);
3599733a808SDag-Erling Smørgrav }
3609733a808SDag-Erling Smørgrav 
3619733a808SDag-Erling Smørgrav /*
3629733a808SDag-Erling Smørgrav  * Destroy a pseudofs instance
3639733a808SDag-Erling Smørgrav  */
3649733a808SDag-Erling Smørgrav int
3659733a808SDag-Erling Smørgrav pfs_uninit(struct pfs_info *pi, struct vfsconf *vfc)
3669733a808SDag-Erling Smørgrav {
36733802b9eSDag-Erling Smørgrav 	int error;
36833802b9eSDag-Erling Smørgrav 
3699733a808SDag-Erling Smørgrav 	pfs_fileno_uninit(pi);
37033802b9eSDag-Erling Smørgrav 	pfs_destroy(pi->pi_root);
37133802b9eSDag-Erling Smørgrav 	pi->pi_root = NULL;
3729733a808SDag-Erling Smørgrav 	mtx_destroy(&pi->pi_mutex);
373b7004390SDag-Erling Smørgrav 	if (bootverbose)
3749733a808SDag-Erling Smørgrav 		printf("%s unregistered\n", pi->pi_name);
37533802b9eSDag-Erling Smørgrav 	error = (pi->pi_uninit)(pi, vfc);
37633802b9eSDag-Erling Smørgrav 	return (error);
3779733a808SDag-Erling Smørgrav }
3789733a808SDag-Erling Smørgrav 
3799733a808SDag-Erling Smørgrav /*
3809733a808SDag-Erling Smørgrav  * Handle load / unload events
3819733a808SDag-Erling Smørgrav  */
3829733a808SDag-Erling Smørgrav static int
3839733a808SDag-Erling Smørgrav pfs_modevent(module_t mod, int evt, void *arg)
3849733a808SDag-Erling Smørgrav {
3859733a808SDag-Erling Smørgrav 	switch (evt) {
3869733a808SDag-Erling Smørgrav 	case MOD_LOAD:
3879733a808SDag-Erling Smørgrav 		pfs_fileno_load();
3889733a808SDag-Erling Smørgrav 		pfs_vncache_load();
3899733a808SDag-Erling Smørgrav 		break;
3909733a808SDag-Erling Smørgrav 	case MOD_UNLOAD:
3919733a808SDag-Erling Smørgrav 	case MOD_SHUTDOWN:
3929733a808SDag-Erling Smørgrav 		pfs_vncache_unload();
3939733a808SDag-Erling Smørgrav 		pfs_fileno_unload();
3949733a808SDag-Erling Smørgrav 		break;
3959733a808SDag-Erling Smørgrav 	default:
3963e019deaSPoul-Henning Kamp 		return EOPNOTSUPP;
3979733a808SDag-Erling Smørgrav 		break;
3989733a808SDag-Erling Smørgrav 	}
3999733a808SDag-Erling Smørgrav 	return 0;
4009733a808SDag-Erling Smørgrav }
4019733a808SDag-Erling Smørgrav 
4029733a808SDag-Erling Smørgrav /*
4039733a808SDag-Erling Smørgrav  * Module declaration
4049733a808SDag-Erling Smørgrav  */
4059733a808SDag-Erling Smørgrav static moduledata_t pseudofs_data = {
4069733a808SDag-Erling Smørgrav 	"pseudofs",
4079733a808SDag-Erling Smørgrav 	pfs_modevent,
4089733a808SDag-Erling Smørgrav 	NULL
4099733a808SDag-Erling Smørgrav };
4109733a808SDag-Erling Smørgrav DECLARE_MODULE(pseudofs, pseudofs_data, SI_SUB_EXEC, SI_ORDER_FIRST);
41198c7e22cSDag-Erling Smørgrav MODULE_VERSION(pseudofs, 1);
412