|
From: Miklos S. <mi...@sz...> - 2012-01-23 16:28:01
|
Mike Shal <ma...@gm...> writes:
> I tried it out, but I ran into the following issues:
> - I don't go through fuse_setup_common() (I use fuse_mount();
> fuse_new(); then pthread_create a new thread to do fuse_loop()), so
> main_thread was never set, resulting in a crash.
Thanks for testing. Yeah f->main_thread should be initialized in
fuse_loop/fuse_loop_mt, rather than in fuse_setup.
Fixed patch below.
> - If instead I explicitly set main_thread to my thread that does
> fuse_loop(), fuse will terminate on fuse_terminate(), but my process
> is already checking for SIGTERM and shuts down as a result. I could
> probably reconfigure things to ignore this SIGTERM, but I don't know
> if it is worth the effort.
Instead of initiating shutdown from SIGTERM you can initiate it after
fuse_loop(). That way you can use the default signal handlers which are
set up with fuse_set_signal_handlers().
>
> So for me it is not so useful - I am content to continue using the
> system(fusermount) way that I do now. I can't speak for the original
> poster though. Maybe he is doing things slightly different.
Doing "fusermount -u -z ..." will cleanly remove the mount and will not
fail.
But note, this is not guaranteed to terminate the filesystem. If some
process is still accessing it (e.g. CWD inside the mount) then the
filesystem process will continue serving requests as long as it needs.
So doing fuse_terminate() and "fusermount -u -z" are two different
things with different purposes. Which one you need is for you to
decide.
Thanks,
Miklos
diff --git a/include/fuse.h b/include/fuse.h
index b05152d..2f9fbe6 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -670,10 +670,27 @@ int fuse_loop(struct fuse *f);
/**
* Exit from event loop
*
+ * This sets the exit flag on the event loop. Note: this will only
+ * cause immediate exit if called from a signal handler or from a
+ * filesystem operation. Otherwise the loop will exit on the next
+ * event (filesystem operation or signal).
+ *
* @param f the FUSE handle
*/
void fuse_exit(struct fuse *f);
+
+/**
+ * Terminate the event loop
+ *
+ * Similar to fuse_exit() but also sends SIGTERM to the loop, causing
+ * immediate exit even if not called from a filesystem operation or
+ * signal handler.
+ *
+ * @param f the FUSE handle
+ */
+void fuse_terminate(struct fuse *f);
+
/**
* FUSE event loop with multiple threads
*
diff --git a/lib/fuse.c b/lib/fuse.c
index e01f450..fb9ec05 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -49,32 +49,6 @@
#define NODE_TABLE_MIN_SIZE 8192
-struct fuse_config {
- unsigned int uid;
- unsigned int gid;
- unsigned int umask;
- double entry_timeout;
- double negative_timeout;
- double attr_timeout;
- double ac_attr_timeout;
- int ac_attr_timeout_set;
- int remember;
- int nopath;
- int debug;
- int hard_remove;
- int use_ino;
- int readdir_ino;
- int set_mode;
- int set_uid;
- int set_gid;
- int direct_io;
- int kernel_cache;
- int auto_cache;
- int intr;
- int intr_signal;
- int help;
- char *modules;
-};
struct fuse_fs {
struct fuse_operations op;
@@ -94,13 +68,6 @@ struct lock_queue_element {
pthread_cond_t cond;
};
-struct node_table {
- struct node **array;
- size_t use;
- size_t size;
- size_t split;
-};
-
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
@@ -108,38 +75,12 @@ struct node_table {
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
-struct list_head {
- struct list_head *next;
- struct list_head *prev;
-};
-
struct node_slab {
struct list_head list; /* must be the first member */
struct list_head freelist;
int used;
};
-struct fuse {
- struct fuse_session *se;
- struct node_table name_table;
- struct node_table id_table;
- struct list_head lru_table;
- fuse_ino_t ctr;
- unsigned int generation;
- unsigned int hidectr;
- pthread_mutex_t lock;
- struct fuse_config conf;
- int intr_installed;
- struct fuse_fs *fs;
- int nullpath_ok;
- int curr_ticket;
- struct lock_queue_element *lockq;
- int pagesize;
- struct list_head partial_slabs;
- struct list_head full_slabs;
- pthread_t prune_thread;
-};
-
struct lock {
int type;
off_t start;
@@ -4188,13 +4129,26 @@ static int fuse_session_loop_remember(struct fuse *f)
int fuse_loop(struct fuse *f)
{
+ int err;
+
if (!f)
return -1;
+ pthread_mutex_lock(&f->lock);
+ f->main_thread = pthread_self();
+ f->in_loop = 1;
+ pthread_mutex_unlock(&f->lock);
+
if (lru_enabled(f))
- return fuse_session_loop_remember(f);
+ err = fuse_session_loop_remember(f);
+ else
+ err = fuse_session_loop(f->se);
- return fuse_session_loop(f->se);
+ pthread_mutex_lock(&f->lock);
+ f->in_loop = 0;
+ pthread_mutex_unlock(&f->lock);
+
+ return err;
}
int fuse_invalidate(struct fuse *f, const char *path)
@@ -4209,6 +4163,15 @@ void fuse_exit(struct fuse *f)
fuse_session_exit(f->se);
}
+void fuse_terminate(struct fuse *f)
+{
+ pthread_mutex_lock(&f->lock);
+ fuse_session_exit(f->se);
+ if (f->in_loop)
+ pthread_kill(f->main_thread, SIGTERM);
+ pthread_mutex_unlock(&f->lock);
+}
+
struct fuse_context *fuse_get_context(void)
{
return &fuse_get_context_internal()->ctx;
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 78f1467..3de5103 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -58,6 +58,68 @@ struct fuse_notify_req {
struct fuse_notify_req *prev;
};
+struct fuse_config {
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int umask;
+ double entry_timeout;
+ double negative_timeout;
+ double attr_timeout;
+ double ac_attr_timeout;
+ int ac_attr_timeout_set;
+ int remember;
+ int nopath;
+ int debug;
+ int hard_remove;
+ int use_ino;
+ int readdir_ino;
+ int set_mode;
+ int set_uid;
+ int set_gid;
+ int direct_io;
+ int kernel_cache;
+ int auto_cache;
+ int intr;
+ int intr_signal;
+ int help;
+ char *modules;
+};
+
+struct list_head {
+ struct list_head *next;
+ struct list_head *prev;
+};
+
+struct node_table {
+ struct node **array;
+ size_t use;
+ size_t size;
+ size_t split;
+};
+
+struct fuse {
+ struct fuse_session *se;
+ struct node_table name_table;
+ struct node_table id_table;
+ struct list_head lru_table;
+ fuse_ino_t ctr;
+ unsigned int generation;
+ unsigned int hidectr;
+ pthread_mutex_t lock;
+ struct fuse_config conf;
+ int intr_installed;
+ struct fuse_fs *fs;
+ int nullpath_ok;
+ int curr_ticket;
+ struct lock_queue_element *lockq;
+ int pagesize;
+ struct list_head partial_slabs;
+ struct list_head full_slabs;
+ pthread_t prune_thread;
+ pthread_t main_thread;
+ int in_loop;
+};
+
struct fuse_ll {
int debug;
int allow_root;
diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c
index f6dbe71..7a8537d 100644
--- a/lib/fuse_mt.c
+++ b/lib/fuse_mt.c
@@ -66,6 +66,24 @@ static int mt_chan_receive(struct fuse_chan **chp, char *buf, size_t size)
return sizeof(cmd);
}
+static int fuse_loop_mt_session(struct fuse *f, struct fuse_session *se)
+{
+ int err;
+
+ pthread_mutex_lock(&f->lock);
+ f->main_thread = pthread_self();
+ f->in_loop = 1;
+ pthread_mutex_unlock(&f->lock);
+
+ err = fuse_session_loop_mt(se);
+
+ pthread_mutex_lock(&f->lock);
+ f->in_loop = 0;
+ pthread_mutex_unlock(&f->lock);
+
+ return err;
+}
+
int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data)
{
int res;
@@ -100,21 +118,23 @@ int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data)
return -1;
}
fuse_session_add_chan(se, ch);
- res = fuse_session_loop_mt(se);
+ res = fuse_loop_mt_session(f, se);
fuse_session_destroy(se);
return res;
}
int fuse_loop_mt(struct fuse *f)
{
+ int res;
+
if (f == NULL)
return -1;
- int res = fuse_start_cleanup_thread(f);
+ res = fuse_start_cleanup_thread(f);
if (res)
return -1;
- res = fuse_session_loop_mt(fuse_get_session(f));
+ res = fuse_loop_mt_session(f, fuse_get_session(f));
fuse_stop_cleanup_thread(f);
return res;
}
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 95bc7d9..5314730 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -196,6 +196,7 @@ FUSE_2.9 {
fuse_clean_cache;
fuse_reply_mmap;
fuse_lowlevel_notify_delete;
+ fuse_terminate;
local:
*;
|