On Fri, Aug 31, 2007 at 09:43:21AM +0300, Thomas Backlund wrote:
> John Johansen skrev:
> >The suse kernel have the apparmor vfs patches which modify the vfs by
> >passing to include passing of the vfsmnt, and as such unionfs needs to
> >be patched to work with them.
> >
> >The attached patch modifies unionfs to pass the vfsmnt where necessary.
> >It has passed limited testing so now it is need of more critical
> >review.
> >
> >
> 
> Care to send it through another mailserver so we actually can get the patch?
> 
Ooops my bad patch attached inline this time.

> I'm very interested of seeing how you have done it...
> 
A quick description is that I pass through the lower vfsmnts that unionfs
already stores off with the lower dentries.  I didn't do any larger
changes like chaning the work queues to act as a given security context.
Which means that the unionfs path is mediated but when unionfs is used
to access the lower paths they aren't mediated.  Ideally the lower paths
would be mediated too.

> We are using AppArmor and Unionfs on Mandriva kernels too...
> 
May I ask which version of AppArmor are you using?

---
 fs/unionfs/commonfops.c |    5 ++-
 fs/unionfs/copyup.c     |   61 ++++++++++++++++++++++++++------------
 fs/unionfs/dirhelper.c  |    5 ++-
 fs/unionfs/inode.c      |   76 +++++++++++++++++++++++++++++++++++-------------
 fs/unionfs/rename.c     |   19 ++++++++----
 fs/unionfs/sioq.c       |    9 +++--
 fs/unionfs/sioq.h       |    4 ++
 fs/unionfs/subr.c       |    6 ++-
 fs/unionfs/union.h      |    2 -
 fs/unionfs/unlink.c     |   10 +++++-
 fs/unionfs/xattr.c      |   20 +++++++++---
 11 files changed, 157 insertions(+), 60 deletions(-)

--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -35,9 +35,11 @@ static int copyup_deleted_file(struct fi
        int err;
        struct dentry *tmp_dentry = NULL;
        struct dentry *lower_dentry;
+       struct vfsmount *lower_mnt;
        struct dentry *lower_dir_dentry = NULL;
 
        lower_dentry = unionfs_lower_dentry_idx(dentry, bstart);
+       lower_mnt = unionfs_lower_mnt_idx(dentry, bstart);
 
        sprintf(name, ".unionfs%*.*lx",
                i_inosize, i_inosize, lower_dentry->d_inode->i_ino);
@@ -81,8 +83,9 @@ retry:
 
        /* bring it to the same state as an unlinked file */
        lower_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
+       lower_mnt = unionfs_lower_mnt_idx(dentry, dbstart(dentry));
        lower_dir_dentry = lock_parent(lower_dentry);
-       err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
+       err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt);
        unlock_dir(lower_dir_dentry);
 
 out:
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -30,12 +30,15 @@ static int copyup_named_dentry(struct in
                               loff_t len);
 static struct dentry *create_parents_named(struct inode *dir,
                                           struct dentry *dentry,
-                                          const char *name, int bindex);
+                                          const char *name, int bindex,
+                                          struct vfsmount **mnt);
 
 #ifdef CONFIG_UNION_FS_XATTR
 /* copyup all extended attrs for a given dentry */
 static int copyup_xattrs(struct dentry *old_lower_dentry,
-                        struct dentry *new_lower_dentry)
+                        struct vfsmount *old_lower_mnt,
+                        struct dentry *new_lower_dentry,
+                        struct vfsmount *new_lower_mnt)
 {
        int err = 0;
        ssize_t list_size = -1;
@@ -43,7 +46,8 @@ static int copyup_xattrs(struct dentry *
        char *attr_value = NULL;
        char *name_list_orig = NULL;
 
-       list_size = vfs_listxattr(old_lower_dentry, NULL, 0);
+       list_size = vfs_listxattr(old_lower_dentry, old_lower_mnt, NULL, 0,
+                                 NULL);
 
        if (list_size <= 0) {
                err = list_size;
@@ -55,7 +59,8 @@ static int copyup_xattrs(struct dentry *
                err = PTR_ERR(name_list);
                goto out;
        }
-       list_size = vfs_listxattr(old_lower_dentry, name_list, list_size);
+       list_size = vfs_listxattr(old_lower_dentry, old_lower_mnt, name_list,
+                                 list_size, NULL);
        attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
        if (!attr_value || IS_ERR(attr_value)) {
                err = PTR_ERR(name_list);
@@ -67,8 +72,8 @@ static int copyup_xattrs(struct dentry *
 
                /* Lock here since vfs_getxattr doesn't lock for us */
                mutex_lock(&old_lower_dentry->d_inode->i_mutex);
-               size = vfs_getxattr(old_lower_dentry, name_list,
-                                   attr_value, XATTR_SIZE_MAX);
+               size = vfs_getxattr(old_lower_dentry, old_lower_mnt, name_list,
+                                   attr_value, XATTR_SIZE_MAX, NULL);
                mutex_unlock(&old_lower_dentry->d_inode->i_mutex);
                if (size < 0) {
                        err = size;
@@ -80,8 +85,8 @@ static int copyup_xattrs(struct dentry *
                        goto out;
                }
                /* Don't lock here since vfs_setxattr does it for us. */
-               err = vfs_setxattr(new_lower_dentry, name_list, attr_value,
-                                  size, 0);
+               err = vfs_setxattr(new_lower_dentry, new_lower_mnt, name_list,
+                                  attr_value, size, 0, NULL);
 
                if (err < 0)
                        goto out;
@@ -104,7 +109,8 @@ out:
 /* Determine the mode based on the copyup flags, and the existing dentry. */
 static int copyup_permissions(struct super_block *sb,
                              struct dentry *old_lower_dentry,
-                             struct dentry *new_lower_dentry)
+                             struct dentry *new_lower_dentry,
+                             struct vfsmount *new_lower_mnt)
 {
        struct inode *i = old_lower_dentry->d_inode;
        struct iattr newattrs;
@@ -123,7 +129,7 @@ static int copyup_permissions(struct sup
                ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
                ATTR_GID | ATTR_UID | ATTR_MODE;
 
-       err = notify_change(new_lower_dentry, &newattrs);
+       err = notify_change(new_lower_dentry, new_lower_mnt, &newattrs);
 
        return err;
 }
@@ -146,6 +152,7 @@ int copyup_dentry(struct inode *dir, str
  */
 static int __copyup_ndentry(struct dentry *old_lower_dentry,
                            struct dentry *new_lower_dentry,
+                           struct vfsmount *new_lower_mnt,
                            struct dentry *new_lower_parent_dentry,
                            char *symbuf)
 {
@@ -156,6 +163,7 @@ static int __copyup_ndentry(struct dentr
        if (S_ISDIR(old_mode)) {
                args.mkdir.parent = new_lower_parent_dentry->d_inode;
                args.mkdir.dentry = new_lower_dentry;
+               args.mkdir.mnt = new_lower_mnt;
                args.mkdir.mode = old_mode;
 
                run_sioq(__unionfs_mkdir, &args);
@@ -163,6 +171,7 @@ static int __copyup_ndentry(struct dentr
        } else if (S_ISLNK(old_mode)) {
                args.symlink.parent = new_lower_parent_dentry->d_inode;
                args.symlink.dentry = new_lower_dentry;
+               args.symlink.mnt = new_lower_mnt;
                args.symlink.symbuf = symbuf;
                args.symlink.mode = old_mode;
 
@@ -172,6 +181,7 @@ static int __copyup_ndentry(struct dentr
                   S_ISFIFO(old_mode) || S_ISSOCK(old_mode)) {
                args.mknod.parent = new_lower_parent_dentry->d_inode;
                args.mknod.dentry = new_lower_dentry;
+               args.mknod.mnt = new_lower_mnt;
                args.mknod.mode = old_mode;
                args.mknod.dev = old_lower_dentry->d_inode->i_rdev;
 
@@ -338,7 +348,9 @@ static int copyup_named_dentry(struct in
                               loff_t len)
 {
        struct dentry *new_lower_dentry;
+       struct vfsmount *new_lower_mnt;
        struct dentry *old_lower_dentry = NULL;
+       struct vfsmount *old_lower_mnt;
        struct super_block *sb;
        int err = 0;
        int old_bindex;
@@ -364,13 +376,15 @@ static int copyup_named_dentry(struct in
 
        /* Create the directory structure above this dentry. */
        new_lower_dentry =
-               create_parents_named(dir, dentry, name, new_bindex);
+               create_parents_named(dir, dentry, name, new_bindex,
+                                    &new_lower_mnt);
        if (IS_ERR(new_lower_dentry)) {
                err = PTR_ERR(new_lower_dentry);
                goto out;
        }
 
        old_lower_dentry = unionfs_lower_dentry_idx(dentry, old_bindex);
+       old_lower_mnt = unionfs_lower_mnt_idx(dentry, old_bindex);
        /* we conditionally dput this old_lower_dentry at end of function */
        dget(old_lower_dentry);
 
@@ -407,7 +421,7 @@ static int copyup_named_dentry(struct in
 
        /* create the new inode */
        err = __copyup_ndentry(old_lower_dentry, new_lower_dentry,
-                              new_lower_parent_dentry, symbuf);
+                              new_lower_mnt, new_lower_parent_dentry, symbuf);
 
        if (err) {
                __clear(dentry, old_lower_dentry,
@@ -426,12 +440,13 @@ static int copyup_named_dentry(struct in
 
        /* Set permissions. */
        if ((err = copyup_permissions(sb, old_lower_dentry,
-                                     new_lower_dentry)))
+                                     new_lower_dentry, new_lower_mnt)))
                goto out_unlink;
 
 #ifdef CONFIG_UNION_FS_XATTR
        /* Selinux uses extended attributes for permissions. */
-       if ((err = copyup_xattrs(old_lower_dentry, new_lower_dentry)))
+       if ((err = copyup_xattrs(old_lower_dentry, old_lower_mnt,
+                                new_lower_dentry, new_lower_mnt)))
                goto out_unlink;
 #endif
 
@@ -447,7 +462,8 @@ out_unlink:
         * quota, or something else happened so let's unlink; we don't
         * really care about the return value of vfs_unlink
         */
-       vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry);
+       vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry,
+                  new_lower_mnt);
 
        if (copyup_file) {
                /* need to close the file */
@@ -531,9 +547,10 @@ int copyup_file(struct inode *dir, struc
  * also.
  */
 struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
-                             int bindex)
+                             int bindex, struct vfsmount **mnt)
 {
-       return create_parents_named(dir, dentry, dentry->d_name.name, bindex);
+       return create_parents_named(dir, dentry, dentry->d_name.name, bindex,
+                                   mnt);
 }
 
 /* purge a dentry's lower-branch states (dput/mntput, etc.) */
@@ -617,13 +634,15 @@ static void __set_dentry(struct dentry *
  */
 static struct dentry *create_parents_named(struct inode *dir,
                                           struct dentry *dentry,
-                                          const char *name, int bindex)
+                                          const char *name, int bindex,
+                                          struct vfsmount **mnt)
 {
        int err;
        struct dentry *child_dentry;
        struct dentry *parent_dentry;
        struct dentry *lower_parent_dentry = NULL;
        struct dentry *lower_dentry = NULL;
+       struct vfsmount *lower_mnt = NULL;
        const char *childname;
        unsigned int childnamelen;
 
@@ -704,6 +723,7 @@ static struct dentry *create_parents_nam
                /* get lower parent dir in the current branch */
                lower_parent_dentry =
                        unionfs_lower_dentry_idx(parent_dentry, bindex);
+               lower_mnt = unionfs_lower_mnt_idx(parent_dentry, bindex);
                unionfs_unlock_dentry(parent_dentry);
 
                /* init the values to lookup */
@@ -756,6 +776,7 @@ static struct dentry *create_parents_nam
 
                        args.mkdir.parent = lower_parent_dentry->d_inode;
                        args.mkdir.dentry = lower_dentry;
+                       args.mkdir.mnt = lower_mnt;
                        args.mkdir.mode = child_dentry->d_inode->i_mode;
 
                        run_sioq(__unionfs_mkdir, &args);
@@ -764,7 +785,8 @@ static struct dentry *create_parents_nam
                        if (!err)
                                err = copyup_permissions(dir->i_sb,
                                                         child_dentry,
-                                                        lower_dentry);
+                                                        lower_dentry,
+                                                        lower_mnt);
                        unlock_dir(lower_parent_dentry);
                        if (err) {
                                struct inode *inode = lower_dentry->d_inode;
@@ -803,5 +825,6 @@ out:
                while (count)
                        unionfs_unlock_dentry(path[count--]);
        kfree(path);
+       *mnt = lower_mnt;
        return lower_dentry;
 }
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -29,6 +29,7 @@ int do_delete_whiteouts(struct dentry *d
        int err = 0;
        struct dentry *lower_dir_dentry = NULL;
        struct dentry *lower_dentry;
+       struct vfsmount *lower_mnt;
        char *name = NULL, *p;
        struct inode *lower_dir;
 
@@ -38,6 +39,7 @@ int do_delete_whiteouts(struct dentry *d
 
        /* Find out lower parent dentry */
        lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+       lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
        BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode));
        lower_dir = lower_dir_dentry->d_inode;
        BUG_ON(!S_ISDIR(lower_dir->i_mode));
@@ -71,7 +73,8 @@ int do_delete_whiteouts(struct dentry *d
                                break;
                        }
                        if (lower_dentry->d_inode)
-                               err = vfs_unlink(lower_dir, lower_dentry);
+                               err = vfs_unlink(lower_dir, lower_dentry,
+                                                lower_mnt);
                        dput(lower_dentry);
                        if (err)
                                break;
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -23,8 +23,11 @@ static int unionfs_create(struct inode *
 {
        int err = 0;
        struct dentry *lower_dentry = NULL;
+       struct vfsmount *lower_mnt = NULL;
        struct dentry *wh_dentry = NULL;
+       struct vfsmount *wh_mnt = NULL;
        struct dentry *new_lower_dentry;
+       struct vfsmount *new_lower_mnt;
        struct dentry *lower_parent_dentry = NULL;
        int bindex = 0, bstart;
        char *name = NULL;
@@ -63,6 +66,7 @@ static int unionfs_create(struct inode *
 
        wh_dentry = lookup_one_len(name, lower_dentry->d_parent,
                                   dentry->d_name.len + UNIONFS_WHLEN);
+       wh_mnt = unionfs_lower_mnt(dentry);
        if (IS_ERR(wh_dentry)) {
                err = PTR_ERR(wh_dentry);
                wh_dentry = NULL;
@@ -92,7 +96,7 @@ static int unionfs_create(struct inode *
                        newattrs.ia_size = 0;
                }
 
-               err = notify_change(wh_dentry, &newattrs);
+               err = notify_change(wh_dentry, wh_mnt, &newattrs);
 
                mutex_unlock(&wh_dentry->d_inode->i_mutex);
 
@@ -102,6 +106,7 @@ static int unionfs_create(struct inode *
                               __FILE__, __LINE__, err);
 
                new_lower_dentry = unionfs_lower_dentry(dentry);
+               new_lower_mnt = unionfs_lower_mnt(dentry);
                dget(new_lower_dentry);
 
                lower_dir_dentry = dget_parent(wh_dentry);
@@ -109,9 +114,9 @@ static int unionfs_create(struct inode *
 
                if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
                        err = vfs_rename(lower_dir_dentry->d_inode,
-                                        wh_dentry,
+                                        wh_dentry, wh_mnt,
                                         lower_dir_dentry->d_inode,
-                                        new_lower_dentry);
+                                        new_lower_dentry, new_lower_mnt);
                }
                if (!err) {
                        fsstack_copy_attr_times(parent,
@@ -159,6 +164,7 @@ static int unionfs_create(struct inode *
 
        for (bindex = bstart; bindex >= 0; bindex--) {
                lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+               lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
                if (!lower_dentry) {
                        /*
                         * if lower_dentry is NULL, create the entire
@@ -167,7 +173,8 @@ static int unionfs_create(struct inode *
                         * because lookup passed as a negative unionfs dentry
                         * pointing to a lone negative underlying dentry.
                         */
-                       lower_dentry = create_parents(parent, dentry, bindex);
+                       lower_dentry = create_parents(parent, dentry, bindex,
+                                                     &lower_mnt);
                        if (!lower_dentry || IS_ERR(lower_dentry)) {
                                if (IS_ERR(lower_dentry))
                                        err = PTR_ERR(lower_dentry);
@@ -256,9 +263,12 @@ static int unionfs_link(struct dentry *o
 {
        int err = 0;
        struct dentry *lower_old_dentry = NULL;
+       struct vfsmount *lower_old_mnt = NULL;
        struct dentry *lower_new_dentry = NULL;
+       struct vfsmount *lower_new_mnt = NULL;
        struct dentry *lower_dir_dentry = NULL;
        struct dentry *whiteout_dentry;
+       struct vfsmount *whiteout_mnt;
        char *name = NULL;
 
        unionfs_read_lock(old_dentry->d_sb);
@@ -289,6 +299,7 @@ static int unionfs_link(struct dentry *o
        whiteout_dentry = lookup_one_len(name, lower_new_dentry->d_parent,
                                         new_dentry->d_name.len +
                                         UNIONFS_WHLEN);
+       whiteout_mnt = unionfs_lower_mnt(new_dentry);
        if (IS_ERR(whiteout_dentry)) {
                err = PTR_ERR(whiteout_dentry);
                goto out;
@@ -303,7 +314,7 @@ static int unionfs_link(struct dentry *o
                err = is_robranch_super(new_dentry->d_sb, dbstart(new_dentry));
                if (!err)
                        err = vfs_unlink(lower_dir_dentry->d_inode,
-                                        whiteout_dentry);
+                                        whiteout_dentry, whiteout_mnt);
 
                fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
                dir->i_nlink = unionfs_get_nlinks(dir);
@@ -316,7 +327,8 @@ static int unionfs_link(struct dentry *o
 
        if (dbstart(old_dentry) != dbstart(new_dentry)) {
                lower_new_dentry =
-                       create_parents(dir, new_dentry, dbstart(old_dentry));
+                       create_parents(dir, new_dentry, dbstart(old_dentry),
+                                      &lower_new_mnt);
                err = PTR_ERR(lower_new_dentry);
                if (IS_COPYUP_ERR(err))
                        goto docopyup;
@@ -324,13 +336,16 @@ static int unionfs_link(struct dentry *o
                        goto out;
        }
        lower_new_dentry = unionfs_lower_dentry(new_dentry);
+       lower_new_mnt = unionfs_lower_mnt(new_dentry);
        lower_old_dentry = unionfs_lower_dentry(old_dentry);
+       lower_old_mnt = unionfs_lower_mnt(old_dentry);
 
        BUG_ON(dbstart(old_dentry) != dbstart(new_dentry));
        lower_dir_dentry = lock_parent(lower_new_dentry);
        if (!(err = is_robranch(old_dentry)))
-               err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
-                              lower_new_dentry);
+               err = vfs_link(lower_old_dentry, lower_old_mnt,
+                              lower_dir_dentry->d_inode,
+                              lower_new_dentry, lower_new_mnt);
        unlock_dir(lower_dir_dentry);
 
 docopyup:
@@ -346,15 +361,19 @@ docopyup:
                        if (!err) {
                                lower_new_dentry =
                                        create_parents(dir, new_dentry,
-                                                      bindex);
+                                                      bindex, &lower_new_mnt);
                                lower_old_dentry =
                                        unionfs_lower_dentry(old_dentry);
+                               lower_old_mnt =
+                                       unionfs_lower_mnt(old_dentry);
                                lower_dir_dentry =
                                        lock_parent(lower_new_dentry);
                                /* do vfs_link */
                                err = vfs_link(lower_old_dentry,
+                                              lower_old_mnt,
                                               lower_dir_dentry->d_inode,
-                                              lower_new_dentry);
+                                              lower_new_dentry,
+                                              lower_new_mnt);
                                unlock_dir(lower_dir_dentry);
                                goto check_link;
                        }
@@ -395,7 +414,9 @@ static int unionfs_symlink(struct inode 
 {
        int err = 0;
        struct dentry *lower_dentry = NULL;
+       struct vfsmount *lower_mnt = NULL;
        struct dentry *whiteout_dentry = NULL;
+       struct vfsmount *whiteout_mnt = NULL;
        struct dentry *lower_dir_dentry = NULL;
        umode_t mode;
        int bindex = 0, bstart;
@@ -441,11 +462,12 @@ static int unionfs_symlink(struct inode 
                 * found a .wh.foo entry, unlink it and then call
                 * vfs_symlink().
                 */
+               whiteout_mnt = unionfs_lower_mnt(dentry);
                lower_dir_dentry = lock_parent(whiteout_dentry);
 
                if (!(err = is_robranch_super(dentry->d_sb, bstart)))
                        err = vfs_unlink(lower_dir_dentry->d_inode,
-                                        whiteout_dentry);
+                                        whiteout_dentry, whiteout_mnt);
                dput(whiteout_dentry);
 
                fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
@@ -472,6 +494,7 @@ static int unionfs_symlink(struct inode 
         */
        for (bindex = bstart; bindex >= 0; bindex--) {
                lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+               lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
                if (!lower_dentry) {
                        /*
                         * if lower_dentry is NULL, create the entire
@@ -481,7 +504,8 @@ static int unionfs_symlink(struct inode 
                         * unionfs dentry pointing to a lone negative
                         * underlying dentry
                         */
-                       lower_dentry = create_parents(dir, dentry, bindex);
+                       lower_dentry = create_parents(dir, dentry, bindex,
+                                                     &lower_mnt);
                        if (!lower_dentry || IS_ERR(lower_dentry)) {
                                if (IS_ERR(lower_dentry))
                                        err = PTR_ERR(lower_dentry);
@@ -499,7 +523,8 @@ static int unionfs_symlink(struct inode 
                        mode = S_IALLUGO;
                        err =
                                vfs_symlink(lower_dir_dentry->d_inode,
-                                           lower_dentry, symname, mode);
+                                           lower_dentry, lower_mnt, symname,
+                                           mode);
                }
                unlock_dir(lower_dir_dentry);
 
@@ -543,6 +568,7 @@ static int unionfs_mkdir(struct inode *p
 {
        int err = 0;
        struct dentry *lower_dentry = NULL, *whiteout_dentry = NULL;
+       struct vfsmount *lower_mnt = NULL, *whiteout_mnt = NULL;
        struct dentry *lower_parent_dentry = NULL;
        int bindex = 0, bstart;
        char *name = NULL;
@@ -561,7 +587,7 @@ static int unionfs_mkdir(struct inode *p
        bstart = dbstart(dentry);
 
        lower_dentry = unionfs_lower_dentry(dentry);
-
+       lower_mnt = unionfs_lower_mnt(dentry);
        /*
         * check if whiteout exists in this branch, i.e. lookup .wh.foo
         * first.
@@ -583,12 +609,14 @@ static int unionfs_mkdir(struct inode *p
                dput(whiteout_dentry);
                whiteout_dentry = NULL;
        } else {
+               whiteout_mnt = unionfs_lower_mnt(dentry);
                lower_parent_dentry = lock_parent(whiteout_dentry);
 
                /* found a.wh.foo entry, remove it then do vfs_mkdir */
                if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
                        args.unlink.parent = lower_parent_dentry->d_inode;
                        args.unlink.dentry = whiteout_dentry;
+                       args.unlink.mnt = whiteout_mnt;
                        run_sioq(__unionfs_unlink, &args);
                        err = args.err;
                }
@@ -613,8 +641,10 @@ static int unionfs_mkdir(struct inode *p
                        continue;
 
                lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+               lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
                if (!lower_dentry) {
-                       lower_dentry = create_parents(parent, dentry, bindex);
+                       lower_dentry = create_parents(parent, dentry, bindex,
+                                                     &lower_mnt);
                        if (!lower_dentry || IS_ERR(lower_dentry)) {
                                printk(KERN_DEBUG "unionfs: lower dentry "
                                       " NULL for bindex = %d\n", bindex);
@@ -630,7 +660,7 @@ static int unionfs_mkdir(struct inode *p
                }
 
                err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry,
-                               mode);
+                               lower_mnt, mode);
 
                unlock_dir(lower_parent_dentry);
 
@@ -684,6 +714,7 @@ static int unionfs_mknod(struct inode *d
 {
        int err = 0;
        struct dentry *lower_dentry = NULL, *whiteout_dentry = NULL;
+       struct vfsmount *lower_mnt = NULL, *whiteout_mnt = NULL;
        struct dentry *lower_parent_dentry = NULL;
        int bindex = 0, bstart;
        char *name = NULL;
@@ -723,13 +754,14 @@ static int unionfs_mknod(struct inode *d
                dput(whiteout_dentry);
                whiteout_dentry = NULL;
        } else {
+               whiteout_mnt = unionfs_lower_mnt(dentry);
                /* found .wh.foo, unlink it */
                lower_parent_dentry = lock_parent(whiteout_dentry);
 
                /* found a.wh.foo entry, remove it then do vfs_mkdir */
                if (!(err = is_robranch_super(dentry->d_sb, bstart)))
                        err = vfs_unlink(lower_parent_dentry->d_inode,
-                                        whiteout_dentry);
+                                        whiteout_dentry, whiteout_mnt);
                dput(whiteout_dentry);
 
                unlock_dir(lower_parent_dentry);
@@ -748,8 +780,10 @@ static int unionfs_mknod(struct inode *d
                        continue;
 
                lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+               lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
                if (!lower_dentry) {
-                       lower_dentry = create_parents(dir, dentry, bindex);
+                       lower_dentry = create_parents(dir, dentry, bindex,
+                                                     &lower_mnt);
                        if (IS_ERR(lower_dentry)) {
                                printk(KERN_DEBUG "unionfs: failed to create "
                                       "parents on %d, err = %ld\n",
@@ -765,7 +799,7 @@ static int unionfs_mknod(struct inode *d
                }
 
                err = vfs_mknod(lower_parent_dentry->d_inode,
-                               lower_dentry, mode, dev);
+                               lower_dentry, lower_mnt, mode, dev);
 
                if (err) {
                        unlock_dir(lower_parent_dentry);
@@ -1014,6 +1048,7 @@ static int unionfs_setattr(struct dentry
 {
        int err = 0;
        struct dentry *lower_dentry;
+       struct vfsmount *lower_mnt;
        struct inode *inode = NULL;
        struct inode *lower_inode = NULL;
        int bstart, bend, bindex;
@@ -1038,6 +1073,7 @@ static int unionfs_setattr(struct dentry
                if (!lower_dentry)
                        continue;
                BUG_ON(lower_dentry->d_inode == NULL);
+               lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
 
                /* If the file is on a read only branch */
                if (is_robranch_super(dentry->d_sb, bindex)
@@ -1068,7 +1104,7 @@ static int unionfs_setattr(struct dentry
                        }
 
                }
-               err = notify_change(lower_dentry, ia);
+               err = notify_change(lower_dentry, lower_mnt, ia);
                if (err)
                        goto out;
                break;
--- a/fs/unionfs/rename.c
+++ b/fs/unionfs/rename.c
@@ -24,20 +24,25 @@ static int __unionfs_rename(struct inode
 {
        int err = 0;
        struct dentry *lower_old_dentry;
+       struct vfsmount *lower_old_mnt;
        struct dentry *lower_new_dentry;
+       struct vfsmount *lower_new_mnt;
        struct dentry *lower_old_dir_dentry;
        struct dentry *lower_new_dir_dentry;
        struct dentry *lower_wh_dentry;
+       struct vfsmount *lower_wh_mnt;
        struct dentry *lower_wh_dir_dentry;
        char *wh_name = NULL;
 
        lower_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
+       lower_new_mnt = unionfs_lower_mnt_idx(new_dentry, bindex);
        lower_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex);
+       lower_old_mnt = unionfs_lower_mnt_idx(old_dentry, bindex);
 
        if (!lower_new_dentry) {
                lower_new_dentry =
                        create_parents(new_dentry->d_parent->d_inode,
-                                      new_dentry, bindex);
+                                      new_dentry, bindex, &lower_new_mnt);
                if (IS_ERR(lower_new_dentry)) {
                        printk(KERN_DEBUG "unionfs: error creating directory "
                               "tree for rename, bindex = %d, err = %ld\n",
@@ -57,6 +62,8 @@ static int __unionfs_rename(struct inode
        lower_wh_dentry = lookup_one_len(wh_name, lower_new_dentry->d_parent,
                                          new_dentry->d_name.len +
                                          UNIONFS_WHLEN);
+       lower_wh_mnt = lower_new_mnt;
+
        if (IS_ERR(lower_wh_dentry)) {
                err = PTR_ERR(lower_wh_dentry);
                goto out;
@@ -76,7 +83,7 @@ static int __unionfs_rename(struct inode
                lower_wh_dir_dentry = lock_parent(lower_wh_dentry);
                if (!(err = is_robranch_super(old_dentry->d_sb, bindex)))
                        err = vfs_unlink(lower_wh_dir_dentry->d_inode,
-                                        lower_wh_dentry);
+                                        lower_wh_dentry, lower_wh_mnt);
 
                dput(lower_wh_dentry);
                unlock_dir(lower_wh_dir_dentry);
@@ -118,7 +125,8 @@ static int __unionfs_rename(struct inode
        }
 
        err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
-                        lower_new_dir_dentry->d_inode, lower_new_dentry);
+                        lower_old_mnt, lower_new_dir_dentry->d_inode,
+                        lower_new_dentry, lower_new_mnt);
 
 out_unlock:
        unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
@@ -187,15 +195,16 @@ static int do_unionfs_rename(struct inod
        for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) {
                struct dentry *unlink_dentry;
                struct dentry *unlink_dir_dentry;
+               struct vfsmount *unlink_mnt;
 
                unlink_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
                if (!unlink_dentry)
                        continue;
-
+               unlink_mnt = unionfs_lower_mnt_idx(new_dentry, bindex);
                unlink_dir_dentry = lock_parent(unlink_dentry);
                if (!(err = is_robranch_super(old_dir->i_sb, bindex)))
                        err = vfs_unlink(unlink_dir_dentry->d_inode,
-                                        unlink_dentry);
+                                        unlink_dentry, unlink_mnt);
 
                fsstack_copy_attr_times(new_dentry->d_parent->d_inode,
                                        unlink_dir_dentry->d_inode);
--- a/fs/unionfs/sioq.c
+++ b/fs/unionfs/sioq.c
@@ -68,7 +68,7 @@ void __unionfs_mkdir(struct work_struct 
        struct sioq_args *args = container_of(work, struct sioq_args, work);
        struct mkdir_args *m = &args->mkdir;
 
-       args->err = vfs_mkdir(m->parent, m->dentry, m->mode);
+       args->err = vfs_mkdir(m->parent, m->dentry, m->mnt, m->mode);
        complete(&args->comp);
 }
 
@@ -77,7 +77,7 @@ void __unionfs_mknod(struct work_struct 
        struct sioq_args *args = container_of(work, struct sioq_args, work);
        struct mknod_args *m = &args->mknod;
 
-       args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev);
+       args->err = vfs_mknod(m->parent, m->dentry, m->mnt, m->mode, m->dev);
        complete(&args->comp);
 }
 
@@ -86,7 +86,8 @@ void __unionfs_symlink(struct work_struc
        struct sioq_args *args = container_of(work, struct sioq_args, work);
        struct symlink_args *s = &args->symlink;
 
-       args->err = vfs_symlink(s->parent, s->dentry, s->symbuf, s->mode);
+       args->err = vfs_symlink(s->parent, s->dentry, s->mnt, s->symbuf,
+                               s->mode);
        complete(&args->comp);
 }
 
@@ -95,7 +96,7 @@ void __unionfs_unlink(struct work_struct
        struct sioq_args *args = container_of(work, struct sioq_args, work);
        struct unlink_args *u = &args->unlink;
 
-       args->err = vfs_unlink(u->parent, u->dentry);
+       args->err = vfs_unlink(u->parent, u->dentry, u->mnt);
        complete(&args->comp);
 }
 
--- a/fs/unionfs/sioq.h
+++ b/fs/unionfs/sioq.h
@@ -34,12 +34,14 @@ struct create_args {
 struct mkdir_args {
        struct inode *parent;
        struct dentry *dentry;
+       struct vfsmount *mnt;
        umode_t mode;
 };
 
 struct mknod_args {
        struct inode *parent;
        struct dentry *dentry;
+       struct vfsmount *mnt;
        umode_t mode;
        dev_t dev;
 };
@@ -47,6 +49,7 @@ struct mknod_args {
 struct symlink_args {
        struct inode *parent;
        struct dentry *dentry;
+       struct vfsmount *mnt;
        char *symbuf;
        umode_t mode;
 };
@@ -54,6 +57,7 @@ struct symlink_args {
 struct unlink_args {
        struct inode *parent;
        struct dentry *dentry;
+       struct vfsmount *mnt;
 };
 
 
--- a/fs/unionfs/subr.c
+++ b/fs/unionfs/subr.c
@@ -28,7 +28,9 @@ int create_whiteout(struct dentry *dentr
        int bstart, bend, bindex;
        struct dentry *lower_dir_dentry;
        struct dentry *lower_dentry;
+       struct vfsmount *lower_mnt;
        struct dentry *lower_wh_dentry;
+
        char *name = NULL;
        int err = -EINVAL;
 
@@ -55,8 +57,8 @@ int create_whiteout(struct dentry *dentr
                         * only want the parent dentry, and hence get rid of
                         * this dentry.
                         */
-                       lower_dentry = create_parents(dentry->d_inode,
-                                                     dentry, bindex);
+                       lower_dentry = create_parents(dentry->d_inode, dentry,
+                                                     bindex, &lower_mnt);
                        if (!lower_dentry || IS_ERR(lower_dentry)) {
                                printk(KERN_DEBUG "unionfs: create_parents "
                                       "failed for bindex = %d\n", bindex);
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -252,7 +252,7 @@ extern void update_bstart(struct dentry 
 
 /* replicates the directory structure up to given dentry in given branch */
 extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
-                                    int bindex);
+                                    int bindex, struct vfsmount **mnt);
 extern int make_dir_opaque(struct dentry *dir, int bindex);
 
 /* partial lookup */
--- a/fs/unionfs/unlink.c
+++ b/fs/unionfs/unlink.c
@@ -22,6 +22,7 @@
 static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry)
 {
        struct dentry *lower_dentry;
+       struct vfsmount *lower_mnt;
        struct dentry *lower_dir_dentry;
        int bindex;
        int err = 0;
@@ -34,13 +35,15 @@ static int unionfs_unlink_whiteout(struc
        lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
        if (!lower_dentry)
                goto out;
+       lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
 
        lower_dir_dentry = lock_parent(lower_dentry);
 
        /* avoid destroying the lower inode if the file is in use */
        dget(lower_dentry);
        if (!(err = is_robranch_super(dentry->d_sb, bindex)))
-               err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
+               err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry,
+                                lower_mnt);
        dput(lower_dentry);
        fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
        unlock_dir(lower_dir_dentry);
@@ -98,6 +101,7 @@ static int unionfs_rmdir_first(struct in
 {
        int err;
        struct dentry *lower_dentry;
+       struct vfsmount *lower_mnt;
        struct dentry *lower_dir_dentry = NULL;
 
        /* Here we need to remove whiteout entries. */
@@ -106,13 +110,15 @@ static int unionfs_rmdir_first(struct in
                goto out;
 
        lower_dentry = unionfs_lower_dentry(dentry);
+       lower_mnt = unionfs_lower_mnt(dentry);
 
        lower_dir_dentry = lock_parent(lower_dentry);
 
        /* avoid destroying the lower inode if the file is in use */
        dget(lower_dentry);
        if (!(err = is_robranch(dentry)))
-               err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
+               err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry,
+                               lower_mnt);
        dput(lower_dentry);
 
        fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
--- a/fs/unionfs/xattr.c
+++ b/fs/unionfs/xattr.c
@@ -55,6 +55,7 @@ ssize_t unionfs_getxattr(struct dentry *
                         size_t size)
 {
        struct dentry *lower_dentry = NULL;
+       struct vfsmount *lower_mnt;
        int err = -EOPNOTSUPP;
 
        unionfs_read_lock(dentry->d_sb);
@@ -66,8 +67,10 @@ ssize_t unionfs_getxattr(struct dentry *
        }
 
        lower_dentry = unionfs_lower_dentry(dentry);
+       lower_mnt = unionfs_lower_mnt(dentry);
 
-       err = vfs_getxattr(lower_dentry, (char*) name, value, size);
+       err = vfs_getxattr(lower_dentry, lower_mnt, (char*) name, value,
+                          size, NULL);
 
 out:
        unionfs_unlock_dentry(dentry);
@@ -83,6 +86,8 @@ int unionfs_setxattr(struct dentry *dent
                     const void *value, size_t size, int flags)
 {
        struct dentry *lower_dentry = NULL;
+       struct vfsmount *lower_mnt;
+
        int err = -EOPNOTSUPP;
 
        unionfs_read_lock(dentry->d_sb);
@@ -94,9 +99,10 @@ int unionfs_setxattr(struct dentry *dent
        }
 
        lower_dentry = unionfs_lower_dentry(dentry);
+       lower_mnt = unionfs_lower_mnt(dentry);
 
-       err = vfs_setxattr(lower_dentry, (char*) name, (void*) value,
-                          size, flags);
+       err = vfs_setxattr(lower_dentry, lower_mnt, (char*) name,
+                          (void*) value, size, flags, NULL);
 
 out:
        unionfs_unlock_dentry(dentry);
@@ -111,6 +117,7 @@ out:
 int unionfs_removexattr(struct dentry *dentry, const char *name)
 {
        struct dentry *lower_dentry = NULL;
+       struct vfsmount *lower_mnt;
        int err = -EOPNOTSUPP;
 
        unionfs_read_lock(dentry->d_sb);
@@ -122,8 +129,9 @@ int unionfs_removexattr(struct dentry *d
        }
 
        lower_dentry = unionfs_lower_dentry(dentry);
+       lower_mnt = unionfs_lower_mnt(dentry);
 
-       err = vfs_removexattr(lower_dentry, (char*) name);
+       err = vfs_removexattr(lower_dentry, lower_mnt, (char*) name, NULL);
 
 out:
        unionfs_unlock_dentry(dentry);
@@ -138,6 +146,7 @@ out:
 ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size)
 {
        struct dentry *lower_dentry = NULL;
+       struct vfsmount *lower_mnt;
        int err = -EOPNOTSUPP;
        char *encoded_list = NULL;
 
@@ -150,9 +159,10 @@ ssize_t unionfs_listxattr(struct dentry 
        }
 
        lower_dentry = unionfs_lower_dentry(dentry);
+       lower_mnt = unionfs_lower_mnt(dentry);
 
        encoded_list = list;
-       err = vfs_listxattr(lower_dentry, encoded_list, size);
+       err = vfs_listxattr(lower_dentry, lower_mnt, encoded_list, size, NULL);
 
 out:
        unionfs_unlock_dentry(dentry);

Attachment: pgpqAgjUxlzjd.pgp
Description: PGP signature

_______________________________________________
unionfs mailing list: http://unionfs.filesystems.org/
unionfs@mail.fsl.cs.sunysb.edu
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs

Reply via email to