--- perl/trunk/Fuse.xs 2005/06/22 16:15:17 16 +++ perl-llin/Fuse.xs 2006/05/23 14:45:53 89 @@ -2,11 +2,36 @@ #include "perl.h" #include "XSUB.h" -#include +#ifdef USE_ITHREADS +# ifdef I_PTHREAD +/* perl implements threads with pthread. So, we use the pthread API for + * handling thread-local storage. */ +# include +PerlInterpreter *master_interp = NULL; +static inline void create_perl_context() { + if(master_interp) { + PerlInterpreter *me = PERL_GET_CONTEXT; + if(!me) { + PERL_SET_CONTEXT(master_interp); + me = perl_clone(master_interp, CLONEf_CLONE_HOST); + } + } +} +# define FUSE_CONTEXT_PRE create_perl_context(); { +# define FUSE_CONTEXT_POST } +# define FUSE_USE_ITHREADS +# else +# error "Sorry, I don't know how to handle ithreads on this architecture." +# endif +#else +# define FUSE_CONTEXT_PRE +# define FUSE_CONTEXT_POST +#endif +#include #undef DEBUGf #if 0 -#define DEBUGf(f, a...) fprintf(stderr, "%s:%d (%i): " f,__BASE_FILE__,__LINE__,PL_stack_sp-PL_stack_base ,##a ) +#define DEBUGf(f, a...) fprintf(stderr, "%s:%d (%i): " f,__BASE_FILE__,__LINE__,sp-PL_stack_base ,##a ) #else #define DEBUGf(a...) #endif @@ -15,8 +40,10 @@ SV *_PLfuse_callbacks[N_CALLBACKS]; int _PLfuse_getattr(const char *file, struct stat *result) { + int rv; + FUSE_CONTEXT_PRE; dSP; - int rv, statcount; + DEBUGf("getattr begin: %s\n",file); ENTER; SAVETMPS; PUSHMARK(SP); @@ -44,23 +71,25 @@ result->st_uid = POPi; result->st_nlink = POPi; result->st_mode = POPi; - /*result->st_ino =*/ POPi; + result->st_ino = POPi; result->st_dev = POPi; rv = 0; } FREETMPS; LEAVE; PUTBACK; + DEBUGf("getattr end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_readlink(const char *file,char *buf,size_t buflen) { int rv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - I32 ax; if(buflen < 1) return EINVAL; + DEBUGf("readlink begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -83,12 +112,23 @@ LEAVE; buf[buflen-1] = 0; PUTBACK; + DEBUGf("readlink end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } +#if 0 +/* + * This doesn't yet work... we alwas get ENOSYS when trying to use readdir(). + * Well, of course, getdir() is fine as well. + */ + int _PLfuse_readdir(const char *file, void *dirh, fuse_fill_dir_t dirfil, off_t off, struct fuse_file_info *fi) { +#endif int _PLfuse_getdir(const char *file, fuse_dirh_t dirh, fuse_dirfil_t dirfil) { int prv, rv; + FUSE_CONTEXT_PRE; dSP; + DEBUGf("getdir begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -99,7 +139,7 @@ if(prv) { rv = POPi; while(--prv) - dirfil(dirh,POPp,0); + dirfil(dirh,POPp,0,0); } else { fprintf(stderr,"getdir() handler returned nothing!\n"); rv = -ENOSYS; @@ -107,14 +147,16 @@ FREETMPS; LEAVE; PUTBACK; + DEBUGf("getdir end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_mknod (const char *file, mode_t mode, dev_t dev) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; + DEBUGf("mknod begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -131,15 +173,16 @@ FREETMPS; LEAVE; PUTBACK; + DEBUGf("mknod end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_mkdir (const char *file, mode_t mode) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("mkdir begin: %i\n",sp-PL_stack_base); + DEBUGf("mkdir begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -155,17 +198,17 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("mkdir end: %i %i\n",sp-PL_stack_base,rv); + DEBUGf("mkdir end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_unlink (const char *file) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("unlink begin: %i\n",sp-PL_stack_base); + DEBUGf("unlink begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -180,16 +223,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("unlink end: %i\n",sp-PL_stack_base); + DEBUGf("unlink end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_rmdir (const char *file) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("rmdir begin: %i\n",sp-PL_stack_base); + DEBUGf("rmdir begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -204,16 +247,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("rmdir end: %i %i\n",sp-PL_stack_base,rv); + DEBUGf("rmdir end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_symlink (const char *file, const char *new) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("symlink begin: %i\n",sp-PL_stack_base); + DEBUGf("symlink begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -229,16 +272,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("symlink end: %i\n",sp-PL_stack_base); + DEBUGf("symlink end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_rename (const char *file, const char *new) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("rename begin: %i\n",sp-PL_stack_base); + DEBUGf("rename begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -254,16 +297,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("rename end: %i\n",sp-PL_stack_base); + DEBUGf("rename end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_link (const char *file, const char *new) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("link begin: %i\n",sp-PL_stack_base); + DEBUGf("link begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -279,16 +322,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("link end: %i\n",sp-PL_stack_base); + DEBUGf("link end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_chmod (const char *file, mode_t mode) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("chmod begin: %i\n",sp-PL_stack_base); + DEBUGf("chmod begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -304,16 +347,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("chmod end: %i\n",sp-PL_stack_base); + DEBUGf("chmod end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_chown (const char *file, uid_t uid, gid_t gid) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("chown begin: %i\n",sp-PL_stack_base); + DEBUGf("chown begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -330,16 +373,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("chown end: %i\n",sp-PL_stack_base); + DEBUGf("chown end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_truncate (const char *file, off_t off) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("truncate begin: %i\n",sp-PL_stack_base); + DEBUGf("truncate begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -355,16 +398,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("truncate end: %i\n",sp-PL_stack_base); + DEBUGf("truncate end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_utime (const char *file, struct utimbuf *uti) { int rv; - SV *rvsv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("utime begin: %i\n",sp-PL_stack_base); + DEBUGf("utime begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -381,16 +424,17 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("utime end: %i\n",sp-PL_stack_base); + DEBUGf("utime end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } -int _PLfuse_open (const char *file, int flags) { +int _PLfuse_open (const char *file, struct fuse_file_info *fi) { int rv; - SV *rvsv; - char *rvstr; + int flags = fi->flags; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("open begin: %i\n",sp-PL_stack_base); + DEBUGf("open begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -406,15 +450,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("open end: %i %i\n",sp-PL_stack_base,rv); + DEBUGf("open end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } -int _PLfuse_read (const char *file, char *buf, size_t buflen, off_t off) { +int _PLfuse_read (const char *file, char *buf, size_t buflen, off_t off, struct fuse_file_info *fi) { int rv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("read begin: %i\n",sp-PL_stack_base); + DEBUGf("read begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -445,15 +490,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("read end: %i %i\n",sp-PL_stack_base,rv); + DEBUGf("read end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } -int _PLfuse_write (const char *file, const char *buf, size_t buflen, off_t off) { +int _PLfuse_write (const char *file, const char *buf, size_t buflen, off_t off, struct fuse_file_info *fi) { int rv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("write begin: %i\n",sp-PL_stack_base); + DEBUGf("write begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -470,29 +516,38 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("write end: %i\n",sp-PL_stack_base); + DEBUGf("write end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } -int _PLfuse_statfs (const char *file, struct statfs *st) { +int _PLfuse_statfs (const char *file, struct statvfs *st) { int rv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("statfs begin: %i\n",sp-PL_stack_base); + DEBUGf("statfs begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); PUTBACK; rv = call_sv(_PLfuse_callbacks[17],G_ARRAY); SPAGAIN; - if(rv > 5) { - st->f_bsize = POPi; - st->f_bfree = POPi; - st->f_blocks = POPi; - st->f_ffree = POPi; - st->f_files = POPi; - st->f_namelen = POPi; - if(rv > 6) + DEBUGf("statfs got %i params\n",rv); + if(rv == 6 || rv == 7) { + st->f_bsize = POPi; + st->f_bfree = POPi; + st->f_blocks = POPi; + st->f_ffree = POPi; + st->f_files = POPi; + st->f_namemax = POPi; + /* zero and fill-in other */ + st->f_fsid = 0; + st->f_frsize = 4096; + st->f_flag = 0; + st->f_bavail = st->f_bfree; + st->f_favail = st->f_ffree; + + if(rv == 7) rv = POPi; else rv = 0; @@ -507,15 +562,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("statfs end: %i\n",sp-PL_stack_base); + DEBUGf("statfs end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } -int _PLfuse_flush (const char *file) { +int _PLfuse_flush (const char *file, struct fuse_file_info *fi) { int rv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("flush begin: %i\n",sp-PL_stack_base); + DEBUGf("flush begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -530,15 +586,17 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("flush end: %i\n",sp-PL_stack_base); + DEBUGf("flush end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } -int _PLfuse_release (const char *file, int flags) { +int _PLfuse_release (const char *file, struct fuse_file_info *fi) { int rv; - char *rvstr; + int flags = fi->flags; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("release begin: %i\n",sp-PL_stack_base); + DEBUGf("release begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -554,15 +612,17 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("release end: %i\n",sp-PL_stack_base); + DEBUGf("release end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } -int _PLfuse_fsync (const char *file, int flags) { +int _PLfuse_fsync (const char *file, int datasync, struct fuse_file_info *fi) { int rv; - char *rvstr; + int flags = fi->flags; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("fsync begin: %i\n",sp-PL_stack_base); + DEBUGf("fsync begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -578,15 +638,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("fsync end: %i\n",sp-PL_stack_base); + DEBUGf("fsync end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_setxattr (const char *file, const char *name, const char *buf, size_t buflen, int flags) { int rv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("setxattr begin: %i\n",sp-PL_stack_base); + DEBUGf("setxattr begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -604,15 +665,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("setxattr end: %i\n",sp-PL_stack_base); + DEBUGf("setxattr end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_getxattr (const char *file, const char *name, char *buf, size_t buflen) { int rv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("getxattr begin: %i\n",sp-PL_stack_base); + DEBUGf("getxattr begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -647,15 +709,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("getxattr end: %i\n",sp-PL_stack_base); + DEBUGf("getxattr end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_listxattr (const char *file, char *list, size_t size) { int prv, rv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("listxattr begin: %i\n",sp-PL_stack_base); + DEBUGf("listxattr begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -670,7 +733,6 @@ char *p = list; int spc = size; int total_len = 0; - int i; rv = POPi; prv--; @@ -712,15 +774,16 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("listxattr end: %i\n",sp-PL_stack_base); + DEBUGf("listxattr end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } int _PLfuse_removexattr (const char *file, const char *name) { int rv; - char *rvstr; + FUSE_CONTEXT_PRE; dSP; - DEBUGf("removexattr begin: %i\n",sp-PL_stack_base); + DEBUGf("removexattr begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); @@ -736,7 +799,8 @@ FREETMPS; LEAVE; PUTBACK; - DEBUGf("removexattr end: %i\n",sp-PL_stack_base); + DEBUGf("removexattr end: %i\n",rv); + FUSE_CONTEXT_POST; return rv; } @@ -744,6 +808,9 @@ getattr: _PLfuse_getattr, readlink: _PLfuse_readlink, getdir: _PLfuse_getdir, +#if 0 +readdir: _PLfuse_readdir, +#endif mknod: _PLfuse_mknod, mkdir: _PLfuse_mkdir, unlink: _PLfuse_unlink, @@ -774,35 +841,82 @@ void perl_fuse_main(...) PREINIT: - struct fuse_operations fops = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; - int i, fd, varnum = 0, debug, have_mnt; + struct fuse_operations fops = + {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + int i, fd, debug, threaded; char *mountpoint; char *mountopts; - STRLEN n_a; - STRLEN l; + struct fuse_args margs = FUSE_ARGS_INIT(0, NULL); + struct fuse_args fargs = FUSE_ARGS_INIT(0, NULL); INIT: - if(items != 28) { + if(items != 29) { fprintf(stderr,"Perl<->C inconsistency or internal error\n"); XSRETURN_UNDEF; } CODE: debug = SvIV(ST(0)); - mountpoint = SvPV_nolen(ST(1)); - mountopts = SvPV_nolen(ST(2)); - /* FIXME: reevaluate multithreading support when perl6 arrives */ + threaded = SvIV(ST(1)); + if(threaded) { +#ifdef FUSE_USE_ITHREADS + master_interp = PERL_GET_INTERP; +#else + fprintf(stderr,"FUSE warning: Your script has requested multithreaded " + "mode, but your perl was not built with -Dusethreads. " + "Threads are disabled.\n"); + threaded = 0; +#endif + } + mountpoint = SvPV_nolen(ST(2)); + mountopts = SvPV_nolen(ST(3)); for(i=0;i