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 55 static struct puffs_usermount *gpu; 56 static struct dtfs_mount gdtm; 57 int dynamicfh; 58 int straightflush; 59 60 static void usage(void); 61 62 static void 63 usage() 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 72 static void 73 wipe_the_sleep_out_of_my_eyes(int v) 74 { 75 76 gdtm.dtm_needwakeup++; 77 } 78 79 static void 80 loopfun(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 96 int 97 main(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