Tomas M:
> As usual, I forgot to note my kernel version, I am sorry.
> I am using 2.6.24-rc4 kernel.
        :::
> > mknod empty/console c 5 1
> > mount -t aufs -o br:empty=rw aufs union
> > ls -l union
> > # in my case, the console device is entirely wrong now

I see XFS in linux-2.6.24-rc[34] changed the semantics of inode
attribute (i_rdev).
Here is a patch for it.
If you succeed, the patch will be included in next Monday release.


Junjiro Okajima

----------------------------------------------------------------------

diff -x CVS -x RCS -x .pdiff -rup ../../aufs.anon/aufs/fs/aufs/Makefile 
./fs/aufs/Makefile
--- ../../aufs.anon/aufs/fs/aufs/Makefile       2007-12-03 10:44:05.000000000 
+0900
+++ ./fs/aufs/Makefile  2007-12-12 02:56:13.416928552 +0900
@@ -24,6 +24,16 @@ fuse = $(shell grep '\#.*define.*FUSE_SU
 EXTRA_CFLAGS += -DFUSE_SUPER_MAGIC=${fuse}
 endif
 
+ifeq ($(strip $(shell test ${SUBLEVEL} -ge 24 && echo t)),t)
+ifdef CONFIG_XFS_FS
+# it isn't defined in a header file
+xfs = $(shell grep '\#.*define.*XFS_SB_MAGIC' ${srctree}/fs/xfs/xfs_sb.h | \
+       head -n 1 | \
+       awk '{print $$3}')
+EXTRA_CFLAGS += -DXFS_SB_MAGIC=${xfs}
+endif
+endif
+
 ifdef CONFIG_TMPFS
 # it isn't defined in a header file
 tmpfs = $(shell grep '\#.*define.*TMPFS_MAGIC' ${srctree}/mm/shmem.c | \
diff -x CVS -x RCS -x .pdiff -rup ../../aufs.anon/aufs/fs/aufs/cpup.c 
./fs/aufs/cpup.c
--- ../../aufs.anon/aufs/fs/aufs/cpup.c 2007-11-26 23:32:05.000000000 +0900
+++ ./fs/aufs/cpup.c    2007-12-12 02:46:17.432531952 +0900
@@ -106,7 +106,8 @@ void au_cpup_attr_all(struct inode *inod
        switch (inode->i_mode & S_IFMT) {
        case S_IFBLK:
        case S_IFCHR:
-               inode->i_rdev = h_inode->i_rdev;
+               inode->i_rdev = au_h_rdev(h_inode, /*h_mnt*/NULL,
+                                         /*h_dentry*/NULL);
        }
        inode->i_blkbits = h_inode->i_blkbits;
        au_cpup_attr_blksize(inode, h_inode);
@@ -388,7 +389,9 @@ static int cpup_entry(struct dentry *den
                /*FALLTHROUGH*/
        case S_IFIFO:
        case S_IFSOCK:
-               err = vfsub_mknod(h_dir, h_dst, mode, h_inode->i_rdev, dlgt);
+               err = vfsub_mknod(h_dir, h_dst, mode,
+                                 au_h_rdev(h_inode, /*h_mnt*/NULL, h_src),
+                                 dlgt);
                //if (LktrCond) {vfs_unlink(h_dir, h_dst); err = -1;}
                break;
        default:
diff -x CVS -x RCS -x .pdiff -rup ../../aufs.anon/aufs/fs/aufs/inode.c 
./fs/aufs/inode.c
--- ../../aufs.anon/aufs/fs/aufs/inode.c        2007-12-10 10:22:41.000000000 
+0900
+++ ./fs/aufs/inode.c   2007-12-12 02:39:49.265542304 +0900
@@ -162,8 +162,8 @@ int au_refresh_hinode(struct inode *inod
 static int set_inode(struct inode *inode, struct dentry *dentry)
 {
        int err, isdir;
-       struct dentry *hidden_dentry;
-       struct inode *hidden_inode;
+       struct dentry *h_dentry;
+       struct inode *h_inode;
        umode_t mode;
        aufs_bindex_t bindex, bstart, btail;
        struct aufs_iinfo *iinfo;
@@ -172,15 +172,15 @@ static int set_inode(struct inode *inode
        LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
        AuDebugOn(!(inode->i_state & I_NEW));
        IiMustWriteLock(inode);
-       hidden_dentry = au_h_dptr(dentry);
-       AuDebugOn(!hidden_dentry);
-       hidden_inode = hidden_dentry->d_inode;
-       AuDebugOn(!hidden_inode);
+       h_dentry = au_h_dptr(dentry);
+       AuDebugOn(!h_dentry);
+       h_inode = h_dentry->d_inode;
+       AuDebugOn(!h_inode);
 
        err = 0;
        isdir = 0;
        bstart = dbstart(dentry);
-       mode = hidden_inode->i_mode;
+       mode = h_inode->i_mode;
        switch (mode & S_IFMT) {
        case S_IFREG:
                btail = dbtail(dentry);
@@ -200,7 +200,8 @@ static int set_inode(struct inode *inode
        case S_IFIFO:
        case S_IFSOCK:
                btail = dbtail(dentry);
-               init_special_inode(inode, mode, hidden_inode->i_rdev);
+               init_special_inode(inode, mode,
+                                  au_h_rdev(h_inode, /*h_mnt*/NULL, h_dentry));
                break;
        default:
                AuIOErr("Unknown file type 0%o\n", mode);
@@ -213,11 +214,11 @@ static int set_inode(struct inode *inode
        iinfo->ii_bstart = bstart;
        iinfo->ii_bend = btail;
        for (bindex = bstart; bindex <= btail; bindex++) {
-               hidden_dentry = au_h_dptr_i(dentry, bindex);
-               if (!hidden_dentry)
+               h_dentry = au_h_dptr_i(dentry, bindex);
+               if (!h_dentry)
                        continue;
-               AuDebugOn(!hidden_dentry->d_inode);
-               set_h_iptr(inode, bindex, igrab(hidden_dentry->d_inode), flags);
+               AuDebugOn(!h_dentry->d_inode);
+               set_h_iptr(inode, bindex, igrab(h_dentry->d_inode), flags);
        }
        au_cpup_attr_all(inode);
 
diff -x CVS -x RCS -x .pdiff -rup ../../aufs.anon/aufs/fs/aufs/super.h 
./fs/aufs/super.h
--- ../../aufs.anon/aufs/fs/aufs/super.h        2007-12-10 10:22:41.000000000 
+0900
+++ ./fs/aufs/super.h   2007-12-12 02:56:19.608987216 +0900
@@ -242,6 +242,21 @@ static inline int au_test_fuse(struct su
        return ret;
 }
 
+static inline int au_test_xfs(struct super_block *sb)
+{
+       int ret = 0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) \
+       && (defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE))
+#ifdef XFS_SB_MAGIC
+       BUILD_BUG_ON(XFS_SB_MAGIC != 0x58465342);
+       ret = (sb->s_magic == XFS_SB_MAGIC);
+#else
+       ret = !strcmp(au_sbtype(sb), "xfs");
+#endif
+#endif
+       return ret;
+}
+
 static inline int au_test_nfs(struct super_block *sb)
 {
 #if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
diff -x CVS -x RCS -x .pdiff -rup ../../aufs.anon/aufs/fs/aufs/vfsub.c 
./fs/aufs/vfsub.c
--- ../../aufs.anon/aufs/fs/aufs/vfsub.c        2007-12-10 10:31:58.000000000 
+0900
+++ ./fs/aufs/vfsub.c   2007-12-12 03:55:08.278547904 +0900
@@ -1040,6 +1040,54 @@ int au_update_fuse_h_inode(struct vfsmou
 }
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) \
+       && (defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE))
+/* h_mnt can be NULL, is it safe? */
+dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
+               struct dentry *h_dentry)
+{
+       dev_t rdev;
+       int err;
+       struct kstat st;
+
+       LKTRTrace("hi%lu\n", h_inode->i_ino);
+       if (h_dentry)
+               LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
+
+       rdev = h_inode->i_rdev;
+       if (!rdev || !au_test_xfs(h_inode->i_sb))
+               goto out;
+
+       rdev = 0;
+       if (!h_dentry) {
+               err = 0;
+               h_dentry = d_find_alias(h_inode);
+               if (unlikely(!h_dentry))
+                       goto failure;
+               err = PTR_ERR(h_dentry);
+               if (IS_ERR(h_dentry)) {
+                       h_dentry = NULL;
+                       goto failure;
+               }
+               LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
+       } else
+               dget(h_dentry);
+
+       err = vfsub_getattr(h_mnt, h_dentry, &st, /*dlgt*/0);
+       if (!err) {
+               rdev = st.rdev;
+               goto out; /* success */
+       }
+
+ failure:
+       AuIOErr("failed rdev for XFS inode, hi%lu, %d\n",
+               h_inode->i_ino, err);
+ out:
+       dput(h_dentry);
+       return rdev;
+}
+#endif /* xfs rdev */
+
 #if 0 // temp
 /*
  * This function was born after a discussion with the FUSE developer.
diff -x CVS -x RCS -x .pdiff -rup ../../aufs.anon/aufs/fs/aufs/vfsub.h 
./fs/aufs/vfsub.h
--- ../../aufs.anon/aufs/fs/aufs/vfsub.h        2007-11-26 23:32:05.000000000 
+0900
+++ ./fs/aufs/vfsub.h   2007-12-12 02:56:05.695102448 +0900
@@ -216,6 +216,19 @@ int au_update_fuse_h_inode(struct vfsmou
 }
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) \
+       && (defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE))
+dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
+               struct dentry *h_dentry);
+#else
+static inline
+dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
+               struct dentry *h_dentry)
+{
+       return h_inode->i_rdev;
+}
+#endif
+
 /* simple abstractions, for future use */
 static inline
 int do_vfsub_permission(struct inode *inode, int mask, struct nameidata *nd)

-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

Reply via email to