commit 2f859fa3db412d0ce1f6dab9f3fac171d2c744ec
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 0780aae..e2ee58f 100644
--- a/fs/unionfs/dirfops.c
+++ b/fs/unionfs/dirfops.c
@@ -25,14 +25,11 @@ static int unionfs_readdir(struct file *file, void *dirent, 
filldir_t filldir)
        struct inode *inode = NULL;
        struct odf_dentry_info *odi = NULL;
        loff_t size;    
-       mm_segment_t oldfs;
        /* dirent */
        u64 ino;
        char *name = NULL;
-       int namelen, magic;
+       int namelen;
        unsigned int d_type;
-       __le32 le32;
-       __le64 le64;
 
        if ((err = unionfs_file_revalidate(file, 0)))
                goto out;
@@ -44,8 +41,24 @@ static int unionfs_readdir(struct file *file, void *dirent, 
filldir_t filldir)
        odi = odf_ic_dir(file->f_dentry);
        if (IS_ERR(odi)){
                err = PTR_ERR(odi);
+               odi = NULL;
                goto out;
        }
+
+       /* check if cached dir does not exist */        
+       if (!odi->dentry->d_inode || !odi->dentry->d_inode->i_size) {
+               err = odf_cache_dir(file->f_dentry, odi->dentry);
+               if (err)
+                       goto out;
+
+               /* Reset file position, since an operation like rm *
+                * will rm the 1st entry, purge and then try to
+                * readdir again after the 1st entry's pos and will
+                * resulting in error reading dirents or skipping files
+                */
+               file->f_pos = 0;
+       }
+
        dget(odi->dentry);
        mntget(UNIONFS_SB(file->f_dentry->d_sb)->odf->mnt);
        odf_file = dentry_open(odi->dentry,
@@ -56,7 +69,7 @@ static int unionfs_readdir(struct file *file, void *dirent, 
filldir_t filldir)
                odf_file = NULL;
                goto out;
        }
-       
+
        /* check EOF */
        size = odi->dentry->d_inode->i_size;
        if (file->f_pos >= size)
@@ -65,62 +78,9 @@ static int unionfs_readdir(struct file *file, void *dirent, 
filldir_t filldir)
        odf_file->f_pos = file->f_pos;
        
        /* read the next dirent */
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
-       
-       err = odf_file->f_op->read(odf_file, (char*)&le32,
-                               sizeof(__le32), &odf_file->f_pos);
-       if (err != sizeof(__le32)) {
-               err = -EIO;
-               goto out;
-       }
-       magic = le32_to_cpu(le32);
-       /* check if we're reading at the correct offset */
-       if (magic != ODF_DIRENT_MAGIC) {
-               err = -EFAULT;
-               goto out;
-       }
-       
-       err = odf_file->f_op->read(odf_file, (char*)&le32,
-                               sizeof(__le32), &odf_file->f_pos);
-       if (err != sizeof(__le32)) {
-               err = -EIO;
-               goto out;
-       }
-       namelen = le32_to_cpu(le32);
-       if (namelen <= 0) {
-               err = -EFAULT;
+       err = odf_read_dirent(odf_file, &name, &namelen, &ino, &d_type);
+       if (err)
                goto out;
-       }
-       
-       name = kmalloc(namelen, GFP_KERNEL);
-       if (!name) {
-               err = -ENOMEM;
-               goto out;
-       }
-       err = odf_file->f_op->read(odf_file, (char*)name,
-                               namelen, &odf_file->f_pos);
-       if (err != namelen) {
-               err = -EIO;
-               goto out;
-       }
-
-       err = odf_file->f_op->read(odf_file, (char*)&le64,
-                               sizeof(__le64), &odf_file->f_pos);
-       if (err != sizeof(__le64)) {
-               err = -EIO;
-               goto out;
-       }
-       ino = le64_to_cpu(le64);
-       err = odf_file->f_op->read(odf_file, (char*)&le32,
-                       sizeof(__le32), &odf_file->f_pos);
-       if (err != sizeof(__le32)) {
-               err = -EIO;
-               goto out;
-       }
-       d_type = le32_to_cpu(le32);
-
-       set_fs(oldfs);
 
        /* filldir */
        err = filldir(dirent, name, namelen, odf_file->f_pos, ino, d_type);
diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index b668fdd..0123f8f 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -37,12 +37,15 @@ 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;
-       __le32 le32;
-       __le64 le64;
-       mm_segment_t oldfs;
+       
+       /* FIXME: do we want to create(assign inode/nos) on reeddirs?
+        * or do we want to do it on interpose? (if we do it on
+        * interpose lsing a fresh union will not assign inos to dirs
+        */
+       int create_flag = d_type == DT_DIR ? ODF_LOOKUP_DIR : ODF_LOOKUP_FILE;
 
        if (buf->mode == RD_CHECK_EMPTY)
                buf->filldir_called = 1;
@@ -50,12 +53,15 @@ static int readdir_util_callback(void *dirent, const char 
*name, int namelen,
                buf->filldir_called++;
 
        if (name[0] == '.' &&
-               (namelen == 1 || (name[1] == '.' && namelen == 2)) &&
-               buf->mode == RD_CHECK_EMPTY)
-               goto out;
-
+               (namelen == 1 || (name[1] == '.' && namelen == 2))){
+               if (buf->mode == RD_CHECK_EMPTY)
+                       goto out;
+               else
+                       create_flag = 0;
+       }
+               
        /* check odf */
-       odi = __odf_lookup(UNIONFS_D(buf->dir)->odf_info, name, namelen, 0, 0);
+       odi = __odf_lookup(UNIONFS_D(buf->dir)->odf_info, name, namelen, 
create_flag, 0);
        if (IS_ERR(odi)){
                odi = NULL;
                goto out;
@@ -78,38 +84,8 @@ static int readdir_util_callback(void *dirent, const char 
*name, int namelen,
        if (err || buf->mode != RD_CACHE_ODF || !buf->filp || whiteout)
                goto out;
 
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
-       le32 = cpu_to_le32(magic);
-       err = buf->filp->f_op->write(buf->filp, (char*)&le32,
-                               sizeof(__le32), &buf->filp->f_pos);
-       if (err != sizeof(__le32))
-               goto out;
-       le32 = cpu_to_le32(namelen);
-       err = buf->filp->f_op->write(buf->filp, (char*)&le32,
-                               sizeof(__le32), &buf->filp->f_pos);
-       if (err != sizeof(__le32))
-               goto out;
-       err = buf->filp->f_op->write(buf->filp, (char*)name,
-                               namelen, &buf->filp->f_pos);
-       if (err != namelen)
-               goto out;
-       le64 = cpu_to_le64(ino);
-       err = buf->filp->f_op->write(buf->filp, (char*)&le64,
-                       sizeof(__le64), &buf->filp->f_pos);
-       if (err != sizeof(__le64))
-               goto out;
-       le32 = cpu_to_le32(d_type);
-       err =buf->filp->f_op->write(buf->filp, (char*)&le32,
-                       sizeof(__le32), &buf->filp->f_pos);
-       if (err != sizeof(__le32))
-               goto out;
-       set_fs(oldfs);
-       err = 0;
+       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;
@@ -228,7 +204,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));
@@ -239,16 +215,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/lookup.c b/fs/unionfs/lookup.c
index cbdf976..4716e62 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -35,8 +35,6 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry, 
struct nameidata *n
        int locked_parent = 0;
        int locked_child = 0;
        int allocated_new_info = 0;
-
-       int opaque;
        const char *name;
        int namelen;
        
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 45cc965..9cc90d7 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -315,6 +315,10 @@ out:
        return odi;
 }
 
+/*
+ * 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;
@@ -374,6 +378,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
@@ -452,11 +608,9 @@ int odf_remove(struct dentry *dentry, int flags)
        /* remove */
        if (S_ISDIR(odi->dentry->d_inode->i_mode))
                err = odf_reclaim(odi->dentry);
-       else {
+       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 5299a59..24e1f4b 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -44,13 +44,18 @@ int odf_putoptions(struct super_block* sb_union, struct 
unionfs_dentry_info *hid
 /* lookup */
 int odf_lookup(struct dentry *parent, struct dentry *dentry, int flags);
 struct odf_dentry_info *__odf_lookup(struct odf_dentry_info *parent, const 
char *name, int len, int flags, struct odf_dentry_info *old_odi);
-struct odf_dentry_info *odf_ic_dir(struct dentry *dir);
 
 struct odf_dentry_info *odf_getpath(char *path);
 struct odf_dentry_info *odf_fill_info(struct odf_dentry_info *odi, struct 
dentry *odf_dentry);
 struct odf_dentry_info *odf_alloc_info(struct dentry *odf_dentry);
 void odf_put_info(struct odf_dentry_info *odi);
 
+/* 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);
 
 /* unlink */
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
index b46fdba..7305fd5 100644
--- a/fs/unionfs/unlink.c
+++ b/fs/unionfs/unlink.c
@@ -66,6 +66,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);
@@ -148,7 +149,7 @@ static int unionfs_do_rmdir(struct inode *dir, struct 
dentry *dentry)
        if (err || dbopaque(dentry) != 1) {
                if (err == -EIO)
                        printk(KERN_WARNING 
-                               "unionfs_unlink: IO error unlinking from branch 
%d\n",
+                               "unionfs_rmdir: IO error removing from branch 
%d\n",
                                bindex);
                err = odf_create_wh(dentry);
                if (err)
@@ -158,6 +159,7 @@ static int unionfs_do_rmdir(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