commit 214fdf8ee7a28437446e107ea7395c1afb8620b3
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Fri Feb 16 17:12:53 2007 -0500

    added purge dir cache which truncates the dir's contents file
    
    (but still kept in the mtime checks)
    moved read/write dirents code to their own odf functions

diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
index 3828ded..1b66fec 100644
--- a/fs/unionfs/dirfops.c
+++ b/fs/unionfs/dirfops.c
@@ -30,8 +30,6 @@ static int unionfs_readdir(struct file *file, void *dirent, 
filldir_t filldir)
        char *name = NULL;
        int namelen;
        unsigned int d_type;
-       __le32 le32;
-       __le64 le64;
 
        unionfs_read_lock(file->f_dentry->d_sb);
        if ((err = unionfs_file_revalidate(file, 0)))
@@ -44,6 +42,7 @@ static int unionfs_readdir(struct file *file, void *dirent, 
filldir_t filldir)
        odi = odf_ic_cache_dentry(file->f_dentry);
        if (IS_ERR(odi)){
                err = PTR_ERR(odi);
+               odi = NULL;
                goto out;
        }
 
diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index 76cafab..7bb9815 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -138,7 +138,7 @@ static int readdir_util_callback(void *dirent, const char 
*name, int namelen,
 
        int err = 0;
        struct unionfs_rdutil_callback *buf = dirent;
-       int whiteout = 0, magic = ODF_DIRENT_MAGIC;
+       int whiteout = 0;
        struct filldir_node *found;
        struct odf_dentry_info *odi = NULL;
        
@@ -190,9 +190,6 @@ find:
 
        err = odf_write_dirent(buf->filp, name, namelen, ino, d_type);
 out:
-       if (err > 0)
-               err = -EIO;
-
        odf_put_info(odi);
        buf->err = err;
        return err;
@@ -700,7 +697,7 @@ int odf_cache_dir(struct dentry *d_upper, struct dentry 
*d_odf)
        struct iattr attr;
        
        sb = d_upper->d_sb;
-
+       
        unionfs_read_lock(sb);
 
        BUG_ON(!S_ISDIR(d_upper->d_inode->i_mode));
@@ -711,16 +708,17 @@ int odf_cache_dir(struct dentry *d_upper, struct dentry 
*d_odf)
        i_odf = d_odf->d_inode;
        
        /* compare mtimes, do not proceed if equal */
-       if (i_odf && timespec_equal(&i_odf->i_mtime, 
+       if (i_odf && i_odf->i_size) { 
+               if( timespec_equal(&i_odf->i_mtime, 
                                &d_upper->d_inode->i_mtime))
-                       goto out;
-
+               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);
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 41bbd9a..29d94c2 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -1332,6 +1332,10 @@ out:
        return err;
 }
 
+/*
+ * Returns odf_dentry_info pointing to the location in the odf
+ * for the given directory's cached contents
+ */
 struct odf_dentry_info *odf_ic_dir(struct dentry *dir)
 {
        struct odf_dentry_info *odi_dir, *odis[4], *odi_ic, *odi_ret = NULL;
@@ -1391,6 +1395,158 @@ out:
                return ERR_PTR(err);
        return odi_ret;
 }
+/*
+ * Write a dirent to the given file
+ * FIXME: Instead of a file we should give the position
+ * in the odf
+ */
+int odf_write_dirent(struct file *filp, const char *name, int namelen, 
+                               u64 ino, unsigned int d_type)
+{
+       int err = 0;
+       __le32 le32;
+       __le64 le64;
+       mm_segment_t oldfs;
+
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+
+       le32 = cpu_to_le32(ODF_DIRENT_MAGIC);
+       err = filp->f_op->write(filp, (char*)&le32,
+                       sizeof(__le32), &filp->f_pos);
+       if (err != sizeof(__le32))
+               goto out;
+
+       le32 = cpu_to_le32(namelen);
+       err = filp->f_op->write(filp, (char*)&le32,
+                       sizeof(__le32), &filp->f_pos);
+       if (err != sizeof(__le32))
+               goto out;
+
+       err = filp->f_op->write(filp, (char*)name,
+                       namelen, &filp->f_pos);
+       if (err != namelen)
+               goto out;
+
+       le64 = cpu_to_le64(ino);
+       err = filp->f_op->write(filp, (char*)&le64,
+                       sizeof(__le64), &filp->f_pos);
+       if (err != sizeof(__le64))
+               goto out;
+
+       le32 = cpu_to_le32(d_type);
+       err =filp->f_op->write(filp, (char*)&le32,
+                       sizeof(__le32), &filp->f_pos);
+       if (err != sizeof(__le32))
+               goto out;
+
+       err = 0;
+out:
+       set_fs(oldfs);
+       if (err > 0)
+               err = -EIO;
+
+       return err;
+}
+/*
+ * Reads the next dirent from the given file
+ */
+int odf_read_dirent(struct file *filp, char **name, int *namelen,
+                               u64 *ino, unsigned int *d_type)
+{
+       int err = 0;
+       mm_segment_t oldfs;
+       __le32 le32;
+       __le64 le64;
+
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+
+       err = filp->f_op->read(filp, (char*)&le32,
+                       sizeof(__le32), &filp->f_pos);
+       if (err != sizeof(__le32)) {
+               err = -EIO;
+               goto out;
+       }
+       
+       /* check if we're reading at the correct offset */
+       if (le32_to_cpu(le32) != ODF_DIRENT_MAGIC) {
+               err = -EFAULT;
+               goto out;
+       }
+
+       err = filp->f_op->read(filp, (char*)&le32,
+                       sizeof(__le32), &filp->f_pos);
+       if (err != sizeof(__le32)) {
+               err = -EIO;
+               goto out;
+       }
+       *namelen = le32_to_cpu(le32);
+       if (*namelen <= 0) {
+               err = -EFAULT;
+               goto out;
+       }
+
+       *name = kmalloc(*namelen, GFP_KERNEL);
+       if (!(*name)) {
+               err = -ENOMEM;
+               goto out;
+       }
+       err = filp->f_op->read(filp, (char*)(*name),
+                       *namelen, &filp->f_pos);
+       if (err != *namelen) {
+               err = -EIO;
+               goto out;
+       }
+
+       err = filp->f_op->read(filp, (char*)&le64,
+                       sizeof(__le64), &filp->f_pos);
+       if (err != sizeof(__le64)) {
+               err = -EIO;
+               goto out;
+       }
+       *ino = le64_to_cpu(le64);
+       err = filp->f_op->read(filp, (char*)&le32,
+                       sizeof(__le32), &filp->f_pos);
+       if (err != sizeof(__le32)) {
+               err = -EIO;
+               goto out;
+       }
+       *d_type = le32_to_cpu(le32);
+
+       err = 0;
+out:
+       set_fs(oldfs);
+       return err;
+}
+
+/*
+ * For now this just truncate the dir's content file
+ */
+int odf_purge_dir_cache(struct dentry *dentry)
+{
+       int err = 0;
+       struct iattr attr;
+       struct odf_dentry_info *odi = NULL;
+
+       odi = odf_ic_dir(dentry);
+       if (IS_ERR(odi)){
+               err = PTR_ERR(odi);
+               odi = NULL;
+               goto out;
+       }
+
+       /* truncate */
+       if (dentry->d_inode) {
+               attr.ia_size = 0;
+               attr.ia_valid = ATTR_SIZE | ATTR_FORCE;
+               err = notify_change(odi->dentry, &attr);
+       }
+out:
+       odf_put_info(odi);
+       return err;
+}
+
 
 /*
  * Unlinks the file from odf if exist, creates a new file with
@@ -1464,9 +1620,7 @@ int odf_remove(struct dentry *dentry, int flags)
                err = odf_reclaim(dentry);
        else 
                err = vfs_unlink(odi->dentry->d_parent->d_inode, odi->dentry);
-               if (!err)
-;//                    odi->dentry = NULL; /*so we dont dput*/ 
-       }
+
        if (err)
                goto out_unlock;
 
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index d6db6ae..d34a61e 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -100,6 +100,12 @@ int odf_read_dirent(struct file *filp, char **name, int 
*namelen, u64 *ino, unsi
 int odf_purge_dir_cache(struct dentry *dentry);
 int odf_cache_dir(struct dentry *d_upper, struct dentry *d_odf, struct 
timespec *mtime);
 
+/* dirents & dir cache */
+struct odf_dentry_info *odf_ic_dir(struct dentry *dir);
+int odf_write_dirent(struct file *filp, const char *name, int namelen, u64 
ino, unsigned int d_type);
+int odf_read_dirent(struct file *filp, char **name, int *namelen, u64 *ino, 
unsigned int *d_type);
+int odf_purge_dir_cache(struct dentry *dentry);
+
 int odf_rename(struct dentry *old_dentry, struct dentry *new_dentry);
 int odf_link(struct dentry *old_dentry, struct dentry *new_dentry);
 
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
index 420e0da..5d17c67 100644
--- a/fs/unionfs/unlink.c
+++ b/fs/unionfs/unlink.c
@@ -133,6 +133,7 @@ static int unionfs_do_unlink(struct inode *dir, struct 
dentry *dentry)
                 * the mtime of that branch has not changed, so the
                 * mtime of the upper file is not updated 
                 */
+               odf_purge_dir_cache(dentry->d_parent);
                attr.ia_mtime = current_kernel_time();
                attr.ia_valid = ATTR_MTIME | ATTR_MTIME_SET | ATTR_FORCE;
                err = notify_change(dentry->d_parent, &attr);
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to