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