commit 5165634a14c51726bced7f4d06c93f3da94c5ffe
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date: Tue Apr 3 19:04:54 2007 -0400
preparing for hardlinks
diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 8da5161..7127cb9 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -471,7 +471,7 @@ static int __open_dir(struct inode *inode, struct file
*file)
unionfs_read_unlock(inode->i_sb);
}
- odi = odf_ic_dir(file->f_dentry);
+ odi = odf_ic_cache_dentry(file->f_dentry);
if (IS_ERR(odi))
return PTR_ERR(odi);
err = odf_cache_dir(file->f_dentry, odi->dentry, newest);
diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
index 8991ca3..0eb0538 100644
--- a/fs/unionfs/dirfops.c
+++ b/fs/unionfs/dirfops.c
@@ -39,7 +39,7 @@ static int unionfs_readdir(struct file *file, void *dirent,
filldir_t filldir)
/* Get the odf/ic file */
/* FIXME: this should be saved somewhere, also check mtime */
- odi = odf_ic_dir(file->f_dentry);
+ odi = odf_ic_cache_dentry(file->f_dentry);
if (IS_ERR(odi)){
err = PTR_ERR(odi);
odi = NULL;
diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index f4cfb0d..7fc8271 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -142,12 +142,6 @@ static int readdir_util_callback(void *dirent, const char
*name, int namelen,
struct filldir_node *found;
struct odf_dentry_info *odi = NULL;
- /* 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->mode == RD_CHECK_HD_EMPTY)
buf->filldir_called = 1;
else
@@ -157,8 +151,6 @@ static int readdir_util_callback(void *dirent, const char
*name, int namelen,
(namelen == 1 || (name[1] == '.' && namelen == 2))){
if (buf->mode != RD_CACHE_ODF)
goto out;
- else
- create_flag = 0;
}
/* we dont care about odf when checking hidden dirs */
@@ -170,7 +162,7 @@ static int readdir_util_callback(void *dirent, const char
*name, int namelen,
/* check odf */
odi = __odf_lookup(UNIONFS_SB(buf->dir->d_sb)->odf,
UNIONFS_D(buf->dir)->odf_info,
- name, namelen, create_flag | ODF_LOOKUP_LOCKED, 0);
+ name, namelen, ODF_LOOKUP_LOCKED, 0);
if (IS_ERR(odi)){
odi = NULL;
goto out;
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index a6176b1..191ae17 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -394,7 +394,38 @@ out:
*/
int odf_lookup(struct dentry *parent, struct dentry *dentry, int flags)
{
- int err = 0;
+ struct odf_dentry_info *links = NULL;
+ struct dentry *lower_dentry = NULL;
+ char *name, *uuid;
+ int bstart, err = 0;
+
+ /* this might be called before interpose */
+ for (bstart = 0; bstart <= dbend(dentry); bstart++) {
+ lower_dentry = unionfs_lower_dentry_idx(dentry, bstart);
+ if (lower_dentry)
+ break;
+ }
+
+ if (lower_dentry && lower_dentry->d_inode &&
+ lower_dentry->d_inode->i_nlink > 1 &&
+ !S_ISDIR(lower_dentry->d_inode->i_mode)) {
+
+ name = kmalloc(UUID_LEN * 2 + 1,GFP_KERNEL);
+ uuid = odf_get_branch_uuid(UNIONFS_SB(dentry->d_sb)->odf,
bstart);
+ sprintf(name,"%x%x%x%x", *(unsigned int *) uuid,
+ *(unsigned int *) uuid + 4,
+ *(unsigned int *) uuid + 8,
+ *(unsigned int *) uuid + 12);
+ links = odf_ic_dentry(UNIONFS_SB(dentry->d_sb)->odf,
+ lower_dentry->d_inode->i_ino, name,
strlen(name));
+ kfree(name);
+ if (IS_ERR(links)) {
+ err = PTR_ERR(links);
+ goto out;
+ }
+ odf_put_info(links);
+ }
+
UNIONFS_D(dentry)->odf_info = __odf_lookup(
UNIONFS_SB(dentry->d_sb)->odf,
UNIONFS_D(parent)->odf_info,
@@ -406,6 +437,7 @@ int odf_lookup(struct dentry *parent, struct dentry
*dentry, int flags)
err = PTR_ERR(UNIONFS_D(dentry)->odf_info);
UNIONFS_D(dentry)->odf_info = NULL;
}
+out:
return err;
}
@@ -530,46 +562,52 @@ out:
* 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 *odf_ic_cache_dentry(struct dentry *dir)
{
- struct odf_dentry_info *odi_dir, *odis[4], *odi_ic, *odi_ret = NULL;
- struct odf_sb_info *osi;
- u64 ino;
+ struct odf_dentry_info *odi_dir;
+
+ odi_dir = UNIONFS_D(dir)->odf_info;
+ if (!odi_dir)
+ return ERR_PTR(-ENOENT);
+
+ if (!S_ISDIR(dir->d_inode->i_mode))
+ return ERR_PTR(-ENOTDIR);
+
+ return odf_ic_dentry(UNIONFS_SB(dir->d_sb)->odf,
+ dir->d_inode->i_ino, ODF_CONTENT, ODF_CONTENT_LEN);
+}
+
+/*
+ * Returns odf_dentry_info pointing to the location in odf/ic
+ * for the requested file name
+ */
+struct odf_dentry_info *odf_ic_dentry(struct odf_sb_info *osi, u64 ino, char
*name, int namelen)
+{
+ struct odf_dentry_info *odis[4], *odi_ic, *odi_ret = NULL;
int breakdown[4];
- char name[6];
+ char tmp_name[6];
int i, err = 0;
- if (!S_ISDIR(dir->d_inode->i_mode)) {
- err = -ENOTDIR;
- goto out;
- }
- osi = UNIONFS_SB(dir->d_sb)->odf;
odi_ic = osi->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, "%x", breakdown[0]);
- odis[0] = __odf_lookup(osi, odi_ic, name, strlen(name), ODF_LOOKUP_DIR,
NULL);
+ memset(tmp_name,0,6);
+ sprintf(tmp_name, "%x", breakdown[0]);
+ odis[0] = __odf_lookup(osi, odi_ic, tmp_name, strlen(tmp_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(osi, odis[i-1], name, strlen(name),
ODF_LOOKUP_DIR, NULL);
+ memset(tmp_name,0,6);
+ sprintf(tmp_name, "%x", breakdown[i]);
+ odis[i] = __odf_lookup(osi, odis[i-1], tmp_name,
strlen(tmp_name), ODF_LOOKUP_DIR, NULL);
if (IS_ERR(odis[i])) {
err = PTR_ERR(odis[i]);
odis[i] = NULL;
@@ -577,7 +615,7 @@ struct odf_dentry_info *odf_ic_dir(struct dentry *dir)
}
}
- odi_ret = __odf_lookup(osi, odis[3], ODF_CONTENT, ODF_CONTENT_LEN,
ODF_LOOKUP_FILE, NULL);
+ odi_ret = __odf_lookup(osi, odis[3], name, namelen, ODF_LOOKUP_FILE,
NULL);
if (IS_ERR(odi_ret)) {
err = PTR_ERR(odi_ret);
odi_ret = NULL;
@@ -726,7 +764,7 @@ int odf_purge_dir_cache(struct dentry *dentry)
//struct iattr attr;
struct odf_dentry_info *odi = NULL;
- odi = odf_ic_dir(dentry);
+ odi = odf_ic_cache_dentry(dentry);
if (IS_ERR(odi)){
err = PTR_ERR(odi);
odi = NULL;
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index 27018a2..5f5044b 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -26,6 +26,7 @@
#define ODF_LOOKUP_OPQ 8
#define ODF_LOOKUP_WH 16
#define ODF_LOOKUP_LOCKED 32
+#define ODF_LOOKUP_LINK 64
/* Unlink/Remove flags */
#define ODF_RMV_WH 1
@@ -74,7 +75,8 @@ struct odf_dentry_info *odf_alloc_info(struct odf_sb_info
*osi, struct dentry *o
void odf_put_info(struct odf_dentry_info *odi);
/* dirents & dir cache */
-struct odf_dentry_info *odf_ic_dir(struct dentry *dir);
+struct odf_dentry_info *odf_ic_cache_dentry(struct dentry *dir);
+struct odf_dentry_info *odf_ic_dentry(struct odf_sb_info *osi, u64 ino, char
*name, int namelen);
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);
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs