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
This commit is contained in:
David van Moolenbroek 2015-09-22 12:41:58 +00:00
parent 7c48de6cc4
commit ba736c7968
25 changed files with 862 additions and 602 deletions

View File

@ -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)

View File

@ -188,18 +188,29 @@ slowccalloc(struct puffs_usermount *pu)
struct puffs_cc *volatile pcc;
void *sp;
size_t stacksize = 1<<pu->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;
/*

View File

@ -39,9 +39,7 @@ __RCSID("$NetBSD: dispatcher.c,v 1.46 2013/11/06 19:56:38 christos Exp $");
#include <assert.h>
#include <errno.h>
#if !defined(__minix)
#include <pthread.h>
#endif /* !defined(__minix) */
#include <puffs.h>
#include <puffsdump.h>
#include <stdio.h>

View File

@ -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 <sys/cdefs.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/hash.h>
#include <assert.h>
#include <errno.h>
#include <puffs.h>
#include <stdlib.h>
#include <string.h>
#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);
}

View File

@ -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;
}

View File

@ -37,16 +37,15 @@ __RCSID("$NetBSD: puffs.c,v 1.117 2011/11/14 01:27:42 chs Exp $");
#include <sys/param.h>
#include <sys/mount.h>
#if defined(__minix)
#include "fs.h"
#endif /* defined(__minix) */
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <mntopts.h>
#include <paths.h>
#ifndef __minix
#include <pthread.h>
#endif /* !__minix */
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
@ -62,77 +61,10 @@ const struct mntopt puffsmopts[] = {
PUFFSMOPT_STD,
MOPT_NULL,
};
#ifdef PUFFS_WITH_THREADS
#include <pthread.h>
#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<<stackshift);
#endif /* !__minix */
}
pu->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) */

View File

@ -37,19 +37,11 @@
#include <puffs.h>
#include <ucontext.h>
#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_ */

View File

@ -38,9 +38,7 @@ __RCSID("$NetBSD: requests.c,v 1.24 2013/01/23 20:22:34 riastradh Exp $");
#include <sys/queue.h>
#include <sys/socket.h>
#if !defined(__minix)
#include <dev/putter/putter.h>
#endif /* !defined(__minix) */
#include <assert.h>
#include <errno.h>

View File

@ -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 */

View File

@ -24,6 +24,14 @@
#include <minix/fsdriver.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "puffs.h"
#include "puffs_priv.h"
#include "const.h"
#include "proto.h"
#include "glo.h"

View File

@ -4,12 +4,6 @@
*/
#include "fs.h"
#include <string.h>
#include <assert.h>
#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);

View File

@ -1,12 +1,5 @@
#include "fs.h"
#include <stdlib.h>
#include <assert.h>
#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);

147
minix/lib/libpuffs/main.c Normal file
View File

@ -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;
}

View File

@ -3,10 +3,6 @@
*/
#include "fs.h"
#include <assert.h>
#include "puffs.h"
#include "puffs_priv.h"
/*===========================================================================*
* fs_sync *

View File

@ -4,11 +4,8 @@
#include "fs.h"
#include <fcntl.h>
#include <string.h>
#include <minix/vfsif.h>
#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. */

View File

@ -3,12 +3,6 @@
*/
#include "fs.h"
#include <string.h>
#include <assert.h>
#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));

View File

@ -12,16 +12,6 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <puffs.h>
#include <stdlib.h>
#include <string.h>
#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);
}

View File

@ -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);

View File

@ -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 */

View File

@ -4,15 +4,9 @@
#include "fs.h"
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <assert.h>
#include <sys/param.h>
#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);
}

View File

@ -3,12 +3,6 @@
*/
#include "fs.h"
#include <sys/stat.h>
#include <sys/statvfs.h>
#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);
}

View File

@ -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);

View File

@ -4,12 +4,21 @@
#include "fs.h"
#include <assert.h>
#include <stdarg.h>
#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);