dtfs.c revision 302408
1/* $NetBSD: dtfs.c,v 1.2 2010/07/21 06:58:25 pooka Exp $ */ 2 3/* 4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28/* 29 * Delectable Test File System: a simple in-memory file system which 30 * demonstrates the use of puffs. 31 * (a.k.a. Detrempe FS ...) 32 */ 33 34#include <sys/types.h> 35 36#include <err.h> 37#include <mntopts.h> 38#include <paths.h> 39#include <puffs.h> 40#include <signal.h> 41#include <stdio.h> 42#include <stdlib.h> 43#include <string.h> 44#include <unistd.h> 45 46#include "dtfs.h" 47 48#ifdef DEEP_ROOTED_CLUE 49#define FSNAME "detrempe" 50#else 51#define FSNAME "dt" 52#endif 53#define MAXREQMAGIC -37 54 55static struct puffs_usermount *gpu; 56static struct dtfs_mount gdtm; 57int dynamicfh; 58int straightflush; 59 60static void usage(void); 61 62static void 63usage() 64{ 65 66 fprintf(stderr, "usage: %s [-bsdftl] [-c hashbuckets] [-m maxreqsize] " 67 "[-n typename]\n [-o mntopt] [-o puffsopt] [-p prot] " 68 "[-r rootnodetype]\n detrempe /mountpoint\n", getprogname()); 69 exit(1); 70} 71 72static void 73wipe_the_sleep_out_of_my_eyes(int v) 74{ 75 76 gdtm.dtm_needwakeup++; 77} 78 79static void 80loopfun(struct puffs_usermount *pu) 81{ 82 struct dtfs_mount *dtm = puffs_getspecific(pu); 83 struct dtfs_poll *dp; 84 85 while (dtm->dtm_needwakeup) { 86 dtm->dtm_needwakeup--; 87 dp = LIST_FIRST(&dtm->dtm_pollent); 88 if (dp == NULL) 89 return; 90 91 LIST_REMOVE(dp, dp_entries); 92 puffs_cc_continue(dp->dp_pcc); 93 } 94} 95 96int 97main(int argc, char *argv[]) 98{ 99 extern char *optarg; 100 extern int optind; 101 struct puffs_usermount *pu; 102 struct puffs_pathobj *po_root; 103 struct puffs_ops *pops; 104 struct timespec ts; 105 const char *typename; 106 char *rtstr; 107 mntoptparse_t mp; 108 int pflags, detach, mntflags; 109 int ch; 110 int khashbuckets; 111 int maxreqsize; 112 113 setprogname(argv[0]); 114 115 rtstr = NULL; 116 detach = 1; 117 mntflags = 0; 118 khashbuckets = 256; 119 pflags = PUFFS_KFLAG_IAONDEMAND; 120 typename = FSNAME; 121 maxreqsize = MAXREQMAGIC; 122 gdtm.dtm_allowprot = VM_PROT_ALL; 123 while ((ch = getopt(argc, argv, "bc:dfilm:n:o:p:r:st")) != -1) { 124 switch (ch) { 125 case 'b': /* build paths, for debugging the feature */ 126 pflags |= PUFFS_FLAG_BUILDPATH; 127 break; 128 case 'c': 129 khashbuckets = atoi(optarg); 130 break; 131 case 'd': 132 dynamicfh = 1; 133 break; 134 case 'f': 135 pflags |= PUFFS_KFLAG_LOOKUP_FULLPNBUF; 136 break; 137 case 'i': 138 pflags &= ~PUFFS_KFLAG_IAONDEMAND; 139 break; 140 case 'l': 141 straightflush = 1; 142 break; 143 case 'm': 144 maxreqsize = atoi(optarg); 145 break; 146 case 'n': 147 typename = optarg; 148 break; 149 case 'o': 150 mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags); 151 if (mp == NULL) 152 err(1, "getmntopts"); 153 freemntopts(mp); 154 break; 155 case 'p': 156 gdtm.dtm_allowprot = atoi(optarg); 157 if ((gdtm.dtm_allowprot | VM_PROT_ALL) != VM_PROT_ALL) 158 usage(); 159 break; 160 case 'r': 161 rtstr = optarg; 162 break; 163 case 's': /* stay on top */ 164 detach = 0; 165 break; 166 case 't': 167 pflags |= PUFFS_KFLAG_WTCACHE; 168 break; 169 default: 170 usage(); 171 /*NOTREACHED*/ 172 } 173 } 174 if (pflags & PUFFS_FLAG_OPDUMP) 175 detach = 0; 176 argc -= optind; 177 argv += optind; 178 179 if (argc != 2) 180 usage(); 181 182 PUFFSOP_INIT(pops); 183 184 PUFFSOP_SET(pops, dtfs, fs, statvfs); 185 PUFFSOP_SET(pops, dtfs, fs, unmount); 186 PUFFSOP_SETFSNOP(pops, sync); 187 PUFFSOP_SET(pops, dtfs, fs, fhtonode); 188 PUFFSOP_SET(pops, dtfs, fs, nodetofh); 189 190 PUFFSOP_SET(pops, dtfs, node, lookup); 191 PUFFSOP_SET(pops, dtfs, node, access); 192 PUFFSOP_SET(pops, puffs_genfs, node, getattr); 193 PUFFSOP_SET(pops, dtfs, node, setattr); 194 PUFFSOP_SET(pops, dtfs, node, create); 195 PUFFSOP_SET(pops, dtfs, node, remove); 196 PUFFSOP_SET(pops, dtfs, node, readdir); 197 PUFFSOP_SET(pops, dtfs, node, poll); 198 PUFFSOP_SET(pops, dtfs, node, mmap); 199 PUFFSOP_SET(pops, dtfs, node, mkdir); 200 PUFFSOP_SET(pops, dtfs, node, rmdir); 201 PUFFSOP_SET(pops, dtfs, node, rename); 202 PUFFSOP_SET(pops, dtfs, node, read); 203 PUFFSOP_SET(pops, dtfs, node, write); 204 PUFFSOP_SET(pops, dtfs, node, link); 205 PUFFSOP_SET(pops, dtfs, node, symlink); 206 PUFFSOP_SET(pops, dtfs, node, readlink); 207 PUFFSOP_SET(pops, dtfs, node, mknod); 208 PUFFSOP_SET(pops, dtfs, node, inactive); 209 PUFFSOP_SET(pops, dtfs, node, pathconf); 210 PUFFSOP_SET(pops, dtfs, node, reclaim); 211 212 srandom(time(NULL)); /* for random generation numbers */ 213 214 pu = puffs_init(pops, _PATH_PUFFS, typename, &gdtm, pflags); 215 if (pu == NULL) 216 err(1, "init"); 217 gpu = pu; 218 219 puffs_setfhsize(pu, sizeof(struct dtfs_fid), 220 PUFFS_FHFLAG_NFSV2 | PUFFS_FHFLAG_NFSV3 221 | (dynamicfh ? PUFFS_FHFLAG_DYNAMIC : 0)); 222 puffs_setncookiehash(pu, khashbuckets); 223 224 if (signal(SIGALRM, wipe_the_sleep_out_of_my_eyes) == SIG_ERR) 225 warn("cannot set alarm sighandler"); 226 227 /* init */ 228 if (dtfs_domount(pu, rtstr) != 0) 229 errx(1, "dtfs_domount failed"); 230 231 po_root = puffs_getrootpathobj(pu); 232 po_root->po_path = argv[0]; 233 po_root->po_len = strlen(argv[0]); 234 235 /* often enough for testing poll */ 236 ts.tv_sec = 1; 237 ts.tv_nsec = 0; 238 puffs_ml_setloopfn(pu, loopfun); 239 puffs_ml_settimeout(pu, &ts); 240 241 if (maxreqsize != MAXREQMAGIC) 242 puffs_setmaxreqlen(pu, maxreqsize); 243 244 puffs_set_errnotify(pu, puffs_kernerr_abort); 245 if (detach) 246 if (puffs_daemon(pu, 1, 1) == -1) 247 err(1, "puffs_daemon"); 248 249 if (puffs_mount(pu, argv[1], mntflags, puffs_getroot(pu)) == -1) 250 err(1, "mount"); 251 if (puffs_mainloop(pu) == -1) 252 err(1, "mainloop"); 253 254 return 0; 255} 256