Per the discussion here: <https://bugzilla.samba.org/show_bug.cgi?id=5847>,
the cause appears to be the fact that libsmbclient is not thread-safe.
While fusesmb uses locking around accesses to SMBC contexts, it uses
different locks for different contexts, and ends up making simultaenous
calls into libsmbclient -- something that is not supported. Therefore,
despite the fact that a reentrant libsmbclient would be great, I believe
the bugs lies in fusesmb. The attached patch causes fusesmb to use a single
mutex for all calls, and fixes the problem for me. Whereas without the
patch, gzip'ing a single file would cause a lockup 9/10 times, I can now
consistently gzip 10 files at once with no problems.


--- fusesmb-0.8.7/fusesmb.c     2007-09-06 19:02:44.000000000 -0500
+++ fusesmb-0.8.7.new/fusesmb.c 2009-03-30 15:27:43.000000000 -0500
@@ -53,7 +53,6 @@
 */
 
 static pthread_mutex_t ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t rwd_ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
 static SMBCCTX *ctx, *rwd_ctx;
 pthread_t cleanup_thread;
 
@@ -129,11 +128,9 @@
 
         pthread_mutex_lock(&ctx_mutex);
         ctx->callbacks.purge_cached_fn(ctx);
-        pthread_mutex_unlock(&ctx_mutex);
 
-        pthread_mutex_lock(&rwd_ctx_mutex);
         rwd_ctx->callbacks.purge_cached_fn(rwd_ctx);
-        pthread_mutex_unlock(&rwd_ctx_mutex);
+        pthread_mutex_unlock(&ctx_mutex);
         /*
          * Look every minute in the notfound cache for items that are
          * no longer used
@@ -204,11 +201,9 @@
         {
             pthread_mutex_lock(&ctx_mutex);
             ctx->timeout = opts.global_timeout * 1000;
-            pthread_mutex_unlock(&ctx_mutex);
 
-            pthread_mutex_lock(&rwd_ctx_mutex);
             rwd_ctx->timeout = opts.global_timeout * 1000;
-            pthread_mutex_unlock(&rwd_ctx_mutex);
+            pthread_mutex_unlock(&ctx_mutex);
         }
 
 
@@ -536,17 +531,17 @@
     //    return -ENOENT;
     strcat(smb_path, stripworkgroup(path));
 
-    pthread_mutex_lock(&rwd_ctx_mutex);
+    pthread_mutex_lock(&ctx_mutex);
     file = rwd_ctx->open(rwd_ctx, smb_path, fi->flags, 0);
 
     if (file == NULL)
     {
-        pthread_mutex_unlock(&rwd_ctx_mutex);
+        pthread_mutex_unlock(&ctx_mutex);
         return -errno;
     }
 
     fi->fh = (unsigned long)file;
-    pthread_mutex_unlock(&rwd_ctx_mutex);
+    pthread_mutex_unlock(&ctx_mutex);
     return 0;
 }
 
@@ -563,7 +558,7 @@
     int tries = 0;              //For number of retries before failing
     ssize_t ssize;              //Returned by ctx->read
 
-    pthread_mutex_lock(&rwd_ctx_mutex);
+    pthread_mutex_lock(&ctx_mutex);
     /* Ugly goto but it works ;) But IMHO easiest solution for error handling 
here */
     goto seek;
   reopen:
@@ -575,7 +570,7 @@
             tries++;
             if (tries > 4)
             {
-                pthread_mutex_unlock(&rwd_ctx_mutex);
+                pthread_mutex_unlock(&ctx_mutex);
                 return -errno;
             }
             goto reopen;
@@ -583,7 +578,7 @@
         /* Other errors from docs cannot be recovered from so returning the 
error */
         else
         {
-            pthread_mutex_unlock(&rwd_ctx_mutex);
+            pthread_mutex_unlock(&ctx_mutex);
             return -errno;
         }
     }
@@ -600,7 +595,7 @@
         else
         {
             //SMB Init failed
-            pthread_mutex_unlock(&rwd_ctx_mutex);
+            pthread_mutex_unlock(&ctx_mutex);
             return -errno;
         }
     }
@@ -614,11 +609,11 @@
         /* Tried opening a directory / or smb_init failed */
         else
         {
-            pthread_mutex_unlock(&rwd_ctx_mutex);
+            pthread_mutex_unlock(&ctx_mutex);
             return -errno;
         }
     }
-    pthread_mutex_unlock(&rwd_ctx_mutex);
+    pthread_mutex_unlock(&ctx_mutex);
     return (size_t) ssize;
 }
 
@@ -632,7 +627,7 @@
     int tries = 0;              //For number of retries before failing
     ssize_t ssize;              //Returned by ctx->read
 
-    pthread_mutex_lock(&rwd_ctx_mutex);
+    pthread_mutex_lock(&ctx_mutex);
     /* Ugly goto but it works ;) But IMHO easiest solution for error handling 
here */
     goto seek;
   reopen:
@@ -644,13 +639,13 @@
             tries++;
             if (tries > 4)
             {
-                pthread_mutex_unlock(&rwd_ctx_mutex);
+                pthread_mutex_unlock(&ctx_mutex);
                 return -errno;
             }
             goto reopen;
         }
         /* Other errors from docs cannot be recovered from so returning the 
error */
-        pthread_mutex_unlock(&rwd_ctx_mutex);
+        pthread_mutex_unlock(&ctx_mutex);
         return -errno;
 
     }
@@ -667,7 +662,7 @@
         else
         {
             //SMB Init failed
-            pthread_mutex_unlock(&rwd_ctx_mutex);
+            pthread_mutex_unlock(&ctx_mutex);
             return -errno;
         }
     }
@@ -681,24 +676,24 @@
         /* Tried opening a directory / or smb_init failed */
         else
         {
-            pthread_mutex_unlock(&rwd_ctx_mutex);
+            pthread_mutex_unlock(&ctx_mutex);
             return -errno;
         }
     }
-    pthread_mutex_unlock(&rwd_ctx_mutex);
+    pthread_mutex_unlock(&ctx_mutex);
     return (size_t) ssize;
 }
 
 static int fusesmb_release(const char *path, struct fuse_file_info *fi)
 {
     (void)path;
-    pthread_mutex_lock(&rwd_ctx_mutex);
+    pthread_mutex_lock(&ctx_mutex);
 #ifdef HAVE_LIBSMBCLIENT_CLOSE_FN
     rwd_ctx->close_fn(rwd_ctx, (SMBCFILE *)fi->fh);
 #else
     rwd_ctx->close(rwd_ctx, (SMBCFILE *)fi->fh);
 #endif
-    pthread_mutex_unlock(&rwd_ctx_mutex);
+    pthread_mutex_unlock(&ctx_mutex);
     return 0;
 
 }

Reply via email to