commit 8f85f2164fcff3dba1dfd8010beec100ae880609
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Mon Mar 19 17:20:35 2007 -0400

    cleanup thread bugs

diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index 60cf8f4..f8d12ff 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -264,7 +264,6 @@ int odf_cache_dir(struct dentry *d_upper, struct dentry 
*d_odf, struct timespec
 retry: 
        unionfs_read_lock(sb);
        odf_lock(UNIONFS_SB(sb)->odf->odi_ic);
-
        BUG_ON(!S_ISDIR(d_upper->d_inode->i_mode));
 
        if ((err = unionfs_partial_lookup(d_upper)))
@@ -275,8 +274,7 @@ retry:
        /* compare mtimes, do not proceed if equal */
        if (i_odf && i_odf->i_size) { 
                if(timespec_compare(&i_odf->i_mtime,mtime) >= 0)
-               goto out;
-               
+                       goto out;       
        }
        dget(d_odf);
        mntget(UNIONFS_SB(sb)->odf->mnt);
@@ -374,6 +372,7 @@ out:
        if (buf && buf->rdstate)
                free_rdstate(buf->rdstate);
        kfree(buf);
+       buf = NULL;
 
        if (odf_file)
                filp_close(odf_file, NULL);
@@ -383,8 +382,7 @@ out:
 
        if (err == -ENOSPC && !cleaned) {
                cleaned = 1;
-               wake_up_sioa(UNIONFS_SB(sb)->odf->cleanup);
-               schedule();
+               wake_up_and_wait_sioa(UNIONFS_SB(sb)->odf->cleanup);
                goto retry;
        }
        return err;
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index d6d2770..aff86f7 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -432,6 +432,8 @@ retry:
                                odf_lock(osi->odi_ic);
                        odf_lock(parent); /* lock parent */
                }
+               else if (cleaned)
+                       odf_lock(osi->odi_ic);
 
                if (flags & ODF_LOOKUP_FILE || flags & ODF_LOOKUP_WH) {
                        current->fsuid = 0;
@@ -459,6 +461,8 @@ retry:
                        if (osi->odi_ic != parent)
                                odf_unlock(osi->odi_ic);
                }
+               else if (cleaned)
+                       odf_unlock(osi->odi_ic);
 
                current->fsuid = oldgid;
                current->fsgid = olduid;
@@ -466,9 +470,10 @@ retry:
                if (err) {
                        if (err == -ENOSPC && !cleaned) {
                                /* let the cleanup thread do its work and retry 
once */
+                               if (flags & ODF_LOOKUP_LOCKED)
+                                       odf_unlock(osi->odi_ic);
                                cleaned = 1;
-                               wake_up_sioa(osi->cleanup);
-                               schedule();
+                               wake_up_and_wait_sioa(osi->cleanup);
                                goto retry;
                        }
                        printk(KERN_WARNING "odf_lookup: could not create odf 
dentry %s, %d\n", name, err);
diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
index e6c8b40..aaa4144 100644
--- a/fs/unionfs/sioq.c
+++ b/fs/unionfs/sioq.c
@@ -64,12 +64,21 @@ int __run_sioa(void *args)
        sioa_args->process = current;
        do {
                sioa_args->work(args);
+               if (sioa_args->waiting) {
+                       complete(&sioa_args->comp_work);
+                       sioa_args->waiting = 0;
+                       schedule();
+               }
                current->state = TASK_INTERRUPTIBLE;
-               mutex_lock(&sioa_args->sleep_lock);
                schedule_timeout(sioa_args->timeout);
-               mutex_unlock(&sioa_args->sleep_lock);
        } while (!sioa_args->done(args));
-       complete(&sioa_args->comp);
+
+       if (sioa_args->waiting) {
+               complete(&sioa_args->comp_work);
+               sioa_args->waiting = 0;
+               schedule();
+       }
+       complete(&sioa_args->comp_thread);
        return 0;
 }
 
@@ -82,8 +91,9 @@ int __run_sioa(void *args)
 void run_sioa(struct sioa_args *args, void (*work) (void*), 
                        int (*done) (void*), signed long timeout)
 {
-       init_completion(&args->comp);
-       mutex_init(&args->sleep_lock);
+       init_completion(&args->comp_thread);
+       mutex_init(&args->lock);
+       args->waiting = 0;
        args->process = NULL;
        args->timeout = timeout;
        args->work = work;
diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
index f6cac22..f58fc50 100644
--- a/fs/unionfs/sioq.h
+++ b/fs/unionfs/sioq.h
@@ -53,12 +53,14 @@ struct sioq_args {
 };
 
 struct sioa_args {
-       struct completion comp;
+       struct completion comp_thread;
+       struct completion comp_work;
        struct task_struct *process;
        signed long timeout;
        void (*work) (void*);
        int (*done) (void*);
-       struct mutex sleep_lock;
+       struct mutex lock;
+       int waiting;
 
        union {
                struct cleanup_args cleanup;
@@ -71,15 +73,26 @@ extern void run_sioq(work_func_t func, struct sioq_args 
*args);
 extern void run_sioa(struct sioa_args *args, void (*work) (void*), int (*done) 
(void*), signed long timeout);
 
 /* wakes up the process and makes sure it resumes before we do */
+static inline void wake_up_and_wait_sioa(struct sioa_args *args)
+{
+       mutex_lock(&args->lock);
+       args->waiting = 1;
+       init_completion(&args->comp_work);
+       wake_up_process(args->process);
+       schedule();
+       wait_for_completion(&args->comp_work);
+       mutex_unlock(&args->lock);
+}
 static inline void wake_up_sioa(struct sioa_args *args)
 {
+       mutex_lock(&args->lock);
        wake_up_process(args->process);
-       mutex_lock(&args->sleep_lock);
-       mutex_unlock(&args->sleep_lock);
+       schedule();
+       mutex_unlock(&args->lock);
 }
 static inline void wait_for_sioa(struct sioa_args *args)
 {
-       wait_for_completion(&args->comp);
+       wait_for_completion(&args->comp_thread);
 }
 
 /* Extern definitions for our privlege escalation helpers */
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to