From 6aff2257e3dbc40c5e53724dbe827eb14af536b7 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Thu, 15 Nov 2007 17:37:29 +0000 Subject: [PATCH] UBUNTU: Backport lookup_one_len_nd NFS changes from Unionfs 2.0 Bug: 137765, 103044 Due to NFS related changes in 2.6.18, Unionfs 1.4 kernel oopses when accessing an NFS mounted filesystem. Signed-off-by: Phillip lougher --- ubuntu/fs/unionfs/dentry.c | 9 ++++++++- ubuntu/fs/unionfs/inode.c | 9 ++++++++- ubuntu/fs/unionfs/lookup.c | 22 ++++++++++++++++------ ubuntu/fs/unionfs/unionfs.h | 2 +- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/ubuntu/fs/unionfs/dentry.c b/ubuntu/fs/unionfs/dentry.c index f7d7994..e6fc28a 100644 --- a/ubuntu/fs/unionfs/dentry.c +++ b/ubuntu/fs/unionfs/dentry.c @@ -42,6 +42,13 @@ int unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) int restart = 0; int interpose_flag; + struct nameidata lowernd; + + if(nd) + memcpy(&lowernd, nd, sizeof(struct nameidata)); + else + memset(&lowernd, 0, sizeof(struct nameidata)); + print_util_entry_location(); restart: @@ -130,7 +137,7 @@ int unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) mutex_unlock(&dentry->d_inode->i_mutex); } - result = unionfs_lookup_backend(dentry, interpose_flag); + result = unionfs_lookup_backend(dentry, &lowernd, interpose_flag); if (result) { if (IS_ERR(result)) { valid = 0; diff --git a/ubuntu/fs/unionfs/inode.c b/ubuntu/fs/unionfs/inode.c index d8d1d9d..8ce33b4 100644 --- a/ubuntu/fs/unionfs/inode.c +++ b/ubuntu/fs/unionfs/inode.c @@ -211,8 +211,15 @@ static int unionfs_create(struct inode *parent, struct dentry *dentry, struct dentry *unionfs_lookup(struct inode *parent, struct dentry *dentry, struct nameidata *nd) { + struct nameidata lowernd; + + if(nd) + memcpy(&lowernd, nd, sizeof(struct nameidata)); + else + memset(&lowernd, 0, sizeof(struct nameidata)); + /* The locking is done by unionfs_lookup_backend. */ - return unionfs_lookup_backend(dentry, INTERPOSE_LOOKUP); + return unionfs_lookup_backend(dentry, &lowernd, INTERPOSE_LOOKUP); } static int unionfs_link(struct dentry *old_dentry, struct inode *dir, diff --git a/ubuntu/fs/unionfs/lookup.c b/ubuntu/fs/unionfs/lookup.c index c657610..e1500d2 100644 --- a/ubuntu/fs/unionfs/lookup.c +++ b/ubuntu/fs/unionfs/lookup.c @@ -25,7 +25,7 @@ static int is_opaque_dir(struct dentry *dentry, int bindex); static int is_validname(const char *name); -struct dentry *unionfs_lookup_backend(struct dentry *dentry, int lookupmode) +struct dentry *unionfs_lookup_backend(struct dentry *dentry, struct nameidata *nd, int lookupmode) { int err = 0; struct dentry *hidden_dentry = NULL; @@ -156,8 +156,12 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry, int lookupmode) wh_hidden_dentry = NULL; /* Now do regular lookup; lookup foo */ - hidden_dentry = LOOKUP_ONE_LEN(name, hidden_dir_dentry, - namelen); + nd->dentry = dtohd_index(dentry, bindex); + /* FIXME: fix following line for mount point crossing */ + nd->mnt = stohiddenmnt_index(parent_dentry->d_sb, bindex); + + hidden_dentry = lookup_one_len_nd(name, hidden_dir_dentry, + namelen, nd); print_dentry("hidden result", hidden_dentry); if (IS_ERR(hidden_dentry)) { DPUT(first_hidden_dentry); @@ -232,8 +236,13 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry, int lookupmode) } /* This should only happen if we found a whiteout. */ if (first_dentry_offset == -1) { - first_hidden_dentry = LOOKUP_ONE_LEN(name, hidden_dir_dentry, - namelen); + nd->dentry = dentry; + /* FIXME: fix following line for mount point crossing */ + nd->mnt = stohiddenmnt_index(parent_dentry->d_sb, bindex); + + first_hidden_dentry = lookup_one_len_nd(name, hidden_dir_dentry, + namelen, nd); + first_dentry_offset = bindex; if (IS_ERR(first_hidden_dentry)) { err = PTR_ERR(first_hidden_dentry); @@ -319,8 +328,9 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry, int lookupmode) int unionfs_partial_lookup(struct dentry *dentry) { struct dentry *tmp; + struct nameidata nd = { .flags = 0 }; - tmp = unionfs_lookup_backend(dentry, INTERPOSE_PARTIAL); + tmp = unionfs_lookup_backend(dentry, &nd, INTERPOSE_PARTIAL); if (!tmp) return 0; if (IS_ERR(tmp)) diff --git a/ubuntu/fs/unionfs/unionfs.h b/ubuntu/fs/unionfs/unionfs.h index 9836476..417dc1c 100644 --- a/ubuntu/fs/unionfs/unionfs.h +++ b/ubuntu/fs/unionfs/unionfs.h @@ -523,7 +523,7 @@ static inline void fist_copy_attr_all(struct inode *dest, print_exit_location(); } -struct dentry *unionfs_lookup_backend(struct dentry *dentry, int lookupmode); +struct dentry *unionfs_lookup_backend(struct dentry *dentry, struct nameidata *nd, int lookupmode); int is_stale_inode(struct inode *inode); void make_stale_inode(struct inode *inode); -- 1.5.3 From 1090737f690b58954a4fe0368f94e660a90e58fa Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Thu, 15 Nov 2007 17:49:36 +0000 Subject: [PATCH] UBUNTU: Backport unionfs_statfs from Unionfs 2.0 Bug: 137765, 103044 Due to NFS related changes in 2.6.18, Unionfs hangs when calling vfs_statfs() on an NFS mount. Unionfs 2.0 avoids this problem because unionfs_statfs() has been changed to only stat the highest priority branch. Signed-off-by: Phillip lougher --- ubuntu/fs/unionfs/super.c | 81 +++++---------------------------------------- 1 files changed, 9 insertions(+), 72 deletions(-) diff --git a/ubuntu/fs/unionfs/super.c b/ubuntu/fs/unionfs/super.c index 3c822f8..f81b699 100644 --- a/ubuntu/fs/unionfs/super.c +++ b/ubuntu/fs/unionfs/super.c @@ -158,89 +158,26 @@ static void unionfs_put_super(struct super_block *sb) print_exit_location(); } +/* Since people use this to answer the "How big of a file can I write?" + * question, we report the size of the highest priority branch as the size of + * the union. + */ static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf) { - int err = 0; + int err = 0; struct super_block *sb, *hidden_sb; - struct kstatfs rsb; - int bindex, bindex1, bstart, bend; - - print_entry_location(); sb = dentry->d_sb; - memset(buf, 0, sizeof(struct kstatfs)); - buf->f_type = UNIONFS_SUPER_MAGIC; - - buf->f_frsize = 0; - buf->f_namelen = 0; - - bstart = sbstart(sb); - bend = sbend(sb); - - for (bindex = bstart; bindex <= bend; bindex++) { - int dup = 0; + hidden_sb = stohs_index(sb, sbstart(sb)); + err = vfs_statfs(hidden_sb->s_root, buf); - hidden_sb = stohs_index(sb, bindex); - /* Ignore duplicate super blocks. */ - for (bindex1 = bstart; bindex1 < bindex; bindex1++) { - if (hidden_sb == stohs_index(sb, bindex1)) { - dup = 1; - break; - } - } - if (dup) { - continue; - } - - err = vfs_statfs(hidden_sb->s_root, &rsb); - dprint(PRINT_DEBUG, - "adding values for bindex:%d bsize:%d blocks:%d bfree:%d bavail:%d\n", - bindex, (int)rsb.f_bsize, (int)rsb.f_blocks, - (int)rsb.f_bfree, (int)rsb.f_bavail); - - if (!buf->f_frsize) - buf->f_frsize = rsb.f_frsize; - if (!buf->f_namelen) { - buf->f_namelen = rsb.f_namelen; - } else { - if (buf->f_namelen > rsb.f_namelen) - buf->f_namelen = rsb.f_namelen; - } - if (!buf->f_bsize) { - buf->f_bsize = rsb.f_bsize; - } else { - if (buf->f_bsize < rsb.f_bsize) { - int shifter = 0; - while (buf->f_bsize < rsb.f_bsize) { - shifter++; - rsb.f_bsize >>= 1; - } - rsb.f_blocks <<= shifter; - rsb.f_bfree <<= shifter; - rsb.f_bavail <<= shifter; - } else { - int shifter = 0; - while (buf->f_bsize > rsb.f_bsize) { - shifter++; - rsb.f_bsize <<= 1; - } - rsb.f_blocks >>= shifter; - rsb.f_bfree >>= shifter; - rsb.f_bavail >>= shifter; - } - } - buf->f_blocks += rsb.f_blocks; - buf->f_bfree += rsb.f_bfree; - buf->f_bavail += rsb.f_bavail; - buf->f_files += rsb.f_files; - buf->f_ffree += rsb.f_ffree; - } + buf->f_type = UNIONFS_SUPER_MAGIC; buf->f_namelen -= WHLEN; memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t)); memset(&buf->f_spare, 0, sizeof(buf->f_spare)); - print_exit_status(err); + return err; } -- 1.5.3