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