commit 2a2f6d2ab966bb94458963b3c0416af60e8f09d2
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Mon Feb 12 17:08:58 2007 -0500

    only cache dir if mtime changed
    
    some other minor fixes

diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index 2444178..c48a2f7 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -184,7 +184,7 @@ static int readdir_util_callback(void *dirent, const char 
*name, int namelen,
 
        err = add_filldir_node(buf->rdstate, name, namelen,
                               buf->rdstate->bindex, whiteout);
-       if (buf->mode != RD_CACHE_ODF || !buf->filp)
+       if (err || buf->mode != RD_CACHE_ODF || !buf->filp || whiteout)
                goto out;
 
        oldfs = get_fs();
@@ -329,11 +329,13 @@ int odf_cache_dir(struct dentry *d_upper, struct dentry 
*d_odf)
 {
        int err = 0;
        struct dentry *hidden_dentry = NULL;
+       struct inode *i_odf;
        struct super_block *sb;
        struct file *hidden_file, *odf_file = NULL;
        struct unionfs_rdutil_callback *buf = NULL;
        int bindex, bstart, bend, bopaque;
-
+       struct iattr attr;
+       
        sb = d_upper->d_sb;
 
        unionfs_read_lock(sb);
@@ -342,9 +344,27 @@ int odf_cache_dir(struct dentry *d_upper, struct dentry 
*d_odf)
 
        if ((err = unionfs_partial_lookup(d_upper)))
                goto out;
+       
+       i_odf = d_odf->d_inode;
+       
+       /* compare mtimes, do not proceed if equal */
+       if (i_odf && timespec_equal(&i_odf->i_mtime, 
+                               &d_upper->d_inode->i_mtime))
+                       goto out;
 
        dget(d_odf);
        mntget(UNIONFS_SB(sb)->odf->mnt);
+               
+       /* force truncate if file exists */
+       if (i_odf) {
+               truncate_inode_pages(i_odf->i_mapping, 0);
+               attr.ia_size = 0;
+               attr.ia_valid = ATTR_SIZE | ATTR_FORCE;
+               err = notify_change(d_odf, &attr);
+               if (err)
+                       goto out;
+
+       }
        odf_file = dentry_open(d_odf,
                        UNIONFS_SB(sb)->odf->mnt,
                        O_TRUNC|O_CREAT|O_WRONLY);
@@ -415,6 +435,11 @@ int odf_cache_dir(struct dentry *d_upper, struct dentry 
*d_odf)
                        goto out;
        }
 
+       /* set mtime of odf file to that of higher file */
+       attr.ia_mtime = d_upper->d_inode->i_mtime;
+       attr.ia_valid = ATTR_MTIME | ATTR_MTIME_SET | ATTR_FORCE;
+       err = notify_change(d_odf, &attr);
+
 out:
        if (buf && buf->rdstate)
                free_rdstate(buf->rdstate);
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 6f9c86f..45cc965 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -178,7 +178,12 @@ int odf_rename(struct dentry *old_dentry, struct dentry 
*new_dentry)
        int err = 0;
        
        err = odf_lookup(old_dentry->d_parent, old_dentry, 0);
+       if (err)
+               goto out;
+
        err = odf_lookup(new_dentry->d_parent, new_dentry, 0);
+       if (err)
+               goto out;
 
        /* if new exists, remove it */
        if (UNIONFS_D(new_dentry)->odf_info)
@@ -249,24 +254,22 @@ struct odf_dentry_info *__odf_lookup(struct 
odf_dentry_info *parent, const char
        
        odf_dentry = lookup_one_len(name, parent->dentry, len);
        
+       if (IS_ERR(odf_dentry)) {
+               odf_put_info(old_odi);
+               odi = (struct odf_dentry_info *)odf_dentry;
+               goto out;
+       } 
+       
        /* if create flags are set, remove existing whiteout */
-       if (!IS_ERR(odf_dentry) 
-               && odf_dentry->d_inode 
-               && (flags & ODF_LOOKUP_RMV_WH)) 
-       {
+       if (odf_dentry->d_inode && (flags & ODF_LOOKUP_RMV_WH)) {
                if (__odf_is_wh(odf_dentry->d_inode)){
                        vfs_unlink(odf_i_dir, odf_dentry);
-                       //dput(odf_dentry);
+                       dput(odf_dentry);
                        odf_dentry = lookup_one_len(name, parent->dentry, len);
                }
        }
 
        /* create inode in odf if dont exist */
-       if (IS_ERR(odf_dentry)) {
-               odf_put_info(old_odi);
-               odi = (void*)odf_dentry;
-               goto out;
-       } 
        if (!odf_dentry->d_inode) {
                
                if (name[0]=='.')
@@ -296,8 +299,10 @@ struct odf_dentry_info *__odf_lookup(struct 
odf_dentry_info *parent, const char
                odf_unlock(parent);
 
                /* set opaqueness to 0 or -1 */
-               __odf_set_opaque(odf_dentry->d_inode,
-                               -!(flags & ODF_LOOKUP_OPQ));
+               if (flags & ODF_LOOKUP_OPQ)
+                       __odf_set_opaque(odf_dentry->d_inode,0);
+               else    
+                       __odf_set_opaque(odf_dentry->d_inode,-1);
                __odf_set_wh(odf_dentry->d_inode,0);
        }
        else {
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
index ce1dee8..05f01be 100644
--- a/fs/unionfs/unlink.c
+++ b/fs/unionfs/unlink.c
@@ -24,6 +24,7 @@ static int unionfs_do_unlink(struct inode *dir, struct dentry 
*dentry)
        struct dentry *hidden_dir_dentry;
        int bstart, bend, bindex;
        int err = 0;
+       struct iattr attr;
 
        if ((err = unionfs_partial_lookup(dentry)))
                goto out;
@@ -58,6 +59,16 @@ static int unionfs_do_unlink(struct inode *dir, struct 
dentry *dentry)
                                "unionfs_unlink: IO error unlinking from branch 
%d\n", 
                                bindex);
                err = odf_create_wh(dentry);
+               if (err)
+                       goto out;
+               /* we want to update mtime here, since if the file to
+                * be removed was only on a rd only branch, then since
+                * the mtime of that branch has not changed, so the
+                * mtime of the upper file is not updated 
+                */
+               attr.ia_mtime = current_kernel_time();
+               attr.ia_valid = ATTR_MTIME | ATTR_MTIME_SET | ATTR_FORCE;
+               err = notify_change(dentry->d_parent, &attr);
        }
 
 out:
@@ -101,6 +112,7 @@ static int unionfs_do_rmdir(struct inode *dir, struct 
dentry *dentry)
        struct dentry *hidden_dir_dentry = NULL;
        int bstart, bend, bindex;
        int err = 0;
+       struct iattr attr;
 
        if ((err = unionfs_partial_lookup(dentry)))
                goto out;
@@ -139,6 +151,16 @@ static int unionfs_do_rmdir(struct inode *dir, struct 
dentry *dentry)
                                "unionfs_unlink: IO error unlinking from branch 
%d\n",
                                bindex);
                err = odf_create_wh(dentry);
+               if (err)
+                       goto out;
+               /* we want to update mtime here, since if the file to
+                * be removed was only on a rd only branch, then since
+                * the mtime of that branch has not changed, so the
+                * mtime of the upper file is not updated 
+                */
+               attr.ia_mtime = current_kernel_time();
+               attr.ia_valid = ATTR_MTIME | ATTR_MTIME_SET | ATTR_FORCE;
+               err = notify_change(dentry->d_parent, &attr);
        }
 
 out:
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to