1272343Sngie/*	$NetBSD: dtfs.c,v 1.2 2010/07/21 06:58:25 pooka Exp $	*/
2272343Sngie
3272343Sngie/*
4272343Sngie * Copyright (c) 2006  Antti Kantee.  All Rights Reserved.
5272343Sngie *
6272343Sngie * Redistribution and use in source and binary forms, with or without
7272343Sngie * modification, are permitted provided that the following conditions
8272343Sngie * are met:
9272343Sngie * 1. Redistributions of source code must retain the above copyright
10272343Sngie *    notice, this list of conditions and the following disclaimer.
11272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
12272343Sngie *    notice, this list of conditions and the following disclaimer in the
13272343Sngie *    documentation and/or other materials provided with the distribution.
14272343Sngie *
15272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16272343Sngie * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17272343Sngie * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18272343Sngie * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21272343Sngie * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25272343Sngie * SUCH DAMAGE.
26272343Sngie */
27272343Sngie
28272343Sngie/*
29272343Sngie * Delectable Test File System: a simple in-memory file system which
30272343Sngie * demonstrates the use of puffs.
31272343Sngie * (a.k.a. Detrempe FS ...)
32272343Sngie */
33272343Sngie
34272343Sngie#include <sys/types.h>
35272343Sngie
36272343Sngie#include <err.h>
37272343Sngie#include <mntopts.h>
38272343Sngie#include <paths.h>
39272343Sngie#include <puffs.h>
40272343Sngie#include <signal.h>
41272343Sngie#include <stdio.h>
42272343Sngie#include <stdlib.h>
43272343Sngie#include <string.h>
44272343Sngie#include <unistd.h>
45272343Sngie
46272343Sngie#include "dtfs.h"
47272343Sngie
48272343Sngie#ifdef DEEP_ROOTED_CLUE
49272343Sngie#define FSNAME "detrempe"
50272343Sngie#else
51272343Sngie#define FSNAME "dt"
52272343Sngie#endif
53272343Sngie#define MAXREQMAGIC -37
54272343Sngie
55272343Sngiestatic struct puffs_usermount *gpu;
56272343Sngiestatic struct dtfs_mount gdtm;
57272343Sngieint dynamicfh;
58272343Sngieint straightflush;
59272343Sngie
60272343Sngiestatic void usage(void);
61272343Sngie
62272343Sngiestatic void
63272343Sngieusage()
64272343Sngie{
65272343Sngie
66272343Sngie	fprintf(stderr, "usage: %s [-bsdftl] [-c hashbuckets] [-m maxreqsize] "
67272343Sngie	    "[-n typename]\n       [-o mntopt] [-o puffsopt] [-p prot] "
68272343Sngie	    "[-r rootnodetype]\n       detrempe /mountpoint\n", getprogname());
69272343Sngie	exit(1);
70272343Sngie}
71272343Sngie
72272343Sngiestatic void
73272343Sngiewipe_the_sleep_out_of_my_eyes(int v)
74272343Sngie{
75272343Sngie
76272343Sngie	gdtm.dtm_needwakeup++;
77272343Sngie}
78272343Sngie
79272343Sngiestatic void
80272343Sngieloopfun(struct puffs_usermount *pu)
81272343Sngie{
82272343Sngie	struct dtfs_mount *dtm = puffs_getspecific(pu);
83272343Sngie	struct dtfs_poll *dp;
84272343Sngie
85272343Sngie	while (dtm->dtm_needwakeup) {
86272343Sngie		dtm->dtm_needwakeup--;
87272343Sngie		dp = LIST_FIRST(&dtm->dtm_pollent);
88272343Sngie		if (dp == NULL)
89272343Sngie			return;
90272343Sngie
91272343Sngie		LIST_REMOVE(dp, dp_entries);
92272343Sngie		puffs_cc_continue(dp->dp_pcc);
93272343Sngie	}
94272343Sngie}
95272343Sngie
96272343Sngieint
97272343Sngiemain(int argc, char *argv[])
98272343Sngie{
99272343Sngie	extern char *optarg;
100272343Sngie	extern int optind;
101272343Sngie	struct puffs_usermount *pu;
102272343Sngie	struct puffs_pathobj *po_root;
103272343Sngie	struct puffs_ops *pops;
104272343Sngie	struct timespec ts;
105272343Sngie	const char *typename;
106272343Sngie	char *rtstr;
107272343Sngie	mntoptparse_t mp;
108272343Sngie	int pflags, detach, mntflags;
109272343Sngie	int ch;
110272343Sngie	int khashbuckets;
111272343Sngie	int maxreqsize;
112272343Sngie
113272343Sngie	setprogname(argv[0]);
114272343Sngie
115272343Sngie	rtstr = NULL;
116272343Sngie	detach = 1;
117272343Sngie	mntflags = 0;
118272343Sngie	khashbuckets = 256;
119272343Sngie	pflags = PUFFS_KFLAG_IAONDEMAND;
120272343Sngie	typename = FSNAME;
121272343Sngie	maxreqsize = MAXREQMAGIC;
122272343Sngie	gdtm.dtm_allowprot = VM_PROT_ALL;
123272343Sngie	while ((ch = getopt(argc, argv, "bc:dfilm:n:o:p:r:st")) != -1) {
124272343Sngie		switch (ch) {
125272343Sngie		case 'b': /* build paths, for debugging the feature */
126272343Sngie			pflags |= PUFFS_FLAG_BUILDPATH;
127272343Sngie			break;
128272343Sngie		case 'c':
129272343Sngie			khashbuckets = atoi(optarg);
130272343Sngie			break;
131272343Sngie		case 'd':
132272343Sngie			dynamicfh = 1;
133272343Sngie			break;
134272343Sngie		case 'f':
135272343Sngie			pflags |= PUFFS_KFLAG_LOOKUP_FULLPNBUF;
136272343Sngie			break;
137272343Sngie		case 'i':
138272343Sngie			pflags &= ~PUFFS_KFLAG_IAONDEMAND;
139272343Sngie			break;
140272343Sngie		case 'l':
141272343Sngie			straightflush = 1;
142272343Sngie			break;
143272343Sngie		case 'm':
144272343Sngie			maxreqsize = atoi(optarg);
145272343Sngie			break;
146272343Sngie		case 'n':
147272343Sngie			typename = optarg;
148272343Sngie			break;
149272343Sngie		case 'o':
150272343Sngie			mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags);
151272343Sngie			if (mp == NULL)
152272343Sngie				err(1, "getmntopts");
153272343Sngie			freemntopts(mp);
154272343Sngie			break;
155272343Sngie		case 'p':
156272343Sngie			gdtm.dtm_allowprot = atoi(optarg);
157272343Sngie			if ((gdtm.dtm_allowprot | VM_PROT_ALL) != VM_PROT_ALL)
158272343Sngie				usage();
159272343Sngie			break;
160272343Sngie		case 'r':
161272343Sngie			rtstr = optarg;
162272343Sngie			break;
163272343Sngie		case 's': /* stay on top */
164272343Sngie			detach = 0;
165272343Sngie			break;
166272343Sngie		case 't':
167272343Sngie			pflags |= PUFFS_KFLAG_WTCACHE;
168272343Sngie			break;
169272343Sngie		default:
170272343Sngie			usage();
171272343Sngie			/*NOTREACHED*/
172272343Sngie		}
173272343Sngie	}
174272343Sngie	if (pflags & PUFFS_FLAG_OPDUMP)
175272343Sngie		detach = 0;
176272343Sngie	argc -= optind;
177272343Sngie	argv += optind;
178272343Sngie
179272343Sngie	if (argc != 2)
180272343Sngie		usage();
181272343Sngie
182272343Sngie	PUFFSOP_INIT(pops);
183272343Sngie
184272343Sngie	PUFFSOP_SET(pops, dtfs, fs, statvfs);
185272343Sngie	PUFFSOP_SET(pops, dtfs, fs, unmount);
186272343Sngie	PUFFSOP_SETFSNOP(pops, sync);
187272343Sngie	PUFFSOP_SET(pops, dtfs, fs, fhtonode);
188272343Sngie	PUFFSOP_SET(pops, dtfs, fs, nodetofh);
189272343Sngie
190272343Sngie	PUFFSOP_SET(pops, dtfs, node, lookup);
191272343Sngie	PUFFSOP_SET(pops, dtfs, node, access);
192272343Sngie	PUFFSOP_SET(pops, puffs_genfs, node, getattr);
193272343Sngie	PUFFSOP_SET(pops, dtfs, node, setattr);
194272343Sngie	PUFFSOP_SET(pops, dtfs, node, create);
195272343Sngie	PUFFSOP_SET(pops, dtfs, node, remove);
196272343Sngie	PUFFSOP_SET(pops, dtfs, node, readdir);
197272343Sngie	PUFFSOP_SET(pops, dtfs, node, poll);
198272343Sngie	PUFFSOP_SET(pops, dtfs, node, mmap);
199272343Sngie	PUFFSOP_SET(pops, dtfs, node, mkdir);
200272343Sngie	PUFFSOP_SET(pops, dtfs, node, rmdir);
201272343Sngie	PUFFSOP_SET(pops, dtfs, node, rename);
202272343Sngie	PUFFSOP_SET(pops, dtfs, node, read);
203272343Sngie	PUFFSOP_SET(pops, dtfs, node, write);
204272343Sngie	PUFFSOP_SET(pops, dtfs, node, link);
205272343Sngie	PUFFSOP_SET(pops, dtfs, node, symlink);
206272343Sngie	PUFFSOP_SET(pops, dtfs, node, readlink);
207272343Sngie	PUFFSOP_SET(pops, dtfs, node, mknod);
208272343Sngie	PUFFSOP_SET(pops, dtfs, node, inactive);
209272343Sngie	PUFFSOP_SET(pops, dtfs, node, pathconf);
210272343Sngie	PUFFSOP_SET(pops, dtfs, node, reclaim);
211272343Sngie
212272343Sngie	srandom(time(NULL)); /* for random generation numbers */
213272343Sngie
214272343Sngie	pu = puffs_init(pops, _PATH_PUFFS, typename, &gdtm, pflags);
215272343Sngie	if (pu == NULL)
216272343Sngie		err(1, "init");
217272343Sngie	gpu = pu;
218272343Sngie
219272343Sngie	puffs_setfhsize(pu, sizeof(struct dtfs_fid),
220272343Sngie	    PUFFS_FHFLAG_NFSV2 | PUFFS_FHFLAG_NFSV3
221272343Sngie	    | (dynamicfh ? PUFFS_FHFLAG_DYNAMIC : 0));
222272343Sngie	puffs_setncookiehash(pu, khashbuckets);
223272343Sngie
224272343Sngie	if (signal(SIGALRM, wipe_the_sleep_out_of_my_eyes) == SIG_ERR)
225272343Sngie		warn("cannot set alarm sighandler");
226272343Sngie
227272343Sngie	/* init */
228272343Sngie	if (dtfs_domount(pu, rtstr) != 0)
229272343Sngie		errx(1, "dtfs_domount failed");
230272343Sngie
231272343Sngie	po_root = puffs_getrootpathobj(pu);
232272343Sngie	po_root->po_path = argv[0];
233272343Sngie	po_root->po_len = strlen(argv[0]);
234272343Sngie
235272343Sngie	/* often enough for testing poll */
236272343Sngie	ts.tv_sec = 1;
237272343Sngie	ts.tv_nsec = 0;
238272343Sngie	puffs_ml_setloopfn(pu, loopfun);
239272343Sngie	puffs_ml_settimeout(pu, &ts);
240272343Sngie
241272343Sngie	if (maxreqsize != MAXREQMAGIC)
242272343Sngie		puffs_setmaxreqlen(pu, maxreqsize);
243272343Sngie
244272343Sngie	puffs_set_errnotify(pu, puffs_kernerr_abort);
245272343Sngie	if (detach)
246272343Sngie		if (puffs_daemon(pu, 1, 1) == -1)
247272343Sngie			err(1, "puffs_daemon");
248272343Sngie
249272343Sngie	if (puffs_mount(pu,  argv[1], mntflags, puffs_getroot(pu)) == -1)
250272343Sngie		err(1, "mount");
251272343Sngie	if (puffs_mainloop(pu) == -1)
252272343Sngie		err(1, "mainloop");
253272343Sngie
254272343Sngie	return 0;
255272343Sngie}
256