Revamp fs initialization code.
This commit is contained in:
parent
7b3b54b8d5
commit
f148047acd
4 changed files with 152 additions and 77 deletions
12
ChangeLog
12
ChangeLog
|
|
@ -1,3 +1,15 @@
|
|||
2006-05-24 Csaba Henk <csaba.henk@creo.hu>
|
||||
* Revamp fs initialization code.
|
||||
- Get rid of both of the kopts/lopts and the fuse_opt stuff,
|
||||
just keep opts in a dict and assemble a simple argc/argv pair
|
||||
from that. This means that for all supported API versions we can
|
||||
get away with the fuse_setup() / *fuse_loop*() / fuse_teardown()
|
||||
call sequence. This is much more clean and correct than the
|
||||
earlier approaches, and differenciating between APIs boils down
|
||||
to differenciating between the exact form of the above routines.
|
||||
- Properly catch and propagate errors.
|
||||
- Add crude support for fetching options from command line to xmp.py.
|
||||
|
||||
2006-05-23 Csaba Henk <csaba.henk@creo.hu>
|
||||
* Fix statfs index mismatch in xmp.py.
|
||||
* Rebase build system on pkg-config.
|
||||
|
|
|
|||
149
_fusemodule.c
149
_fusemodule.c
|
|
@ -43,6 +43,8 @@ static PyObject *getattr_cb=NULL, *readlink_cb=NULL, *getdir_cb=NULL,
|
|||
|
||||
static int debuglevel=0;
|
||||
|
||||
static PyObject *Py_FuseError;
|
||||
|
||||
//@-node:globals
|
||||
//@+node:PROLOGUE
|
||||
#define PROLOGUE \
|
||||
|
|
@ -449,21 +451,24 @@ static void process_cmd(struct fuse *f, struct fuse_cmd *cmd, void *data)
|
|||
//@-node:process_cmd
|
||||
//@+node:pyfuse_loop_mt
|
||||
|
||||
static void pyfuse_loop_mt(struct fuse *f)
|
||||
static int pyfuse_loop_mt(struct fuse *f)
|
||||
{
|
||||
PyInterpreterState *interp;
|
||||
PyThreadState *save;
|
||||
int err;
|
||||
|
||||
PyEval_InitThreads();
|
||||
interp = PyThreadState_Get()->interp;
|
||||
save = PyEval_SaveThread();
|
||||
#if FUSE_VERSION >= 22
|
||||
fuse_loop_mt_proc(f, process_cmd, interp);
|
||||
err = fuse_loop_mt_proc(f, process_cmd, interp);
|
||||
#else
|
||||
__fuse_loop_mt(f, process_cmd, interp);
|
||||
err = __fuse_loop_mt(f, process_cmd, interp);
|
||||
#endif
|
||||
/* Not yet reached: */
|
||||
PyEval_RestoreThread(save);
|
||||
|
||||
return(err);
|
||||
}
|
||||
//@-node:pyfuse_loop_mt
|
||||
//@+node:Fuse_main
|
||||
|
|
@ -473,40 +478,36 @@ static struct fuse *fuse=NULL;
|
|||
static PyObject *
|
||||
Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
#if FUSE_VERSION >= 26
|
||||
struct fuse_chan *chanfd;
|
||||
#else
|
||||
int chanfd;
|
||||
#if FUSE_VERSION < 26
|
||||
int fd;
|
||||
#endif
|
||||
int multithreaded=0;
|
||||
char *lopts=NULL;
|
||||
char *kopts=NULL;
|
||||
int multithreaded=0, mthp;
|
||||
char *mountpoint;
|
||||
|
||||
#if FUSE_VERSION >= 25
|
||||
struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);
|
||||
struct fuse_args fargs = FUSE_ARGS_INIT(0, NULL);
|
||||
#endif
|
||||
PyObject *fargseq;
|
||||
int err;
|
||||
int i;
|
||||
char *fmp;
|
||||
struct fuse_operations op;
|
||||
int fargc;
|
||||
char **fargv;
|
||||
|
||||
static char *kwlist[] = {
|
||||
"getattr", "readlink", "getdir", "mknod",
|
||||
"mkdir", "unlink", "rmdir", "symlink", "rename",
|
||||
"link", "chmod", "chown", "truncate", "utime",
|
||||
"open", "read", "write", "release", "statfs", "fsync",
|
||||
"mountpoint", "kopts", "lopts", "multithreaded",
|
||||
"debug", NULL};
|
||||
"fuse_args", "mountpoint", "multithreaded", "debug", NULL};
|
||||
|
||||
memset(&op, 0, sizeof(op));
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOOOOOOOOOOOOOOOsssii",
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOOOOOOOOOOOOOOOOsii",
|
||||
kwlist, &getattr_cb, &readlink_cb, &getdir_cb, &mknod_cb,
|
||||
&mkdir_cb, &unlink_cb, &rmdir_cb, &symlink_cb, &rename_cb,
|
||||
&link_cb, &chmod_cb, &chown_cb, &truncate_cb, &utime_cb,
|
||||
&open_cb, &read_cb, &write_cb, &release_cb, &statfs_cb, &fsync_cb,
|
||||
&mountpoint, &kopts, &lopts, &multithreaded, &debuglevel))
|
||||
&fargseq, &mountpoint, &multithreaded, &debuglevel))
|
||||
return NULL;
|
||||
|
||||
|
||||
#define DO_ONE_ATTR(name) if(name ## _cb) { Py_INCREF(name ## _cb); op.name = name ## _func; } else { op.name = NULL; }
|
||||
|
||||
DO_ONE_ATTR(getattr);
|
||||
|
|
@ -530,56 +531,75 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
|
|||
DO_ONE_ATTR(statfs);
|
||||
DO_ONE_ATTR(fsync);
|
||||
|
||||
#if FUSE_VERSION >= 25
|
||||
/*
|
||||
* XXX: What comes here is just a ridiculous use of the option parsing API
|
||||
* to hack on compatibility with other parts of the new API. First and
|
||||
* foremost, real C argc/argv would be good to get at...
|
||||
*/
|
||||
|
||||
#define opts2args(opts, args) \
|
||||
(opts && \
|
||||
(fuse_opt_add_arg(args, "") == -1 || \
|
||||
fuse_opt_add_arg(args, "-o") == -1 || \
|
||||
fuse_opt_add_arg(args, opts) == -1))
|
||||
|
||||
if (opts2args(kopts, &margs) || opts2args(lopts, &fargs)) {
|
||||
fuse_opt_free_args(&margs);
|
||||
fuse_opt_free_args(&fargs);
|
||||
fprintf(stderr, "out of memory\n");
|
||||
if (fargseq && !PySequence_Check(fargseq)) {
|
||||
PyErr_SetString(PyExc_TypeError, "fuse_args is not a sequence");
|
||||
return(NULL);
|
||||
}
|
||||
chanfd = fuse_mount(mountpoint,&margs);
|
||||
fuse_opt_free_args(&margs);
|
||||
|
||||
#if FUSE_VERSION >= 26
|
||||
if (! chanfd)
|
||||
#else
|
||||
if (chanfd < 0)
|
||||
#endif
|
||||
fprintf(stderr, "could not mount fuse filesystem\n");
|
||||
fargc = (fargseq ? PySequence_Length(fargseq) : 0) + 2;
|
||||
fargv = malloc(fargc * sizeof(char *));
|
||||
if (! fargv)
|
||||
return(PyErr_NoMemory());
|
||||
|
||||
fargv[0] = PyString_AsString(PySequence_GetItem(PySys_GetObject("argv"), 0));
|
||||
fargv[1] = mountpoint;
|
||||
|
||||
if (fargseq) {
|
||||
for (i=0; i < PySequence_Length(fargseq); i++) {
|
||||
PyObject *pa;
|
||||
|
||||
pa = PySequence_GetItem(fargseq, i);
|
||||
if (! PyString_Check(pa)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"fuse argument is not a string");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
fargv[i + 2] = PyString_AsString(pa);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't use the mthp value, set below. We just pass it on so that
|
||||
* the lib won't end up in dereferring a NULL pointer.
|
||||
* (Later versions check for NULL, nevertheless we play safe.)
|
||||
*/
|
||||
#if FUSE_VERSION >= 26
|
||||
fuse = fuse_new(chanfd, &fargs, &op, sizeof(op), NULL);
|
||||
fuse = fuse_setup(fargc, fargv, &op, sizeof(op), &fmp, &mthp, NULL);
|
||||
#elif FUSE_VERSION >= 22
|
||||
fuse = fuse_setup(fargc, fargv, &op, sizeof(op), &fmp, &mthp, &fd);
|
||||
#else
|
||||
fuse = fuse_new(chanfd, &fargs, &op, sizeof(op));
|
||||
fuse = __fuse_setup(fargc, fargv, &op, &fmp, &mthp, &fd);
|
||||
#endif
|
||||
#else /* FUSE_VERSION >= 25 */
|
||||
chanfd = fuse_mount(mountpoint, kopts);
|
||||
#if FUSE_VERSION >= 22
|
||||
fuse = fuse_new(chanfd, lopts, &op, sizeof(op));
|
||||
#else
|
||||
fuse = fuse_new(chanfd, lopts, &op);
|
||||
#endif
|
||||
#endif /* FUSE_VERSION >= 25 */
|
||||
free(fargv);
|
||||
assert(strcmp(mountpoint, fmp) == 0);
|
||||
|
||||
if (fuse == NULL) {
|
||||
PyErr_SetString(Py_FuseError, "filesystem initialization failed");
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if(multithreaded)
|
||||
pyfuse_loop_mt(fuse);
|
||||
err = pyfuse_loop_mt(fuse);
|
||||
else
|
||||
fuse_loop(fuse);
|
||||
|
||||
#if FUSE_VERSION >= 25
|
||||
fuse_opt_free_args(&fargs);
|
||||
err = fuse_loop(fuse);
|
||||
|
||||
#if FUSE_VERSION >= 26
|
||||
fuse_teardown(fuse, fmp);
|
||||
#elif FUSE_VERSION >= 25
|
||||
fuse_teardown(fuse, fd, fmp);
|
||||
#elif FUSE_VERSION >= 22
|
||||
fuse_teardown(fuse, fd, strdup(mountpoint));
|
||||
#else
|
||||
__fuse_teardown(fuse, fd, strdup(mountpoint));
|
||||
#endif
|
||||
//printf("Fuse_main: called\n");
|
||||
|
||||
if (err == -1) {
|
||||
PyErr_SetString(Py_FuseError, "service loop failed");
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
|
@ -658,15 +678,16 @@ DL_EXPORT(void)
|
|||
init_fuse(void)
|
||||
{
|
||||
PyObject *m, *d;
|
||||
static PyObject *ErrorObject;
|
||||
|
||||
/* Create the module and add the functions */
|
||||
m = Py_InitModule("_fuse", Fuse_methods);
|
||||
|
||||
/* Add some symbolic constants to the module */
|
||||
d = PyModule_GetDict(m);
|
||||
ErrorObject = PyErr_NewException("fuse.error", NULL, NULL);
|
||||
PyDict_SetItemString(d, "error", ErrorObject);
|
||||
Py_FuseError = PyErr_NewException("fuse.FuseError", NULL, NULL);
|
||||
PyDict_SetItemString(d, "FuseError", Py_FuseError);
|
||||
/* compat */
|
||||
PyDict_SetItemString(d, "error", Py_FuseError);
|
||||
// PyDict_SetItemString(d, "DEBUG", PyInt_FromLong(FUSE_DEBUG));
|
||||
}
|
||||
//@-node:DL_EXPORT
|
||||
|
|
|
|||
61
fuse.py
61
fuse.py
|
|
@ -21,7 +21,7 @@ try:
|
|||
except:
|
||||
pass
|
||||
|
||||
from _fuse import main, FuseGetContext, FuseInvalidate
|
||||
from _fuse import main, FuseGetContext, FuseInvalidate, FuseError
|
||||
from string import join
|
||||
import sys
|
||||
from errno import *
|
||||
|
|
@ -75,7 +75,17 @@ class Fuse:
|
|||
self.mountpoint = self.optlist[0]
|
||||
else:
|
||||
self.mountpoint = None
|
||||
|
||||
|
||||
# This kind of forced commandline parsing still sucks,
|
||||
# but:
|
||||
# - changing it would hurt compatibility
|
||||
# - if changed, that should be done cleverly:
|
||||
# either by calling down to fuse_opt or coded
|
||||
# purely in python, it should cherry-pick
|
||||
# some args/opts based on a template and place
|
||||
# that into a dict, and return the rest, so that
|
||||
# can be passed to fuselib
|
||||
|
||||
# grab command-line arguments, if any.
|
||||
# Those will override whatever parameters
|
||||
# were passed to __init__ directly.
|
||||
|
|
@ -107,23 +117,48 @@ class Fuse:
|
|||
|
||||
d = {'mountpoint': self.mountpoint}
|
||||
d['multithreaded'] = self.multithreaded
|
||||
if hasattr( self, 'debug'):
|
||||
d['lopts'] = 'debug';
|
||||
|
||||
k=[]
|
||||
if hasattr(self,'allow_other'):
|
||||
k.append('allow_other')
|
||||
if not hasattr(self, 'fuse_opt_list'):
|
||||
self.fuse_opt_list = []
|
||||
|
||||
if hasattr(self,'kernel_cache'):
|
||||
k.append('kernel_cache')
|
||||
# deprecated direct attributes for some fuse options
|
||||
for a in 'debug', 'allow_other', 'kernel_cache':
|
||||
if hasattr(self, a):
|
||||
self.fuse_opt_list.append(a);
|
||||
|
||||
if not hasattr(self, 'fuse_opts'):
|
||||
self.fuse_opts = {}
|
||||
for o in self.fuse_opt_list:
|
||||
self.fuse_opts[o] = True
|
||||
|
||||
nomount = False
|
||||
d['fuse_args'] = []
|
||||
# Regarding those lib options which are direct options
|
||||
# (used as `-x' or `--foo', rather than `-o foo'):
|
||||
# we still prefer to have them as attributes
|
||||
for a in 'help', 'version':
|
||||
if hasattr(self, 'show' + a):
|
||||
d['fuse_args'].append('--' + a)
|
||||
nomount = True
|
||||
if hasattr(self, 'foreground'):
|
||||
d['fuse_args'].append('-f')
|
||||
|
||||
opta = []
|
||||
for k in self.fuse_opts.keys():
|
||||
if self.fuse_opts[k] == True:
|
||||
opta.append(str(k))
|
||||
else:
|
||||
opta.append(str(k) + '=' + str(self.fuse_opts[k]))
|
||||
|
||||
d['fuse_args'].append("-o" + ",".join(opta))
|
||||
|
||||
if len(k):
|
||||
d['kopts'] = join(k,',')
|
||||
|
||||
for a in self._attrs:
|
||||
if hasattr(self,a):
|
||||
d[a] = ErrnoWrapper(getattr(self, a))
|
||||
apply(main, (), d)
|
||||
try:
|
||||
apply(main, (), d)
|
||||
except FuseError:
|
||||
if not nomount: raise
|
||||
#@-node:main
|
||||
#@-others
|
||||
#@-node:class Fuse
|
||||
|
|
|
|||
7
xmp.py
7
xmp.py
|
|
@ -191,6 +191,13 @@ if __name__ == '__main__':
|
|||
|
||||
server = Xmp()
|
||||
server.multithreaded = 1;
|
||||
# pass on cmdline arguments to FUSE, ending up with the very crude
|
||||
# syntax "xmp.py mp opt1 ...", ie. we can type things like
|
||||
# "xmp.py /mnt/fuse debug max_read=4096"
|
||||
# (This looks bad, but it's _not_ xmp.py who should properly parse the
|
||||
# arguments, so we don't do anything more sophisticated here ATM.)
|
||||
server.fuse_opt_list = server.optlist
|
||||
server.fuse_opts = server.optdict
|
||||
server.main()
|
||||
#@-node:mainline
|
||||
#@-others
|
||||
|
|
|
|||
Loading…
Reference in a new issue