libfuse: refcount fuse_chan objects
authorMiklos Szeredi <mszeredi@suse.cz>
Mon, 18 May 2015 14:55:20 +0000 (16:55 +0200)
committerMiklos Szeredi <mszeredi@suse.cz>
Mon, 18 May 2015 14:55:20 +0000 (16:55 +0200)
New functions: fuse_chan_get(), fuse_chan_put().  Removed function:
fuse_chan_destroy().

ChangeLog
include/fuse_lowlevel.h
lib/fuse_i.h
lib/fuse_lowlevel.c
lib/fuse_session.c
lib/helper.c

index 5c1c267da1136b03a917eb65db331ea4758c9497..8a6576371c4d2124ba5057877ee5072e36dacd4a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-05-23  Miklos Szeredi <miklos@szeredi.hu>
+
+       * libfuse: refcount fuse_chan objects.  New functions:
+       fuse_chan_get(), fuse_chan_put().  Removed function:
+       fuse_chan_destroy().
+
 2015-04-23  Miklos Szeredi <miklos@szeredi.hu>
 
        * libfuse: add FUSE_CAP_NO_OPEN_SUPPORT flag to ->init()
index 20e7692edadb71424d813f771b83f7d4b29e4938..3cc9db574518fe4c4e34fb2bd39d1ad8ed8104a8 100644 (file)
@@ -1705,11 +1705,19 @@ int fuse_session_loop_mt(struct fuse_session *se);
 int fuse_chan_fd(struct fuse_chan *ch);
 
 /**
- * Destroy a channel
+ * Obtain counted reference to the channel
+ *
+ * @param ch the channel
+ * @return the channel
+ */
+struct fuse_chan *fuse_chan_get(struct fuse_chan *ch);
+
+/**
+ * Drop counted reference to a channel
  *
  * @param ch the channel
  */
-void fuse_chan_destroy(struct fuse_chan *ch);
+void fuse_chan_put(struct fuse_chan *ch);
 
 #ifdef __cplusplus
 }
index 4bbcbd61b439b8d9bc131fba83b8297bc2b9f268..16adc69aa7cd6ac238f370bdf3684c673a2506f3 100644 (file)
@@ -23,6 +23,8 @@ struct fuse_session {
 struct fuse_chan {
        struct fuse_session *se;
 
+       pthread_mutex_t lock;
+       int ctr;
        int fd;
 };
 
index f25d56fe3c8892a4cea19215f25c07115229fe5f..e70733ac799b41126442945adf65e03140933010 100755 (executable)
@@ -2735,8 +2735,7 @@ static void fuse_ll_destroy(struct fuse_ll *f)
 void fuse_session_destroy(struct fuse_session *se)
 {
        fuse_ll_destroy(se->f);
-       if (se->ch != NULL)
-               fuse_chan_destroy(se->ch);
+       fuse_chan_put(se->ch);
        free(se);
 }
 
index e919e731ff78cc3c427d550cb4386fd98eaecb00..42fe5c3233b515059807cb31515448964d46f3eb 100644 (file)
@@ -84,6 +84,8 @@ struct fuse_chan *fuse_chan_new(int fd)
 
        memset(ch, 0, sizeof(*ch));
        ch->fd = fd;
+       ch->ctr = 1;
+       fuse_mutex_init(&ch->lock);
 
        return ch;
 }
@@ -98,9 +100,30 @@ struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
        return ch->se;
 }
 
-void fuse_chan_destroy(struct fuse_chan *ch)
+struct fuse_chan *fuse_chan_get(struct fuse_chan *ch)
 {
-       fuse_session_remove_chan(ch);
-       fuse_chan_close(ch);
-       free(ch);
+       assert(ch->ctr > 0);
+       pthread_mutex_lock(&ch->lock);
+       ch->ctr++;
+       pthread_mutex_unlock(&ch->lock);
+
+       return ch;
+}
+
+void fuse_chan_put(struct fuse_chan *ch)
+{
+       if (ch) {
+               pthread_mutex_lock(&ch->lock);
+               ch->ctr--;
+               if (!ch->ctr) {
+                       pthread_mutex_unlock(&ch->lock);
+                       fuse_session_remove_chan(ch);
+                       fuse_chan_close(ch);
+                       pthread_mutex_destroy(&ch->lock);
+                       free(ch);
+               } else {
+                       pthread_mutex_unlock(&ch->lock);
+               }
+
+       }
 }
index e5550c947ed638faa8d09f77f352ad677cd0e00c..cca21b528c35716fb11d79f0652ab144cf2b3f1f 100644 (file)
@@ -243,8 +243,7 @@ void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
        if (mountpoint) {
                int fd = ch ? fuse_chan_clearfd(ch) : -1;
                fuse_kern_unmount(mountpoint, fd);
-               if (ch)
-                       fuse_chan_destroy(ch);
+               fuse_chan_put(ch);
        }
 }