[packages/kernel] - aufs updated but build still fails
arekm
arekm at pld-linux.org
Sat Aug 24 00:05:18 CEST 2013
commit c2b27bf2e94b20b2576c4191ce00ad744682ca70
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Sat Aug 24 00:05:11 2013 +0200
- aufs updated but build still fails
kernel-aufs3.patch | 1565 ++++++++++++++++++++++++++++++++++++----------------
kernel.spec | 2 +-
2 files changed, 1097 insertions(+), 470 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index 19347b1..f3eabbd 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -188,7 +188,7 @@ Patch85: kernel-hostap.patch
# http://www.linuxtv.org/wiki/index.php/TechniSat_CableStar_Combo_HD_CI#Patch
Patch90: kernel-technisat-combo-hd-ci.patch
-# http://vserver.13thfloor.at/Experimental/patch-3.9.5-vs2.3.6.5.diff
+# http://vserver.13thfloor.at/Experimental/patch-3.10.9-vs2.3.6.6.diff
# note there are additional patches from above url:
# - *fix* are real fixes (we want these)
# - *feat* are new features/tests (we don't want these)
diff --git a/kernel-aufs3.patch b/kernel-aufs3.patch
index 653e14b..a93df4a 100644
--- a/kernel-aufs3.patch
+++ b/kernel-aufs3.patch
@@ -661,8 +661,8 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt lin
+about it. But currently I have implemented it in kernel space.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2013-07-06 13:20:47.730197761 +0200
-@@ -0,0 +1,226 @@
++++ linux/Documentation/filesystems/aufs/design/02struct.txt 2013-08-23 23:59:39.631583456 +0200
+@@ -0,0 +1,243 @@
+
+# Copyright (C) 2005-2013 Junjiro R. Okajima
+#
@@ -889,6 +889,23 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt li
+internally and makes change to the new file on the upper writable branch.
+When the trigger systemcall does not update the timestamps of the parent
+dir, aufs reverts it after copy-up.
++
++
++Move-down (aufs3.9 and later)
++----------------------------------------------------------------------
++"Copy-up" is one of the essential feature in aufs. It copies a file from
++the lower readonly branch to the upper writable branch when a user
++changes something about the file.
++"Move-down" is an opposite action of copy-up. Basically this action is
++ran manually instead of automatically and internally.
++
++Sometimes users want to move-down a file from the upper writable branch
++to the lower readonly or writable branch. For instance,
++- the free space of the upper writable branch is going to run out.
++- create a new intermediate branch between the upper and lower branch.
++- etc.
++
++For this purpose, use "aumvdown" command in aufs-util.git.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2013-07-06 13:20:47.730197761 +0200
@@ -3404,8 +3421,8 @@ diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
+-include ${srctree}/${src}/conf_priv.mk
diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/cpup.c 2013-07-30 22:42:46.232612606 +0200
-@@ -0,0 +1,1247 @@
++++ linux/fs/aufs/cpup.c 2013-08-23 23:59:39.631583456 +0200
+@@ -0,0 +1,1255 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -3753,18 +3770,11 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ return err;
+}
+
-+/* internal use only */
-+struct au_cpup_basic {
-+ struct dentry *dentry;
-+ aufs_bindex_t bdst, bsrc;
-+ loff_t len;
-+};
-+
+/*
+ * to support a sparse file which is opened with O_APPEND,
+ * we need to close the file.
+ */
-+static int au_cp_regular(struct au_cpup_basic *basic)
++static int au_cp_regular(struct au_cp_generic *cpg)
+{
+ int err, i;
+ enum { SRC, DST };
@@ -3776,14 +3786,14 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ void *label, *label_file;
+ } *f, file[] = {
+ {
-+ .bindex = basic->bsrc,
++ .bindex = cpg->bsrc,
+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
+ .file = NULL,
+ .label = &&out,
+ .label_file = &&out_src
+ },
+ {
-+ .bindex = basic->bdst,
++ .bindex = cpg->bdst,
+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
+ .file = NULL,
+ .label = &&out_src,
@@ -3793,11 +3803,11 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ struct super_block *sb;
+
+ /* bsrc branch can be ro/rw. */
-+ sb = basic->dentry->d_sb;
++ sb = cpg->dentry->d_sb;
+ f = file;
+ for (i = 0; i < 2; i++, f++) {
-+ f->dentry = au_h_dptr(basic->dentry, f->bindex);
-+ f->file = au_h_open(basic->dentry, f->bindex, f->flags,
++ f->dentry = au_h_dptr(cpg->dentry, f->bindex);
++ f->file = au_h_open(cpg->dentry, f->bindex, f->flags,
+ /*file*/NULL);
+ err = PTR_ERR(f->file);
+ if (IS_ERR(f->file))
@@ -3809,7 +3819,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+
+ /* try stopping to update while we copyup */
+ IMustLock(file[SRC].dentry->d_inode);
-+ err = au_copy_file(file[DST].file, file[SRC].file, basic->len);
++ err = au_copy_file(file[DST].file, file[SRC].file, cpg->len);
+
+out_dst:
+ fput(file[DST].file);
@@ -3821,7 +3831,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ return err;
+}
+
-+static int au_do_cpup_regular(struct au_cpup_basic *basic, struct au_pin *pin,
++static int au_do_cpup_regular(struct au_cp_generic *cpg,
+ struct au_cpup_reg_attr *h_src_attr)
+{
+ int err, rerr;
@@ -3830,17 +3840,17 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ struct inode *h_src_inode;
+
+ err = 0;
-+ h_src_inode = au_h_iptr(basic->dentry->d_inode, basic->bsrc);
++ h_src_inode = au_h_iptr(cpg->dentry->d_inode, cpg->bsrc);
+ l = i_size_read(h_src_inode);
-+ if (basic->len == -1 || l < basic->len)
-+ basic->len = l;
-+ if (basic->len) {
++ if (cpg->len == -1 || l < cpg->len)
++ cpg->len = l;
++ if (cpg->len) {
+ /* try stopping to update while we are referencing */
+ mutex_lock_nested(&h_src_inode->i_mutex, AuLsc_I_CHILD);
-+ au_pin_hdir_unlock(pin);
++ au_pin_hdir_unlock(cpg->pin);
+
-+ h_path.dentry = au_h_dptr(basic->dentry, basic->bsrc);
-+ h_path.mnt = au_sbr_mnt(basic->dentry->d_sb, basic->bsrc);
++ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
++ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc);
+ h_src_attr->iflags = h_src_inode->i_flags;
+ err = vfs_getattr(&h_path, &h_src_attr->st);
+ if (unlikely(err)) {
@@ -3848,9 +3858,9 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ goto out;
+ }
+ h_src_attr->valid = 1;
-+ err = au_cp_regular(basic);
++ err = au_cp_regular(cpg);
+ mutex_unlock(&h_src_inode->i_mutex);
-+ rerr = au_pin_hdir_relock(pin);
++ rerr = au_pin_hdir_relock(cpg->pin);
+ if (!err && rerr)
+ err = rerr;
+ }
@@ -3896,15 +3906,14 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+}
+
+static noinline_for_stack
-+int cpup_entry(struct au_cpup_basic *basic, unsigned int flags,
-+ struct dentry *dst_parent, struct au_pin *pin,
++int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent,
+ struct au_cpup_reg_attr *h_src_attr)
+{
+ int err;
+ umode_t mode;
+ unsigned int mnt_flags;
+ unsigned char isdir;
-+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
++ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME);
+ struct au_dtime dt;
+ struct path h_path;
+ struct dentry *h_src, *h_dst, *h_parent;
@@ -3912,13 +3921,13 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ struct super_block *sb;
+
+ /* bsrc branch can be ro/rw. */
-+ h_src = au_h_dptr(basic->dentry, basic->bsrc);
++ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
+ h_inode = h_src->d_inode;
-+ AuDebugOn(h_inode != au_h_iptr(basic->dentry->d_inode, basic->bsrc));
++ AuDebugOn(h_inode != au_h_iptr(cpg->dentry->d_inode, cpg->bsrc));
+
+ /* try stopping to be referenced while we are creating */
-+ h_dst = au_h_dptr(basic->dentry, basic->bdst);
-+ if (au_ftest_cpup(flags, RENAME))
++ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
++ if (au_ftest_cpup(cpg->flags, RENAME))
+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX,
+ AUFS_WH_PFX_LEN));
+ h_parent = h_dst->d_parent; /* dir inode is locked */
@@ -3926,8 +3935,8 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ IMustLock(h_dir);
+ AuDebugOn(h_parent != h_dst->d_parent);
+
-+ sb = basic->dentry->d_sb;
-+ h_path.mnt = au_sbr_mnt(sb, basic->bdst);
++ sb = cpg->dentry->d_sb;
++ h_path.mnt = au_sbr_mnt(sb, cpg->bdst);
+ if (do_dt) {
+ h_path.dentry = h_parent;
+ au_dtime_store(&dt, dst_parent, &h_path);
@@ -3941,7 +3950,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR,
+ /*want_excl*/true);
+ if (!err)
-+ err = au_do_cpup_regular(basic, pin, h_src_attr);
++ err = au_do_cpup_regular(cpg, h_src_attr);
+ break;
+ case S_IFDIR:
+ isdir = 1;
@@ -3951,10 +3960,10 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ * strange behaviour from the users view,
+ * particularry setattr case
+ */
-+ if (au_ibstart(dst_parent->d_inode) == basic->bdst)
++ if (au_ibstart(dst_parent->d_inode) == cpg->bdst)
+ au_cpup_attr_nlink(dst_parent->d_inode,
+ /*force*/1);
-+ au_cpup_attr_nlink(basic->dentry->d_inode, /*force*/1);
++ au_cpup_attr_nlink(cpg->dentry->d_inode, /*force*/1);
+ }
+ break;
+ case S_IFLNK:
@@ -3979,10 +3988,10 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ && au_opt_test(mnt_flags, XINO)
+ && h_inode->i_nlink == 1
+ /* todo: unnecessary? */
-+ /* && basic->dentry->d_inode->i_nlink == 1 */
-+ && basic->bdst < basic->bsrc
-+ && !au_ftest_cpup(flags, KEEPLINO))
-+ au_xino_write(sb, basic->bsrc, h_inode->i_ino, /*ino*/0);
++ /* && cpg->dentry->d_inode->i_nlink == 1 */
++ && cpg->bdst < cpg->bsrc
++ && !au_ftest_cpup(cpg->flags, KEEPLINO))
++ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0);
+ /* ignore this error */
+
+ if (do_dt)
@@ -4023,82 +4032,87 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ * the caller must set the both of lower dentries.
+ * @len is for truncating when it is -1 copyup the entire file.
+ * in link/rename cases, @dst_parent may be different from the real one.
++ * basic->bsrc can be larger than basic->bdst.
+ */
-+static int au_cpup_single(struct au_cpup_basic *basic, unsigned int flags,
-+ struct dentry *dst_parent, struct au_pin *pin)
++static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
+{
+ int err, rerr;
+ aufs_bindex_t old_ibstart;
+ unsigned char isdir, plink;
-+ struct au_dtime dt;
-+ struct path h_path;
+ struct dentry *h_src, *h_dst, *h_parent;
+ struct inode *dst_inode, *h_dir, *inode;
+ struct super_block *sb;
+ struct au_branch *br;
-+ struct au_cpup_reg_attr h_src_attr = {
-+ .valid = 0
-+ };
++ /* to reuduce stack size */
++ struct {
++ struct au_dtime dt;
++ struct path h_path;
++ struct au_cpup_reg_attr h_src_attr;
++ } *a;
+
-+ AuDebugOn(basic->bsrc <= basic->bdst);
++ err = -ENOMEM;
++ a = kmalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++ a->h_src_attr.valid = 0;
+
-+ sb = basic->dentry->d_sb;
-+ br = au_sbr(sb, basic->bdst);
-+ h_path.mnt = au_br_mnt(br);
-+ h_dst = au_h_dptr(basic->dentry, basic->bdst);
++ sb = cpg->dentry->d_sb;
++ br = au_sbr(sb, cpg->bdst);
++ a->h_path.mnt = au_br_mnt(br);
++ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
+ h_parent = h_dst->d_parent; /* dir inode is locked */
+ h_dir = h_parent->d_inode;
+ IMustLock(h_dir);
+
-+ h_src = au_h_dptr(basic->dentry, basic->bsrc);
-+ inode = basic->dentry->d_inode;
++ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
++ inode = cpg->dentry->d_inode;
+
+ if (!dst_parent)
-+ dst_parent = dget_parent(basic->dentry);
++ dst_parent = dget_parent(cpg->dentry);
+ else
+ dget(dst_parent);
+
+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
-+ dst_inode = au_h_iptr(inode, basic->bdst);
++ dst_inode = au_h_iptr(inode, cpg->bdst);
+ if (dst_inode) {
+ if (unlikely(!plink)) {
+ err = -EIO;
+ AuIOErr("hi%lu(i%lu) exists on b%d "
+ "but plink is disabled\n",
-+ dst_inode->i_ino, inode->i_ino, basic->bdst);
-+ goto out;
++ dst_inode->i_ino, inode->i_ino, cpg->bdst);
++ goto out_parent;
+ }
+
+ if (dst_inode->i_nlink) {
-+ const int do_dt = au_ftest_cpup(flags, DTIME);
++ const int do_dt = au_ftest_cpup(cpg->flags, DTIME);
+
-+ h_src = au_plink_lkup(inode, basic->bdst);
++ h_src = au_plink_lkup(inode, cpg->bdst);
+ err = PTR_ERR(h_src);
+ if (IS_ERR(h_src))
-+ goto out;
++ goto out_parent;
+ if (unlikely(!h_src->d_inode)) {
+ err = -EIO;
+ AuIOErr("i%lu exists on a upper branch "
+ "but not pseudo-linked\n",
+ inode->i_ino);
+ dput(h_src);
-+ goto out;
++ goto out_parent;
+ }
+
+ if (do_dt) {
-+ h_path.dentry = h_parent;
-+ au_dtime_store(&dt, dst_parent, &h_path);
++ a->h_path.dentry = h_parent;
++ au_dtime_store(&a->dt, dst_parent, &a->h_path);
+ }
+
-+ h_path.dentry = h_dst;
-+ err = vfsub_link(h_src, h_dir, &h_path);
-+ if (!err && au_ftest_cpup(flags, RENAME))
++ a->h_path.dentry = h_dst;
++ err = vfsub_link(h_src, h_dir, &a->h_path);
++ if (!err && au_ftest_cpup(cpg->flags, RENAME))
+ err = au_do_ren_after_cpup
-+ (basic->dentry, basic->bdst, &h_path);
++ (cpg->dentry, cpg->bdst, &a->h_path);
+ if (do_dt)
-+ au_dtime_revert(&dt);
++ au_dtime_revert(&a->dt);
+ dput(h_src);
-+ goto out;
++ goto out_parent;
+ } else
+ /* todo: cpup_wh_file? */
+ /* udba work */
@@ -4107,38 +4121,40 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+
+ isdir = S_ISDIR(inode->i_mode);
+ old_ibstart = au_ibstart(inode);
-+ err = cpup_entry(basic, flags, dst_parent, pin, &h_src_attr);
++ err = cpup_entry(cpg, dst_parent, &a->h_src_attr);
+ if (unlikely(err))
+ goto out_rev;
+ dst_inode = h_dst->d_inode;
+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
+ /* todo: necessary? */
-+ /* au_pin_hdir_unlock(pin); */
++ /* au_pin_hdir_unlock(cpg->pin); */
+
-+ err = cpup_iattr(basic->dentry, basic->bdst, h_src, &h_src_attr);
++ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr);
+ if (unlikely(err)) {
+ /* todo: necessary? */
-+ /* au_pin_hdir_relock(pin); */ /* ignore an error */
++ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */
+ mutex_unlock(&dst_inode->i_mutex);
+ goto out_rev;
+ }
+
-+ if (basic->bdst < old_ibstart) {
++ if (cpg->bdst < old_ibstart) {
+ if (S_ISREG(inode->i_mode)) {
-+ err = au_dy_iaop(inode, basic->bdst, dst_inode);
++ err = au_dy_iaop(inode, cpg->bdst, dst_inode);
+ if (unlikely(err)) {
-+ /* au_pin_hdir_relock(pin); ignore an error */
++ /* ignore an error */
++ /* au_pin_hdir_relock(cpg->pin); */
+ mutex_unlock(&dst_inode->i_mutex);
+ goto out_rev;
+ }
+ }
-+ au_set_ibstart(inode, basic->bdst);
-+ }
-+ au_set_h_iptr(inode, basic->bdst, au_igrab(dst_inode),
++ au_set_ibstart(inode, cpg->bdst);
++ } else
++ au_set_ibend(inode, cpg->bdst);
++ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode),
+ au_hi_flags(inode, isdir));
+
+ /* todo: necessary? */
-+ /* err = au_pin_hdir_relock(pin); */
++ /* err = au_pin_hdir_relock(cpg->pin); */
+ mutex_unlock(&dst_inode->i_mutex);
+ if (unlikely(err))
+ goto out_rev;
@@ -4146,53 +4162,55 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ if (!isdir
+ && h_src->d_inode->i_nlink > 1
+ && plink)
-+ au_plink_append(inode, basic->bdst, h_dst);
++ au_plink_append(inode, cpg->bdst, h_dst);
+
-+ if (au_ftest_cpup(flags, RENAME)) {
-+ h_path.dentry = h_dst;
-+ err = au_do_ren_after_cpup(basic->dentry, basic->bdst, &h_path);
++ if (au_ftest_cpup(cpg->flags, RENAME)) {
++ a->h_path.dentry = h_dst;
++ err = au_do_ren_after_cpup(cpg->dentry, cpg->bdst, &a->h_path);
+ }
+ if (!err)
-+ goto out; /* success */
++ goto out_parent; /* success */
+
+ /* revert */
+out_rev:
-+ h_path.dentry = h_parent;
-+ au_dtime_store(&dt, dst_parent, &h_path);
-+ h_path.dentry = h_dst;
++ a->h_path.dentry = h_parent;
++ au_dtime_store(&a->dt, dst_parent, &a->h_path);
++ a->h_path.dentry = h_dst;
+ rerr = 0;
+ if (h_dst->d_inode) {
+ if (!isdir)
-+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ rerr = vfsub_unlink(h_dir, &a->h_path, /*force*/0);
+ else
-+ rerr = vfsub_rmdir(h_dir, &h_path);
++ rerr = vfsub_rmdir(h_dir, &a->h_path);
+ }
-+ au_dtime_revert(&dt);
++ au_dtime_revert(&a->dt);
+ if (rerr) {
+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
+ err = -EIO;
+ }
-+out:
++out_parent:
+ dput(dst_parent);
++ kfree(a);
++out:
+ return err;
+}
+
++#if 0 /* unused */
+struct au_cpup_single_args {
+ int *errp;
-+ struct au_cpup_basic *basic;
-+ unsigned int flags;
++ struct au_cp_generic *cpg;
+ struct dentry *dst_parent;
-+ struct au_pin *pin;
+};
+
+static void au_call_cpup_single(void *args)
+{
+ struct au_cpup_single_args *a = args;
+
-+ au_pin_hdir_acquire_nest(a->pin);
-+ *a->errp = au_cpup_single(a->basic, a->flags, a->dst_parent, a->pin);
-+ au_pin_hdir_release(a->pin);
++ au_pin_hdir_acquire_nest(a->cpg->pin);
++ *a->errp = au_cpup_single(a->cpg, a->dst_parent);
++ au_pin_hdir_release(a->cpg->pin);
+}
++#endif
+
+/*
+ * prevent SIGXFSZ in copy-up.
@@ -4233,29 +4251,20 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ return do_sio;
+}
+
-+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
-+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
-+ struct dentry *dst_parent, struct au_pin *pin)
++#if 0 /* unused */
++int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
+{
+ int err, wkq_err;
+ struct dentry *h_dentry;
-+ struct au_cpup_basic basic = {
-+ .dentry = dentry,
-+ .bdst = bdst,
-+ .bsrc = bsrc,
-+ .len = len
-+ };
+
-+ h_dentry = au_h_dptr(dentry, bsrc);
++ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
+ if (!au_cpup_sio_test(pin, h_dentry->d_inode->i_mode))
-+ err = au_cpup_single(&basic, flags, dst_parent, pin);
++ err = au_cpup_single(cpg, dst_parent);
+ else {
+ struct au_cpup_single_args args = {
+ .errp = &err,
-+ .basic = &basic,
-+ .flags = flags,
-+ .dst_parent = dst_parent,
-+ .pin = pin
++ .cpg = cpg,
++ .dst_parent = dst_parent
+ };
+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
+ if (unlikely(wkq_err))
@@ -4264,44 +4273,35 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+
+ return err;
+}
++#endif
+
+/*
+ * copyup the @dentry from the first active lower branch to @bdst,
+ * using au_cpup_single().
+ */
-+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+ unsigned int flags, struct au_pin *pin)
++static int au_cpup_simple(struct au_cp_generic *cpg)
+{
+ int err;
-+ aufs_bindex_t bsrc, bend;
-+ struct dentry *h_dentry;
++ unsigned int flags_orig;
++ struct dentry *dentry;
++
++ AuDebugOn(cpg->bsrc < 0);
+
++ dentry = cpg->dentry;
+ DiMustWriteLock(dentry);
-+ bend = au_dbend(dentry);
-+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++) {
-+ h_dentry = au_h_dptr(dentry, bsrc);
-+ if (h_dentry) {
-+ AuDebugOn(!h_dentry->d_inode);
-+ break;
-+ }
-+ }
-+ AuDebugOn(bsrc > bend);
+
-+ err = au_lkup_neg(dentry, bdst, /*wh*/1);
++ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1);
+ if (!err) {
-+ struct au_cpup_basic basic = {
-+ .dentry = dentry,
-+ .bdst = bdst,
-+ .bsrc = bsrc,
-+ .len = len
-+ };
-+ err = au_cpup_single(&basic, flags | AuCpup_RENAME, NULL, pin);
++ flags_orig = cpg->flags;
++ au_fset_cpup(cpg->flags, RENAME);
++ err = au_cpup_single(cpg, NULL);
++ cpg->flags = flags_orig;
+ if (!err)
+ return 0; /* success */
+
+ /* revert */
-+ au_set_h_dptr(dentry, bdst, NULL);
-+ au_set_dbstart(dentry, bsrc);
++ au_set_h_dptr(dentry, cpg->bdst, NULL);
++ au_set_dbstart(dentry, cpg->bsrc);
+ }
+
+ return err;
@@ -4309,42 +4309,44 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+
+struct au_cpup_simple_args {
+ int *errp;
-+ struct dentry *dentry;
-+ aufs_bindex_t bdst;
-+ loff_t len;
-+ unsigned int flags;
-+ struct au_pin *pin;
++ struct au_cp_generic *cpg;
+};
+
+static void au_call_cpup_simple(void *args)
+{
+ struct au_cpup_simple_args *a = args;
+
-+ au_pin_hdir_acquire_nest(a->pin);
-+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags, a->pin);
-+ au_pin_hdir_release(a->pin);
++ au_pin_hdir_acquire_nest(a->cpg->pin);
++ *a->errp = au_cpup_simple(a->cpg);
++ au_pin_hdir_release(a->cpg->pin);
+}
+
-+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+ unsigned int flags, struct au_pin *pin)
++static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
+{
+ int err, wkq_err;
-+ struct dentry *parent;
++ struct dentry *dentry, *parent;
++ struct file *h_file;
+ struct inode *h_dir;
+
++ dentry = cpg->dentry;
++ h_file = NULL;
++ if (au_ftest_cpup(cpg->flags, HOPEN)) {
++ AuDebugOn(cpg->bsrc < 0);
++ h_file = au_h_open_pre(dentry, cpg->bsrc);
++ err = PTR_ERR(h_file);
++ if (IS_ERR(h_file))
++ goto out;
++ }
++
+ parent = dget_parent(dentry);
-+ h_dir = au_h_iptr(parent->d_inode, bdst);
++ h_dir = au_h_iptr(parent->d_inode, cpg->bdst);
+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
-+ && !au_cpup_sio_test(pin, dentry->d_inode->i_mode))
-+ err = au_cpup_simple(dentry, bdst, len, flags, pin);
++ && !au_cpup_sio_test(cpg->pin, dentry->d_inode->i_mode))
++ err = au_cpup_simple(cpg);
+ else {
+ struct au_cpup_simple_args args = {
+ .errp = &err,
-+ .dentry = dentry,
-+ .bdst = bdst,
-+ .len = len,
-+ .flags = flags,
-+ .pin = pin
++ .cpg = cpg
+ };
+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
+ if (unlikely(wkq_err))
@@ -4352,26 +4354,39 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ }
+
+ dput(parent);
++ if (h_file)
++ au_h_open_post(dentry, cpg->bsrc, h_file);
++
++out:
+ return err;
+}
+
-+/* generalized cpup_simple() with h_open_pre/post() calls */
-+int au_sio_cpup_simple_h_open(struct dentry *dentry, aufs_bindex_t bdst,
-+ loff_t len, unsigned int flags,
-+ struct au_pin *pin, aufs_bindex_t bsrc)
++int au_sio_cpup_simple(struct au_cp_generic *cpg)
+{
-+ int err;
-+ struct file *h_file;
++ aufs_bindex_t bsrc, bend;
++ struct dentry *dentry, *h_dentry;
+
-+ h_file = au_h_open_pre(dentry, bsrc);
-+ if (IS_ERR(h_file))
-+ err = PTR_ERR(h_file);
-+ else {
-+ err = au_sio_cpup_simple(dentry, bdst, len, flags, pin);
-+ au_h_open_post(dentry, bsrc, h_file);
++ if (cpg->bsrc < 0) {
++ dentry = cpg->dentry;
++ bend = au_dbend(dentry);
++ for (bsrc = cpg->bdst + 1; bsrc <= bend; bsrc++) {
++ h_dentry = au_h_dptr(dentry, bsrc);
++ if (h_dentry) {
++ AuDebugOn(!h_dentry->d_inode);
++ break;
++ }
++ }
++ AuDebugOn(bsrc > bend);
++ cpg->bsrc = bsrc;
+ }
++ AuDebugOn(cpg->bsrc <= cpg->bdst);
++ return au_do_sio_cpup_simple(cpg);
++}
+
-+ return err;
++int au_sio_cpdown_simple(struct au_cp_generic *cpg)
++{
++ AuDebugOn(cpg->bdst <= cpg->bsrc);
++ return au_do_sio_cpup_simple(cpg);
+}
+
+/* ---------------------------------------------------------------------- */
@@ -4379,55 +4394,57 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+/*
+ * copyup the deleted file for writing.
+ */
-+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
-+ struct dentry *wh_dentry, struct file *file,
-+ loff_t len, struct au_pin *pin)
++static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry,
++ struct file *file)
+{
+ int err;
-+ struct au_cpup_basic basic = {
-+ .dentry = dentry,
-+ .bdst = bdst,
-+ .bsrc = -1,
-+ .len = len
-+ };
-+ struct au_dinfo *dinfo;
++ unsigned int flags_orig;
++ aufs_bindex_t bsrc_orig;
+ struct dentry *h_d_dst, *h_d_start;
++ struct au_dinfo *dinfo;
+ struct au_hdentry *hdp;
+
-+ dinfo = au_di(dentry);
++ dinfo = au_di(cpg->dentry);
+ AuRwMustWriteLock(&dinfo->di_rwsem);
+
-+ basic.bsrc = dinfo->di_bstart;
++ bsrc_orig = cpg->bsrc;
++ cpg->bsrc = dinfo->di_bstart;
+ hdp = dinfo->di_hdentry;
-+ h_d_dst = hdp[0 + bdst].hd_dentry;
-+ dinfo->di_bstart = bdst;
-+ hdp[0 + bdst].hd_dentry = wh_dentry;
++ h_d_dst = hdp[0 + cpg->bdst].hd_dentry;
++ dinfo->di_bstart = cpg->bdst;
++ hdp[0 + cpg->bdst].hd_dentry = wh_dentry;
+ h_d_start = NULL;
+ if (file) {
-+ h_d_start = hdp[0 + basic.bsrc].hd_dentry;
-+ hdp[0 + basic.bsrc].hd_dentry = au_hf_top(file)->f_dentry;
++ h_d_start = hdp[0 + cpg->bsrc].hd_dentry;
++ hdp[0 + cpg->bsrc].hd_dentry = au_hf_top(file)->f_dentry;
+ }
-+ err = au_cpup_single(&basic, !AuCpup_DTIME, /*h_parent*/NULL, pin);
++ flags_orig = cpg->flags;
++ cpg->flags = !AuCpup_DTIME;
++ err = au_cpup_single(cpg, /*h_parent*/NULL);
++ cpg->flags = flags_orig;
+ if (file) {
+ if (!err)
+ err = au_reopen_nondir(file);
-+ hdp[0 + basic.bsrc].hd_dentry = h_d_start;
++ hdp[0 + cpg->bsrc].hd_dentry = h_d_start;
+ }
-+ hdp[0 + bdst].hd_dentry = h_d_dst;
-+ dinfo->di_bstart = basic.bsrc;
++ hdp[0 + cpg->bdst].hd_dentry = h_d_dst;
++ dinfo->di_bstart = cpg->bsrc;
++ cpg->bsrc = bsrc_orig;
+
+ return err;
+}
+
-+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+ struct file *file, struct au_pin *pin)
++static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file)
+{
+ int err;
++ aufs_bindex_t bdst;
+ struct au_dtime dt;
-+ struct dentry *parent, *h_parent, *wh_dentry;
++ struct dentry *dentry, *parent, *h_parent, *wh_dentry;
+ struct au_branch *br;
+ struct path h_path;
+
++ dentry = cpg->dentry;
++ bdst = cpg->bdst;
+ br = au_sbr(dentry->d_sb, bdst);
+ parent = dget_parent(dentry);
+ h_parent = au_h_dptr(parent, bdst);
@@ -4439,7 +4456,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ h_path.dentry = h_parent;
+ h_path.mnt = au_br_mnt(br);
+ au_dtime_store(&dt, parent, &h_path);
-+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len, pin);
++ err = au_do_cpup_wh(cpg, wh_dentry, file);
+ if (unlikely(err))
+ goto out_wh;
+
@@ -4466,37 +4483,37 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+
+struct au_cpup_wh_args {
+ int *errp;
-+ struct dentry *dentry;
-+ aufs_bindex_t bdst;
-+ loff_t len;
++ struct au_cp_generic *cpg;
+ struct file *file;
-+ struct au_pin *pin;
+};
+
+static void au_call_cpup_wh(void *args)
+{
+ struct au_cpup_wh_args *a = args;
+
-+ au_pin_hdir_acquire_nest(a->pin);
-+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file, a->pin);
-+ au_pin_hdir_release(a->pin);
++ au_pin_hdir_acquire_nest(a->cpg->pin);
++ *a->errp = au_cpup_wh(a->cpg, a->file);
++ au_pin_hdir_release(a->cpg->pin);
+}
+
-+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+ struct file *file, struct au_pin *pin)
++int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
+{
+ int err, wkq_err;
-+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
++ aufs_bindex_t bdst;
++ struct dentry *dentry, *parent, *h_orph, *h_parent, *h_dentry;
+ struct inode *dir, *h_dir, *h_tmpdir;
+ struct au_wbr *wbr;
-+ struct au_pin wh_pin;
++ struct au_pin wh_pin, *pin_orig;
+
++ dentry = cpg->dentry;
++ bdst = cpg->bdst;
+ parent = dget_parent(dentry);
+ dir = parent->d_inode;
+ h_orph = NULL;
+ h_parent = NULL;
+ h_dir = au_igrab(au_h_iptr(dir, bdst));
+ h_tmpdir = h_dir;
++ pin_orig = NULL;
+ if (!h_dir->i_nlink) {
+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
+ h_orph = wbr->wbr_orph;
@@ -4513,22 +4530,20 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
+ /* todo: au_h_open_pre()? */
+
++ pin_orig = cpg->pin;
+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT,
-+ AuLsc_I_PARENT3, pin->udba, AuPin_DI_LOCKED);
-+ pin = &wh_pin;
++ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED);
++ cpg->pin = &wh_pin;
+ }
+
+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
-+ && !au_cpup_sio_test(pin, dentry->d_inode->i_mode))
-+ err = au_cpup_wh(dentry, bdst, len, file, pin);
++ && !au_cpup_sio_test(cpg->pin, dentry->d_inode->i_mode))
++ err = au_cpup_wh(cpg, file);
+ else {
+ struct au_cpup_wh_args args = {
+ .errp = &err,
-+ .dentry = dentry,
-+ .bdst = bdst,
-+ .len = len,
-+ .file = file,
-+ .pin = pin
++ .cpg = cpg,
++ .file = file
+ };
+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
+ if (unlikely(wkq_err))
@@ -4540,6 +4555,8 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ /* todo: au_h_open_post()? */
+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
+ au_set_h_dptr(parent, bdst, h_parent);
++ AuDebugOn(!pin_orig);
++ cpg->pin = pin_orig;
+ }
+ iput(h_dir);
+ dput(parent);
@@ -4622,7 +4639,15 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ struct dentry *h_parent __maybe_unused ,
+ void *arg __maybe_unused)
+{
-+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME, pin);
++ struct au_cp_generic cpg = {
++ .dentry = dentry,
++ .bdst = bdst,
++ .bsrc = -1,
++ .len = 0,
++ .pin = pin,
++ .flags = AuCpup_DTIME
++ };
++ return au_sio_cpup_simple(&cpg);
+}
+
+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
@@ -4655,8 +4680,8 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+}
diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/cpup.h 2013-07-30 22:42:46.232612606 +0200
-@@ -0,0 +1,87 @@
++++ linux/fs/aufs/cpup.h 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -4699,11 +4724,21 @@ diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
+
+/* ---------------------------------------------------------------------- */
+
++struct au_cp_generic {
++ struct dentry *dentry;
++ aufs_bindex_t bdst, bsrc;
++ loff_t len;
++ struct au_pin *pin;
++ unsigned int flags;
++};
++
+/* cpup flags */
+#define AuCpup_DTIME 1 /* do dtime_store/revert */
+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
+ for link(2) */
+#define AuCpup_RENAME (1 << 2) /* rename after cpup */
++#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in cpup */
++
+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
+#define au_fset_cpup(flags, name) \
+ do { (flags) |= AuCpup_##name; } while (0)
@@ -4711,16 +4746,9 @@ diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
+ do { (flags) &= ~AuCpup_##name; } while (0)
+
+int au_copy_file(struct file *dst, struct file *src, loff_t len);
-+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
-+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
-+ struct dentry *dst_parent, struct au_pin *pin);
-+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+ unsigned int flags, struct au_pin *pin);
-+int au_sio_cpup_simple_h_open(struct dentry *dentry, aufs_bindex_t bdst,
-+ loff_t len, unsigned int flags,
-+ struct au_pin *pin, aufs_bindex_t bsrc);
-+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+ struct file *file, struct au_pin *pin);
++int au_sio_cpup_simple(struct au_cp_generic *cpg);
++int au_sio_cpdown_simple(struct au_cp_generic *cpg);
++int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file);
+
+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
@@ -5581,7 +5609,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
+#endif /* __AUFS_DCSUB_H__ */
diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/debug.c 2013-07-30 22:42:55.839613269 +0200
++++ linux/fs/aufs/debug.c 2013-08-23 23:59:39.634916914 +0200
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
@@ -5672,7 +5700,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
+ return -1;
+ }
+
-+ /* the type of i_blocks depends upon CONFIG_LSF */
++ /* the type of i_blocks depends upon CONFIG_LBDAF */
+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
+ && sizeof(inode->i_blocks) != sizeof(u64));
+ if (wh) {
@@ -10246,8 +10274,8 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
+}
diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/file.c 2013-07-30 22:42:55.842946719 +0200
-@@ -0,0 +1,689 @@
++++ linux/fs/aufs/file.c 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,708 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -10472,28 +10500,35 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+{
+ int err;
+ struct inode *inode, *h_inode;
-+ struct dentry *dentry, *h_dentry, *hi_wh;
++ struct dentry *h_dentry, *hi_wh;
++ struct au_cp_generic cpg = {
++ .dentry = file->f_dentry,
++ .bdst = bcpup,
++ .bsrc = -1,
++ .len = len,
++ .pin = pin
++ };
+
-+ dentry = file->f_dentry;
-+ au_update_dbstart(dentry);
-+ inode = dentry->d_inode;
++ au_update_dbstart(cpg.dentry);
++ inode = cpg.dentry->d_inode;
+ h_inode = NULL;
-+ if (au_dbstart(dentry) <= bcpup && au_dbend(dentry) >= bcpup) {
-+ h_dentry = au_h_dptr(dentry, bcpup);
++ if (au_dbstart(cpg.dentry) <= bcpup
++ && au_dbend(cpg.dentry) >= bcpup) {
++ h_dentry = au_h_dptr(cpg.dentry, bcpup);
+ if (h_dentry)
+ h_inode = h_dentry->d_inode;
+ }
+ hi_wh = au_hi_wh(inode, bcpup);
+ if (!hi_wh && !h_inode)
-+ err = au_sio_cpup_wh(dentry, bcpup, len, file, pin);
++ err = au_sio_cpup_wh(&cpg, file);
+ else
+ /* already copied-up after unlink */
+ err = au_reopen_wh(file, bcpup, hi_wh);
+
+ if (!err
+ && inode->i_nlink > 1
-+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
-+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
++ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK))
++ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup));
+
+ return err;
+}
@@ -10504,72 +10539,79 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
+{
+ int err;
-+ aufs_bindex_t bstart, bcpup, dbstart;
-+ struct dentry *dentry, *parent, *h_dentry;
++ aufs_bindex_t dbstart;
++ struct dentry *parent, *h_dentry;
+ struct inode *inode;
+ struct super_block *sb;
+ struct file *h_file;
++ struct au_cp_generic cpg = {
++ .dentry = file->f_dentry,
++ .bdst = -1,
++ .bsrc = -1,
++ .len = len,
++ .pin = pin,
++ .flags = AuCpup_DTIME
++ };
+
-+ dentry = file->f_dentry;
-+ sb = dentry->d_sb;
-+ inode = dentry->d_inode;
++ sb = cpg.dentry->d_sb;
++ inode = cpg.dentry->d_inode;
+ AuDebugOn(au_special_file(inode->i_mode));
-+ bstart = au_fbstart(file);
-+ err = au_test_ro(sb, bstart, inode);
++ cpg.bsrc = au_fbstart(file);
++ err = au_test_ro(sb, cpg.bsrc, inode);
+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
-+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
++ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE,
++ /*flags*/0);
+ goto out;
+ }
+
+ /* need to cpup or reopen */
-+ parent = dget_parent(dentry);
++ parent = dget_parent(cpg.dentry);
+ di_write_lock_parent(parent);
-+ err = AuWbrCopyup(au_sbi(sb), dentry);
-+ bcpup = err;
++ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
++ cpg.bdst = err;
+ if (unlikely(err < 0))
+ goto out_dgrade;
+ err = 0;
+
-+ if (!d_unhashed(dentry) && !au_h_dptr(parent, bcpup)) {
-+ err = au_cpup_dirs(dentry, bcpup);
++ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) {
++ err = au_cpup_dirs(cpg.dentry, cpg.bdst);
+ if (unlikely(err))
+ goto out_dgrade;
+ }
+
-+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
++ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
+ if (unlikely(err))
+ goto out_dgrade;
+
+ h_dentry = au_hf_top(file)->f_dentry;
-+ dbstart = au_dbstart(dentry);
-+ if (dbstart <= bcpup) {
-+ h_dentry = au_h_dptr(dentry, bcpup);
++ dbstart = au_dbstart(cpg.dentry);
++ if (dbstart <= cpg.bdst) {
++ h_dentry = au_h_dptr(cpg.dentry, cpg.bdst);
+ AuDebugOn(!h_dentry);
-+ bstart = bcpup;
++ cpg.bsrc = cpg.bdst;
+ }
+
-+ if (dbstart <= bcpup /* just reopen */
-+ || !d_unhashed(dentry) /* copyup and reopen */
++ if (dbstart <= cpg.bdst /* just reopen */
++ || !d_unhashed(cpg.dentry) /* copyup and reopen */
+ ) {
-+ h_file = au_h_open_pre(dentry, bstart);
++ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc);
+ if (IS_ERR(h_file))
+ err = PTR_ERR(h_file);
+ else {
+ di_downgrade_lock(parent, AuLock_IR);
-+ if (dbstart > bcpup)
-+ err = au_sio_cpup_simple(dentry, bcpup, len,
-+ AuCpup_DTIME, pin);
++ if (dbstart > cpg.bdst)
++ err = au_sio_cpup_simple(&cpg);
+ if (!err)
+ err = au_reopen_nondir(file);
-+ au_h_open_post(dentry, bstart, h_file);
++ au_h_open_post(cpg.dentry, cpg.bsrc, h_file);
+ }
+ } else { /* copyup as wh and reopen */
+ /*
+ * since writable hfsplus branch is not supported,
+ * h_open_pre/post() are unnecessary.
+ */
-+ err = au_ready_to_write_wh(file, len, bcpup, pin);
++ err = au_ready_to_write_wh(file, len, cpg.bdst, pin);
+ di_downgrade_lock(parent, AuLock_IR);
+ }
+
@@ -10619,29 +10661,35 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
+{
+ int err;
-+ aufs_bindex_t bstart;
+ struct au_pin pin;
+ struct au_finfo *finfo;
-+ struct dentry *dentry, *parent, *hi_wh;
++ struct dentry *parent, *hi_wh;
+ struct inode *inode;
+ struct super_block *sb;
++ struct au_cp_generic cpg = {
++ .dentry = file->f_dentry,
++ .bdst = -1,
++ .bsrc = -1,
++ .len = -1,
++ .pin = &pin,
++ .flags = AuCpup_DTIME
++ };
+
+ FiMustWriteLock(file);
+
+ err = 0;
+ finfo = au_fi(file);
-+ dentry = file->f_dentry;
-+ sb = dentry->d_sb;
-+ inode = dentry->d_inode;
-+ bstart = au_ibstart(inode);
-+ if (bstart == finfo->fi_btop || IS_ROOT(dentry))
++ sb = cpg.dentry->d_sb;
++ inode = cpg.dentry->d_inode;
++ cpg.bdst = au_ibstart(inode);
++ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry))
+ goto out;
+
-+ parent = dget_parent(dentry);
-+ if (au_test_ro(sb, bstart, inode)) {
++ parent = dget_parent(cpg.dentry);
++ if (au_test_ro(sb, cpg.bdst, inode)) {
+ di_read_lock_parent(parent, !AuLock_IR);
-+ err = AuWbrCopyup(au_sbi(sb), dentry);
-+ bstart = err;
++ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
++ cpg.bdst = err;
+ di_read_unlock(parent, !AuLock_IR);
+ if (unlikely(err < 0))
+ goto out_parent;
@@ -10649,27 +10697,26 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+ }
+
+ di_read_lock_parent(parent, AuLock_IR);
-+ hi_wh = au_hi_wh(inode, bstart);
++ hi_wh = au_hi_wh(inode, cpg.bdst);
+ if (!S_ISDIR(inode->i_mode)
+ && au_opt_test(au_mntflags(sb), PLINK)
+ && au_plink_test(inode)
-+ && !d_unhashed(dentry)
-+ && bstart < au_dbstart(dentry)) {
-+ err = au_test_and_cpup_dirs(dentry, bstart);
++ && !d_unhashed(cpg.dentry)
++ && cpg.bdst < au_dbstart(cpg.dentry)) {
++ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst);
+ if (unlikely(err))
+ goto out_unlock;
+
+ /* always superio. */
-+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
++ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
+ if (!err) {
-+ err = au_sio_cpup_simple(dentry, bstart, -1,
-+ AuCpup_DTIME, &pin);
++ err = au_sio_cpup_simple(&cpg);
+ au_unpin(&pin);
+ }
+ } else if (hi_wh) {
+ /* already copied-up after unlink */
-+ err = au_reopen_wh(file, bstart, hi_wh);
++ err = au_reopen_wh(file, cpg.bdst, hi_wh);
+ *need_reopen = 0;
+ }
+
@@ -10939,8 +10986,8 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+};
diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/file.h 2013-07-06 13:20:47.750198454 +0200
-@@ -0,0 +1,308 @@
++++ linux/fs/aufs/file.h 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -11086,6 +11133,8 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
+#ifdef CONFIG_COMPAT
+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
+ unsigned long arg);
++long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
++ unsigned long arg);
+#endif
+
+/* ---------------------------------------------------------------------- */
@@ -11412,7 +11461,7 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
+}
diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/f_op.c 2013-07-30 22:42:55.839613269 +0200
++++ linux/fs/aufs/f_op.c 2013-08-23 23:59:39.634916914 +0200
@@ -0,0 +1,721 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
@@ -12118,7 +12167,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
+#endif
+ .unlocked_ioctl = aufs_ioctl_nondir,
+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = aufs_ioctl_nondir, /* same */
++ .compat_ioctl = aufs_compat_ioctl_nondir,
+#endif
+ .mmap = aufs_mmap,
+ .open = aufs_open_nondir,
@@ -12137,8 +12186,8 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
+};
diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/f_op_sp.c 2013-07-06 13:20:47.750198454 +0200
-@@ -0,0 +1,376 @@
++++ linux/fs/aufs/f_op_sp.c 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -12178,7 +12227,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
+
+struct au_finfo_sp {
+ struct hlist_node hlist;
-+ struct file *file;
++ struct file *file;
+ struct au_finfo *finfo;
+};
+
@@ -12388,12 +12437,19 @@ diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
+static int au_cpup_sp(struct dentry *dentry)
+{
+ int err;
-+ aufs_bindex_t bcpup;
+ struct au_pin pin;
+ struct au_wr_dir_args wr_dir_args = {
+ .force_btgt = -1,
+ .flags = 0
+ };
++ struct au_cp_generic cpg = {
++ .dentry = dentry,
++ .bdst = -1,
++ .bsrc = -1,
++ .len = -1,
++ .pin = &pin,
++ .flags = AuCpup_DTIME
++ };
+
+ AuDbg("%.*s\n", AuDLNPair(dentry));
+
@@ -12402,15 +12458,15 @@ diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
+ if (unlikely(err < 0))
+ goto out;
-+ bcpup = err;
++ cpg.bdst = err;
+ err = 0;
-+ if (bcpup == au_dbstart(dentry))
++ if (cpg.bdst == au_dbstart(dentry))
+ goto out; /* success */
+
-+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
++ err = au_pin(&pin, dentry, cpg.bdst, au_opt_udba(dentry->d_sb),
+ AuPin_MNT_WRITE);
+ if (!err) {
-+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME, &pin);
++ err = au_sio_cpup_simple(&cpg);
+ au_unpin(&pin);
+ }
+
@@ -12517,8 +12573,8 @@ diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
+}
diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/fstype.h 2013-07-06 13:20:47.750198454 +0200
-@@ -0,0 +1,480 @@
++++ linux/fs/aufs/fstype.h 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -12631,15 +12687,6 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
+#endif
+}
+
-+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
-+ return sb->s_magic == SMB_SUPER_MAGIC;
-+#else
-+ return 0;
-+#endif
-+}
-+
+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
@@ -12678,7 +12725,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
+
+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
+{
-+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
++#if defined(CONFIG_EXT4_FS) || defined(CONFIG_EXT4_FS_MODULE)
+ return sb->s_magic == EXT4_SUPER_MAGIC;
+#else
+ return 0;
@@ -12886,7 +12933,6 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
+{
+ return au_test_nfs(sb)
+ || au_test_fuse(sb)
-+ /* || au_test_smbfs(sb) */ /* untested */
+ /* || au_test_ocfs2(sb) */ /* untested */
+ /* || au_test_btrfs(sb) */ /* untested */
+ /* || au_test_coda(sb) */ /* untested */
@@ -15457,8 +15503,8 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
+#endif /* __AUFS_INODE_H__ */
diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/ioctl.c 2013-07-06 13:20:47.750198454 +0200
-@@ -0,0 +1,196 @@
++++ linux/fs/aufs/ioctl.c 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -15481,8 +15527,11 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
+ * ioctl
+ * plink-management and readdir in userspace.
+ * assist the pathconf(3) wrapper library.
++ * move-down
+ */
+
++#include <linux/compat.h>
++#include <linux/file.h>
+#include "aufs.h"
+
+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
@@ -15609,6 +15658,11 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
+ long err;
+
+ switch (cmd) {
++ case AUFS_CTL_MVDOWN:
++ WARN_ONCE(1, "move-down is still testing...\n");
++ err = au_mvdown(file->f_dentry, (void __user *)arg);
++ break;
++
+ case AUFS_CTL_WBR_FD:
+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
+ break;
@@ -15647,18 +15701,16 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
+ return err;
+}
+
-+#if 0 /* unused yet */
+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
-+#endif
diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/i_op_add.c 2013-07-30 22:42:46.235946055 +0200
-@@ -0,0 +1,716 @@
++++ linux/fs/aufs/i_op_add.c 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,739 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -15895,47 +15947,55 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+ int err;
+ aufs_bindex_t bstart;
+ unsigned char created;
-+ struct au_dtime dt;
-+ struct au_pin pin;
-+ struct path h_path;
+ struct dentry *wh_dentry, *parent;
+ struct inode *h_dir;
-+ struct au_wr_dir_args wr_dir_args = {
-+ .force_btgt = -1,
-+ .flags = AuWrDir_ADD_ENTRY
-+ };
++ /* to reuduce stack size */
++ struct {
++ struct au_dtime dt;
++ struct au_pin pin;
++ struct path h_path;
++ struct au_wr_dir_args wr_dir_args;
++ } *a;
+
+ AuDbg("%.*s\n", AuDLNPair(dentry));
+ IMustLock(dir);
+
++ err = -ENOMEM;
++ a = kmalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++ a->wr_dir_args.force_btgt = -1;
++ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY;
++
+ parent = dentry->d_parent; /* dir inode is locked */
+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
+ if (unlikely(err))
-+ goto out;
++ goto out_free;
+ err = au_d_may_add(dentry);
+ if (unlikely(err))
+ goto out_unlock;
+ di_write_lock_parent(parent);
-+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
-+ &wr_dir_args);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
++ &a->pin, &a->wr_dir_args);
+ err = PTR_ERR(wh_dentry);
+ if (IS_ERR(wh_dentry))
+ goto out_parent;
+
+ bstart = au_dbstart(dentry);
-+ h_path.dentry = au_h_dptr(dentry, bstart);
-+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
-+ h_dir = au_pinned_h_dir(&pin);
++ a->h_path.dentry = au_h_dptr(dentry, bstart);
++ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
++ h_dir = au_pinned_h_dir(&a->pin);
+ switch (arg->type) {
+ case Creat:
-+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode,
++ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode,
+ arg->u.c.want_excl);
+ break;
+ case Symlink:
-+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
++ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname);
+ break;
+ case Mknod:
-+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
++ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode,
++ arg->u.m.dev);
+ break;
+ default:
+ BUG();
@@ -15945,18 +16005,18 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+ err = epilog(dir, bstart, wh_dentry, dentry);
+
+ /* revert */
-+ if (unlikely(created && err && h_path.dentry->d_inode)) {
++ if (unlikely(created && err && a->h_path.dentry->d_inode)) {
+ int rerr;
-+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ rerr = vfsub_unlink(h_dir, &a->h_path, /*force*/0);
+ if (rerr) {
+ AuIOErr("%.*s revert failure(%d, %d)\n",
+ AuDLNPair(dentry), err, rerr);
+ err = -EIO;
+ }
-+ au_dtime_revert(&dt);
++ au_dtime_revert(&a->dt);
+ }
+
-+ au_unpin(&pin);
++ au_unpin(&a->pin);
+ dput(wh_dentry);
+
+out_parent:
@@ -15967,6 +16027,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+ d_drop(dentry);
+ }
+ aufs_read_unlock(dentry, AuLock_DW);
++out_free:
++ kfree(a);
+out:
+ return err;
+}
@@ -16020,6 +16082,14 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+{
+ int err;
+ struct dentry *h_src_dentry;
++ struct au_cp_generic cpg = {
++ .dentry = src_dentry,
++ .bdst = a->bdst,
++ .bsrc = a->bsrc,
++ .len = -1,
++ .pin = &a->pin,
++ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */
++ };
+
+ di_read_lock_parent(a->src_parent, AuLock_IR);
+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
@@ -16033,9 +16103,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+ if (unlikely(err))
+ goto out;
+
-+ err = au_sio_cpup_simple_h_open(src_dentry, a->bdst, -1,
-+ AuCpup_DTIME /* | AuCpup_KEEPLINO */,
-+ &a->pin, a->bsrc);
++ err = au_sio_cpup_simple(&cpg);
+ au_unpin(&a->pin);
+
+out:
@@ -16074,8 +16142,15 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+ if (IS_ERR(h_file))
+ err = PTR_ERR(h_file);
+ else {
-+ err = au_sio_cpup_simple(dentry, a->bdst, -1,
-+ AuCpup_KEEPLINO, &a->pin);
++ struct au_cp_generic cpg = {
++ .dentry = dentry,
++ .bdst = a->bdst,
++ .bsrc = -1,
++ .len = -1,
++ .pin = &a->pin,
++ .flags = AuCpup_KEEPLINO
++ };
++ err = au_sio_cpup_simple(&cpg);
+ au_h_open_post(dentry, a->bsrc, h_file);
+ if (!err) {
+ dput(a->h_path.dentry);
@@ -16377,8 +16452,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+}
diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/i_op.c 2013-07-30 22:42:46.235946055 +0200
-@@ -0,0 +1,1100 @@
++++ linux/fs/aufs/i_op.c 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,1115 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -16641,10 +16716,12 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+
+ err = 0;
+ if (!au_h_dptr(parent, bcpup)) {
-+ if (bstart < bcpup)
++ if (bstart > bcpup)
++ err = au_cpup_dirs(dentry, bcpup);
++ else if (bstart < bcpup)
+ err = au_cpdown_dirs(dentry, bcpup);
+ else
-+ err = au_cpup_dirs(dentry, bcpup);
++ BUG();
+ }
+ if (!err && add_entry) {
+ h_parent = au_h_dptr(parent, bcpup);
@@ -17056,8 +17133,14 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
+ hi_wh = au_hi_wh(inode, a->btgt);
+ if (!hi_wh) {
-+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL,
-+ &a->pin);
++ struct au_cp_generic cpg = {
++ .dentry = dentry,
++ .bdst = a->btgt,
++ .bsrc = -1,
++ .len = sz,
++ .pin = &a->pin
++ };
++ err = au_sio_cpup_wh(&cpg, /*file*/NULL);
+ if (unlikely(err))
+ goto out_unlock;
+ hi_wh = au_hi_wh(inode, a->btgt);
@@ -17075,8 +17158,15 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ goto out; /* success */
+
+ if (!d_unhashed(dentry)) {
-+ err = au_sio_cpup_simple_h_open(dentry, a->btgt, sz,
-+ AuCpup_DTIME, &a->pin, bstart);
++ struct au_cp_generic cpg = {
++ .dentry = dentry,
++ .bdst = a->btgt,
++ .bsrc = bstart,
++ .len = sz,
++ .pin = &a->pin,
++ .flags = AuCpup_DTIME | AuCpup_HOPEN
++ };
++ err = au_sio_cpup_simple(&cpg);
+ if (!err)
+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
+ } else if (!hi_wh)
@@ -17481,8 +17571,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+};
diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/i_op_del.c 2013-07-06 13:20:47.750198454 +0200
-@@ -0,0 +1,477 @@
++++ linux/fs/aufs/i_op_del.c 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -17784,17 +17874,25 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+{
+ int err;
+ aufs_bindex_t bwh, bindex, bstart;
-+ struct au_dtime dt;
-+ struct au_pin pin;
-+ struct path h_path;
+ struct inode *inode, *h_dir;
+ struct dentry *parent, *wh_dentry;
++ /* to reuduce stack size */
++ struct {
++ struct au_dtime dt;
++ struct au_pin pin;
++ struct path h_path;
++ } *a;
+
+ IMustLock(dir);
+
++ err = -ENOMEM;
++ a = kmalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
+ if (unlikely(err))
-+ goto out;
++ goto out_free;
+ err = au_d_hashed_positive(dentry);
+ if (unlikely(err))
+ goto out_unlock;
@@ -17809,17 +17907,18 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+ bindex = -1;
+ parent = dentry->d_parent; /* dir inode is locked */
+ di_write_lock_parent(parent);
-+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
++ &a->pin);
+ err = PTR_ERR(wh_dentry);
+ if (IS_ERR(wh_dentry))
+ goto out_parent;
+
-+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
-+ h_path.dentry = au_h_dptr(dentry, bstart);
-+ dget(h_path.dentry);
++ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
++ a->h_path.dentry = au_h_dptr(dentry, bstart);
++ dget(a->h_path.dentry);
+ if (bindex == bstart) {
-+ h_dir = au_pinned_h_dir(&pin);
-+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ h_dir = au_pinned_h_dir(&a->pin);
++ err = vfsub_unlink(h_dir, &a->h_path, /*force*/0);
+ } else {
+ /* dir inode is locked */
+ h_dir = wh_dentry->d_parent->d_inode;
@@ -17833,8 +17932,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+
+ /* update target timestamps */
+ if (bindex == bstart) {
-+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
-+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
++ vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
++ /*ignore*/
++ inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
+ } else
+ /* todo: this timestamp may be reverted later */
+ inode->i_ctime = h_dir->i_ctime;
@@ -17845,19 +17945,22 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+ if (wh_dentry) {
+ int rerr;
+
-+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
++ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
++ &a->dt);
+ if (rerr)
+ err = rerr;
+ }
+
+out_unpin:
-+ au_unpin(&pin);
++ au_unpin(&a->pin);
+ dput(wh_dentry);
-+ dput(h_path.dentry);
++ dput(a->h_path.dentry);
+out_parent:
+ di_write_unlock(parent);
+out_unlock:
+ aufs_read_unlock(dentry, AuLock_DW);
++out_free:
++ kfree(a);
+out:
+ return err;
+}
@@ -17866,17 +17969,25 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+{
+ int err, rmdir_later;
+ aufs_bindex_t bwh, bindex, bstart;
-+ struct au_dtime dt;
-+ struct au_pin pin;
+ struct inode *inode;
+ struct dentry *parent, *wh_dentry, *h_dentry;
+ struct au_whtmp_rmdir *args;
++ /* to reuduce stack size */
++ struct {
++ struct au_dtime dt;
++ struct au_pin pin;
++ } *a;
+
+ IMustLock(dir);
+
++ err = -ENOMEM;
++ a = kmalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
+ if (unlikely(err))
-+ goto out;
++ goto out_free;
+ err = au_alive_dir(dentry);
+ if (unlikely(err))
+ goto out_unlock;
@@ -17900,7 +18011,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+ bstart = au_dbstart(dentry);
+ bwh = au_dbwh(dentry);
+ bindex = -1;
-+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt,
++ &a->pin);
+ err = PTR_ERR(wh_dentry);
+ if (IS_ERR(wh_dentry))
+ goto out_parent;
@@ -17941,13 +18053,14 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+ if (wh_dentry) {
+ int rerr;
+
-+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
++ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
++ &a->dt);
+ if (rerr)
+ err = rerr;
+ }
+
+out_unpin:
-+ au_unpin(&pin);
++ au_unpin(&a->pin);
+ dput(wh_dentry);
+ dput(h_dentry);
+out_parent:
@@ -17956,14 +18069,16 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+ au_whtmp_rmdir_free(args);
+out_unlock:
+ aufs_read_unlock(dentry, AuLock_DW);
++out_free:
++ kfree(a);
+out:
+ AuTraceErr(err);
+ return err;
+}
diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/i_op_ren.c 2013-07-30 22:42:46.235946055 +0200
-@@ -0,0 +1,1045 @@
++++ linux/fs/aufs/i_op_ren.c 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,1009 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -18174,33 +18289,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
+ AuDebugOn(au_dbstart(d) != a->btgt);
+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
+ a->dst_h_dir, &a->h_path);
-+ } else {
-+#if 1
++ } else
+ BUG();
-+#else
-+ struct file *h_file;
+
-+ au_fset_ren(a->flags, CPUP);
-+ au_set_dbstart(d, a->btgt);
-+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
-+ h_file = au_h_open_pre(d, a->src_bstart);
-+ if (IS_ERR(h_file))
-+ err = PTR_ERR(h_file);
-+ else {
-+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
-+ !AuCpup_DTIME, a->dst_parent);
-+ au_h_open_post(d, a->src_bstart, h_file);
-+ }
-+ if (!err) {
-+ d = a->dst_dentry;
-+ au_set_h_dptr(d, a->btgt, NULL);
-+ au_update_dbstart(d);
-+ } else {
-+ au_set_h_dptr(d, a->btgt, NULL);
-+ au_set_dbstart(d, a->src_bstart);
-+ }
-+#endif
-+ }
+ if (!err && a->h_dst)
+ /* it will be set to dinfo later */
+ dget(a->h_dst);
@@ -18307,25 +18398,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
+ }
+
-+ /* cpup src */
-+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
-+#if 1
-+ BUG();
-+#else
-+ struct file *h_file;
-+
-+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
-+ if (IS_ERR(h_file))
-+ err = PTR_ERR(h_file);
-+ else {
-+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
-+ !AuCpup_DTIME);
-+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
-+ }
-+ if (unlikely(err))
-+ goto out_whtmp;
-+#endif
-+ }
++ BUG_ON(a->dst_h_dentry->d_inode && a->src_bstart != a->btgt);
+
+ /* rename by vfs_rename or cpup */
+ d = a->dst_dentry;
@@ -18933,10 +19006,16 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
+ au_opt_udba(a->src_dentry->d_sb),
+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
+ if (!err) {
++ struct au_cp_generic cpg = {
++ .dentry = a->src_dentry,
++ .bdst = a->btgt,
++ .bsrc = a->src_bstart,
++ .len = -1,
++ .pin = &pin,
++ .flags = AuCpup_DTIME | AuCpup_HOPEN
++ };
+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
-+ err = au_sio_cpup_simple_h_open(a->src_dentry, a->btgt,
-+ -1, AuCpup_DTIME, &pin,
-+ a->src_bstart);
++ err = au_sio_cpup_simple(&cpg);
+ au_unpin(&pin);
+ }
+ if (unlikely(err))
@@ -19468,7 +19547,7 @@ diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
+endif
diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/Makefile 2013-07-06 13:20:47.736864659 +0200
++++ linux/fs/aufs/Makefile 2013-08-23 23:59:39.631583456 +0200
@@ -0,0 +1,42 @@
+
+include ${src}/magic.mk
@@ -19496,7 +19575,7 @@ diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
+ finfo.o file.o f_op.o \
+ dir.o vdir.o \
+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
-+ ioctl.o
++ mvdown.o ioctl.o
+
+# all are boolean
+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
@@ -19828,8 +19907,545 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_MODULE_H__ */
-diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
---- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
+diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+--- /usr/share/empty/fs/aufs/mvdown.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/mvdown.c 2013-08-23 23:59:39.634916914 +0200
+@@ -0,0 +1,533 @@
++/*
++ * Copyright (C) 2011-2013 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "aufs.h"
++
++enum {
++ AUFS_MVDOWN_SRC,
++ AUFS_MVDOWN_DST,
++ AUFS_MVDOWN_NARRAY
++};
++
++struct au_mvd_args {
++ struct {
++ aufs_bindex_t bindex;
++ struct super_block *h_sb;
++ struct dentry *h_parent;
++ struct au_hinode *hdir;
++ struct inode *h_dir;
++ } info[AUFS_MVDOWN_NARRAY];
++
++ struct aufs_mvdown mvdown;
++ struct dentry *dentry, *parent;
++ struct inode *inode, *dir;
++ struct super_block *sb;
++ aufs_bindex_t bopq, bwh, bfound;
++ unsigned char rename_lock;
++ struct au_pin pin;
++};
++
++#define mvd_bsrc info[AUFS_MVDOWN_SRC].bindex
++#define mvd_h_src_sb info[AUFS_MVDOWN_SRC].h_sb
++#define mvd_h_src_parent info[AUFS_MVDOWN_SRC].h_parent
++#define mvd_hdir_src info[AUFS_MVDOWN_SRC].hdir
++#define mvd_h_src_dir info[AUFS_MVDOWN_SRC].h_dir
++
++#define mvd_bdst info[AUFS_MVDOWN_DST].bindex
++#define mvd_h_dst_sb info[AUFS_MVDOWN_DST].h_sb
++#define mvd_h_dst_parent info[AUFS_MVDOWN_DST].h_parent
++#define mvd_hdir_dst info[AUFS_MVDOWN_DST].hdir
++#define mvd_h_dst_dir info[AUFS_MVDOWN_DST].h_dir
++
++#define AU_MVD_PR(flag, ...) do { \
++ if (flag) \
++ pr_err(__VA_ARGS__); \
++ } while (0)
++
++/* make the parent dir on bdst */
++static int au_do_mkdir(const unsigned char verbose, struct au_mvd_args *a)
++{
++ int err;
++
++ err = 0;
++ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc);
++ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst);
++ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc);
++ a->mvd_h_dst_parent = NULL;
++ if (au_dbend(a->parent) >= a->mvd_bdst)
++ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
++ if (!a->mvd_h_dst_parent) {
++ err = au_cpdown_dirs(a->dentry, a->mvd_bdst);
++ if (unlikely(err)) {
++ AU_MVD_PR(verbose, "cpdown_dirs failed\n");
++ goto out;
++ }
++ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
++ }
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++/* lock them all */
++static int au_do_lock(const unsigned char verbose, struct au_mvd_args *a)
++{
++ int err;
++ struct dentry *h_trap;
++
++ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
++ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
++ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
++ a->rename_lock = 0;
++ err = au_pin(&a->pin, a->dentry, a->mvd_bdst, au_opt_udba(a->sb),
++ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
++ if (!err) {
++ a->mvd_h_src_dir = a->mvd_h_src_parent->d_inode;
++ mutex_lock_nested(&a->mvd_h_src_dir->i_mutex,
++ AuLsc_I_PARENT3);
++ } else
++ AU_MVD_PR(verbose, "pin failed\n");
++ goto out;
++ }
++
++ err = 0;
++ a->rename_lock = 1;
++ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
++ a->mvd_h_dst_parent, a->mvd_hdir_dst);
++ if (h_trap) {
++ err = (h_trap != a->mvd_h_src_parent);
++ if (err)
++ err = (h_trap != a->mvd_h_dst_parent);
++ }
++ BUG_ON(err); /* it should never happen */
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++static void au_do_unlock(const unsigned char verbose, struct au_mvd_args *a)
++{
++ if (!a->rename_lock) {
++ mutex_unlock(&a->mvd_h_src_dir->i_mutex);
++ au_unpin(&a->pin);
++ } else
++ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
++ a->mvd_h_dst_parent, a->mvd_hdir_dst);
++}
++
++/* copy-down the file */
++static int au_do_cpdown(const unsigned char verbose, struct au_mvd_args *a)
++{
++ int err;
++ struct au_cp_generic cpg = {
++ .dentry = a->dentry,
++ .bdst = a->mvd_bdst,
++ .bsrc = a->mvd_bsrc,
++ .len = -1,
++ .pin = &a->pin,
++ .flags = AuCpup_DTIME | AuCpup_HOPEN
++ };
++
++ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
++ err = au_sio_cpdown_simple(&cpg);
++ if (unlikely(err))
++ AU_MVD_PR(verbose, "cpdown failed\n");
++
++ AuTraceErr(err);
++ return err;
++}
++
++/*
++ * unlink the whiteout on bdst if exist which may be created by UDBA while we
++ * were sleeping
++ */
++static int au_do_unlink_wh(const unsigned char verbose, struct au_mvd_args *a)
++{
++ int err;
++ struct path h_path;
++ struct au_branch *br;
++
++ br = au_sbr(a->sb, a->mvd_bdst);
++ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br);
++ err = PTR_ERR(h_path.dentry);
++ if (IS_ERR(h_path.dentry)) {
++ AU_MVD_PR(verbose, "wh_lkup failed\n");
++ goto out;
++ }
++
++ err = 0;
++ if (h_path.dentry->d_inode) {
++ h_path.mnt = au_br_mnt(br);
++ err = vfsub_unlink(a->mvd_h_dst_parent->d_inode, &h_path,
++ /*force*/0);
++ if (unlikely(err))
++ AU_MVD_PR(verbose, "wh_unlink failed\n");
++ }
++ dput(h_path.dentry);
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++/*
++ * unlink the topmost h_dentry
++ * Note: the target file MAY be modified by UDBA between this mutex_unlock() and
++ * mutex_lock() in vfs_unlink(). in this case, such changes may be lost.
++ */
++static int au_do_unlink(const unsigned char verbose, struct au_mvd_args *a)
++{
++ int err;
++ struct path h_path;
++
++ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc);
++ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc);
++ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, /*force*/0);
++ if (unlikely(err))
++ AU_MVD_PR(verbose, "unlink failed\n");
++
++ AuTraceErr(err);
++ return err;
++}
++
++/*
++ * copy-down the file and unlink the bsrc file.
++ * - unlink the bdst whout if exist
++ * - copy-down the file (with whtmp name and rename)
++ * - unlink the bsrc file
++ */
++static int au_do_mvdown(const unsigned char verbose, struct au_mvd_args *a)
++{
++ int err;
++
++ err = au_do_mkdir(verbose, a);
++ if (!err)
++ err = au_do_lock(verbose, a);
++ if (unlikely(err))
++ goto out;
++
++ /*
++ * do not revert the activities we made on bdst since they should be
++ * harmless in aufs.
++ */
++
++ err = au_do_cpdown(verbose, a);
++ if (!err)
++ err = au_do_unlink_wh(verbose, a);
++ if (!err)
++ err = au_do_unlink(verbose, a);
++ if (unlikely(err))
++ goto out_unlock;
++
++ /* maintain internal array */
++ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
++ au_set_dbstart(a->dentry, a->mvd_bdst);
++ if (au_dbend(a->dentry) < a->mvd_bdst)
++ au_set_dbend(a->dentry, a->mvd_bdst);
++ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
++ au_set_ibstart(a->inode, a->mvd_bdst);
++ if (au_ibend(a->inode) < a->mvd_bdst)
++ au_set_ibend(a->inode, a->mvd_bdst);
++
++out_unlock:
++ au_do_unlock(verbose, a);
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int find_lower_writable(struct super_block *sb, aufs_bindex_t bindex)
++{
++ aufs_bindex_t bend;
++ struct au_branch *br;
++
++ bend = au_sbend(sb);
++ for (bindex++; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ if (!au_br_rdonly(br))
++ return bindex;
++ }
++
++ return -1;
++}
++
++/* make sure the file is idle */
++static int au_mvd_args_busy(const unsigned char verbose, struct au_mvd_args *a)
++{
++ int err, plinked;
++ struct inode *h_src_inode;
++
++ err = 0;
++ h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc);
++ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK);
++ if (au_dbstart(a->dentry) == a->mvd_bsrc
++ && a->dentry->d_count == 1
++ && atomic_read(&a->inode->i_count) == 1
++ /* && h_src_inode->i_nlink == 1 */
++ && (!plinked || !au_plink_test(a->inode))
++ && a->inode->i_nlink == 1)
++ goto out;
++
++ err = -EBUSY;
++ AU_MVD_PR(verbose,
++ "b%d, d{b%d, c%u?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
++ a->mvd_bsrc, au_dbstart(a->dentry), a->dentry->d_count,
++ atomic_read(&a->inode->i_count), a->inode->i_nlink,
++ h_src_inode->i_nlink,
++ plinked, plinked ? au_plink_test(a->inode) : 0);
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++/* make sure the parent dir is fine */
++static int au_mvd_args_parent(const unsigned char verbose,
++ struct au_mvd_args *a)
++{
++ int err;
++ aufs_bindex_t bindex;
++
++ err = 0;
++ if (unlikely(au_alive_dir(a->parent))) {
++ err = -ENOENT;
++ AU_MVD_PR(verbose, "parent dir is dead\n");
++ goto out;
++ }
++
++ a->bopq = au_dbdiropq(a->parent);
++ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst);
++ AuDbg("b%d\n", bindex);
++ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst)
++ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) {
++ err = -EINVAL;
++ AU_MVD_PR(verbose, "parent dir is opaque b%d, b%d\n",
++ a->bopq, a->mvd_bdst);
++ }
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++static int au_mvd_args_intermediate(const unsigned char verbose,
++ struct au_mvd_args *a)
++{
++ int err;
++ struct au_dinfo *dinfo, *tmp;
++
++ /* lookup the next lower positive entry */
++ err = -ENOMEM;
++ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP);
++ if (unlikely(!tmp))
++ goto out;
++
++ a->bfound = -1;
++ a->bwh = -1;
++ dinfo = au_di(a->dentry);
++ au_di_cp(tmp, dinfo);
++ au_di_swap(tmp, dinfo);
++
++ /* returns the number of positive dentries */
++ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1, /*type*/0);
++ if (!err)
++ a->bwh = au_dbwh(a->dentry);
++ else if (err > 0)
++ a->bfound = au_dbstart(a->dentry);
++
++ au_di_swap(tmp, dinfo);
++ au_rw_write_unlock(&tmp->di_rwsem);
++ au_di_free(tmp);
++ if (unlikely(err < 0))
++ AU_MVD_PR(verbose, "failed look-up lower\n");
++
++ /*
++ * here, we have these cases.
++ * bfound == -1
++ * no positive dentry under bsrc. there are more sub-cases.
++ * bwh < 0
++ * there no whiteout, we can safely move-down.
++ * bwh <= bsrc
++ * impossible
++ * bsrc < bwh && bwh < bdst
++ * there is a whiteout on RO branch. cannot proceed.
++ * bwh == bdst
++ * there is a whiteout on the RW target branch. it should
++ * be removed.
++ * bdst < bwh
++ * there is a whiteout somewhere unrelated branch.
++ * -1 < bfound && bfound <= bsrc
++ * impossible.
++ * bfound < bdst
++ * found, but it is on RO branch between bsrc and bdst. cannot
++ * proceed.
++ * bfound == bdst
++ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return
++ * error.
++ * bdst < bfound
++ * found, after we create the file on bdst, it will be hidden.
++ */
++
++ AuDebugOn(a->bfound == -1
++ && a->bwh != -1
++ && a->bwh <= a->mvd_bsrc);
++ AuDebugOn(-1 < a->bfound
++ && a->bfound <= a->mvd_bsrc);
++
++ err = -EINVAL;
++ if (a->bfound == -1
++ && a->mvd_bsrc < a->bwh
++ && a->bwh != -1
++ && a->bwh < a->mvd_bdst) {
++ AU_MVD_PR(verbose, "bsrc %d, bdst %d, bfound %d, bwh %d\n",
++ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh);
++ goto out;
++ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) {
++ AU_MVD_PR(verbose, "bdst %d, bfound %d\n",
++ a->mvd_bdst, a->bfound);
++ goto out;
++ }
++
++ err = 0; /* success */
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++static int au_mvd_args_exist(const unsigned char verbose, struct au_mvd_args *a)
++{
++ int err;
++
++ err = (a->bfound != a->mvd_bdst) ? 0 : -EEXIST;
++ AuTraceErr(err);
++ return err;
++}
++
++static int au_mvd_args(const unsigned char verbose, struct au_mvd_args *a)
++{
++ int err;
++ struct au_branch *br;
++
++ err = -EISDIR;
++ if (unlikely(S_ISDIR(a->inode->i_mode)))
++ goto out;
++
++ err = -EINVAL;
++ a->mvd_bsrc = au_ibstart(a->inode);
++ if (unlikely(a->mvd_bsrc == au_sbend(a->sb))) {
++ AU_MVD_PR(verbose, "on the bottom\n");
++ goto out;
++ }
++ br = au_sbr(a->sb, a->mvd_bsrc);
++ err = au_br_rdonly(br);
++ if (unlikely(err))
++ goto out;
++
++ err = -EINVAL;
++ a->mvd_bdst = find_lower_writable(a->sb, a->mvd_bsrc);
++ if (unlikely(a->mvd_bdst < 0)) {
++ AU_MVD_PR(verbose, "no writable lower branch\n");
++ goto out;
++ }
++
++ err = au_mvd_args_busy(verbose, a);
++ if (!err)
++ err = au_mvd_args_parent(verbose, a);
++ if (!err)
++ err = au_mvd_args_intermediate(verbose, a);
++ if (!err)
++ err = au_mvd_args_exist(verbose, a);
++ if (!err)
++ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst);
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg)
++{
++ int err;
++ unsigned char verbose;
++ struct au_mvd_args args = {
++ .dentry = dentry,
++ .inode = dentry->d_inode,
++ .sb = dentry->d_sb
++ };
++
++ err = -EPERM;
++ if (unlikely(!capable(CAP_SYS_ADMIN)))
++ goto out;
++
++ err = copy_from_user(&args.mvdown, uarg, sizeof(args.mvdown));
++ if (unlikely(err)) {
++ err = -EFAULT;
++ goto out;
++ }
++ AuDbg("flags 0x%x\n", args.mvdown.flags);
++
++ err = -EBUSY;
++ verbose = !!(args.mvdown.flags & AUFS_MVDOWN_VERBOSE);
++ args.parent = dget_parent(dentry);
++ args.dir = args.parent->d_inode;
++ mutex_lock_nested(&args.dir->i_mutex, I_MUTEX_PARENT);
++ dput(args.parent);
++ if (unlikely(args.parent != dentry->d_parent)) {
++ AU_MVD_PR(verbose, "parent dir is moved\n");
++ goto out_dir;
++ }
++
++ mutex_lock_nested(&args.inode->i_mutex, I_MUTEX_CHILD);
++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
++ if (unlikely(err))
++ goto out_inode;
++
++ di_write_lock_parent(args.parent);
++ err = au_mvd_args(verbose, &args);
++ if (unlikely(err))
++ goto out_parent;
++
++ AuDbgDentry(dentry);
++ AuDbgInode(args.inode);
++ err = au_do_mvdown(verbose, &args);
++ if (unlikely(err))
++ goto out_parent;
++ AuDbgDentry(dentry);
++ AuDbgInode(args.inode);
++
++ au_cpup_attr_timesizes(args.dir);
++ au_cpup_attr_timesizes(args.inode);
++ au_cpup_igen(args.inode, au_h_iptr(args.inode, args.mvd_bdst));
++ /* au_digen_dec(dentry); */
++
++out_parent:
++ di_write_unlock(args.parent);
++ aufs_read_unlock(dentry, AuLock_DW);
++out_inode:
++ mutex_unlock(&args.inode->i_mutex);
++out_dir:
++ mutex_unlock(&args.dir->i_mutex);
++out:
++ AuTraceErr(err);
++ return err;
++}
+diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
+++ linux/fs/aufs/opts.c 2013-07-06 13:20:47.753531903 +0200
@@ -0,0 +1,1697 @@
+/*
@@ -23548,7 +24164,7 @@ diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
+#endif /* __AUFS_SPL_H__ */
diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/super.c 2013-07-06 13:20:47.753531903 +0200
++++ linux/fs/aufs/super.c 2013-08-23 23:59:39.634916914 +0200
@@ -0,0 +1,992 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
@@ -23683,14 +24299,14 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
+
+ AuRwMustAnyLock(&sbinfo->si_rwsem);
+
-+ seq_printf(m, ",create=");
++ seq_puts(m, ",create=");
+ pat = au_optstr_wbr_create(v);
+ switch (v) {
+ case AuWbrCreate_TDP:
+ case AuWbrCreate_RR:
+ case AuWbrCreate_MFS:
+ case AuWbrCreate_PMFS:
-+ seq_printf(m, pat);
++ seq_puts(m, pat);
+ break;
+ case AuWbrCreate_MFSV:
+ seq_printf(m, /*pat*/"mfs:%lu",
@@ -24544,8 +25160,8 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
+};
diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/super.h 2013-07-06 13:20:47.753531903 +0200
-@@ -0,0 +1,555 @@
++++ linux/fs/aufs/super.h 2013-08-23 23:59:39.638250372 +0200
+@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -24819,6 +25435,10 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
+extern struct au_wbr_create_operations au_wbr_create_ops[];
+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex);
++
++/* mvdown.c */
++int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg);
+
+/* ---------------------------------------------------------------------- */
+
@@ -27689,8 +28309,8 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
+#endif /* __AUFS_VFSUB_H__ */
diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/wbr_policy.c 2013-07-06 13:20:47.753531903 +0200
-@@ -0,0 +1,701 @@
++++ linux/fs/aufs/wbr_policy.c 2013-08-23 23:59:39.638250372 +0200
+@@ -0,0 +1,693 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -27753,13 +28373,8 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+#define au_fclr_cpdown(flags, name) \
+ do { (flags) &= ~AuCpdown_##name; } while (0)
+
-+struct au_cpdown_dir_args {
-+ struct dentry *parent;
-+ unsigned int flags;
-+};
-+
+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
-+ struct au_cpdown_dir_args *a)
++ unsigned int *flags)
+{
+ int err;
+ struct dentry *opq_dentry;
@@ -27769,7 +28384,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+ if (IS_ERR(opq_dentry))
+ goto out;
+ dput(opq_dentry);
-+ au_fset_cpdown(a->flags, DIROPQ);
++ au_fset_cpdown(*flags, DIROPQ);
+
+out:
+ return err;
@@ -27809,7 +28424,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+ struct path h_path;
+ struct dentry *parent;
+ struct inode *h_dir, *h_inode, *inode, *dir;
-+ struct au_cpdown_dir_args *args = arg;
++ unsigned int *flags = arg;
+
+ bstart = au_dbstart(dentry);
+ /* dentry is di-locked */
@@ -27828,19 +28443,19 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+ S_IRWXU | S_IRUGO | S_IXUGO);
+ if (unlikely(err))
+ goto out_put;
-+ au_fset_cpdown(args->flags, MADE_DIR);
++ au_fset_cpdown(*flags, MADE_DIR);
+
+ bopq = au_dbdiropq(dentry);
-+ au_fclr_cpdown(args->flags, WHED);
-+ au_fclr_cpdown(args->flags, DIROPQ);
++ au_fclr_cpdown(*flags, WHED);
++ au_fclr_cpdown(*flags, DIROPQ);
+ if (au_dbwh(dentry) == bdst)
-+ au_fset_cpdown(args->flags, WHED);
-+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
-+ au_fset_cpdown(args->flags, PARENT_OPQ);
++ au_fset_cpdown(*flags, WHED);
++ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst)
++ au_fset_cpdown(*flags, PARENT_OPQ);
+ h_inode = h_path.dentry->d_inode;
+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
-+ if (au_ftest_cpdown(args->flags, WHED)) {
-+ err = au_cpdown_dir_opq(dentry, bdst, args);
++ if (au_ftest_cpdown(*flags, WHED)) {
++ err = au_cpdown_dir_opq(dentry, bdst, flags);
+ if (unlikely(err)) {
+ mutex_unlock(&h_inode->i_mutex);
+ goto out_dir;
@@ -27852,7 +28467,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+ if (unlikely(err))
+ goto out_opq;
+
-+ if (au_ftest_cpdown(args->flags, WHED)) {
++ if (au_ftest_cpdown(*flags, WHED)) {
+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
+ if (unlikely(err))
+ goto out_opq;
@@ -27867,7 +28482,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+
+ /* revert */
+out_opq:
-+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
++ if (au_ftest_cpdown(*flags, DIROPQ)) {
+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
+ rerr = au_diropq_remove(dentry, bdst);
+ mutex_unlock(&h_inode->i_mutex);
@@ -27879,7 +28494,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+ }
+ }
+out_dir:
-+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
++ if (au_ftest_cpdown(*flags, MADE_DIR)) {
+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
+ if (unlikely(rerr)) {
+ AuIOErr("failed removing %.*s b%d (%d)\n",
@@ -27899,13 +28514,10 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
+{
+ int err;
-+ struct au_cpdown_dir_args args = {
-+ .parent = dget_parent(dentry),
-+ .flags = 0
-+ };
++ unsigned int flags;
+
-+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
-+ dput(args.parent);
++ flags = 0;
++ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags);
+
+ return err;
+}
@@ -27914,7 +28526,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+
+/* policies for create */
+
-+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
++int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
+{
+ int err, i, j, ndentry;
+ aufs_bindex_t bopq;
@@ -29511,7 +30123,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
+#endif /* __AUFS_WHOUT_H__ */
diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/wkq.c 2013-07-06 13:20:47.760198800 +0200
++++ linux/fs/aufs/wkq.c 2013-08-23 23:59:39.638250372 +0200
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
@@ -29577,7 +30189,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
+/*
+ * Since struct completion is large, try allocating it dynamically.
+ */
-+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
++#if 1 /* defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) */
+#define AuWkqCompDeclare(name) struct completion *comp = NULL
+
+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
@@ -31115,8 +31727,8 @@ diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_ty
+#include <uapi/linux/aufs_type.h>
diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/linux/aufs_type.h
--- /usr/share/empty/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/include/uapi/linux/aufs_type.h 2013-07-30 22:42:55.842946719 +0200
-@@ -0,0 +1,235 @@
++++ linux/include/uapi/linux/aufs_type.h 2013-08-23 23:59:39.638250372 +0200
+@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
+ *
@@ -31159,7 +31771,7 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin
+
+#include <linux/limits.h>
+
-+#define AUFS_VERSION "3.10-20130722"
++#define AUFS_VERSION "3.10-20130819"
+
+/* todo? move this to linux-2.6.19/include/magic.h */
+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
@@ -31252,7 +31864,10 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin
+ AuCtl_WBR_FD,
+
+ /* busy inode */
-+ AuCtl_IBUSY
++ AuCtl_IBUSY,
++
++ /* move-down */
++ AuCtl_MVDOWN
+};
+
+/* borrowed from linux/include/linux/kernel.h */
@@ -31344,12 +31959,24 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin
+
+/* ---------------------------------------------------------------------- */
+
++/* flags for move-down */
++#define AUFS_MVDOWN_VERBOSE 1
++/* will be added more */
++
++struct aufs_mvdown {
++ uint8_t flags;
++ /* will be added more */
++} __aligned(8);
++
++/* ---------------------------------------------------------------------- */
++
+#define AuCtlType 'A'
+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
+ struct aufs_wbr_fd)
+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
++#define AUFS_CTL_MVDOWN _IOR(AuCtlType, AuCtl_MVDOWN, \
++ struct aufs_mvdown)
+
+#endif /* __AUFS_TYPE_H__ */
-
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/kernel.git/commitdiff/c2b27bf2e94b20b2576c4191ce00ad744682ca70
More information about the pld-cvs-commit
mailing list