commit 2223996ab85c41c90c029e5f67a9826f18eca1e2
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Sat Mar 17 22:19:19 2007 -0400

    odf_cache_dir wakes up cleanup thread if it fails to write a dirent with 
ENOSPC

diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index dce4b3e..60cf8f4 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -116,12 +116,9 @@ static int readdir_util_callback(void *dirent, const char 
*name, int namelen,
        }
        
        /* check odf */
-       /* XXX: lookup might require to lock it, so unlock for now */
-       odf_unlock(UNIONFS_D(buf->dir)->odf_info);
        odi = __odf_lookup(UNIONFS_D(buf->dir)->odf_info, 
                        UNIONFS_SB(buf->dir->d_sb)->odf,
-                       name, namelen, create_flag, 0);
-       odf_lock(UNIONFS_D(buf->dir)->odf_info);
+                       name, namelen, create_flag | ODF_LOOKUP_LOCKED, 0);
        if (IS_ERR(odi)){
                odi = NULL;
                goto out;
@@ -260,11 +257,13 @@ int odf_cache_dir(struct dentry *d_upper, struct dentry 
*d_odf, struct timespec
        struct file *hidden_file, *odf_file = NULL;
        struct unionfs_rdutil_callback *buf = NULL;
        int bindex, bstart, bend, bopaque;
+       int cleaned = 0;
        struct iattr attr;
        
        sb = d_upper->d_sb;
-       
+retry: 
        unionfs_read_lock(sb);
+       odf_lock(UNIONFS_SB(sb)->odf->odi_ic);
 
        BUG_ON(!S_ISDIR(d_upper->d_inode->i_mode));
 
@@ -379,8 +378,15 @@ out:
        if (odf_file)
                filp_close(odf_file, NULL);
 
+       odf_unlock(UNIONFS_SB(sb)->odf->odi_ic);
        unionfs_read_unlock(sb);
 
+       if (err == -ENOSPC && !cleaned) {
+               cleaned = 1;
+               wake_up_sioa(UNIONFS_SB(sb)->odf->cleanup);
+               schedule();
+               goto retry;
+       }
        return err;
 }
 
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index c55c6a2..c186c21 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -363,6 +363,7 @@ out:
  *             (useful for create where we want to rmv wh's)
  *     - ODF_LOOKUP_OPQ: if a dir is created, set it opaque (branch 0)
  *     - ODF_LOOKUP_WH: create a whiteout
+ *     - ODF_LOOKUP_LOCKED: dont lock parent and ic (already locked from 
caller)
  */
 int odf_lookup(struct dentry *parent, struct dentry *dentry, int flags)
 {      
@@ -426,9 +427,11 @@ retry:
                oldgid = current->fsgid;
 
                /* FIXME need to check hardlinks before create */
-               if (osi->odi_ic != parent)
-                       odf_lock(osi->odi_ic);
-               odf_lock(parent); /* lock parent */
+               if (!(flags & ODF_LOOKUP_LOCKED)){
+                       if (osi->odi_ic != parent)
+                               odf_lock(osi->odi_ic);
+                       odf_lock(parent); /* lock parent */
+               }
 
                if (flags & ODF_LOOKUP_FILE || flags & ODF_LOOKUP_WH) {
                        current->fsuid = 0;
@@ -442,16 +445,20 @@ retry:
                }
                else {
                        dput(odf_dentry);
-                       odf_unlock(parent);
-                       if (osi->odi_ic != parent)
-                               odf_unlock(osi->odi_ic);
+                       if (!(flags & ODF_LOOKUP_LOCKED)){
+                               odf_unlock(parent);
+                               if (osi->odi_ic != parent)
+                                       odf_unlock(osi->odi_ic);
+                       }
                        odf_put_info(old_odi);
                        odi = NULL;
                        goto out;
                }
-               odf_unlock(parent);
-               if (osi->odi_ic != parent)
-                       odf_unlock(osi->odi_ic);
+               if (!(flags & ODF_LOOKUP_LOCKED)){
+                       odf_unlock(parent);
+                       if (osi->odi_ic != parent)
+                               odf_unlock(osi->odi_ic);
+               }
 
                current->fsuid = oldgid;
                current->fsgid = olduid;
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index d83519b..f994a7d 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -25,6 +25,7 @@
 #define ODF_LOOKUP_RMV_WH 4
 #define ODF_LOOKUP_OPQ 8
 #define ODF_LOOKUP_WH 16
+#define ODF_LOOKUP_LOCKED 32
 
 /* Unlink/Remove flags */
 #define ODF_RMV_WH 1
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to