diff --git a/lib/libpuffs/Makefile b/lib/libpuffs/Makefile index 1c29729fd..c43a4c710 100644 --- a/lib/libpuffs/Makefile +++ b/lib/libpuffs/Makefile @@ -10,7 +10,7 @@ WARNS?= 5 LIB= puffs SRCS= puffs.c callcontext.c creds.c \ - null.c pnode.c \ + paths.c pnode.c \ subr.c MAN= puffs.3 puffs_cc.3 puffs_cred.3 puffs_flush.3 \ puffs_framebuf.3 puffs_node.3 puffs_ops.3 puffs_path.3 @@ -19,10 +19,12 @@ INCSDIR= /usr/include LINTFLAGS+=-S -w .if defined(__MINIX) -SRCS+= inode.c link.c misc.c mount.c open.c path.c path_puffs.c \ - protect.c read.c stadir.c time.c utility.c table.c +.PATH: ${NETBSDSRCDIR}/minix/lib/libpuffs +SRCS+= inode.c link.c main.c misc.c mount.c open.c path.c \ + protect.c read.c stadir.c time.c utility.c \ + table.c -CPPFLAGS+= -D_MINIX_SYSTEM +CPPFLAGS+= -D_MINIX_SYSTEM -I${.CURDIR} -I${NETBSDSRCDIR}/minix/lib/libpuffs NOGCCERROR=yes .endif # defined(__MINIX) diff --git a/lib/libpuffs/callcontext.c b/lib/libpuffs/callcontext.c index eddcdeea0..53af07345 100644 --- a/lib/libpuffs/callcontext.c +++ b/lib/libpuffs/callcontext.c @@ -188,18 +188,29 @@ slowccalloc(struct puffs_usermount *pu) struct puffs_cc *volatile pcc; void *sp; size_t stacksize = 1<pu_cc_stackshift; +#ifndef __minix + const long psize = sysconf(_SC_PAGESIZE); +#endif /* !__minix */ if (puffs_fakecc) return &fakecc; sp = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, - MAP_ANON|MAP_PRIVATE, -1, 0); + MAP_ANON|MAP_PRIVATE|MAP_ALIGNED(pu->pu_cc_stackshift), -1, 0); if (sp == MAP_FAILED) return NULL; pcc = sp; memset(pcc, 0, sizeof(struct puffs_cc)); +#ifndef __minix +#ifndef __MACHINE_STACK_GROWS_UP + mprotect((uint8_t *)sp + psize, (size_t)psize, PROT_NONE); +#else + mprotect((uint8_t *)sp + stacksize - psize, (size_t)psize, PROT_NONE); +#endif +#endif /* !__minix */ + /* initialize both ucontext's */ if (getcontext(&pcc->pcc_uc) == -1) { munmap(pcc, stacksize); @@ -242,6 +253,8 @@ puffs__cc_create(struct puffs_usermount *pu, puffs_ccfunc func, pcc->pcc_func = func; pcc->pcc_farg = pcc; } else { + const long psize = sysconf(_SC_PAGESIZE); + /* link context */ pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret; @@ -251,8 +264,8 @@ puffs__cc_create(struct puffs_usermount *pu, puffs_ccfunc func, * swapcontext(). However, it gets lost. So reinit it. */ st = &pcc->pcc_uc.uc_stack; - st->ss_sp = pcc; - st->ss_size = stacksize; + st->ss_sp = ((uint8_t *)(void *)pcc) + psize; + st->ss_size = stacksize - psize; st->ss_flags = 0; /* diff --git a/lib/libpuffs/dispatcher.c b/lib/libpuffs/dispatcher.c index 590c8a802..d45706715 100644 --- a/lib/libpuffs/dispatcher.c +++ b/lib/libpuffs/dispatcher.c @@ -39,9 +39,7 @@ __RCSID("$NetBSD: dispatcher.c,v 1.46 2013/11/06 19:56:38 christos Exp $"); #include #include -#if !defined(__minix) #include -#endif /* !defined(__minix) */ #include #include #include diff --git a/lib/libpuffs/path_puffs.c b/lib/libpuffs/path_puffs.c deleted file mode 100644 index 70a64ad6c..000000000 --- a/lib/libpuffs/path_puffs.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2007 Antti Kantee. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - - -/* - * Generic routines for pathbuilding code - */ - -int -puffs_path_pcnbuild(struct puffs_usermount *pu, struct puffs_cn *pcn, - puffs_cookie_t parent) -{ - struct puffs_node *pn_parent = PU_CMAP(pu, parent); - struct puffs_cn pcn_orig; - struct puffs_pathobj po; - int rv; - - assert(pn_parent->pn_po.po_path != NULL); - assert(pu->pu_flags & PUFFS_FLAG_BUILDPATH); - pcn_orig = *pcn; - - if (pu->pu_pathtransform) { - rv = pu->pu_pathtransform(pu, &pn_parent->pn_po, pcn, &po); - if (rv) - return rv; - } else { - po.po_path = pcn->pcn_name; - po.po_len = pcn->pcn_namelen; - } - - if (pu->pu_namemod) { - rv = pu->pu_namemod(pu, &pn_parent->pn_po, pcn); - if (rv) - return rv; - } - - rv = pu->pu_pathbuild(pu, &pn_parent->pn_po, &po, 0, - &pcn->pcn_po_full); - puffs_path_buildhash(pu, &pcn->pcn_po_full); - - if (pu->pu_pathtransform) - pu->pu_pathfree(pu, &po); - - if (pu->pu_namemod && rv) - *pcn = pcn_orig; - - return rv; -} - -/* - * substitute all (child) patch prefixes. called from nodewalk, which - * in turn is called from rename - */ -void * -puffs_path_prefixadj(struct puffs_usermount *pu, struct puffs_node *pn, - void *arg) -{ - struct puffs_pathinfo *pi = arg; - struct puffs_pathobj localpo; - struct puffs_pathobj oldpo; - int rv; - - /* can't be a path prefix */ - if (pn->pn_po.po_len < pi->pi_old->po_len) - return NULL; - - if (pu->pu_pathcmp(pu, &pn->pn_po, pi->pi_old, pi->pi_old->po_len, 1)) - return NULL; - - /* otherwise we'd have two nodes with an equal path */ - assert(pn->pn_po.po_len > pi->pi_old->po_len); - - /* found a matching prefix */ - rv = pu->pu_pathbuild(pu, pi->pi_new, &pn->pn_po, - pi->pi_old->po_len, &localpo); - /* - * XXX: technically we shouldn't fail, but this is the only - * sensible thing to do here. If the buildpath routine fails, - * we will have paths in an inconsistent state. Should fix this, - * either by having two separate passes or by doing other tricks - * to make an invalid path with BUILDPATHS acceptable. - */ - if (rv != 0) - abort(); - - /* adjust hash sum */ - puffs_path_buildhash(pu, &localpo); - - /* out with the old and in with the new */ - oldpo = pn->pn_po; - pn->pn_po = localpo; - pu->pu_pathfree(pu, &oldpo); - - /* continue the walk */ - return NULL; -} - -/* - * called from nodewalk, checks for exact match - */ -void * -puffs_path_walkcmp(struct puffs_usermount *pu, struct puffs_node *pn, void *arg) -{ - struct puffs_pathobj *po = arg; - struct puffs_pathobj po2; - - if (po->po_len != PNPLEN(pn)) - return NULL; - - /* - * If hashing and the hash doesn't match, we know this is - * definitely not a match. Otherwise check for collisions. - */ - if (pu->pu_flags & PUFFS_FLAG_HASHPATH) - if (pn->pn_po.po_hash != po->po_hash) - return NULL; - - po2.po_path = PNPATH(pn); - po2.po_len = PNPLEN(pn); - - if (pu->pu_pathcmp(pu, po, &po2, PNPLEN(pn), 0) == 0) - return pn; - return NULL; -} - -/* - * Hash sum building routine. Use string hash if the buildpath routine - * is the standard one, otherwise use binary hashes. A bit whimsical - * way to choose the routine, but the binary works for strings also, - * so don't sweat it. - */ -void -puffs_path_buildhash(struct puffs_usermount *pu, struct puffs_pathobj *po) -{ - - if ((pu->pu_flags & PUFFS_FLAG_HASHPATH) == 0) - return; - - if (pu->pu_pathbuild == puffs_stdpath_buildpath) - po->po_hash = hash32_strn(po->po_path, po->po_len, - HASH32_STR_INIT); - else - po->po_hash = hash32_buf(po->po_path, po->po_len, - HASH32_BUF_INIT); -} - -/* - * Routines provided to file systems which consider a path a tuple of - * strings and / the component separator. - */ - -/*ARGSUSED*/ -int -puffs_stdpath_cmppath(struct puffs_usermount *pu, struct puffs_pathobj *c1, - struct puffs_pathobj *c2, size_t clen, int checkprefix) -{ - char *p; - int rv; - - rv = strncmp(c1->po_path, c2->po_path, clen); - if (rv) - return 1; - - if (checkprefix == 0) - return 0; - - /* sanity for next step */ - if (!(c1->po_len > c2->po_len)) - return 1; - - /* check if it's really a complete path prefix */ - p = c1->po_path; - if ((*(p + clen)) != '/') - return 1; - - return 0; -} - -/*ARGSUSED*/ -int -puffs_stdpath_buildpath(struct puffs_usermount *pu, - const struct puffs_pathobj *po_pre, const struct puffs_pathobj *po_comp, - size_t offset, struct puffs_pathobj *newpath) -{ - char *path, *pcomp; - size_t plen, complen; - size_t prelen; - int isdotdot; - - complen = po_comp->po_len - offset; - - /* seek to correct place & remove all leading '/' from component */ - pcomp = po_comp->po_path; - pcomp += offset; - while (*pcomp == '/') { - pcomp++; - complen--; - } - - /* todotdot or nottodotdot */ - if (complen == 2 && strcmp(pcomp, "..") == 0) - isdotdot = 1; - else - isdotdot = 0; - - /* - * Strip trailing components from the preceending component. - * This is an issue only for the root node, which we might want - * to be at path "/" for some file systems. - */ - prelen = po_pre->po_len; - while (prelen > 0 && *((char *)po_pre->po_path + (prelen-1)) == '/') { - assert(isdotdot == 0); - prelen--; - } - - if (isdotdot) { - char *slash; /* sweet char of mine */ - - slash = strrchr(po_pre->po_path, '/'); - assert(slash != NULL); - - plen = slash - (char *)po_pre->po_path; - - /* - * As the converse to not stripping the initial "/" above, - * don't nuke it here either. - */ - if (plen == 0) - plen++; - - path = malloc(plen + 1); - if (path == NULL) - return errno; - - strlcpy(path, po_pre->po_path, plen+1); - } else { - /* + '/' + '\0' */ - plen = prelen + 1 + complen; - path = malloc(plen + 1); - if (path == NULL) - return errno; - - strlcpy(path, po_pre->po_path, prelen+1); - strcat(path, "/"); - strncat(path, pcomp, complen); - } - - newpath->po_path = path; - newpath->po_len = plen; - - return 0; -} - -/*ARGSUSED*/ -void -puffs_stdpath_freepath(struct puffs_usermount *pu, struct puffs_pathobj *po) -{ - - free(po->po_path); -} diff --git a/lib/libpuffs/pnode.c b/lib/libpuffs/pnode.c index 49438cf96..717b4a8a1 100644 --- a/lib/libpuffs/pnode.c +++ b/lib/libpuffs/pnode.c @@ -68,12 +68,14 @@ puffs_pn_new(struct puffs_usermount *pu, void *privdata) void puffs_pn_remove(struct puffs_node *pn) { - struct puffs_usermount *pu = pn->pn_mnt; - assert(pu != NULL); LIST_REMOVE(pn, pn_entries); pn->pn_flags |= PUFFS_NODE_REMOVED; +#ifdef __minix if (pn->pn_count != 0) { + struct puffs_usermount *pu = pn->pn_mnt; + assert(pu != NULL); + /* XXX FS removes this pn from the list to prevent further * lookups from finding node after remove/rm/rename op. * But VFS still uses it, i.e. pnode is still open, and @@ -82,6 +84,7 @@ puffs_pn_remove(struct puffs_node *pn) */ LIST_INSERT_HEAD(&pu->pu_pnode_removed_lst, pn, pn_entries); } +#endif /* __minix */ } void @@ -95,10 +98,7 @@ puffs_pn_put(struct puffs_node *pn) free(pn); } -/* walk list, rv can be used either to halt or to return a value - * XXX (MINIX note): if fn is 0, then arg is ino_t and we search - * node with ino_t. TODO: modify docs. - */ +/* walk list, rv can be used either to halt or to return a value */ void * puffs_pn_nodewalk(struct puffs_usermount *pu, puffs_nodewalk_fn fn, void *arg) { @@ -108,14 +108,9 @@ puffs_pn_nodewalk(struct puffs_usermount *pu, puffs_nodewalk_fn fn, void *arg) pn_cur = LIST_FIRST(&pu->pu_pnodelst); while (pn_cur) { pn_next = LIST_NEXT(pn_cur, pn_entries); - if (fn) { - rv = fn(pu, pn_cur, arg); - if (rv) - return rv; - } else { - if (pn_cur->pn_va.va_fileid == *((ino_t*) arg)) - return pn_cur; - } + rv = fn(pu, pn_cur, arg); + if (rv) + return rv; pn_cur = pn_next; } diff --git a/lib/libpuffs/puffs.c b/lib/libpuffs/puffs.c index 5e645536f..abf37571b 100644 --- a/lib/libpuffs/puffs.c +++ b/lib/libpuffs/puffs.c @@ -37,16 +37,15 @@ __RCSID("$NetBSD: puffs.c,v 1.117 2011/11/14 01:27:42 chs Exp $"); #include #include -#if defined(__minix) -#include "fs.h" -#endif /* defined(__minix) */ - #include #include #include #include #include #include +#ifndef __minix +#include +#endif /* !__minix */ #include #include #include @@ -62,77 +61,10 @@ const struct mntopt puffsmopts[] = { PUFFSMOPT_STD, MOPT_NULL, }; -#ifdef PUFFS_WITH_THREADS -#include + +#ifndef __minix pthread_mutex_t pu_lock = PTHREAD_MUTEX_INITIALIZER; -#endif - -#if defined(__minix) -static message fs_msg; -static int fs_ipc_status; -#endif - -/* Declare some local functions. */ -static int get_work(message *msg, int *ipc_status); - -/* SEF functions and variables. */ -static void sef_local_startup(void); -static int sef_cb_init_fresh(int type, sef_init_info_t *info); -static void sef_cb_signal_handler(int signo); - -EXTERN int env_argc; -EXTERN char **env_argv; - - -#define PUFFS_MAX_ARGS 20 - -int __real_main(int argc, char* argv[]); -int __wrap_main(int argc, char* argv[]); - -int __wrap_main(int argc, char *argv[]) -{ - int i; - int new_argc = 0; - static char* new_argv[PUFFS_MAX_ARGS]; - char *name; - - /* SEF local startup. */ - env_setargs(argc, argv); - sef_local_startup(); - - global_kcred.pkcr_type = PUFFCRED_TYPE_INTERNAL; - - if (argc < 3) { - panic("Unexpected arguments, use:\ - mount -t fs /dev/ /dir [-o option1,option2]\n"); - } - - name = argv[0] + strlen(argv[0]); - while (*name != '/' && name != argv[0]) - name--; - if (name != argv[0]) - name++; - strcpy(fs_name, name); - - new_argv[new_argc] = argv[0]; - new_argc++; - - for (i = 1; i < argc; i++) { - if (new_argc >= PUFFS_MAX_ARGS) { - panic("Too many arguments, change PUFFS_MAX_ARGS"); - } - new_argv[new_argc] = argv[i]; - new_argc++; - } - - assert(new_argc > 0); - - /* Get the mount request from VFS, so we can deal with it later. */ - (void)get_work(&fs_msg, &fs_ipc_status); - - return __real_main(new_argc, new_argv); -} - +#endif /* !__minix */ #define FILLOP(lower, upper) \ do { \ @@ -170,22 +102,106 @@ fillvnopmask(struct puffs_ops *pops, struct puffs_kargs *pa) FILLOP(print, PRINT); FILLOP(read, READ); FILLOP(write, WRITE); + FILLOP(advlock, ADVLOCK); FILLOP(abortop, ABORTOP); + FILLOP(pathconf, PATHCONF); + + FILLOP(getextattr, GETEXTATTR); + FILLOP(setextattr, SETEXTATTR); + FILLOP(listextattr, LISTEXTATTR); + FILLOP(deleteextattr, DELETEEXTATTR); } #undef FILLOP +/* + * Go over all framev entries and write everything we can. This is + * mostly for the benefit of delivering "unmount" to the kernel. + */ +static void +finalpush(struct puffs_usermount *pu) +{ +#ifndef __minix + struct puffs_fctrl_io *fio; + + LIST_FOREACH(fio, &pu->pu_ios, fio_entries) { + if (fio->stat & FIO_WRGONE) + continue; + + puffs__framev_output(pu, fio->fctrl, fio); + } +#endif /* !__minix */ +} /*ARGSUSED*/ -__dead static void -puffs_defaulterror(struct puffs_usermount *pu, uint8_t type, +void +puffs_kernerr_abort(struct puffs_usermount *pu, uint8_t type, int error, const char *str, puffs_cookie_t cookie) { +#ifndef __minix + fprintf(stderr, "abort: type %d, error %d, cookie %p (%s)\n", +#else /* __minix */ lpuffs_debug("abort: type %d, error %d, cookie %p (%s)\n", +#endif /* __minix */ type, error, cookie, str); abort(); } +/*ARGSUSED*/ +void +puffs_kernerr_log(struct puffs_usermount *pu, uint8_t type, + int error, const char *str, puffs_cookie_t cookie) +{ + + syslog(LOG_WARNING, "kernel: type %d, error %d, cookie %p (%s)\n", + type, error, cookie, str); +} + +#ifndef __minix +int +puffs_getselectable(struct puffs_usermount *pu) +{ + + return pu->pu_fd; +} + +uint64_t +puffs__nextreq(struct puffs_usermount *pu) +{ + uint64_t rv; + + PU_LOCK(); + rv = pu->pu_nextreq++ | (uint64_t)1<<63; + PU_UNLOCK(); + + return rv; +} + +int +puffs_setblockingmode(struct puffs_usermount *pu, int mode) +{ + int rv, x; + + assert(puffs_getstate(pu) == PUFFS_STATE_RUNNING); + + if (mode != PUFFSDEV_BLOCK && mode != PUFFSDEV_NONBLOCK) { + errno = EINVAL; + return -1; + } + + x = mode; + rv = ioctl(pu->pu_fd, FIONBIO, &x); + + if (rv == 0) { + if (mode == PUFFSDEV_BLOCK) + pu->pu_state &= ~PU_ASYNCFD; + else + pu->pu_state |= PU_ASYNCFD; + } + + return rv; +} +#endif /* !__minix */ int puffs_getstate(struct puffs_usermount *pu) @@ -207,8 +223,10 @@ puffs_setstacksize(struct puffs_usermount *pu, size_t ss) minsize = 4*psize; if (ss < (size_t)minsize || ss == PUFFS_STACKSIZE_MIN) { if (ss != PUFFS_STACKSIZE_MIN) - lpuffs_debug("puffs_setstacksize: adjusting " +#ifndef __minix + fprintf(stderr, "puffs_setstacksize: adjusting " "stacksize to minimum %ld\n", minsize); +#endif /* !__minix */ ss = 4*psize; } @@ -222,8 +240,10 @@ puffs_setstacksize(struct puffs_usermount *pu, size_t ss) } if (bonus > 1) { stackshift++; - lpuffs_debug("puffs_setstacksize: using next power of two: " +#ifndef __minix + fprintf(stderr, "puffs_setstacksize: using next power of two: " "%d\n", 1<pu_cc_stackshift = stackshift; @@ -416,30 +436,223 @@ puffs_set_prepost(struct puffs_usermount *pu, pu->pu_oppost = pst; } +#ifndef __minix +void +puffs_setback(struct puffs_cc *pcc, int whatback) +{ + struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb); + + assert(PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN && ( + preq->preq_optype == PUFFS_VN_OPEN || + preq->preq_optype == PUFFS_VN_MMAP || + preq->preq_optype == PUFFS_VN_REMOVE || + preq->preq_optype == PUFFS_VN_RMDIR || + preq->preq_optype == PUFFS_VN_INACTIVE)); + + preq->preq_setbacks |= whatback & PUFFS_SETBACK_MASK; +} + +int +puffs_daemon(struct puffs_usermount *pu, int nochdir, int noclose) +{ + long int n; + int parent, value, fd; + + if (pipe(pu->pu_dpipe) == -1) + return -1; + + switch (fork()) { + case -1: + return -1; + case 0: + parent = 0; + break; + default: + parent = 1; + break; + } + pu->pu_state |= PU_PUFFSDAEMON; + + if (parent) { + close(pu->pu_dpipe[1]); + n = read(pu->pu_dpipe[0], &value, sizeof(int)); + if (n == -1) + err(1, "puffs_daemon"); + if (n != sizeof(value)) + errx(1, "puffs_daemon got %ld bytes", n); + if (value) { + errno = value; + err(1, "puffs_daemon"); + } + exit(0); + } else { + if (setsid() == -1) + goto fail; + + if (!nochdir) + chdir("/"); + + if (!noclose) { + fd = open(_PATH_DEVNULL, O_RDWR, 0); + if (fd == -1) + goto fail; + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + if (fd > STDERR_FILENO) + close(fd); + } + return 0; + } + + fail: + n = write(pu->pu_dpipe[1], &errno, sizeof(int)); + assert(n == 4); + return -1; +} +#endif /* !__minix */ + +static void +shutdaemon(struct puffs_usermount *pu, int error) +{ +#ifndef __minix + ssize_t n; + + n = write(pu->pu_dpipe[1], &error, sizeof(int)); + assert(n == 4); + close(pu->pu_dpipe[0]); + close(pu->pu_dpipe[1]); +#endif /* !__minix */ + pu->pu_state &= ~PU_PUFFSDAEMON; +} + int puffs_mount(struct puffs_usermount *pu, const char *dir, int mntflags, puffs_cookie_t cookie) { -#if defined(__minix) +#ifndef __minix + int rv, fd, sverrno; + char *comfd; +#endif /* !__minix */ + pu->pu_kargp->pa_root_cookie = cookie; - /* Process the already-received mount request. */ - fsdriver_process(&puffs_table, &fs_msg, fs_ipc_status, FALSE); +#ifndef __minix + /* XXXkludgehere */ + /* kauth doesn't provide this service any longer */ + if (geteuid() != 0) + mntflags |= MNT_NOSUID | MNT_NODEV; - if (!mounted) { - /* This should never happen, unless VFS misbehaves.. */ + /* + * Undocumented... Well, documented only here. + * + * This is used for imaginative purposes. If the env variable is + * set, puffs_mount() doesn't do the regular mount procedure. + * Rather, it crams the mount data down the comfd and sets comfd as + * the puffs descriptor. + * + * This shouldn't be used unless you can read my mind ( ... or write + * it, not to mention execute it, but that's starting to get silly). + */ + if ((comfd = getenv("PUFFS_COMFD")) != NULL) { + size_t len; + + if (sscanf(comfd, "%d", &pu->pu_fd) != 1) { + errno = EINVAL; + rv = -1; + goto out; + } + /* check that what we got at least resembles an fd */ + if (fcntl(pu->pu_fd, F_GETFL) == -1) { + rv = -1; + goto out; + } + +#define allwrite(buf, len) \ +do { \ + ssize_t al_rv; \ + al_rv = write(pu->pu_fd, buf, len); \ + if ((size_t)al_rv != len) { \ + if (al_rv != -1) \ + errno = EIO; \ + rv = -1; \ + goto out; \ + } \ +} while (/*CONSTCOND*/0) + len = strlen(dir)+1; + allwrite(&len, sizeof(len)); + allwrite(dir, len); + len = strlen(pu->pu_kargp->pa_mntfromname)+1; + allwrite(&len, sizeof(len)); + allwrite(pu->pu_kargp->pa_mntfromname, len); + allwrite(&mntflags, sizeof(mntflags)); + len = sizeof(*pu->pu_kargp); + allwrite(&len, sizeof(len)); + allwrite(pu->pu_kargp, sizeof(*pu->pu_kargp)); + allwrite(&pu->pu_flags, sizeof(pu->pu_flags)); +#undef allwrite + + rv = 0; + } else { + char rp[MAXPATHLEN]; + + if (realpath(dir, rp) == NULL) { + rv = -1; + goto out; + } + + if (strcmp(dir, rp) != 0) { + warnx("puffs_mount: \"%s\" is a relative path.", dir); + warnx("puffs_mount: using \"%s\" instead.", rp); + } + + fd = open(_PATH_PUFFS, O_RDWR); + if (fd == -1) { + warnx("puffs_mount: cannot open %s", _PATH_PUFFS); + rv = -1; + goto out; + } + if (fd <= 2) + warnx("puffs_mount: device fd %d (<= 2), sure this is " + "what you want?", fd); + + pu->pu_kargp->pa_fd = pu->pu_fd = fd; + if ((rv = mount(MOUNT_PUFFS, rp, mntflags, + pu->pu_kargp, sizeof(struct puffs_kargs))) == -1) + goto out; + } +#else /* __minix */ + /* Process the already-received mount request. */ + if (!lpuffs_pump()) { + /* Not mounted? This should never happen.. */ free(pu->pu_kargp); pu->pu_kargp = NULL; - errno = -EINVAL; + errno = EINVAL; return -1; } +#endif /* __minix */ PU_SETSTATE(pu, PUFFS_STATE_RUNNING); + +#ifndef __minix + out: + if (rv != 0) + sverrno = errno; + else + sverrno = 0; + free(pu->pu_kargp); + pu->pu_kargp = NULL; + + if (pu->pu_state & PU_PUFFSDAEMON) + shutdaemon(pu, sverrno); + + errno = sverrno; + return rv; +#else /* __minix */ return 0; -#endif /* defined(__minix) */ +#endif /* __minix */ } -/*ARGSUSED*/ struct puffs_usermount * puffs_init(struct puffs_ops *pops, const char *mntfromname, const char *puffsname, void *priv, uint32_t pflags) @@ -482,19 +695,25 @@ puffs_init(struct puffs_ops *pops, const char *mntfromname, pargs->pa_time32 = 0; pu->pu_flags = pflags; - buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH; /* XXX */ pu->pu_ops = *pops; free(pops); /* XXX */ pu->pu_privdata = priv; pu->pu_cc_stackshift = PUFFS_CC_STACKSHIFT_DEFAULT; LIST_INIT(&pu->pu_pnodelst); - LIST_INIT(&pu->pu_pnode_removed_lst); LIST_INIT(&pu->pu_ios); LIST_INIT(&pu->pu_ios_rmlist); LIST_INIT(&pu->pu_ccmagazin); TAILQ_INIT(&pu->pu_sched); +#ifndef __minix + pu->pu_framectrl[PU_FRAMECTRL_FS].rfb = puffs__fsframe_read; + pu->pu_framectrl[PU_FRAMECTRL_FS].wfb = puffs__fsframe_write; + pu->pu_framectrl[PU_FRAMECTRL_FS].cmpfb = puffs__fsframe_cmp; + pu->pu_framectrl[PU_FRAMECTRL_FS].gotfb = puffs__fsframe_gotframe; + pu->pu_framectrl[PU_FRAMECTRL_FS].fdnotfn = puffs_framev_unmountonclose; +#endif /* !__minix */ + /* defaults for some user-settable translation functions */ pu->pu_cmap = NULL; /* identity translation */ @@ -504,11 +723,14 @@ puffs_init(struct puffs_ops *pops, const char *mntfromname, pu->pu_pathtransform = NULL; pu->pu_namemod = NULL; - pu->pu_errnotify = puffs_defaulterror; + pu->pu_errnotify = puffs_kernerr_log; PU_SETSTATE(pu, PUFFS_STATE_BEFOREMOUNT); - global_pu = pu; +#ifdef __minix + /* Do the MINIX3-specific side of the initialization. */ + lpuffs_init(pu); +#endif /* __minix */ return pu; @@ -525,16 +747,45 @@ puffs_cancel(struct puffs_usermount *pu, int error) { assert(puffs_getstate(pu) < PUFFS_STATE_RUNNING); + shutdaemon(pu, error); free(pu); } /*ARGSUSED1*/ int -puffs_exit(struct puffs_usermount *pu, int force) +puffs_exit(struct puffs_usermount *pu, int unused /* strict compat */) { +#ifndef __minix + struct puffs_framebuf *pb; + struct puffs_req *preq; + void *winp; + size_t winlen; + int sverrno; + + pb = puffs_framebuf_make(); + if (pb == NULL) { + errno = ENOMEM; + return -1; + } + + winlen = sizeof(struct puffs_req); + if (puffs_framebuf_getwindow(pb, 0, &winp, &winlen) == -1) { + sverrno = errno; + puffs_framebuf_destroy(pb); + errno = sverrno; + return -1; + } + preq = winp; + + preq->preq_buflen = sizeof(struct puffs_req); + preq->preq_opclass = PUFFSOP_UNMOUNT; + preq->preq_id = puffs__nextreq(pu); + + puffs_framev_enqueue_justsend(pu, puffs_getselectable(pu), pb, 1, 0); +#else /* __minix */ struct puffs_node *pn; - - lpuffs_debug("puffs_exit\n"); + + lpuffs_debug("puffs_exit\n"); while ((pn = LIST_FIRST(&pu->pu_pnodelst)) != NULL) puffs_pn_put(pn); @@ -546,10 +797,36 @@ puffs_exit(struct puffs_usermount *pu, int force) if (pu->pu_state & PU_HASKQ) close(pu->pu_kq); free(pu); +#endif /* __minix */ - return 0; /* always succesful for now, WILL CHANGE */ + return 0; } +#ifndef __minix +/* no sigset_t static intializer */ +static int sigs[NSIG] = { 0, }; +static int sigcatch = 0; + +int +puffs_unmountonsignal(int sig, bool sigignore) +{ + + if (sig < 0 || sig >= (int)NSIG) { + errno = EINVAL; + return -1; + } + if (sigignore) + if (signal(sig, SIG_IGN) == SIG_ERR) + return -1; + + if (!sigs[sig]) + sigcatch++; + sigs[sig] = 1; + + return 0; +} +#endif /* !__minix */ + /* * Actual mainloop. This is called from a context which can block. * It is called either from puffs_mainloop (indirectly, via @@ -559,46 +836,235 @@ void puffs__theloop(struct puffs_cc *pcc) { struct puffs_usermount *pu = pcc->pcc_pu; +#ifndef __minix + struct puffs_framectrl *pfctrl; + struct puffs_fctrl_io *fio; + struct kevent *curev; + size_t nchanges; + int ndone; +#endif /* !__minix */ + +#ifndef __minix + while (puffs_getstate(pu) != PUFFS_STATE_UNMOUNTED) { +#else /* __minix */ + do { +#endif /* __minix */ - while (mounted || !exitsignaled) { /* * Schedule existing requests. */ while ((pcc = TAILQ_FIRST(&pu->pu_sched)) != NULL) { - lpuffs_debug("scheduling existing tasks\n"); TAILQ_REMOVE(&pu->pu_sched, pcc, pcc_schedent); puffs__goto(pcc); } - if (pu->pu_ml_lfn) { - lpuffs_debug("Calling user mainloop handler\n"); + if (pu->pu_ml_lfn) pu->pu_ml_lfn(pu); + +#ifndef __minix + /* XXX: can we still do these optimizations? */ +#if 0 + /* + * Do this here, because: + * a) loopfunc might generate some results + * b) it's still "after" event handling (except for round 1) + */ + if (puffs_req_putput(ppr) == -1) + goto out; + puffs_req_resetput(ppr); + + /* micro optimization: skip kevent syscall if possible */ + if (pu->pu_nfds == 1 && pu->pu_ml_timep == NULL + && (pu->pu_state & PU_ASYNCFD) == 0) { + pfctrl = XXX->fctrl; + puffs_framev_input(pu, pfctrl, XXX); + continue; + } +#endif + + /* else: do full processing */ + /* Don't bother worrying about O(n) for now */ + LIST_FOREACH(fio, &pu->pu_ios, fio_entries) { + if (fio->stat & FIO_WRGONE) + continue; + + pfctrl = fio->fctrl; + + /* + * Try to write out everything to avoid the + * need for enabling EVFILT_WRITE. The likely + * case is that we can fit everything into the + * socket buffer. + */ + puffs__framev_output(pu, pfctrl, fio); } - /* Wait for request message. */ - if (get_work(&fs_msg, &fs_ipc_status) != OK) - continue; /* recheck loop conditions */ + /* + * Build list of which to enable/disable in writecheck. + */ + nchanges = 0; + LIST_FOREACH(fio, &pu->pu_ios, fio_entries) { + if (fio->stat & FIO_WRGONE) + continue; - /* Process it, and send a reply. */ - fsdriver_process(&puffs_table, &fs_msg, fs_ipc_status, FALSE); + /* en/disable write checks for kqueue as needed */ + assert((FIO_EN_WRITE(fio) && FIO_RM_WRITE(fio)) == 0); + if (FIO_EN_WRITE(fio)) { + EV_SET(&pu->pu_evs[nchanges], fio->io_fd, + EVFILT_WRITE, EV_ENABLE, 0, 0, + (uintptr_t)fio); + fio->stat |= FIO_WR; + nchanges++; + } + if (FIO_RM_WRITE(fio)) { + EV_SET(&pu->pu_evs[nchanges], fio->io_fd, + EVFILT_WRITE, EV_DISABLE, 0, 0, + (uintptr_t)fio); + fio->stat &= ~FIO_WR; + nchanges++; + } + } + + ndone = kevent(pu->pu_kq, pu->pu_evs, nchanges, + pu->pu_evs, pu->pu_nevs, pu->pu_ml_timep); + + if (ndone == -1) { + if (errno != EINTR) + break; + else + continue; + } + + /* uoptimize */ + if (ndone == 0) + continue; + + /* iterate over the results */ + for (curev = pu->pu_evs; ndone--; curev++) { + int what; + +#if 0 + /* get & possibly dispatch events from kernel */ + if (curev->ident == puffsfd) { + if (puffs_req_handle(pgr, ppr, 0) == -1) + goto out; + continue; + } +#endif + + fio = (void *)curev->udata; + if (__predict_true(fio)) + pfctrl = fio->fctrl; + else + pfctrl = NULL; + if (curev->flags & EV_ERROR) { + assert(curev->filter == EVFILT_WRITE); + fio->stat &= ~FIO_WR; + + /* XXX: how to know if it's a transient error */ + puffs__framev_writeclose(pu, fio, + (int)curev->data); + puffs__framev_notify(fio, PUFFS_FBIO_ERROR); + continue; + } + + what = 0; + if (curev->filter == EVFILT_READ) { + puffs__framev_input(pu, pfctrl, fio); + what |= PUFFS_FBIO_READ; + } + + else if (curev->filter == EVFILT_WRITE) { + puffs__framev_output(pu, pfctrl, fio); + what |= PUFFS_FBIO_WRITE; + } + + else if (__predict_false(curev->filter==EVFILT_SIGNAL)){ + if ((pu->pu_state & PU_DONEXIT) == 0) { + PU_SETSFLAG(pu, PU_DONEXIT); + puffs_exit(pu, 0); + } + } + if (what) + puffs__framev_notify(fio, what); + } + + /* + * Really free fd's now that we don't have references + * to them. + */ + while ((fio = LIST_FIRST(&pu->pu_ios_rmlist)) != NULL) { + LIST_REMOVE(fio, fio_entries); + free(fio); + } +#endif /* !__minix */ } +#ifdef __minix + while (lpuffs_pump()); +#endif /* __minix */ if (puffs__cc_restoremain(pu) == -1) warn("cannot restore main context. impending doom"); - - /* May get here, if puffs_fakecc is set to 1. Currently librefuse sets it. - * Now we just return to the caller. - */ } int puffs_mainloop(struct puffs_usermount *pu) { +#ifndef __minix + struct puffs_fctrl_io *fio; +#endif /* !__minix */ struct puffs_cc *pcc; +#ifndef __minix + struct kevent *curev; + size_t nevs; + int sverrno, i; +#else /* __minix */ int sverrno; +#endif /* !__minix */ assert(puffs_getstate(pu) >= PUFFS_STATE_RUNNING); - pu->pu_state |= PU_HASKQ | PU_INLOOP; +#ifndef __minix + pu->pu_kq = kqueue(); + if (pu->pu_kq == -1) + goto out; +#endif /* !__minix */ + pu->pu_state |= PU_HASKQ; + +#ifndef __minix + puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK); + if (puffs__framev_addfd_ctrl(pu, puffs_getselectable(pu), + PUFFS_FBIO_READ | PUFFS_FBIO_WRITE, + &pu->pu_framectrl[PU_FRAMECTRL_FS]) == -1) + goto out; + + nevs = pu->pu_nevs + sigcatch; + curev = realloc(pu->pu_evs, nevs * sizeof(struct kevent)); + if (curev == NULL) + goto out; + pu->pu_evs = curev; + pu->pu_nevs = nevs; + + LIST_FOREACH(fio, &pu->pu_ios, fio_entries) { + EV_SET(curev, fio->io_fd, EVFILT_READ, EV_ADD, + 0, 0, (uintptr_t)fio); + curev++; + EV_SET(curev, fio->io_fd, EVFILT_WRITE, EV_ADD | EV_DISABLE, + 0, 0, (uintptr_t)fio); + curev++; + } + for (i = 0; i < NSIG; i++) { + if (sigs[i]) { + EV_SET(curev, i, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, + 0, 0, 0); + curev++; + } + } + assert(curev - pu->pu_evs == (ssize_t)pu->pu_nevs); + if (kevent(pu->pu_kq, pu->pu_evs, pu->pu_nevs, NULL, 0, NULL) == -1) + goto out; +#endif /* !__minix */ + + pu->pu_state |= PU_INLOOP; /* * Create alternate execution context and jump to it. Note @@ -611,12 +1077,34 @@ puffs_mainloop(struct puffs_usermount *pu) if (puffs__cc_create(pu, puffs__theloop, &pcc) == -1) { goto out; } + +#if 0 if (puffs__cc_savemain(pu) == -1) { goto out; } +#else + /* + * XXX + * puffs__cc_savemain() uses getcontext() and then returns. + * the caller (this function) may overwrite the stack frame + * of puffs__cc_savemain(), so when we call setcontext() later and + * return from puffs__cc_savemain() again, the return address or + * saved stack pointer can be garbage. + * avoid this by calling getcontext() directly here. + */ + extern int puffs_fakecc; + if (!puffs_fakecc) { + PU_CLRSFLAG(pu, PU_MAINRESTORE); + if (getcontext(&pu->pu_mainctx) == -1) { + goto out; + } + } +#endif + if ((pu->pu_state & PU_MAINRESTORE) == 0) puffs_cc_continue(pcc); + finalpush(pu); errno = 0; out: @@ -629,64 +1117,3 @@ puffs_mainloop(struct puffs_usermount *pu) else return 0; } - -#if defined(__minix) -/*===========================================================================* - * sef_local_startup * - *===========================================================================*/ -static void sef_local_startup(void) -{ - /* Register init callbacks. */ - sef_setcb_init_fresh(sef_cb_init_fresh); - - /* Register signal callbacks. */ - sef_setcb_signal_handler(sef_cb_signal_handler); - - /* Let SEF perform startup. */ - sef_startup(); -} - -/*===========================================================================* - * sef_cb_init_fresh * - *===========================================================================*/ -static int sef_cb_init_fresh(int type, sef_init_info_t *info) -{ -/* Initialize the Minix file server. */ - return(OK); -} - -/*===========================================================================* - * sef_cb_signal_handler * - *===========================================================================*/ -static void sef_cb_signal_handler(int signo) -{ - /* Only check for termination signal, ignore anything else. */ - if (signo != SIGTERM) return; - - exitsignaled = 1; - fs_sync(); - - sef_cancel(); -} - -/*===========================================================================* - * get_work * - *===========================================================================*/ -static int get_work(message *msg, int *ipc_status) -{ - int r; - - for (;;) { - if ((r = sef_receive_status(ANY, msg, ipc_status)) != OK) { - if (r == EINTR) /* sef_cancel from signal handler? */ - break; /* see if we can exit the main loop */ - panic("sef_receive failed: %d", r); - } - if (msg->m_source == VFS_PROC_NR) - break; - lpuffs_debug("libpuffs: unexpected source %d\n", msg->m_source); - } - - return r; -} -#endif /* defined(__minix) */ diff --git a/lib/libpuffs/puffs_priv.h b/lib/libpuffs/puffs_priv.h index 39bc9826d..15ea12716 100644 --- a/lib/libpuffs/puffs_priv.h +++ b/lib/libpuffs/puffs_priv.h @@ -37,19 +37,11 @@ #include #include -#if defined(__minix) - -/* XXX: MINIX */ -#define ATIME 002 /* set if atime field needs updating */ -#define CTIME 004 /* set if ctime field needs updating */ -#define MTIME 010 /* set if mtime field needs updating */ - -#else +#if !defined(__minix) extern pthread_mutex_t pu_lock; #define PU_LOCK() pthread_mutex_lock(&pu_lock) #define PU_UNLOCK() pthread_mutex_unlock(&pu_lock) -#endif /* defined(__minix) */ -#if defined(__minix) +#else /* defined(__minix) */ #define PU_LOCK() /* nothing */ #define PU_UNLOCK() /* nothing */ #endif /* defined(__minix) */ @@ -135,7 +127,7 @@ struct puffs_usermount { struct puffs_node *pu_pn_root; LIST_HEAD(, puffs_node) pu_pnodelst; -#if defined(__minix) // LSC TO KEEP?? +#if defined(__minix) LIST_HEAD(, puffs_node) pu_pnode_removed_lst; #endif /* defined(__minix) */ @@ -272,6 +264,15 @@ int puffs__fsframe_cmp(struct puffs_usermount *, struct puffs_framebuf *, void puffs__fsframe_gotframe(struct puffs_usermount *, struct puffs_framebuf *); +uint64_t puffs__nextreq(struct puffs_usermount *pu); + +#ifdef __minix +int lpuffs_pump(void); +void lpuffs_init(struct puffs_usermount *); +void lpuffs_debug(const char *format, ...) + __attribute__((__format__(__printf__, 1, 2))); +#endif /* __minix */ + __END_DECLS #endif /* _PUFFS_PRIVATE_H_ */ diff --git a/lib/libpuffs/requests.c b/lib/libpuffs/requests.c index ce8473c1e..e33fe017b 100644 --- a/lib/libpuffs/requests.c +++ b/lib/libpuffs/requests.c @@ -38,9 +38,7 @@ __RCSID("$NetBSD: requests.c,v 1.24 2013/01/23 20:22:34 riastradh Exp $"); #include #include -#if !defined(__minix) #include -#endif /* !defined(__minix) */ #include #include diff --git a/minix/lib/libpuffs/const.h b/minix/lib/libpuffs/const.h new file mode 100644 index 000000000..4b3eee080 --- /dev/null +++ b/minix/lib/libpuffs/const.h @@ -0,0 +1,8 @@ +#ifndef _LIBPUFFS_CONST_H +#define _LIBPUFFS_CONST_H + +#define ATIME 002 /* set if atime field needs updating */ +#define CTIME 004 /* set if ctime field needs updating */ +#define MTIME 010 /* set if mtime field needs updating */ + +#endif /* !_LIBPUFFS_CONST_H */ diff --git a/lib/libpuffs/fs.h b/minix/lib/libpuffs/fs.h similarity index 85% rename from lib/libpuffs/fs.h rename to minix/lib/libpuffs/fs.h index d7ac39298..add8a17d2 100644 --- a/lib/libpuffs/fs.h +++ b/minix/lib/libpuffs/fs.h @@ -24,6 +24,14 @@ #include +#include +#include +#include + +#include "puffs.h" +#include "puffs_priv.h" + +#include "const.h" #include "proto.h" #include "glo.h" diff --git a/lib/libpuffs/glo.h b/minix/lib/libpuffs/glo.h similarity index 100% rename from lib/libpuffs/glo.h rename to minix/lib/libpuffs/glo.h diff --git a/lib/libpuffs/inode.c b/minix/lib/libpuffs/inode.c similarity index 94% rename from lib/libpuffs/inode.c rename to minix/lib/libpuffs/inode.c index a773b6edd..4b581b3a3 100644 --- a/lib/libpuffs/inode.c +++ b/minix/lib/libpuffs/inode.c @@ -4,12 +4,6 @@ */ #include "fs.h" -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - void release_node(struct puffs_usermount *pu, struct puffs_node *pn) { @@ -37,7 +31,7 @@ int fs_putnode(ino_t ino_nr, unsigned int count) */ struct puffs_node *pn; - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) { + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) { /* XXX Probably removed from the list, see puffs_pn_remove() */ struct puffs_node *pn_cur, *pn_next; pn_cur = LIST_FIRST(&global_pu->pu_pnode_removed_lst); diff --git a/lib/libpuffs/link.c b/minix/lib/libpuffs/link.c similarity index 93% rename from lib/libpuffs/link.c rename to minix/lib/libpuffs/link.c index 3d07fa6c2..b55ed00ee 100644 --- a/lib/libpuffs/link.c +++ b/minix/lib/libpuffs/link.c @@ -1,12 +1,5 @@ #include "fs.h" -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - - /*===========================================================================* * fs_trunc * *===========================================================================*/ @@ -16,7 +9,7 @@ int fs_trunc(ino_t ino_nr, off_t start, off_t end) struct puffs_node *pn; PUFFS_MAKECRED(pcr, &global_kcred); - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) return(EINVAL); if (end == 0) { @@ -27,7 +20,7 @@ int fs_trunc(ino_t ino_nr, off_t start, off_t end) if (global_pu->pu_ops.puffs_node_setattr == NULL) return(EINVAL); - + puffs_vattr_null(&va); va.va_size = start; @@ -74,9 +67,9 @@ int fs_link(ino_t dir_nr, char *name, ino_t ino_nr) struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}}; if (global_pu->pu_ops.puffs_node_link == NULL) - return(OK); + return(OK); - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) return(EINVAL); /* Check to see if the file has maximum number of links already. */ @@ -87,7 +80,7 @@ int fs_link(ino_t dir_nr, char *name, ino_t ino_nr) if (S_ISDIR(pn->pn_va.va_mode)) return(EPERM); - if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL) + if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL) return(EINVAL); if (pn_dir->pn_va.va_nlink == NO_LINK) { @@ -120,7 +113,7 @@ int fs_link(ino_t dir_nr, char *name, ino_t ino_nr) if (buildpath) global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full); - + if (r != OK) return(EINVAL); (void)clock_time(&cur_time); @@ -143,8 +136,8 @@ ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes) if (bytes > sizeof(path)) bytes = sizeof(path); - - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) + + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) return(EINVAL); if (!S_ISLNK(pn->pn_va.va_mode)) @@ -199,7 +192,8 @@ int fs_rename(ino_t old_dir_nr, char *old_name, ino_t new_dir_nr, strcpy(pcn_targ.pcn_name, new_name); /* Get old dir pnode */ - if ((old_dirp = puffs_pn_nodewalk(global_pu, 0, &old_dir_nr)) == NULL) + if ((old_dirp = puffs_pn_nodewalk(global_pu, find_inode_cb, + &old_dir_nr)) == NULL) return(ENOENT); old_ip = advance(old_dirp, pcn_src.pcn_name); @@ -210,7 +204,8 @@ int fs_rename(ino_t old_dir_nr, char *old_name, ino_t new_dir_nr, return(EBUSY); /* Get new dir pnode */ - if ((new_dirp = puffs_pn_nodewalk(global_pu, 0, &new_dir_nr)) == NULL) { + if ((new_dirp = puffs_pn_nodewalk(global_pu, find_inode_cb, + &new_dir_nr)) == NULL) { return(ENOENT); } else { if (new_dirp->pn_va.va_nlink == NO_LINK) { @@ -345,7 +340,7 @@ int fs_unlink(ino_t dir_nr, char *name, int call) assert(pcn.pcn_namelen <= NAME_MAX); strcpy(pcn.pcn_name, name); - if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL) + if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL) return(EINVAL); /* The last directory exists. Does the file also exist? */ @@ -388,12 +383,12 @@ int fs_unlink(ino_t dir_nr, char *name, int call) *===========================================================================*/ static int remove_dir( struct puffs_node *pn_dir, /* parent directory */ - struct puffs_node *pn, /* directory to be removed */ - struct puffs_cn *pcn /* Name, creads of directory */ + struct puffs_node *pn, /* directory to be removed */ + struct puffs_cn *pcn /* Name, creads of directory */ ) { /* A directory file has to be removed. Five conditions have to met: - * - The file must be a directory + * - The file must be a directory * - The directory must be empty (except for . and ..) * - The final component of the path must not be . or .. * - The directory must not be the root of a mounted file system (VFS) @@ -423,7 +418,7 @@ static int remove_dir( if (pn->pn_va.va_fileid == global_pu->pu_pn_root->pn_va.va_fileid) return(EBUSY); /* can't remove 'root' */ - + if (buildpath) { r = puffs_path_pcnbuild(global_pu, pcn, pn_dir); if (r) return(EINVAL); @@ -444,8 +439,8 @@ static int remove_dir( *===========================================================================*/ static int unlink_file( struct puffs_node *dirp, /* parent directory of file */ - struct puffs_node *pn, /* pnode of file, may be NULL too. */ - struct puffs_cn *pcn /* Name, creads of file */ + struct puffs_node *pn, /* pnode of file, may be NULL too. */ + struct puffs_cn *pcn /* Name, creads of file */ ) { /* Unlink 'file_name'; pn must be the pnode of 'file_name' */ @@ -454,7 +449,7 @@ static int unlink_file( assert(pn != NULL); if (global_pu->pu_ops.puffs_node_remove == NULL) - return(EINVAL); + return(EINVAL); if (S_ISDIR(pn->pn_va.va_mode)) return(EPERM); diff --git a/minix/lib/libpuffs/main.c b/minix/lib/libpuffs/main.c new file mode 100644 index 000000000..54e98f21d --- /dev/null +++ b/minix/lib/libpuffs/main.c @@ -0,0 +1,147 @@ + +#include "fs.h" + +static message fs_msg; +static int fs_ipc_status; +static int fs_pending; + +#define PUFFS_MAX_ARGS 20 + +/*===========================================================================* + * sef_cb_init_fresh * + *===========================================================================*/ +static int sef_cb_init_fresh(int type, sef_init_info_t *info) +{ +/* Initialize the Minix file server. */ + return(OK); +} + +/*===========================================================================* + * sef_cb_signal_handler * + *===========================================================================*/ +static void sef_cb_signal_handler(int signo) +{ + /* Only check for termination signal, ignore anything else. */ + if (signo != SIGTERM) return; + + exitsignaled = 1; + if (mounted) + fs_sync(); + + sef_cancel(); +} + +/*===========================================================================* + * sef_local_startup * + *===========================================================================*/ +static void sef_local_startup(void) +{ + /* Register init callbacks. */ + sef_setcb_init_fresh(sef_cb_init_fresh); + + /* Register signal callbacks. */ + sef_setcb_signal_handler(sef_cb_signal_handler); + + /* Let SEF perform startup. */ + sef_startup(); +} + +/*===========================================================================* + * get_work * + *===========================================================================*/ +static int get_work(message *msg, int *ipc_status) +{ + int r; + + for (;;) { + if ((r = sef_receive_status(ANY, msg, ipc_status)) != OK) { + if (r == EINTR) /* sef_cancel from signal handler? */ + break; /* see if we can exit the main loop */ + panic("sef_receive failed: %d", r); + } + if (msg->m_source == VFS_PROC_NR) + break; + lpuffs_debug("libpuffs: unexpected source %d\n", msg->m_source); + } + + return r; +} + +int __wrap_main(int argc, char *argv[]); +int __real_main(int argc, char* argv[]); + +int __wrap_main(int argc, char *argv[]) +{ + int i; + int new_argc = 0; + static char* new_argv[PUFFS_MAX_ARGS]; + char *name; + + /* SEF local startup. */ + env_setargs(argc, argv); + sef_local_startup(); + + global_kcred.pkcr_type = PUFFCRED_TYPE_INTERNAL; + + if (argc < 3) { + panic("Unexpected arguments, use:\ + mount -t fs /dev/ /dir [-o option1,option2]\n"); + } + + name = argv[0] + strlen(argv[0]); + while (*name != '/' && name != argv[0]) + name--; + if (name != argv[0]) + name++; + strcpy(fs_name, name); + + new_argv[new_argc] = argv[0]; + new_argc++; + + for (i = 1; i < argc; i++) { + if (new_argc >= PUFFS_MAX_ARGS) { + panic("Too many arguments, change PUFFS_MAX_ARGS"); + } + new_argv[new_argc] = argv[i]; + new_argc++; + } + + assert(new_argc > 0); + + /* Get the mount request from VFS, so we can deal with it later. */ + (void)get_work(&fs_msg, &fs_ipc_status); + fs_pending = TRUE; + + return __real_main(new_argc, new_argv); +} + +/* + * Receive a message unless one was already pending. Process the message, and + * send a reply if necessary. Return whether puffs should keep running. + */ +int +lpuffs_pump(void) +{ + + if (fs_pending == TRUE || get_work(&fs_msg, &fs_ipc_status) == OK) { + fs_pending = FALSE; + + fsdriver_process(&puffs_table, &fs_msg, fs_ipc_status, FALSE); + } + + return mounted || !exitsignaled; +} + +/* + * Initialize MINIX3-specific settings. + */ +void +lpuffs_init(struct puffs_usermount * pu) +{ + + buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH; /* XXX */ + + LIST_INIT(&pu->pu_pnode_removed_lst); + + global_pu = pu; +} diff --git a/lib/libpuffs/misc.c b/minix/lib/libpuffs/misc.c similarity index 90% rename from lib/libpuffs/misc.c rename to minix/lib/libpuffs/misc.c index f58c225ed..19391e8c4 100644 --- a/lib/libpuffs/misc.c +++ b/minix/lib/libpuffs/misc.c @@ -3,10 +3,6 @@ */ #include "fs.h" -#include - -#include "puffs.h" -#include "puffs_priv.h" /*===========================================================================* * fs_sync * diff --git a/lib/libpuffs/mount.c b/minix/lib/libpuffs/mount.c similarity index 92% rename from lib/libpuffs/mount.c rename to minix/lib/libpuffs/mount.c index 237744e15..c3d712f3d 100644 --- a/lib/libpuffs/mount.c +++ b/minix/lib/libpuffs/mount.c @@ -4,11 +4,8 @@ #include "fs.h" #include -#include #include -#include "puffs_priv.h" - /*===========================================================================* * fs_mount * *===========================================================================*/ @@ -51,7 +48,7 @@ int fs_mountpt(ino_t ino_nr) struct puffs_node *pn; mode_t bits; - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) return(EINVAL); if (pn->pn_mountpoint) r = EBUSY; @@ -77,10 +74,10 @@ void fs_unmount(void) /* Always force unmounting, as VFS will not tolerate failure. */ error = global_pu->pu_ops.puffs_fs_unmount(global_pu, MNT_FORCE); if (error) { - lpuffs_debug("user handler failed to unmount filesystem!\ + lpuffs_debug("user handler failed to unmount filesystem!\ Force unmount!\n"); - } - + } + fs_sync(); /* Finish off the unmount. */ diff --git a/lib/libpuffs/open.c b/minix/lib/libpuffs/open.c similarity index 94% rename from lib/libpuffs/open.c rename to minix/lib/libpuffs/open.c index 6fbe414cf..ccd588572 100644 --- a/lib/libpuffs/open.c +++ b/minix/lib/libpuffs/open.c @@ -3,12 +3,6 @@ */ #include "fs.h" -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - /*===========================================================================* * fs_create * @@ -27,7 +21,7 @@ int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid, struct timespec cur_time; if (global_pu->pu_ops.puffs_node_create == NULL) { - lpuffs_debug("No puffs_node_create"); + lpuffs_debug("No puffs_node_create"); return(ENFILE); } @@ -37,14 +31,14 @@ int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid, strcpy(pcn.pcn_name, name); /* Get last directory pnode (i.e., directory that will hold the new pnode) */ - if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL) + if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL) return(ENOENT); memset(&pni, 0, sizeof(pni)); pni.pni_cookie = (void** )&pn; (void)clock_time(&cur_time); - + memset(&va, 0, sizeof(va)); va.va_type = VREG; va.va_mode = mode; @@ -111,7 +105,7 @@ int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid, struct timespec cur_time; if (global_pu->pu_ops.puffs_node_mknod == NULL) { - lpuffs_debug("No puffs_node_mknod"); + lpuffs_debug("No puffs_node_mknod"); return(ENFILE); } @@ -121,7 +115,7 @@ int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid, strcpy(pcn.pcn_name, name); /* Get last directory pnode */ - if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL) + if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL) return(ENOENT); memset(&pni, 0, sizeof(pni)); @@ -183,7 +177,7 @@ int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid) struct timespec cur_time; if (global_pu->pu_ops.puffs_node_mkdir == NULL) { - lpuffs_debug("No puffs_node_mkdir"); + lpuffs_debug("No puffs_node_mkdir"); return(ENFILE); } @@ -193,9 +187,9 @@ int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid) strcpy(pcn.pcn_name, name); /* Get last directory pnode */ - if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL) + if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL) return(ENOENT); - + (void)clock_time(&cur_time); memset(&pni, 0, sizeof(pni)); @@ -283,7 +277,7 @@ int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid, return(ENAMETOOLONG); } - if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL) + if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL) return(EINVAL); memset(&pni, 0, sizeof(pni)); diff --git a/lib/libpuffs/path.c b/minix/lib/libpuffs/path.c similarity index 94% rename from lib/libpuffs/path.c rename to minix/lib/libpuffs/path.c index 76a4de60b..5c08eef29 100644 --- a/lib/libpuffs/path.c +++ b/minix/lib/libpuffs/path.c @@ -12,16 +12,6 @@ #include #include -#include -#include -#include -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - - /*===========================================================================* * fs_lookup * *===========================================================================*/ @@ -31,7 +21,7 @@ int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node, struct puffs_node *pn, *pn_dir; /* Find the pnode of the directory node. */ - if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL) { + if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL) { lpuffs_debug("nodewalk failed\n"); return(EINVAL); } diff --git a/lib/libpuffs/protect.c b/minix/lib/libpuffs/protect.c similarity index 91% rename from lib/libpuffs/protect.c rename to minix/lib/libpuffs/protect.c index b612552fc..ef3480848 100644 --- a/lib/libpuffs/protect.c +++ b/minix/lib/libpuffs/protect.c @@ -21,9 +21,9 @@ int fs_chmod(ino_t ino_nr, mode_t *mode) if (global_pu->pu_ops.puffs_node_setattr == NULL) return(EINVAL); - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) return(EINVAL); - + puffs_vattr_null(&va); /* Clear setgid bit if file is not in caller's grp */ va.va_mode = (pn->pn_va.va_mode & ~ALL_MODES) | (*mode & ALL_MODES); @@ -48,7 +48,7 @@ int fs_chown(ino_t ino_nr, uid_t uid, gid_t gid, mode_t *mode) struct vattr va; PUFFS_MAKECRED(pcr, &global_kcred); - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) return(EINVAL); puffs_vattr_null(&va); diff --git a/lib/libpuffs/proto.h b/minix/lib/libpuffs/proto.h similarity index 95% rename from lib/libpuffs/proto.h rename to minix/lib/libpuffs/proto.h index 35a14826d..b566a1ba9 100644 --- a/lib/libpuffs/proto.h +++ b/minix/lib/libpuffs/proto.h @@ -61,8 +61,8 @@ int fs_statvfs(struct statvfs *st); int fs_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime); /* utility.c */ +void *find_inode_cb(struct puffs_usermount *pu, struct puffs_node *pn, + void *arg); int update_timens(struct puffs_node *pn, int fl, struct timespec *); -void lpuffs_debug(const char *format, ...) - __attribute__((__format__(__printf__, 1, 2))); #endif /* PUFFS_PROTO_H */ diff --git a/lib/libpuffs/read.c b/minix/lib/libpuffs/read.c similarity index 92% rename from lib/libpuffs/read.c rename to minix/lib/libpuffs/read.c index a528a708b..5fdbe5b50 100644 --- a/lib/libpuffs/read.c +++ b/minix/lib/libpuffs/read.c @@ -4,15 +4,9 @@ #include "fs.h" #include -#include -#include #include -#include #include -#include "puffs.h" -#include "puffs_priv.h" - #define GETDENTS_BUFSIZ 4096 static char getdents_buf[GETDENTS_BUFSIZ]; @@ -32,7 +26,7 @@ ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, struct puffs_node *pn; PUFFS_MAKECRED(pcr, &global_kcred); - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) { + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) { lpuffs_debug("walk failed...\n"); return(EINVAL); } @@ -76,7 +70,7 @@ ssize_t fs_write(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, struct timespec cur_time; PUFFS_MAKECRED(pcr, &global_kcred); - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) { + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) { lpuffs_debug("walk failed...\n"); return(EINVAL); } @@ -127,7 +121,7 @@ ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, int eofflag = 0; PUFFS_MAKECRED(pcr, &global_kcred); - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) { + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) { lpuffs_debug("walk failed...\n"); return(EINVAL); } diff --git a/lib/libpuffs/stadir.c b/minix/lib/libpuffs/stadir.c similarity index 91% rename from lib/libpuffs/stadir.c rename to minix/lib/libpuffs/stadir.c index c617bc4bf..d6decd364 100644 --- a/lib/libpuffs/stadir.c +++ b/minix/lib/libpuffs/stadir.c @@ -3,12 +3,6 @@ */ #include "fs.h" -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - /*===========================================================================* * fs_stat * @@ -26,8 +20,8 @@ int fs_stat(ino_t ino_nr, struct stat *statbuf) return(EINVAL); } - if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) { - lpuffs_debug("walk failed...\n"); + if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) { + lpuffs_debug("walk failed...\n"); return(EINVAL); } diff --git a/lib/libpuffs/table.c b/minix/lib/libpuffs/table.c similarity index 100% rename from lib/libpuffs/table.c rename to minix/lib/libpuffs/table.c diff --git a/lib/libpuffs/time.c b/minix/lib/libpuffs/time.c similarity index 87% rename from lib/libpuffs/time.c rename to minix/lib/libpuffs/time.c index 4edcca59f..73c07aaf6 100644 --- a/lib/libpuffs/time.c +++ b/minix/lib/libpuffs/time.c @@ -3,8 +3,6 @@ */ #include "fs.h" -#include "puffs.h" -#include "puffs_priv.h" /*===========================================================================* @@ -19,7 +17,7 @@ int fs_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime) if (global_pu->pu_ops.puffs_node_setattr == NULL) return(EINVAL); - if( (pn = puffs_pn_nodewalk(global_pu, 0, &ino_nr)) == NULL) + if( (pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) return(EINVAL); puffs_vattr_null(&va); diff --git a/lib/libpuffs/utility.c b/minix/lib/libpuffs/utility.c similarity index 84% rename from lib/libpuffs/utility.c rename to minix/lib/libpuffs/utility.c index bbd5123e2..4c0a6bad8 100644 --- a/lib/libpuffs/utility.c +++ b/minix/lib/libpuffs/utility.c @@ -4,12 +4,21 @@ #include "fs.h" -#include #include -#include "puffs.h" -#include "puffs_priv.h" +/* + * Match by inode number in a puffs_pn_nodewalk call. This should not exist. + */ +void * +find_inode_cb(struct puffs_usermount * __unused pu, struct puffs_node * pn, + void * arg) +{ + if (pn->pn_va.va_fileid == *(ino_t *)arg) + return pn; + else + return NULL; +} /*===========================================================================* * update_timens * @@ -31,7 +40,7 @@ int update_timens(struct puffs_node *pn, int flags, struct timespec *t) new_time = *t; else (void)clock_time(&new_time); - + puffs_vattr_null(&va); /* librefuse modifies atime and mtime together, * so set old values to avoid setting either one @@ -57,7 +66,7 @@ int update_timens(struct puffs_node *pn, int flags, struct timespec *t) * lpuffs_debug * *===========================================================================*/ void lpuffs_debug(const char *format, ...) -{ +{ char buffer[256]; va_list args; va_start (args, format);