Merge 2_2_bugfix up to 2_2_merge1
authorMiklos Szeredi <miklos@szeredi.hu>
Mon, 21 Mar 2005 11:47:04 +0000 (11:47 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Mon, 21 Mar 2005 11:47:04 +0000 (11:47 +0000)
ChangeLog
example/Makefile.am
kernel/configure.ac
kernel/dev.c
kernel/fuse_i.h
kernel/inode.c
lib/fuse_mt.c

index 4fb2babf1f80ba9e4bcaa4fdd318a502da39344b..4aa92de746b4b653a9a18e0b9ac77d4dcd635ab4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2005-03-19  Miklos Szeredi <miklos@szeredi.hu>
+
+       * kernel: add locking to background list (fixes previous fix)
+
+2005-03-18  Miklos Szeredi <miklos@szeredi.hu>
+
+       * kernel: fix bug which could cause leave busy inodes after
+       unmount, and Oops.
+
+2005-03-08  Miklos Szeredi <miklos@szeredi.hu>
+
+       * examples: add -lpthread to link flags to work around valgrind
+       quirk
+
+       * lib: don't exit threads, so cancelation doesn't cause segfault
+
 2005-03-04  Miklos Szeredi <miklos@szeredi.hu>
 
        * kernel: fix nasty bug which could cause an Oops under certain
index 475cabf10854514aa363433779562245fb236bc5..e8c8a6dccc8ab270ccfc9b6c5af491047d98fda4 100644 (file)
@@ -6,4 +6,4 @@ fusexmp_SOURCES = fusexmp.c
 null_SOURCES = null.c
 hello_SOURCES = hello.c
 
-LDADD = ../lib/libfuse.la
+LDADD = ../lib/libfuse.la -lpthread
index a27cecaedf79c58dfd69c72cf83351f117e1cf08..62c2b2ffef82cdb0206c78e4af801116a561348d 100644 (file)
@@ -1,4 +1,4 @@
-AC_INIT(fuse-kernel, 2.2.1)
+AC_INIT(fuse-kernel, 2.2)
 AC_CONFIG_HEADERS([config.h])
 
 AC_PROG_INSTALL
index f3de9de71746cb2e25f0f00f1245d8686e753f6e..5941035196c3336cc97cbfe2b0b38db8ffa333f8 100644 (file)
@@ -178,6 +178,19 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
                fuse_putback_request(fc, req);
 }
 
+void fuse_release_background(struct fuse_req *req)
+{
+       if (req->inode)
+               iput(req->inode);
+       if (req->inode2)
+               iput(req->inode2);
+       if (req->file)
+               fput(req->file);
+       spin_lock(&fuse_lock);
+       list_del(&req->bg_entry);
+       spin_unlock(&fuse_lock);
+}
+
 /* Called with fuse_lock, unlocks it */
 static void request_end(struct fuse_conn *fc, struct fuse_req *req)
 {
@@ -186,12 +199,10 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
        putback = atomic_dec_and_test(&req->count);
        spin_unlock(&fuse_lock);
        if (req->background) {
-               if (req->inode)
-                       iput(req->inode);
-               if (req->inode2)
-                       iput(req->inode2);
-               if (req->file)
-                       fput(req->file);
+               down_read(&fc->sbput_sem);
+               if (fc->sb)
+                       fuse_release_background(req);
+               up_read(&fc->sbput_sem);
        }
        wake_up(&req->waitq);
        if (req->in.h.opcode == FUSE_INIT) {
@@ -207,11 +218,12 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
                fuse_putback_request(fc, req);
 }
 
-static void background_request(struct fuse_req *req)
+static void background_request(struct fuse_conn *fc, struct fuse_req *req)
 {
        /* Need to get hold of the inode(s) and/or file used in the
           request, so FORGET and RELEASE are not sent too early */
        req->background = 1;
+       list_add(&req->bg_entry, &fc->background);
        if (req->inode)
                req->inode = igrab(req->inode);
        if (req->inode2)
@@ -231,7 +243,8 @@ static int request_wait_answer_nonint(struct fuse_req *req)
 }
 
 /* Called with fuse_lock held.  Releases, and then reacquires it. */
-static void request_wait_answer(struct fuse_req *req, int interruptible)
+static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req,
+                               int interruptible)
 {
        int intr;
 
@@ -271,7 +284,7 @@ static void request_wait_answer(struct fuse_req *req, int interruptible)
                list_del(&req->list);
                __fuse_put_request(req);
        } else if (!req->finished && req->sent)
-               background_request(req);
+               background_request(fc, req);
 }
 
 static unsigned len_args(unsigned numargs, struct fuse_arg *args)
@@ -315,7 +328,7 @@ static void request_send_wait(struct fuse_conn *fc, struct fuse_req *req,
                   after request_end() */
                __fuse_get_request(req);
 
-               request_wait_answer(req, interruptible);
+               request_wait_answer(fc, req, interruptible);
        }
        spin_unlock(&fuse_lock);
 }
@@ -351,7 +364,9 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req)
 void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
 {
        req->isreply = 1;
-       background_request(req);
+       spin_lock(&fuse_lock);
+       background_request(fc, req);
+       spin_unlock(&fuse_lock);
        request_send_nowait(fc, req);
 }
 
index 4aa643bdf5c84e129654d669bb65c97e0e8fcf43..d8770718f7b66ab8212d1e6214fbf5e3e760dacc 100644 (file)
@@ -190,6 +190,9 @@ struct fuse_req {
            lists in fuse_conn */
        struct list_head list;
 
+       /** Entry on the background list */
+       struct list_head bg_entry;
+
        /** refcount */
        atomic_t count;
 
@@ -284,6 +287,10 @@ struct fuse_conn {
        /** The list of requests being processed */
        struct list_head processing;
 
+       /** Requests put in the background (RELEASE or any other
+           interrupted request) */
+       struct list_head background;
+
        /** Controls the maximum number of outstanding requests */
        struct semaphore outstanding_sem;
 
@@ -291,6 +298,9 @@ struct fuse_conn {
            outstanding_sem would go negative */
        unsigned outstanding_debt;
 
+       /** RW semaphore for exclusion with fuse_put_super() */
+       struct rw_semaphore sbput_sem;
+
        /** The list of unused requests */
        struct list_head unused_list;
 
@@ -361,6 +371,7 @@ extern struct file_operations fuse_dev_operations;
  *  - the private_data field of the device file
  *  - the s_fs_info field of the super block
  *  - unused_list, pending, processing lists in fuse_conn
+ *  - background list in fuse_conn
  *  - the unique request ID counter reqctr in fuse_conn
  *  - the sb (super_block) field in fuse_conn
  *  - the file (device file) field in fuse_conn
@@ -488,6 +499,11 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req);
  */
 void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
 
+/**
+ * Release inodes and file assiciated with background request
+ */
+void fuse_release_background(struct fuse_req *req);
+
 /**
  * Get the attributes of a file
  */
index d935d588f6133ddfc2d99c39f0dd601798b0e3d2..1feaba9ab1bb6251b5d63938245863f327242d02 100644 (file)
@@ -100,7 +100,7 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
 static void fuse_clear_inode(struct inode *inode)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
-       if (fc) {
+       if (fc && (inode->i_sb->s_flags & MS_ACTIVE)) {
                struct fuse_inode *fi = get_fuse_inode(inode);
                fuse_send_forget(fc, fi->forget_req, fi->nodeid, inode->i_version);
                fi->forget_req = NULL;
@@ -254,12 +254,18 @@ static void fuse_put_super(struct super_block *sb)
 {
        struct fuse_conn *fc = get_fuse_conn_super(sb);
 
+       down_write(&fc->sbput_sem);
+       while (!list_empty(&fc->background))
+               fuse_release_background(list_entry(fc->background.next,
+                                                  struct fuse_req, bg_entry));
+
        spin_lock(&fuse_lock);
        fc->sb = NULL;
        fc->user_id = 0;
        fc->flags = 0;
        /* Flush all readers on this fs */
        wake_up_all(&fc->waitq);
+       up_write(&fc->sbput_sem);
        fuse_release_conn(fc);
        *get_fuse_conn_super_p(sb) = NULL;
        spin_unlock(&fuse_lock);
@@ -467,7 +473,9 @@ static struct fuse_conn *new_conn(void)
                INIT_LIST_HEAD(&fc->pending);
                INIT_LIST_HEAD(&fc->processing);
                INIT_LIST_HEAD(&fc->unused_list);
+               INIT_LIST_HEAD(&fc->background);
                sema_init(&fc->outstanding_sem, 0);
+               init_rwsem(&fc->sbput_sem);
                for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
                        struct fuse_req *req = fuse_request_alloc();
                        if (!req) {
index 2e43671282e3290f569e438300c3c8f6b90d95ef..819a2b9c189751072a467692ac80e4cd25a3820b 100644 (file)
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
+#include <unistd.h>
 #include <signal.h>
 #include <errno.h>
 #include <sys/time.h>
@@ -36,6 +37,7 @@ static void *do_work(void *data)
     struct fuse_worker *w = (struct fuse_worker *) data;
     struct fuse *f = w->f;
     struct fuse_context *ctx;
+    int is_mainthread = (f->numworker == 1);
 
     ctx = (struct fuse_context *) malloc(sizeof(struct fuse_context));
     if (ctx == NULL) {
@@ -83,6 +85,10 @@ static void *do_work(void *data)
         w->proc(w->f, cmd, w->data);
     }
 
+    /* Wait for cancellation */
+    if (!is_mainthread)
+        pause();
+
     return NULL;
 }