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