From ea7227db439cc0e02a7ed69feae75fac6dfcc637 Mon Sep 17 00:00:00 2001 From: Joachim Schiele Date: Thu, 20 Jun 2013 19:18:18 +0200 Subject: - added a doxygen main page - modified all examples to be included in doxygen - modified the API documentation to have more details - added the 490px_FUSE_structure.svg.png (c) wikipedia --- doc/Doxyfile | 8 +-- doc/how-fuse-works | 0 doc/images/490px-FUSE_structure.svg.png | Bin 0 -> 22606 bytes doc/mainpage.dox | 92 ++++++++++++++++++++++++++++++++ example/cusexmp.c | 15 +++++- example/fioc.c | 15 +++++- example/fioc.h | 9 ++++ example/fioclient.c | 17 +++++- example/fsel.c | 15 +++++- example/fselclient.c | 15 +++++- example/fusexmp.c | 16 +++++- example/fusexmp_fh.c | 15 +++++- example/hello.c | 31 ++++++++++- example/hello_ll.c | 41 ++++++++++++-- example/null.c | 15 +++++- include/fuse.h | 23 ++++++++ include/fuse_common.h | 9 ++++ include/fuse_lowlevel.h | 13 ++++- lib/fuse_loop_mt.c | 0 lib/fuse_signals.c | 2 + 20 files changed, 327 insertions(+), 24 deletions(-) mode change 100644 => 100755 doc/Doxyfile mode change 100644 => 100755 doc/how-fuse-works create mode 100644 doc/images/490px-FUSE_structure.svg.png create mode 100755 doc/mainpage.dox mode change 100644 => 100755 example/cusexmp.c mode change 100644 => 100755 example/fioc.c mode change 100644 => 100755 example/fioc.h mode change 100644 => 100755 example/fioclient.c mode change 100644 => 100755 example/fsel.c mode change 100644 => 100755 example/fselclient.c mode change 100644 => 100755 example/fusexmp.c mode change 100644 => 100755 example/fusexmp_fh.c mode change 100644 => 100755 example/hello.c mode change 100644 => 100755 example/hello_ll.c mode change 100644 => 100755 example/null.c mode change 100644 => 100755 lib/fuse_loop_mt.c diff --git a/doc/Doxyfile b/doc/Doxyfile old mode 100644 new mode 100755 index 3926aaf..16ce23a --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -544,7 +544,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = include +INPUT = . ../include ../example ../lib # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -561,7 +561,7 @@ INPUT_ENCODING = UTF-8 # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 -FILE_PATTERNS = *.h +FILE_PATTERNS = *.h *.c *.h *.dox # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. @@ -601,7 +601,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = . ../example/ ../lib # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -621,7 +621,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = images/ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program diff --git a/doc/how-fuse-works b/doc/how-fuse-works old mode 100644 new mode 100755 diff --git a/doc/images/490px-FUSE_structure.svg.png b/doc/images/490px-FUSE_structure.svg.png new file mode 100644 index 0000000..a4a9731 Binary files /dev/null and b/doc/images/490px-FUSE_structure.svg.png differ diff --git a/doc/mainpage.dox b/doc/mainpage.dox new file mode 100755 index 0000000..9202207 --- /dev/null +++ b/doc/mainpage.dox @@ -0,0 +1,92 @@ +/*! +\mainpage FUSE API documentation + +Filesystem in Userspace (FUSE) is a loadable kernel module for Unix-like computer operating systems that lets non-privileged users create their own file systems without editing kernel code. This is achieved by running file system code in user space while the FUSE module provides only a "bridge" to the actual kernel interfaces. + +(c) Wikipedia + +@tableofcontents + + + + + +\section section1 How FUSE works + +@image html 490px-FUSE_structure.svg.png "Structural diagramm of Filesystem in Userspace from http://en.wikipedia.org/wiki/File:FUSE_structure.svg" + +\include how-fuse-works + + + + +\section section2 Kernel + +\include kernel.txt + + + + + +\section section_examples examples + +have a look at the examples listed in the example directory, which can be found here: files.html. + +- @ref hello.c - minimal FUSE example featuring fuse_main usage + +- @ref hello_ll.c - FUSE: Filesystem in Userspace + +- @ref null.c - FUSE: Filesystem in Userspace + +- @ref cusexmp.c - CUSE example: Character device in Userspace + +- @ref fioc.c - FUSE fioc: FUSE ioctl example + +- @ref fioclient.c - FUSE fioclient: FUSE ioctl example client + +- @ref fsel.c - FUSE fsel: FUSE select example + +- @ref fselclient.c - FUSE fselclient: FUSE select example client + +- @ref fusexmp.c - FUSE: Filesystem in Userspace + +- @ref fusexmp_fh.c - FUSE: Filesystem in Userspace + + +\section section_links links + +http://sourceforge.net/apps/mediawiki/fuse/index.php?title=Main_Page - the fuse wiki + +http://en.wikipedia.org/wiki/Filesystem_in_Userspace - FUSE on wikipedia + + +\section section_todo todo + +general: + + - fuse_lowlevel.h, describe: + - a channel (or communication channel) is created by fuse_mount(..) + - a fuse session is associated with a channel and a signal handler and runs until the assigned signal handler + shuts the session down, see fuse_session_loop(se) and hello_ll.c + + - http://www.cs.nmsu.edu/~pfeiffer/fuse-tutorial/ + + - http://cinwell.wordpress.com/ + + - http://sourceforge.net/apps/mediawiki/fuse/index.php?title=FuseProtocolSketch + + - http://muratbuffalo.blogspot.de/2011/05/refuse-to-crash-with-re-fuse.html + +examples: + - demonstrate the effect of single vs multithreaded -> fuse_loop fuse_loop_mt + + - add comments and source form all existing examples + + - also add examples form here: http://sourceforge.net/apps/mediawiki/fuse/index.php?title=Main_Page#How_should_threads_be_startedx3f + + - add this new example: http://fuse.996288.n3.nabble.com/Create-multiple-filesystems-in-same-process-td9292.html + + \section section_thanks thanks + - Mark Glines, for his coments on fuse_loop() and fuse_loop_mt(). + - Wikipedia - copied the FUSE introduction from the Filesystem in userspace article. +*/ diff --git a/example/cusexmp.c b/example/cusexmp.c old mode 100644 new mode 100755 index b69f97c..a02818c --- a/example/cusexmp.c +++ b/example/cusexmp.c @@ -6,9 +6,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall cusexmp.c `pkg-config fuse --cflags --libs` -o cusexmp */ +/** @file + * @tableofcontents + * + * cusexmp.c - CUSE example: Character device in Userspace + * + * \section section_compile compiling this example + * + * gcc -Wall cusexmp.c `pkg-config fuse --cflags --libs` -o cusexmp + * + * \section section_source the complete source + * \include cusexmp.c + */ + + #define FUSE_USE_VERSION 30 #include diff --git a/example/fioc.c b/example/fioc.c old mode 100644 new mode 100755 index 849bd5d..cfb18ae --- a/example/fioc.c +++ b/example/fioc.c @@ -6,9 +6,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall fioc.c `pkg-config fuse --cflags --libs` -o fioc */ +/** @file + * @tableofcontents + * + * fioc.c - FUSE fioc: FUSE ioctl example + * + * \section section_compile compiling this example + * + * gcc -Wall fioc.c `pkg-config fuse --cflags --libs` -o fioc + * + * \section section_source the complete source + * \include fioc.c + */ + + #define FUSE_USE_VERSION 30 #include diff --git a/example/fioc.h b/example/fioc.h old mode 100644 new mode 100755 index ec1a39d..c9bf358 --- a/example/fioc.h +++ b/example/fioc.h @@ -7,6 +7,15 @@ See the file COPYING. */ +/** @file + * @tableofcontents + * + * fioc.h - FUSE-ioctl: ioctl support for FUSE + * + * \include fioc.h + */ + + #include #include #include diff --git a/example/fioclient.c b/example/fioclient.c old mode 100644 new mode 100755 index 5f05525..9718622 --- a/example/fioclient.c +++ b/example/fioclient.c @@ -5,10 +5,23 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall fioclient.c -o fioclient */ +/** @file + * @tableofcontents + * + * fioclient.c - FUSE fioclient: FUSE ioctl example client + * + * \section section_compile compiling this example + * + * gcc -Wall fioclient.c -o fioclient + * + * \section section_source the complete source + * fioclient.c + * \include fioclient.c + */ + + #include #include #include diff --git a/example/fsel.c b/example/fsel.c old mode 100644 new mode 100755 index bddc1aa..3c52033 --- a/example/fsel.c +++ b/example/fsel.c @@ -6,9 +6,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall fsel.c `pkg-config fuse --cflags --libs` -o fsel */ +/** @file + * @tableofcontents + * + * fsel.c - FUSE fsel: FUSE select example + * + * \section section_compile compiling this example + * + * gcc -Wall fsel.c `pkg-config fuse --cflags --libs` -o fsel + * + * \section section_source the complete source + * \include fsel.c + */ + + #define FUSE_USE_VERSION 30 #include diff --git a/example/fselclient.c b/example/fselclient.c old mode 100644 new mode 100755 index 7c4b837..2e2e571 --- a/example/fselclient.c +++ b/example/fselclient.c @@ -6,9 +6,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall fselclient.c -o fselclient */ +/** @file + * @tableofcontents + * + * fselclient.c - FUSE fselclient: FUSE select example client + * + * \section section_compile compiling this example + * + * gcc -Wall fselclient.c -o fselclient + * + * \section section_source the complete source + * \include fselclient.c + */ + + #include #include #include diff --git a/example/fusexmp.c b/example/fusexmp.c old mode 100644 new mode 100755 index 42a8134..73e9898 --- a/example/fusexmp.c +++ b/example/fusexmp.c @@ -5,10 +5,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall fusexmp.c `pkg-config fuse --cflags --libs` -o fusexmp */ +/** @file + * @tableofcontents + * + * fusexmp.c - FUSE: Filesystem in Userspace + * + * \section section_compile compiling this example + * + * gcc -Wall fusexmp.c `pkg-config fuse --cflags --libs` -o fusexmp + * + * \section section_source the complete source + * \include fusexmp.c + */ + + #define FUSE_USE_VERSION 30 #ifdef HAVE_CONFIG_H diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c old mode 100644 new mode 100755 index eea6b9b..e538b49 --- a/example/fusexmp_fh.c +++ b/example/fusexmp_fh.c @@ -5,10 +5,21 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall fusexmp_fh.c `pkg-config fuse --cflags --libs` -lulockmgr -o fusexmp_fh */ +/** @file + * @tableofcontents + * + * fusexmp_fh.c - FUSE: Filesystem in Userspace + * + * \section section_compile compiling this example + * + * gcc -Wall fusexmp_fh.c `pkg-config fuse --cflags --libs` -lulockmgr -o fusexmp_fh + * + * \section section_source the complete source + * \include fusexmp_fh.c + */ + #define FUSE_USE_VERSION 30 #ifdef HAVE_CONFIG_H diff --git a/example/hello.c b/example/hello.c old mode 100644 new mode 100755 index b31fbe5..c8b4a48 --- a/example/hello.c +++ b/example/hello.c @@ -4,10 +4,35 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello */ +/** @file + * + * hello.c - minimal FUSE example featuring fuse_main usage + * +* \section section_compile compiling this example + * + * gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello + * + * \section section_usage usage + \verbatim + % mkdir mnt + % ./hello mnt # program will vanish into the background + % ls -la mnt + total 4 + drwxr-xr-x 2 root root 0 Jan 1 1970 ./ + drwxrwx--- 1 root vboxsf 4096 Jun 16 23:12 ../ + -r--r--r-- 1 root root 13 Jan 1 1970 hello + % cat mnt/hello + Hello World! + % fusermount -u mnt + \endverbatim + * + * \section section_source the complete source + * \include hello.c + */ + + #define FUSE_USE_VERSION 30 #include @@ -83,6 +108,7 @@ static int hello_read(const char *path, char *buf, size_t size, off_t offset, return size; } +// fuse_operations hello_oper is redirecting function-calls to _our_ functions implemented above static struct fuse_operations hello_oper = { .getattr = hello_getattr, .readdir = hello_readdir, @@ -90,6 +116,7 @@ static struct fuse_operations hello_oper = { .read = hello_read, }; +// in the main function we call the blocking fuse_main(..) function with &hello_oper int main(int argc, char *argv[]) { return fuse_main(argc, argv, &hello_oper, NULL); diff --git a/example/hello_ll.c b/example/hello_ll.c old mode 100644 new mode 100755 index baf41bc..687c6f1 --- a/example/hello_ll.c +++ b/example/hello_ll.c @@ -4,10 +4,39 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall hello_ll.c `pkg-config fuse --cflags --libs` -o hello_ll */ +/** @file + * + * hello_ll.c - fuse low level functionality + * + * unlike hello.c this example will stay in the foreground. it also replaced + * the convenience function fuse_main(..) with a more low level approach. + * + * \section section_compile compiling this example + * + * gcc -Wall hello_ll.c `pkg-config fuse --cflags --libs` -o hello_ll + * + * \section section_usage usage + \verbatim + % mkdir mnt + % ./hello_ll mnt # program will wait in foreground until you press CTRL+C + in a different shell do: + % ls -la mnt + total 4 + drwxr-xr-x 2 root root 0 Jan 1 1970 ./ + drwxrwx--- 1 root vboxsf 4096 Jun 16 23:12 ../ + -r--r--r-- 1 root root 13 Jan 1 1970 hello + % cat mnt/hello + Hello World! + finally either press ctrl+c or do: + % fusermount -u mnt + \endverbatim + * + * \section section_source the complete source + * \include hello_ll.c + */ + #define FUSE_USE_VERSION 30 #include @@ -151,6 +180,7 @@ static struct fuse_lowlevel_ops hello_ll_oper = { .read = hello_ll_read, }; +//! [doxygen_fuse_lowlevel_usage] int main(int argc, char *argv[]) { struct fuse_args args = FUSE_ARGS_INIT(argc, argv); @@ -161,13 +191,15 @@ int main(int argc, char *argv[]) if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 && (ch = fuse_mount(mountpoint, &args)) != NULL) { struct fuse_session *se; - se = fuse_lowlevel_new(&args, &hello_ll_oper, sizeof(hello_ll_oper), NULL); if (se != NULL) { if (fuse_set_signal_handlers(se) != -1) { fuse_session_add_chan(se, ch); - err = fuse_session_loop(se); + + // fuse_session_loop(..) blocks until ctrl+c or fusermount -u + err = fuse_session_loop(se); + fuse_remove_signal_handlers(se); fuse_session_remove_chan(ch); } @@ -179,3 +211,4 @@ int main(int argc, char *argv[]) return err ? 1 : 0; } +//! [doxygen_fuse_lowlevel_usage] diff --git a/example/null.c b/example/null.c old mode 100644 new mode 100755 index 4e2bb8f..6952333 --- a/example/null.c +++ b/example/null.c @@ -4,10 +4,21 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall null.c `pkg-config fuse --cflags --libs` -o null */ +/** @file + * + * null.c - FUSE: Filesystem in Userspace + * + * \section section_compile compiling this example + * + * gcc -Wall null.c `pkg-config fuse --cflags --libs` -o null + * + * \section section_source the complete source + * \include null.c + */ + + #define FUSE_USE_VERSION 30 #include diff --git a/include/fuse.h b/include/fuse.h index 793862e..c7647ce 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -589,6 +589,8 @@ struct fuse_context { * @param op the file system operation * @param user_data user data supplied in the context during the init() method * @return 0 on success, nonzero on failure + * + * Example usage, see hello.c */ /* int fuse_main(int argc, char *argv[], const struct fuse_operations *op, @@ -635,6 +637,8 @@ void fuse_destroy(struct fuse *f); * * @param f the FUSE handle * @return 0 if no error occurred, -1 otherwise + * + * See also: fuse_loop() */ int fuse_loop(struct fuse *f); @@ -654,9 +658,28 @@ void fuse_exit(struct fuse *f); * * Calling this function requires the pthreads library to be linked to * the application. + * + * Note: using fuse_loop() instead of fuse_loop_mt() means you are running in single-threaded mode, + * and that you will not have to worry about reentrancy, + * though you will have to worry about recursive lookups. In single-threaded mode, FUSE + * holds a global lock on your filesystem, and will wait for one callback to return + * before calling another. This can lead to deadlocks, if your script makes any attempt + * to access files or directories in the filesystem it is providing. + * (This includes calling stat() on the mount-point, statfs() calls from the 'df' command, + * and so on and so forth.) It is worth paying a little attention and being careful about this. + * + * Enabling multiple threads, by using fuse_loop_mt(), will cause FUSE to make multiple simultaneous + * calls into the various callback functions given by your fuse_operations record. + * + * If you are using multiple threads, you can enjoy all the parallel execution and interactive + * response benefits of threads, and you get to enjoy all the benefits of race conditions + * and locking bugs, too. Ensure that any code used in the callback funtion of fuse_operations + * is also thread-safe. * * @param f the FUSE handle * @return 0 if no error occurred, -1 otherwise + * + * See also: fuse_loop() */ int fuse_loop_mt(struct fuse *f); diff --git a/include/fuse_common.h b/include/fuse_common.h index af16203..9fd4bbb 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -451,8 +451,14 @@ ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, * Stores session in a global variable. May only be called once per * process until fuse_remove_signal_handlers() is called. * + * Once either of the POSIX signals arrives, the exit_handler() in fuse_signals.c is called: + * \snippet fuse_signals.c doxygen_exit_handler + * * @param se the session to exit * @return 0 on success, -1 on failure + * + * See also: + * fuse_remove_signal_handlers() */ int fuse_set_signal_handlers(struct fuse_session *se); @@ -463,6 +469,9 @@ int fuse_set_signal_handlers(struct fuse_session *se); * be called again. * * @param se the same session as given in fuse_set_signal_handlers() + * + * See also: + * fuse_set_signal_handlers() */ void fuse_remove_signal_handlers(struct fuse_session *se); diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index d46ef86..ada5ce8 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -1565,6 +1565,9 @@ int fuse_req_interrupted(fuse_req_t req); * @param op_size sizeof(struct fuse_lowlevel_ops) * @param userdata user data * @return the created session object, or NULL on failure + * + * Example: See hello_ll.c: + * \snippet hello_ll.c doxygen_fuse_lowlevel_usage */ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, @@ -1707,7 +1710,9 @@ int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, void fuse_session_destroy(struct fuse_session *se); /** - * Exit a session + * Exit a session. This function is invoked by the POSIX signal handlers, when registered using: + * * fuse_set_signal_handlers() + * * fuse_remove_signal_handlers() * * @param se the session */ @@ -1737,7 +1742,11 @@ int fuse_session_exited(struct fuse_session *se); void *fuse_session_data(struct fuse_session *se); /** - * Enter a single threaded event loop + * Enter a single threaded, blocking event loop. + * + * Using POSIX signals this event loop can be exited but the session + * needs to be configued by issuing: + * fuse_set_signal_handlers() first. * * @param se the session * @return 0 on success, -1 on error diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c old mode 100644 new mode 100755 diff --git a/lib/fuse_signals.c b/lib/fuse_signals.c index 88ac39e..cab9951 100644 --- a/lib/fuse_signals.c +++ b/lib/fuse_signals.c @@ -14,12 +14,14 @@ static struct fuse_session *fuse_instance; +//! [doxygen_exit_handler] static void exit_handler(int sig) { (void) sig; if (fuse_instance) fuse_session_exit(fuse_instance); } +//! [doxygen_exit_handler] static int set_one_signal_handler(int sig, void (*handler)(int)) { -- cgit v1.2.3