From: David van Moolenbroek Date: Tue, 22 Sep 2015 12:41:58 +0000 (+0000) Subject: libpuffs: clean up, unbreak X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=refs%2Fchanges%2F96%2F3196%2F1;p=minix.git libpuffs: clean up, unbreak - move MINIX3-specific files into minix/lib/libpuffs; - resynchronize the remaining files with NetBSD code; - remove a few unnecessary changes; - put remaining MINIX3-specific changes in __minix blocks; - sort out the source files being linked at all. The result is that libpuffs now successfully links against FUSE file system programs again. It can successfully mount, perform some of the most basic operations, and unmount the file system. Change-Id: Ieac220f7ad8c4d1fa293abda81967e8045be0bb4 --- 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 -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); -} +#ifndef __minix +pthread_mutex_t pu_lock = PTHREAD_MUTEX_INITIALIZER; +#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; + + /* + * 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 (!mounted) { - /* This should never happen, unless VFS misbehaves.. */ + 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 - /* Wait for request message. */ - if (get_work(&fs_msg, &fs_ipc_status) != OK) - continue; /* recheck loop conditions */ + /* 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); + } - /* Process it, and send a reply. */ - fsdriver_process(&puffs_table, &fs_msg, fs_ipc_status, FALSE); + /* + * 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; + + /* 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);