commit 3b76f155f163c7e0093eb731805955de38bbbefc
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Sat Feb 10 19:25:36 2007 -0500

    readdir and seekdir
    
    still need to check mtime and only update file in ic
    if necessary

diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
index 7f20de9..c64022f 100644
--- a/fs/unionfs/dirfops.c
+++ b/fs/unionfs/dirfops.c
@@ -42,7 +42,6 @@ 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;
        }
 
@@ -88,6 +87,7 @@ static int unionfs_readdir(struct file *file, void *dirent, 
filldir_t filldir)
        err = odf_read_dirent(odf_file, &name, &namelen, &ino, &d_type);
        if (err)
                goto out;
+       }
 
        /* filldir */
        err = filldir(dirent, name, namelen, odf_file->f_pos, ino, d_type);
@@ -111,7 +111,6 @@ static loff_t unionfs_dir_llseek(struct file *file, loff_t 
offset, int origin)
 {
        loff_t err;
 
-       unionfs_read_lock(file->f_dentry->d_sb);
        if ((err = unionfs_file_revalidate(file, 0)))
                goto out;
 
diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index 840e6e3..a921b61 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;
+       int whiteout = 0, magic = ODF_DIRENT_MAGIC;
        struct filldir_node *found;
        struct odf_dentry_info *odi = NULL;
        
@@ -190,6 +190,9 @@ 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;
@@ -684,3 +687,108 @@ out:
        return err;
 }
 
+/* Cache contents of dir to an odf/ic file */
+int odf_cache_dir(struct dentry *d_upper, struct dentry *d_odf)
+{
+       int err = 0;
+       struct dentry *hidden_dentry = NULL;
+       struct super_block *sb;
+       struct file *hidden_file, *odf_file = NULL;
+       struct unionfs_rdutil_callback *buf = NULL;
+       int bindex, bstart, bend, bopaque;
+
+       sb = d_upper->d_sb;
+
+       unionfs_read_lock(sb);
+
+       BUG_ON(!S_ISDIR(d_upper->d_inode->i_mode));
+
+       if ((err = unionfs_partial_lookup(d_upper)))
+               goto out;
+
+       dget(d_odf);
+       mntget(UNIONFS_SB(sb)->odf->mnt);
+       odf_file = dentry_open(d_odf,
+                       UNIONFS_SB(sb)->odf->mnt,
+                       O_TRUNC|O_CREAT|O_WRONLY);
+       if (IS_ERR(odf_file)){
+               err = PTR_ERR(odf_file);
+               odf_file = NULL;
+               goto out;
+       }
+
+       bstart = dbstart(d_upper);
+       bend = dbend(d_upper);
+       bopaque = dbopaque(d_upper);
+       if (0 <= bopaque && bopaque < bend)
+               bend = bopaque;
+
+       buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
+       if (!buf) {
+               err = -ENOMEM;
+               goto out;
+       }
+       buf->err = 0;
+       buf->mode = RD_CACHE_ODF;
+       buf->rdstate = alloc_rdstate(d_upper->d_inode, bstart);
+       if (!buf->rdstate) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* Process the hidden directories with rdutil_callback as a filldir. */
+       for (bindex = bstart; bindex <= bend; bindex++) {
+               hidden_dentry = unionfs_lower_dentry_idx(d_upper, bindex);
+               if (!hidden_dentry)
+                       continue;
+               if (!hidden_dentry->d_inode)
+                       continue;
+               if (!S_ISDIR(hidden_dentry->d_inode->i_mode))
+                       continue;
+
+               dget(hidden_dentry);
+               mntget(unionfs_lower_mnt_idx(d_upper, bindex));
+               branchget(sb, bindex);
+               hidden_file =
+                   dentry_open(hidden_dentry, unionfs_lower_mnt_idx(d_upper, 
bindex),
+                               O_RDONLY);
+               if (IS_ERR(hidden_file)) {
+                       err = PTR_ERR(hidden_file);
+                       dput(hidden_dentry);
+                       branchput(sb, bindex);
+                       goto out;
+               }
+
+               do {
+                       buf->filldir_called = 0;
+                       buf->dir = d_upper;
+                       buf->filp = odf_file;
+                       buf->rdstate->bindex = bindex;
+                       err = vfs_readdir(hidden_file,
+                                         readdir_util_callback, buf);
+                       if (buf->err)
+                               err = buf->err;
+               } while ((err >= 0) && buf->filldir_called);
+
+               /* fput calls dput for hidden_dentry */
+               fput(hidden_file);
+               branchput(sb, bindex);
+
+               if (err < 0)
+                       goto out;
+       }
+
+out:
+       if (buf) {
+               if (buf->rdstate)
+                       free_rdstate(buf->rdstate);
+               kfree(buf);
+       }
+
+       if (odf_file)
+               filp_close(odf_file, NULL);
+
+       unionfs_read_unlock(sb);
+
+       return err;
+}
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index c64995e..ea45cfe 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -1327,6 +1327,66 @@ out:
        return err;
 }
 
+struct odf_dentry_info *odf_ic_dir(struct dentry *dir)
+{
+       struct odf_dentry_info *odi_dir, *odis[4], *odi_ic, *odi_ret = NULL;
+       u64 ino;
+       int breakdown[4];
+       char name[6];
+       int i, err = 0;
+
+       if (!S_ISDIR(dir->d_inode->i_mode)) {
+               err = -ENOTDIR;
+               goto out;
+       }
+       odi_ic = UNIONFS_SB(dir->d_sb)->odf->odi_ic;
+       odi_dir = UNIONFS_D(dir)->odf_info;
+       if (!odi_dir) {
+               err = -ENOENT;
+               goto out;
+       }
+       
+       ino = odi_dir->inum;
+       for (i = 3; i >= 0; i--) {
+               breakdown[i] = ino & 0xFFFF;
+               ino >>= 16;
+               odis[i] = NULL;
+       }
+
+       memset(name,0,6);
+       sprintf(name, "%d", breakdown[0]);
+       odis[0] = __odf_lookup(odi_ic, name, strlen(name), ODF_LOOKUP_DIR, 
NULL);
+       if (IS_ERR(odis[0])) {
+               err = PTR_ERR(odis[0]);
+               odis[0] = NULL;
+               goto out;
+       }
+       for (i = 1; i < 4; i++) {
+               memset(name,0,6);
+               sprintf(name, "%x", breakdown[i]);
+               odis[i] = __odf_lookup(odis[i-1], name, strlen(name), 
ODF_LOOKUP_DIR, NULL);
+               if (IS_ERR(odis[i])) {
+                       err = PTR_ERR(odis[i]);
+                       odis[i] = NULL;
+                       goto out;
+               }
+       }
+       
+       odi_ret = __odf_lookup(odis[3], "content", 7, ODF_LOOKUP_FILE, NULL);
+       if (IS_ERR(odi_ret)) {
+               err = PTR_ERR(odi_ret);
+               odi_ret = NULL;
+               goto out;
+       }
+
+out:
+       for (i = 0; i < 4; i++)
+               odf_put_info(odis[i]);
+       if (err) 
+               return ERR_PTR(err);
+       return odi_ret;
+}
+
 /*
  * Unlinks the file from odf if exist, creates a new file with
  * the same name and sets its whiteout flag
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index e32e97f..d6db6ae 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -58,6 +58,8 @@
 #define ODF_CLEAN_INODES 3
 #define ODF_CLEAN_BLOCKS 4
 
+#define ODF_DIRENT_MAGIC 0x0DFD1300
+
 /* super */
 struct odf_sb_info* odf_read_super(char *options);
 void odf_put_super(struct odf_sb_info *osi);
@@ -146,6 +148,8 @@ static inline void odf_unlock(struct odf_dentry_info *odi)
 
 extern void generate_random_uuid(unsigned char uuid_out[16]);
 
+int odf_cache_dir(struct dentry *d_upper, struct dentry *d_odf);
+
 /* Macros for locking an odf dentry info. */
 static inline void odf_lock(struct odf_dentry_info *odi)
 {
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to