commit 8f6afc8ba911b7fcbf4a036c631503e1b6199329
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/commonfops.c b/fs/unionfs/commonfops.c
index 9e6341d..a2f7f10 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -371,7 +371,8 @@ static int __open_dir(struct inode *inode, struct file
*file)
struct dentry *hidden_dentry;
struct file *hidden_file;
int bindex, bstart, bend;
-
+ struct odf_dentry_info *odi;
+ int err;
bstart = fbstart(file) = dbstart(file->f_dentry);
bend = fbend(file) = dbend(file->f_dentry);
@@ -397,7 +398,13 @@ static int __open_dir(struct inode *inode, struct file
*file)
branchget(inode->i_sb, bindex);
unionfs_read_unlock(inode->i_sb);
}
-
+
+ odi = odf_ic_dir(file->f_dentry);
+ if (IS_ERR(odi))
+ return PTR_ERR(odi);
+ err = odf_cache_dir(file->f_dentry, odi->dentry);
+ /* FIXME: store the dentry somewhere */
+ odf_put_info(odi);
return 0;
}
diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
index caf5689..9d9035b 100644
--- a/fs/unionfs/dirfops.c
+++ b/fs/unionfs/dirfops.c
@@ -18,255 +18,129 @@
#include "union.h"
-/* Make sure our rdstate is playing by the rules. */
-static void verify_rdstate_offset(struct unionfs_dir_state *rdstate)
-{
- BUG_ON(rdstate->offset >= DIREOF);
- BUG_ON(rdstate->cookie >= MAXRDCOOKIE);
-}
-
-struct unionfs_getdents_callback {
- struct unionfs_dir_state *rdstate;
- void *dirent;
- struct dentry *dir;
- int entries_written;
- int filldir_called;
- int filldir_error;
- filldir_t filldir;
- struct super_block *sb;
-};
-
-/* based on generic filldir in fs/readir.c */
-static int unionfs_filldir(void *dirent, const char *name, int namelen,
- loff_t offset, u64 ino, unsigned int d_type)
+static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
{
- struct unionfs_getdents_callback *buf = dirent;
- struct filldir_node *found = NULL;
- struct odf_dentry_info *odi = NULL;
int err = 0;
- int is_wh_entry = 0;
- int odf_flag = ODF_LOOKUP_FILE;
+ struct file *odf_file = NULL;
+ 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;
+ unsigned int d_type;
- buf->filldir_called++;
+ if ((err = unionfs_file_revalidate(file, 0)))
+ goto out;
- /* odf check whiteouts */
- if (d_type == DT_DIR)
- odf_flag = ODF_LOOKUP_DIR;
- odi = __odf_lookup(buf->dir, name, namelen, odf_flag, 0);
+ inode = file->f_dentry->d_inode;
+
+ /* Get the odf/ic file */
+ /* FIXME: this should be saved somewhere, also check mtime */
+ odi = odf_ic_dir(file->f_dentry);
if (IS_ERR(odi)){
err = PTR_ERR(odi);
- odi = NULL;
goto out;
}
- if (odi && odi->whiteout)
+ dget(odi->dentry);
+ mntget(UNIONFS_SB(file->f_dentry->d_sb)->odf->mnt);
+ odf_file = dentry_open(odi->dentry,
+ UNIONFS_SB(file->f_dentry->d_sb)->odf->mnt,
+ O_RDONLY);
+ if (IS_ERR(odf_file)){
+ err = PTR_ERR(odf_file);
+ odf_file = NULL;
goto out;
-
- if ((namelen > UNIONFS_WHLEN) &&
- !strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
- name += UNIONFS_WHLEN;
- namelen -= UNIONFS_WHLEN;
- is_wh_entry = 1;
}
-
- found = find_filldir_node(buf->rdstate, name, namelen);
-
- if (found)
+
+ /* check EOF */
+ size = odi->dentry->d_inode->i_size;
+ if (file->f_pos >= size)
goto out;
- /* if 'name' isn't a whiteout, filldir it. */
- if (!is_wh_entry) {
- off_t pos = rdstate2offset(buf->rdstate);
- u64 unionfs_ino = ino;
-
- if (!err) {
- err = buf->filldir(buf->dirent, name, namelen, pos,
- unionfs_ino, d_type);
- buf->rdstate->offset++;
- verify_rdstate_offset(buf->rdstate);
- }
+ 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*)&magic,
+ sizeof(int), &odf_file->f_pos);
+ if (err != sizeof(int)) {
+ err = -EIO;
+ goto out;
}
- /* If we did fill it, stuff it in our hash, otherwise return an error */
- if (err) {
- buf->filldir_error = err;
+ /* check if we're reading at the correct offset */
+ if (magic != ODF_DIRENT_MAGIC) {
+ err = -EFAULT;
goto out;
}
- buf->entries_written++;
- if ((err = add_filldir_node(buf->rdstate, name, namelen,
- buf->rdstate->bindex, is_wh_entry)))
- buf->filldir_error = err;
-
-out:
- odf_put_info(odi);
- return err;
-}
-
-static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
-{
- int err = 0;
- struct file *hidden_file = NULL;
- struct inode *inode = NULL;
- struct unionfs_getdents_callback buf;
- struct unionfs_dir_state *uds;
- int bend;
- loff_t offset;
-
- unionfs_read_lock(file->f_dentry->d_sb);
- if ((err = unionfs_file_revalidate(file, 0)))
+
+ err = odf_file->f_op->read(odf_file, (char*)&namelen,
+ sizeof(int), &odf_file->f_pos);
+ if (err != sizeof(int)) {
+ err = -EIO;
+ goto out;
+ }
+ if (namelen <= 0) {
+ err = -EFAULT;
+ 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;
-
- inode = file->f_dentry->d_inode;
-
- uds = UNIONFS_F(file)->rdstate;
- if (!uds) {
- if (file->f_pos == DIREOF) {
- goto out;
- } else if (file->f_pos > 0) {
- uds = find_rdstate(inode, file->f_pos);
- if (!uds) {
- err = -ESTALE;
- goto out;
- }
- UNIONFS_F(file)->rdstate = uds;
- } else {
- init_rdstate(file);
- uds = UNIONFS_F(file)->rdstate;
- }
}
- bend = fbend(file);
-
- while (uds->bindex <= bend) {
- hidden_file = unionfs_lower_file_idx(file, uds->bindex);
- if (!hidden_file) {
- uds->bindex++;
- uds->dirpos = 0;
- continue;
- }
-
- /* prepare callback buffer */
- buf.filldir_called = 0;
- buf.filldir_error = 0;
- buf.entries_written = 0;
- buf.dir = file->f_dentry;
- buf.dirent = dirent;
- buf.filldir = filldir;
- buf.rdstate = uds;
- buf.sb = inode->i_sb;
-
- /* Read starting from where we last left off. */
- offset = vfs_llseek(hidden_file, uds->dirpos, SEEK_SET);
- if (offset < 0) {
- err = offset;
- goto out;
- }
- err = vfs_readdir(hidden_file, unionfs_filldir, &buf);
-
- /* Save the position for when we continue. */
- offset = vfs_llseek(hidden_file, 0, SEEK_CUR);
- if (offset < 0) {
- err = offset;
- goto out;
- }
- uds->dirpos = offset;
- /* Copy the atime. */
- fsstack_copy_attr_atime(inode, hidden_file->f_dentry->d_inode);
+ err = odf_file->f_op->read(odf_file, (char*)&ino,
+ sizeof(u64), &odf_file->f_pos);
+ if (err != sizeof(u64)) {
+ err = -EIO;
+ goto out;
+ }
+ err = odf_file->f_op->read(odf_file, (char*)&d_type,
+ sizeof(unsigned int), &odf_file->f_pos);
+ if (err != sizeof(unsigned int)) {
+ err = -EIO;
+ goto out;
+ }
- if (err < 0)
- goto out;
+ set_fs(oldfs);
- if (buf.filldir_error)
- break;
+ /* filldir */
+ err = filldir(dirent, name, namelen, odf_file->f_pos, ino, d_type);
- if (!buf.entries_written) {
- uds->bindex++;
- uds->dirpos = 0;
- }
- }
+ /* Copy the atime. */
+ fsstack_copy_attr_atime(inode, odi->dentry->d_inode);
- if (!buf.filldir_error && uds->bindex >= bend) {
- /* Save the number of hash entries for next time. */
- UNIONFS_I(inode)->hashsize = uds->hashentries;
- free_rdstate(uds);
- UNIONFS_F(file)->rdstate = NULL;
- file->f_pos = DIREOF;
- } else
- file->f_pos = rdstate2offset(uds);
+ /* save the file position */
+ file->f_pos = odf_file->f_pos;
out:
- unionfs_read_unlock(file->f_dentry->d_sb);
+ kfree(name);
+ if (odf_file)
+ filp_close(odf_file, NULL);
+ odf_put_info(odi);
return err;
}
-/* This is not meant to be a generic repositioning function. If you do
- * things that aren't supported, then we return EINVAL.
- *
- * What is allowed:
- * (1) seeking to the same position that you are currently at
- * This really has no effect, but returns where you are.
- * (2) seeking to the beginning of the file
- * This throws out all state, and lets you begin again.
- */
static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin)
{
- struct unionfs_dir_state *rdstate;
loff_t err;
- unionfs_read_lock(file->f_dentry->d_sb);
if ((err = unionfs_file_revalidate(file, 0)))
- goto out;
+ return err;
- rdstate = UNIONFS_F(file)->rdstate;
-
- /* We let users seek to their current position, but not anywhere else.
*/
- if (!offset) {
- switch (origin) {
- case SEEK_SET:
- if (rdstate) {
- free_rdstate(rdstate);
- UNIONFS_F(file)->rdstate = NULL;
- }
- init_rdstate(file);
- err = 0;
- break;
- case SEEK_CUR:
- err = file->f_pos;
- break;
- case SEEK_END:
- /* Unsupported, because we would break everything. */
- err = -EINVAL;
- break;
- }
- } else {
- switch (origin) {
- case SEEK_SET:
- if (rdstate) {
- if (offset == rdstate2offset(rdstate))
- err = offset;
- else if (file->f_pos == DIREOF)
- err = DIREOF;
- else
- err = -EINVAL;
- } else {
- rdstate = find_rdstate(file->f_dentry->d_inode,
- offset);
- if (rdstate) {
- UNIONFS_F(file)->rdstate = rdstate;
- err = rdstate->offset;
- } else
- err = -EINVAL;
- }
- break;
- case SEEK_CUR:
- case SEEK_END:
- /* Unsupported, because we would break everything. */
- err = -EINVAL;
- break;
- }
- }
-
-out:
- unionfs_read_unlock(file->f_dentry->d_sb);
- return err;
+ return generic_file_llseek(file, offset, origin);
}
/* Trimmed directory options, we shouldn't pass everything down since
diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index d3edd0d..00ed474 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -129,11 +129,13 @@ out:
#define RD_NONE 0
#define RD_CHECK_EMPTY 1
+#define RD_CACHE_ODF 2
/* The callback structure for check_empty. */
struct unionfs_rdutil_callback {
int err;
int filldir_called;
struct dentry *dir;
+ struct file *filp;
struct unionfs_dir_state *rdstate;
int mode;
};
@@ -144,46 +146,73 @@ 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;
+ mm_segment_t oldfs;
- buf->filldir_called = 1;
+ if (buf->mode == RD_CHECK_EMPTY)
+ buf->filldir_called = 1;
+ else
+ buf->filldir_called++;
- if (name[0] == '.' && (namelen == 1 || (name[1] == '.' && namelen ==
2)))
+ if (name[0] == '.'
+ && (namelen == 1 || (name[1] == '.' && namelen == 2))
+ && buf->mode == RD_CHECK_EMPTY)
goto out;
/* check odf */
- odi = __odf_lookup(buf->dir, name, namelen, 0, 0);
+ odi = __odf_lookup(UNIONFS_D(buf->dir)->odf_info, name, namelen, 0, 0);
if (IS_ERR(odi)){
odi = NULL;
goto out;
}
- if ((odi && !odi->whiteout) || !odi)
- err = -ENOTEMPTY;
- goto out; /* FIXME: bypass old code */
-
- if (namelen > UNIONFS_WHLEN &&
- !strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
- namelen -= UNIONFS_WHLEN;
- name += UNIONFS_WHLEN;
- whiteout = 1;
+ if ((odi && !odi->whiteout) || !odi) {
+ if (buf->mode == RD_CHECK_EMPTY) {
+ err = -ENOTEMPTY;
+ goto out;
+ }
}
-
+ if (odi && odi->whiteout)
+ whiteout = 1;
found = find_filldir_node(buf->rdstate, name, namelen);
/* If it was found in the table there was a previous whiteout. */
if (found)
goto out;
- /* If it wasn't found and isn't a whiteout, the directory isn't empty.
*/
- err = -ENOTEMPTY;
- if ((buf->mode == RD_CHECK_EMPTY) && !whiteout)
- goto out;
-
err = add_filldir_node(buf->rdstate, name, namelen,
buf->rdstate->bindex, whiteout);
+ if (buf->mode != RD_CACHE_ODF || !buf->filp)
+ goto out;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ err = buf->filp->f_op->write(buf->filp, (char*)&magic,
+ sizeof(int), &buf->filp->f_pos);
+ if (err != sizeof(int))
+ goto out;
+ err = buf->filp->f_op->write(buf->filp, (char*)&namelen,
+ sizeof(int), &buf->filp->f_pos);
+ if (err != sizeof(int))
+ goto out;
+ err = buf->filp->f_op->write(buf->filp, (char*)name,
+ namelen, &buf->filp->f_pos);
+ if (err != namelen)
+ goto out;
+ err = buf->filp->f_op->write(buf->filp, (char*)&ino,
+ sizeof(u64), &buf->filp->f_pos);
+ if (err != sizeof(u64))
+ goto out;
+ err =buf->filp->f_op->write(buf->filp, (char*)&d_type,
+ sizeof(unsigned int), &buf->filp->f_pos);
+ if (err != sizeof(unsigned int))
+ goto out;
+ set_fs(oldfs);
+ err = 0;
out:
+ if (err > 0)
+ err = -EIO;
+
odf_put_info(odi);
buf->err = err;
return err;
@@ -257,6 +286,7 @@ int check_empty(struct dentry *dentry, struct
unionfs_dir_state **namelist)
do {
buf->filldir_called = 0;
buf->dir = dentry;
+ buf->filp = NULL;
buf->rdstate->bindex = bindex;
err = vfs_readdir(hidden_file,
readdir_util_callback, buf);
@@ -288,3 +318,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 66d089c..eaeb2be 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -227,9 +227,9 @@ int odf_lookup(struct dentry *parent, struct dentry
*dentry, int flags)
{
int err = 0;
UNIONFS_D(dentry)->odf_info = __odf_lookup(
- parent,
- dentry->d_name.name,
- dentry->d_name.len,
+ UNIONFS_D(parent)->odf_info,
+ dentry->d_name.name,
+ dentry->d_name.len,
flags,
UNIONFS_D(dentry)->odf_info);
if (IS_ERR(UNIONFS_D(dentry)->odf_info)){
@@ -239,16 +239,15 @@ int odf_lookup(struct dentry *parent, struct dentry
*dentry, int flags)
return err;
}
-struct odf_dentry_info *__odf_lookup(struct dentry *parent, const char *name,
+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 dentry *odf_dentry;
struct odf_dentry_info *odi = old_odi;
- struct inode *odf_i_dir = UNIONFS_D(parent)->odf_info->dentry->d_inode;
+ struct inode *odf_i_dir = parent->dentry->d_inode;
int err = 0;
- odf_dentry = lookup_one_len(name,
- UNIONFS_D(parent)->odf_info->dentry, len);
+ odf_dentry = lookup_one_len(name, parent->dentry, len);
/* if create flags are set, remove existing whiteout */
if (!IS_ERR(odf_dentry)
@@ -258,8 +257,7 @@ struct odf_dentry_info *__odf_lookup(struct dentry *parent,
const char *name,
if (__odf_is_wh(odf_dentry->d_inode)){
vfs_unlink(odf_i_dir, odf_dentry);
//dput(odf_dentry);
- odf_dentry = lookup_one_len(name,
- UNIONFS_D(parent)->odf_info->dentry, len);
+ odf_dentry = lookup_one_len(name, parent->dentry, len);
}
}
@@ -275,7 +273,7 @@ struct odf_dentry_info *__odf_lookup(struct dentry *parent,
const char *name,
BUG_ON(len==1 || (name[1]=='.'&&len==2));
/* FIXME need to check hardlinks before create */
- odf_lock(UNIONFS_D(parent)->odf_info); /* lock parent */
+ odf_lock(parent); /* lock parent */
if (flags & ODF_LOOKUP_FILE)
err = vfs_create(odf_i_dir, odf_dentry, S_IRWXUGO, 0 );
@@ -285,7 +283,7 @@ struct odf_dentry_info *__odf_lookup(struct dentry *parent,
const char *name,
else {
dput(odf_dentry);
- odf_unlock(UNIONFS_D(parent)->odf_info);
+ odf_unlock(parent);
goto out;
}
if (err) {
@@ -295,7 +293,7 @@ struct odf_dentry_info *__odf_lookup(struct dentry *parent,
const char *name,
goto out;
}
- odf_unlock(UNIONFS_D(parent)->odf_info);
+ odf_unlock(parent);
/* set opaqueness to 0 or -1 */
__odf_set_opaque(odf_dentry->d_inode,
@@ -312,6 +310,66 @@ out:
return odi;
}
+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 2be1dc2..5299a59 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -32,6 +32,8 @@
#define ODF_OPQ_BASE 26 /* 0x04000000, bits 26 - 30 */
#define ODF_OPQ_BITS 5
+#define ODF_DIRENT_MAGIC 0x0DFD1300
+
/* super */
struct odf_sb_info* odf_read_super(char *odffile);
void odf_put_super(struct odf_sb_info *osi);
@@ -41,7 +43,9 @@ 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 dentry *parent, const char *name,
int len, int flags, struct odf_dentry_info *old_odi);
+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);
@@ -68,6 +72,8 @@ int __odf_is_opaque(struct inode *i);
int __odf_get_opaque(struct inode *i);
int __odf_set_opaque(struct inode *i, int branch);
+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