summaryrefslogtreecommitdiff
path: root/target/linux/patches
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2015-08-02 21:18:16 +0200
committerWaldemar Brodkorb <wbx@openadk.org>2015-08-02 21:18:39 +0200
commitf20cc753998dfb4e273a7f12c7e05fd5bab7eaef (patch)
tree44657dd2c3db5b07ca9c160935c7ce99a9df32be /target/linux/patches
parent93ab3942cc01b4e42bffcbb6541ec57930f3e354 (diff)
remove non-lts kernel
Diffstat (limited to 'target/linux/patches')
-rw-r--r--target/linux/patches/4.0.6/aufs4.patch33447
-rw-r--r--target/linux/patches/4.0.6/cleankernel.patch11
-rw-r--r--target/linux/patches/4.0.6/cris-header.patch12
-rw-r--r--target/linux/patches/4.0.6/initramfs-nosizelimit.patch57
-rw-r--r--target/linux/patches/4.0.6/startup.patch37
5 files changed, 0 insertions, 33564 deletions
diff --git a/target/linux/patches/4.0.6/aufs4.patch b/target/linux/patches/4.0.6/aufs4.patch
deleted file mode 100644
index db38c850a..000000000
--- a/target/linux/patches/4.0.6/aufs4.patch
+++ /dev/null
@@ -1,33447 +0,0 @@
-diff -Nur linux-4.0.5.orig/drivers/block/loop.c linux-4.0.5/drivers/block/loop.c
---- linux-4.0.5.orig/drivers/block/loop.c 2015-06-06 10:21:22.000000000 -0500
-+++ linux-4.0.5/drivers/block/loop.c 2015-06-21 14:08:17.146432521 -0500
-@@ -592,6 +592,24 @@
- return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
- }
-
-+/*
-+ * for AUFS
-+ * no get/put for file.
-+ */
-+struct file *loop_backing_file(struct super_block *sb)
-+{
-+ struct file *ret;
-+ struct loop_device *l;
-+
-+ ret = NULL;
-+ if (MAJOR(sb->s_dev) == LOOP_MAJOR) {
-+ l = sb->s_bdev->bd_disk->private_data;
-+ ret = l->lo_backing_file;
-+ }
-+ return ret;
-+}
-+EXPORT_SYMBOL(loop_backing_file);
-+
- /* loop sysfs attributes */
-
- static ssize_t loop_attr_show(struct device *dev, char *page,
-diff -Nur linux-4.0.5.orig/fs/aufs/aufs.h linux-4.0.5/fs/aufs/aufs.h
---- linux-4.0.5.orig/fs/aufs/aufs.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-4.0.5/fs/aufs/aufs.h 2015-06-21 14:07:48.682432781 -0500
-@@ -0,0 +1,59 @@
-+/*
-+ * Copyright (C) 2005-2015 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+/*
-+ * all header files
-+ */
-+
-+#ifndef __AUFS_H__
-+#define __AUFS_H__
-+
-+#ifdef __KERNEL__
-+
-+#define AuStub(type, name, body, ...) \
-+ static inline type name(__VA_ARGS__) { body; }
-+
-+#define AuStubVoid(name, ...) \
-+ AuStub(void, name, , __VA_ARGS__)
-+#define AuStubInt0(name, ...) \
-+ AuStub(int, name, return 0, __VA_ARGS__)
-+
-+#include "debug.h"
-+
-+#include "branch.h"
-+#include "cpup.h"
-+#include "dcsub.h"
-+#include "dbgaufs.h"
-+#include "dentry.h"
-+#include "dir.h"
-+#include "dynop.h"
-+#include "file.h"
-+#include "fstype.h"
-+#include "inode.h"
-+#include "loop.h"
-+#include "module.h"
-+#include "opts.h"
-+#include "rwsem.h"
-+#include "spl.h"
-+#include "super.h"
-+#include "sysaufs.h"
-+#include "vfsub.h"
-+#include "whout.h"
-+#include "wkq.h"
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_H__ */
-diff -Nur linux-4.0.5.orig/fs/aufs/branch.c linux-4.0.5/fs/aufs/branch.c
---- linux-4.0.5.orig/fs/aufs/branch.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-4.0.5/fs/aufs/branch.c 2015-06-21 14:07:48.682432781 -0500
-@@ -0,0 +1,1406 @@
-+/*
-+ * Copyright (C) 2005-2015 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+/*
-+ * branch management
-+ */
-+
-+#include <linux/compat.h>
-+#include <linux/statfs.h>
-+#include "aufs.h"
-+
-+/*
-+ * free a single branch
-+ */
-+static void au_br_do_free(struct au_branch *br)
-+{
-+ int i;
-+ struct au_wbr *wbr;
-+ struct au_dykey **key;
-+
-+ au_hnotify_fin_br(br);
-+
-+ if (br->br_xino.xi_file)
-+ fput(br->br_xino.xi_file);
-+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
-+
-+ AuDebugOn(atomic_read(&br->br_count));
-+
-+ wbr = br->br_wbr;
-+ if (wbr) {
-+ for (i = 0; i < AuBrWh_Last; i++)
-+ dput(wbr->wbr_wh[i]);
-+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
-+ AuRwDestroy(&wbr->wbr_wh_rwsem);
-+ }
-+
-+ if (br->br_fhsm) {
-+ au_br_fhsm_fin(br->br_fhsm);
-+ kfree(br->br_fhsm);
-+ }
-+
-+ key = br->br_dykey;
-+ for (i = 0; i < AuBrDynOp; i++, key++)
-+ if (*key)
-+ au_dy_put(*key);
-+ else
-+ break;
-+
-+ /* recursive lock, s_umount of branch's */
-+ lockdep_off();
-+ path_put(&br->br_path);
-+ lockdep_on();
-+ kfree(wbr);
-+ kfree(br);
-+}
-+
-+/*
-+ * frees all branches
-+ */
-+void au_br_free(struct au_sbinfo *sbinfo)
-+{
-+ aufs_bindex_t bmax;
-+ struct au_branch **br;
-+
-+ AuRwMustWriteLock(&sbinfo->si_rwsem);
-+
-+ bmax = sbinfo->si_bend + 1;
-+ br = sbinfo->si_branch;
-+ while (bmax--)
-+ au_br_do_free(*br++);
-+}
-+
-+/*
-+ * find the index of a branch which is specified by @br_id.
-+ */
-+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
-+{
-+ aufs_bindex_t bindex, bend;
-+
-+ bend = au_sbend(sb);
-+ for (bindex = 0; bindex <= bend; bindex++)
-+ if (au_sbr_id(sb, bindex) == br_id)
-+ return bindex;
-+ return -1;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/*
-+ * add a branch
-+ */
-+
-+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
-+ struct dentry *h_root)
-+{
-+ if (unlikely(h_adding == h_root
-+ || au_test_loopback_overlap(sb, h_adding)))
-+ return 1;
-+ if (h_adding->d_sb != h_root->d_sb)
-+ return 0;
-+ return au_test_subdir(h_adding, h_root)
-+ || au_test_subdir(h_root, h_adding);
-+}
-+
-+/*
-+ * returns a newly allocated branch. @new_nbranch is a number of branches
-+ * after adding a branch.
-+ */
-+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
-+ int perm)
-+{
-+ struct au_branch *add_branch;
-+ struct dentry *root;
-+ int err;
-+
-+ err = -ENOMEM;
-+ root = sb->s_root;
-+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
-+ if (unlikely(!add_branch))
-+ goto out;
-+
-+ err = au_hnotify_init_br(add_branch, perm);
-+ if (unlikely(err))
-+ goto out_br;
-+
-+ add_branch->br_wbr = NULL;
-+ if (au_br_writable(perm)) {
-+ /* may be freed separately at changing the branch permission */
-+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
-+ GFP_NOFS);
-+ if (unlikely(!add_branch->br_wbr))
-+ goto out_hnotify;
-+ }
-+
-+ add_branch->br_fhsm = NULL;
-+ if (au_br_fhsm(perm)) {
-+ err = au_fhsm_br_alloc(add_branch);
-+ if (unlikely(err))
-+ goto out_wbr;
-+ }
-+
-+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
-+ if (!err)
-+ err = au_di_realloc(au_di(root), new_nbranch);
-+ if (!err)
-+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
-+ if (!err)
-+ return add_branch; /* success */
-+
-+out_wbr:
-+ kfree(add_branch->br_wbr);
-+out_hnotify:
-+ au_hnotify_fin_br(add_branch);
-+out_br:
-+ kfree(add_branch);
-+out:
-+ return ERR_PTR(err);
-+}
-+
-+/*
-+ * test if the branch permission is legal or not.
-+ */
-+static int test_br(struct inode *inode, int brperm, char *path)
-+{
-+ int err;
-+
-+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
-+ if (!err)
-+ goto out;
-+
-+ err = -EINVAL;
-+ pr_err("write permission for readonly mount or inode, %s\n", path);
-+
-+out:
-+ return err;
-+}
-+
-+/*
-+ * returns:
-+ * 0: success, the caller will add it
-+ * plus: success, it is already unified, the caller should ignore it
-+ * minus: error
-+ */
-+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
-+{
-+ int err;
-+ aufs_bindex_t bend, bindex;
-+ struct dentry *root;
-+ struct inode *inode, *h_inode;
-+
-+ root = sb->s_root;
-+ bend = au_sbend(sb);
-+ if (unlikely(bend >= 0
-+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
-+ err = 1;
-+ if (!remount) {
-+ err = -EINVAL;
-+ pr_err("%s duplicated\n", add->pathname);
-+ }
-+ goto out;
-+ }
-+
-+ err = -ENOSPC; /* -E2BIG; */
-+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
-+ || AUFS_BRANCH_MAX - 1 <= bend)) {
-+ pr_err("number of branches exceeded %s\n", add->pathname);
-+ goto out;
-+ }
-+
-+ err = -EDOM;
-+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
-+ pr_err("bad index %d\n", add->bindex);
-+ goto out;
-+ }
-+
-+ inode = add->path.dentry->d_inode;
-+ err = -ENOENT;
-+ if (unlikely(!inode->i_nlink)) {
-+ pr_err("no existence %s\n", add->pathname);
-+ goto out;
-+ }
-+
-+ err = -EINVAL;
-+ if (unlikely(inode->i_sb == sb)) {
-+ pr_err("%s must be outside\n", add->pathname);
-+ goto out;
-+ }
-+
-+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
-+ pr_err("unsupported filesystem, %s (%s)\n",
-+ add->pathname, au_sbtype(inode->i_sb));
-+ goto out;
-+ }
-+
-+ if (unlikely(inode->i_sb->s_stack_depth)) {
-+ pr_err("already stacked, %s (%s)\n",
-+ add->pathname, au_sbtype(inode->i_sb));
-+ goto out;
-+ }
-+
-+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
-+ if (unlikely(err))
-+ goto out;
-+
-+ if (bend < 0)
-+ return 0; /* success */
-+
-+ err = -EINVAL;
-+ for (bindex = 0; bindex <= bend; bindex++)
-+ if (unlikely(test_overlap(sb, add->path.dentry,
-+ au_h_dptr(root, bindex)))) {
-+ pr_err("%s is overlapped\n", add->pathname);
-+ goto out;
-+ }
-+
-+ err = 0;
-+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
-+ h_inode = au_h_dptr(root, 0)->d_inode;
-+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
-+ || !uid_eq(h_inode->i_uid, inode->i_uid)
-+ || !gid_eq(h_inode->i_gid, inode->i_gid))
-+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
-+ add->pathname,
-+ i_uid_read(inode), i_gid_read(inode),
-+ (inode->i_mode & S_IALLUGO),
-+ i_uid_read(h_inode), i_gid_read(h_inode),
-+ (h_inode->i_mode & S_IALLUGO));
-+ }
-+
-+out:
-+ return err;
-+}
-+
-+/*
-+ * initialize or clean the whiteouts for an adding branch
-+ */
-+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
-+ int new_perm)
-+{
-+ int err, old_perm;
-+ aufs_bindex_t bindex;
-+ struct mutex *h_mtx;
-+ struct au_wbr *wbr;
-+ struct au_hinode *hdir;
-+
-+ err = vfsub_mnt_want_write(au_br_mnt(br));
-+ if (unlikely(err))
-+ goto out;
-+
-+ wbr = br->br_wbr;
-+ old_perm = br->br_perm;
-+ br->br_perm = new_perm;
-+ hdir = NULL;
-+ h_mtx = NULL;
-+ bindex = au_br_index(sb, br->br_id);
-+ if (0 <= bindex) {
-+ hdir = au_hi(sb->s_root->d_inode, bindex);
-+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
-+ } else {
-+ h_mtx = &au_br_dentry(br)->d_inode->i_mutex;
-+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
-+ }
-+ if (!wbr)
-+ err = au_wh_init(br, sb);
-+ else {
-+ wbr_wh_write_lock(wbr);
-+ err = au_wh_init(br, sb);
-+ wbr_wh_write_unlock(wbr);
-+ }
-+ if (hdir)
-+ au_hn_imtx_unlock(hdir);
-+ else
-+ mutex_unlock(h_mtx);
-+ vfsub_mnt_drop_write(au_br_mnt(br));
-+ br->br_perm = old_perm;
-+
-+ if (!err && wbr && !au_br_writable(new_perm)) {
-+ kfree(wbr);
-+ br->br_wbr = NULL;
-+ }
-+
-+out:
-+ return err;
-+}
-+
-+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
-+ int perm)
-+{
-+ int err;
-+ struct kstatfs kst;
-+ struct au_wbr *wbr;
-+
-+ wbr = br->br_wbr;
-+ au_rw_init(&wbr->wbr_wh_rwsem);
-+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
-+ atomic_set(&wbr->wbr_wh_running, 0);
-+ wbr->wbr_bytes = 0;
-+
-+ /*
-+ * a limit for rmdir/rename a dir
-+ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h
-+ */
-+ err = vfs_statfs(&br->br_path, &kst);
-+ if (unlikely(err))
-+ goto out;
-+ err = -EINVAL;
-+ if (kst.f_namelen >= NAME_MAX)
-+ err = au_br_init_wh(sb, br, perm);
-+ else
-+ pr_err("%pd(%s), unsupported namelen %ld\n",
-+ au_br_dentry(br),
-+ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen);
-+
-+out:
-+ return err;
-+}
-+
-+/* initialize a new branch */
-+static int au_br_init(struct au_branch *br, struct super_block *sb,
-+ struct au_opt_add *add)
-+{
-+ int err;
-+
-+ err = 0;
-+ memset(&br->br_xino, 0, sizeof(br->br_xino));
-+ mutex_init(&br->br_xino.xi_nondir_mtx);
-+ br->br_perm = add->perm;
-+ br->br_path = add->path; /* set first, path_get() later */
-+ spin_lock_init(&br->br_dykey_lock);
-+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
-+ atomic_set(&br->br_count, 0);
-+ atomic_set(&br->br_xino_running, 0);
-+ br->br_id = au_new_br_id(sb);
-+ AuDebugOn(br->br_id < 0);
-+
-+ if (au_br_writable(add->perm)) {
-+ err = au_wbr_init(br, sb, add->perm);
-+ if (unlikely(err))
-+ goto out_err;
-+ }
-+
-+ if (au_opt_test(au_mntflags(sb), XINO)) {
-+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
-+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
-+ if (unlikely(err)) {
-+ AuDebugOn(br->br_xino.xi_file);
-+ goto out_err;
-+ }
-+ }
-+
-+ sysaufs_br_init(br);
-+ path_get(&br->br_path);
-+ goto out; /* success */
-+
-+out_err:
-+ memset(&br->br_path, 0, sizeof(br->br_path));
-+out:
-+ return err;
-+}
-+
-+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
-+ struct au_branch *br, aufs_bindex_t bend,
-+ aufs_bindex_t amount)
-+{
-+ struct au_branch **brp;
-+
-+ AuRwMustWriteLock(&sbinfo->si_rwsem);
-+
-+ brp = sbinfo->si_branch + bindex;
-+ memmove(brp + 1, brp, sizeof(*brp) * amount);
-+ *brp = br;
-+ sbinfo->si_bend++;
-+ if (unlikely(bend < 0))
-+ sbinfo->si_bend = 0;
-+}
-+
-+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
-+ aufs_bindex_t bend, aufs_bindex_t amount)
-+{
-+ struct au_hdentry *hdp;
-+
-+ AuRwMustWriteLock(&dinfo->di_rwsem);
-+
-+ hdp = dinfo->di_hdentry + bindex;
-+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
-+ au_h_dentry_init(hdp);
-+ dinfo->di_bend++;
-+ if (unlikely(bend < 0))
-+ dinfo->di_bstart = 0;
-+}
-+
-+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
-+ aufs_bindex_t bend, aufs_bindex_t amount)
-+{
-+ struct au_hinode *hip;
-+
-+ AuRwMustWriteLock(&iinfo->ii_rwsem);
-+
-+ hip = iinfo->ii_hinode + bindex;
-+ memmove(hip + 1, hip, sizeof(*hip) * amount);
-+ hip->hi_inode = NULL;
-+ au_hn_init(hip);
-+ iinfo->ii_bend++;
-+ if (unlikely(bend < 0))
-+ iinfo->ii_bstart = 0;
-+}
-+
-+static void au_br_do_add(struct super_block *sb, struct au_branch *br,
-+ aufs_bindex_t bindex)
-+{
-+ struct dentry *root, *h_dentry;
-+ struct inode *root_inode;
-+ aufs_bindex_t bend, amount;
-+
-+ root = sb->s_root;
-+ root_inode = root->d_inode;
-+ bend = au_sbend(sb);
-+ amount = bend + 1 - bindex;
-+ h_dentry = au_br_dentry(br);
-+ au_sbilist_lock();
-+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
-+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
-+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
-+ au_set_h_dptr(root, bindex, dget(h_dentry));
-+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
-+ /*flags*/0);
-+ au_sbilist_unlock();
-+}
-+
-+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
-+{
-+ int err;
-+ aufs_bindex_t bend, add_bindex;
-+ struct dentry *root, *h_dentry;
-+ struct inode *root_inode;
-+ struct au_branch *add_branch;
-+
-+ root = sb->s_root;
-+ root_inode = root->d_inode;
-+ IMustLock(root_inode);
-+ err = test_add(sb, add, remount);
-+ if (unlikely(err < 0))
-+ goto out;
-+ if (err) {
-+ err = 0;
-+ goto out; /* success */
-+ }
-+
-+ bend = au_sbend(sb);
-+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
-+ err = PTR_ERR(add_branch);
-+ if (IS_ERR(add_branch))
-+ goto out;
-+
-+ err = au_br_init(add_branch, sb, add);
-+ if (unlikely(err)) {
-+ au_br_do_free(add_branch);
-+ goto out;
-+ }
-+
-+ add_bindex = add->bindex;
-+ if (!remount)
-+ au_br_do_add(sb, add_branch, add_bindex);
-+ else {
-+ sysaufs_brs_del(sb, add_bindex);
-+ au_br_do_add(sb, add_branch, add_bindex);
-+ sysaufs_brs_add(sb, add_bindex);
-+ }
-+
-+ h_dentry = add->path.dentry;
-+ if (!add_bindex) {
-+ au_cpup_attr_all(root_inode, /*force*/1);
-+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
-+ } else
-+ au_add_nlink(root_inode, h_dentry->d_inode);
-+
-+ /*
-+ * this test/set prevents aufs from handling unnecesary notify events
-+ * of xino files, in case of re-adding a writable branch which was
-+ * once detached from aufs.
-+ */
-+ if (au_xino_brid(sb) < 0
-+ && au_br_writable(add_branch->br_perm)
-+ && !au_test_fs_bad_xino(h_dentry->d_sb)
-+ && add_branch->br_xino.xi_file
-+ && add_branch->br_xino.xi_file->f_path.dentry->d_parent == h_dentry)
-+ au_xino_brid_set(sb, add_branch->br_id);
-+
-+out:
-+ return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static unsigned long long au_farray_cb(void *a,
-+ unsigned long long max __maybe_unused,
-+ void *arg)
-+{
-+ unsigned long long n;
-+ struct file **p, *f;
-+ struct au_sphlhead *files;
-+ struct au_finfo *finfo;
-+ struct super_block *sb = arg;
-+
-+ n = 0;
-+ p = a;
-+ files = &au_sbi(sb)->si_files;
-+ spin_lock(&files->spin);
-+ hlist_for_each_entry(finfo, &files->head, fi_hlist) {
-+ f = finfo->fi_file;
-+ if (file_count(f)
-+ && !special_file(file_inode(f)->i_mode)) {
-+ get_file(f);
-+ *p++ = f;
-+ n++;
-+ AuDebugOn(n > max);
-+ }
-+ }
-+ spin_unlock(&files->spin);
-+
-+ return n;
-+}
-+
-+static struct file **au_farray_alloc(struct super_block *sb,
-+ unsigned long long *max)
-+{
-+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
-+ return au_array_alloc(max, au_farray_cb, sb);
-+}
-+
-+static void au_farray_free(struct file **a, unsigned long long max)
-+{
-+ unsigned long long ull;
-+
-+ for (ull = 0; ull < max; ull++)
-+ if (a[ull])
-+ fput(a[ull]);
-+ au_array_free(a);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/*
-+ * delete a branch
-+ */
-+
-+/* to show the line number, do not make it inlined function */
-+#define AuVerbose(do_info, fmt, ...) do { \
-+ if (do_info) \
-+ pr_info(fmt, ##__VA_ARGS__); \
-+} while (0)
-+
-+static int au_test_ibusy(struct inode *inode, aufs_bindex_t bstart,
-+ aufs_bindex_t bend)
-+{
-+ return (inode && !S_ISDIR(inode->i_mode)) || bstart == bend;
-+}
-+
-+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t bstart,
-+ aufs_bindex_t bend)
-+{
-+ return au_test_ibusy(dentry->d_inode, bstart, bend);
-+}
-+
-+/*
-+ * test if the branch is deletable or not.
-+ */
-+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
-+ unsigned int sigen, const unsigned int verbose)
-+{
-+ int err, i, j, ndentry;
-+ aufs_bindex_t bstart, bend;
-+ struct au_dcsub_pages dpages;
-+ struct au_dpage *dpage;
-+ struct dentry *d;
-+
-+ err = au_dpages_init(&dpages, GFP_NOFS);
-+ if (unlikely(err))
-+ goto out;
-+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
-+ if (unlikely(err))
-+ goto out_dpages;
-+
-+ for (i = 0; !err && i < dpages.ndpage; i++) {
-+ dpage = dpages.dpages + i;
-+ ndentry = dpage->ndentry;
-+ for (j = 0; !err && j < ndentry; j++) {
-+ d = dpage->dentries[j];
-+ AuDebugOn(au_dcount(d) <= 0);
-+ if (!au_digen_test(d, sigen)) {
-+ di_read_lock_child(d, AuLock_IR);
-+ if (unlikely(au_dbrange_test(d))) {
-+ di_read_unlock(d, AuLock_IR);
-+ continue;
-+ }
-+ } else {
-+ di_write_lock_child(d);
-+ if (unlikely(au_dbrange_test(d))) {
-+ di_write_unlock(d);
-+ continue;
-+ }
-+ err = au_reval_dpath(d, sigen);
-+ if (!err)
-+ di_downgrade_lock(d, AuLock_IR);
-+ else {
-+ di_write_unlock(d);
-+ break;
-+ }
-+ }
-+
-+ /* AuDbgDentry(d); */
-+ bstart = au_dbstart(d);
-+ bend = au_dbend(d);
-+ if (bstart <= bindex
-+ && bindex <= bend
-+ && au_h_dptr(d, bindex)
-+ && au_test_dbusy(d, bstart, bend)) {
-+ err = -EBUSY;
-+ AuVerbose(verbose, "busy %pd\n", d);
-+ AuDbgDentry(d);
-+ }
-+ di_read_unlock(d, AuLock_IR);
-+ }
-+ }
-+
-+out_dpages:
-+ au_dpages_free(&dpages);
-+out:
-+ return err;
-+}
-+
-+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
-+ unsigned int sigen, const unsigned int verbose)
-+{
-+ int err;
-+ unsigned long long max, ull;
-+ struct inode *i, **array;
-+ aufs_bindex_t bstart, bend;
-+
-+ array = au_iarray_alloc(sb, &max);
-+ err = PTR_ERR(array);
-+ if (IS_ERR(array))
-+ goto out;
-+
-+ err = 0;
-+ AuDbg("b%d\n", bindex);
-+ for (ull = 0; !err && ull < max; ull++) {
-+ i = array[ull];
-+ if (unlikely(!i))
-+ break;
-+ if (i->i_ino == AUFS_ROOT_INO)
-+ continue;
-+
-+ /* AuDbgInode(i); */
-+ if (au_iigen(i, NULL) == sigen)
-+ ii_read_lock_child(i);
-+ else {
-+ ii_write_lock_child(i);
-+ err = au_refresh_hinode_self(i);
-+ au_iigen_dec(i);
-+ if (!err)
-+ ii_downgrade_lock(i);
-+ else {
-+ ii_write_unlock(i);
-+ break;
-+ }
-+ }
-+
-+ bstart = au_ibstart(i);
-+ bend = au_ibend(i);
-+ if (bstart <= bindex
-+ && bindex <= bend
-+ && au_h_iptr(i, bindex)
-+ && au_test_ibusy(i, bstart, bend)) {
-+ err = -EBUSY;
-+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
-+ AuDbgInode(i);
-+ }
-+ ii_read_unlock(i);
-+ }
-+ au_iarray_free(array, max);
-+
-+out:
-+ return err;
-+}
-+
-+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
-+ const unsigned int verbose)
-+{
-+ int err;
-+ unsigned int sigen;
-+
-+ sigen = au_sigen(root->d_sb);
-+ DiMustNoWaiters(root);
-+ IiMustNoWaiters(root->d_inode);
-+ di_write_unlock(root);
-+ err = test_dentry_busy(root, bindex, sigen, verbose);
-+ if (!err)
-+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
-+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
-+
-+ return err;
-+}
-+
-+static int test_dir_busy(struct file *file, aufs_bindex_t br_id,
-+ struct file **to_free, int *idx)
-+{
-+ int err;
-+ unsigned char matched, root;
-+ aufs_bindex_t bindex, bend;
-+ struct au_fidir *fidir;
-+ struct au_hfile *hfile;
-+
-+ err = 0;
-+ root = IS_ROOT(file->f_path.dentry);
-+ if (root) {
-+ get_file(file);
-+ to_free[*idx] = file;
-+ (*idx)++;
-+ goto out;
-+ }
-+
-+ matched = 0;
-+ fidir = au_fi(file)->fi_hdir;
-+ AuDebugOn(!fidir);
-+ bend = au_fbend_dir(file);
-+ for (bindex = au_fbstart(file); bindex <= bend; bindex++) {
-+ hfile = fidir->fd_hfile + bindex;
-+ if (!hfile->hf_file)
-+ continue;
-+
-+ if (hfile->hf_br->br_id == br_id) {
-+ matched = 1;
-+ break;
-+ }
-+ }
-+ if (matched)
-+ err = -EBUSY;
-+
-+out:
-+ return err;
-+}
-+
-+static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id,
-+ struct file **to_free, int opened)
-+{
-+ int err, idx;
-+ unsigned long long ull, max;
-+ aufs_bindex_t bstart;
-+ struct file *file, **array;
-+ struct dentry *root;
-+ struct au_hfile *hfile;
-+
-+ array = au_farray_alloc(sb, &max);
-+ err = PTR_ERR(array);
-+ if (IS_ERR(array))
-+ goto out;
-+
-+ err = 0;
-+ idx = 0;
-+ root = sb->s_root;
-+ di_write_unlock(root);
-+ for (ull = 0; ull < max; ull++) {
-+ file = array[ull];
-+ if (unlikely(!file))
-+ break;
-+
-+ /* AuDbg("%pD\n", file); */
-+ fi_read_lock(file);
-+ bstart = au_fbstart(file);
-+ if (!d_is_dir(file->f_path.dentry)) {
-+ hfile = &au_fi(file)->fi_htop;
-+ if (hfile->hf_br->br_id == br_id)
-+ err = -EBUSY;
-+ } else
-+ err = test_dir_busy(file, br_id, to_free, &idx);
-+ fi_read_unlock(file);
-+ if (unlikely(err))
-+ break;
-+ }
-+ di_write_lock_child(root);
-+ au_farray_free(array, max);
-+ AuDebugOn(idx > opened);
-+
-+out:
-+ return err;
-+}
-+
-+static void br_del_file(struct file **to_free, unsigned long long opened,
-+ aufs_bindex_t br_id)
-+{
-+ unsigned long long ull;
-+ aufs_bindex_t bindex, bstart, bend, bfound;
-+ struct file *file;
-+ struct au_fidir *fidir;
-+ struct au_hfile *hfile;
-+
-+ for (ull = 0; ull < opened; ull++) {
-+ file = to_free[ull];
-+ if (unlikely(!file))
-+ break;
-+
-+ /* AuDbg("%pD\n", file); */
-+ AuDebugOn(!d_is_dir(file->f_path.dentry));
-+ bfound = -1;
-+ fidir = au_fi(file)->fi_hdir;
-+ AuDebugOn(!fidir);
-+ fi_write_lock(file);
-+ bstart = au_fbstart(file);
-+ bend = au_fbend_dir(file);
-+ for (bindex = bstart; bindex <= bend; bindex++) {
-+ hfile = fidir->fd_hfile + bindex;
-+ if (!hfile->hf_file)
-+ continue;
-+
-+ if (hfile->hf_br->br_id == br_id) {
-+ bfound = bindex;
-+ break;
-+ }
-+ }
-+ AuDebugOn(bfound < 0);
-+ au_set_h_fptr(file, bfound, NULL);
-+ if (bfound == bstart) {
-+ for (bstart++; bstart <= bend; bstart++)
-+ if (au_hf_dir(file, bstart)) {
-+ au_set_fbstart(file, bstart);
-+ break;
-+ }
-+ }
-+ fi_write_unlock(file);
-+ }
-+}
-+
-+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
-+ const aufs_bindex_t bindex,
-+ const aufs_bindex_t bend)
-+{
-+ struct au_branch **brp, **p;
-+
-+ AuRwMustWriteLock(&sbinfo->si_rwsem);
-+
-+ brp = sbinfo->si_branch + bindex;
-+ if (bindex < bend)
-+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
-+ sbinfo->si_branch[0 + bend] = NULL;
-+ sbinfo->si_bend--;
-+
-+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, AuGFP_SBILIST);
-+ if (p)
-+ sbinfo->si_branch = p;
-+ /* harmless error */
-+}
-+
-+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
-+ const aufs_bindex_t bend)
-+{
-+ struct au_hdentry *hdp, *p;
-+
-+ AuRwMustWriteLock(&dinfo->di_rwsem);
-+
-+ hdp = dinfo->di_hdentry;
-+ if (bindex < bend)
-+ memmove(hdp + bindex, hdp + bindex + 1,
-+ sizeof(*hdp) * (bend - bindex));
-+ hdp[0 + bend].hd_dentry = NULL;
-+ dinfo->di_bend--;
-+
-+ p = krealloc(hdp, sizeof(*p) * bend, AuGFP_SBILIST);
-+ if (p)
-+ dinfo->di_hdentry = p;
-+ /* harmless error */
-+}
-+
-+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
-+ const aufs_bindex_t bend)
-+{
-+ struct au_hinode *hip, *p;
-+
-+ AuRwMustWriteLock(&iinfo->ii_rwsem);
-+
-+ hip = iinfo->ii_hinode + bindex;
-+ if (bindex < bend)
-+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
-+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
-+ au_hn_init(iinfo->ii_hinode + bend);
-+ iinfo->ii_bend--;
-+
-+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, AuGFP_SBILIST);
-+ if (p)
-+ iinfo->ii_hinode = p;
-+ /* harmless error */
-+}
-+
-+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
-+ struct au_branch *br)
-+{
-+ aufs_bindex_t bend;
-+ struct au_sbinfo *sbinfo;
-+ struct dentry *root, *h_root;
-+ struct inode *inode, *h_inode;
-+ struct au_hinode *hinode;
-+
-+ SiMustWriteLock(sb);
-+
-+ root = sb->s_root;
-+ inode = root->d_inode;
-+ sbinfo = au_sbi(sb);
-+ bend = sbinfo->si_bend;
-+
-+ h_root = au_h_dptr(root, bindex);
-+ hinode = au_hi(inode, bindex);
-+ h_inode = au_igrab(hinode->hi_inode);
-+ au_hiput(hinode);
-+
-+ au_sbilist_lock();
-+ au_br_do_del_brp(sbinfo, bindex, bend);
-+ au_br_do_del_hdp(au_di(root), bindex, bend);
-+ au_br_do_del_hip(au_ii(inode), bindex, bend);
-+ au_sbilist_unlock();
-+
-+ dput(h_root);
-+ iput(h_inode);
-+ au_br_do_free(br);
-+}
-+
-+static unsigned long long empty_cb(void *array, unsigned long long max,
-+ void *arg)
-+{
-+ return max;
-+}
-+
-+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
-+{
-+ int err, rerr, i;
-+ unsigned long long opened;
-+ unsigned int mnt_flags;
-+ aufs_bindex_t bindex, bend, br_id;
-+ unsigned char do_wh, verbose;
-+ struct au_branch *br;
-+ struct au_wbr *wbr;
-+ struct dentry *root;
-+ struct file **to_free;
-+
-+ err = 0;
-+ opened = 0;
-+ to_free = NULL;
-+ root = sb->s_root;
-+ bindex = au_find_dbindex(root, del->h_path.dentry);
-+ if (bindex < 0) {
-+ if (remount)
-+ goto out; /* success */
-+ err = -ENOENT;
-+ pr_err("%s no such branch\n", del->pathname);
-+ goto out;
-+ }
-+ AuDbg("bindex b%d\n", bindex);
-+
-+ err = -EBUSY;
-+ mnt_flags = au_mntflags(sb);
-+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
-+ bend = au_sbend(sb);
-+ if (unlikely(!bend)) {
-+ AuVerbose(verbose, "no more branches left\n");
-+ goto out;
-+ }
-+ br = au_sbr(sb, bindex);
-+ AuDebugOn(!path_equal(&br->br_path, &del->h_path));
-+
-+ br_id = br->br_id;
-+ opened = atomic_read(&br->br_count);
-+ if (unlikely(opened)) {
-+ to_free = au_array_alloc(&opened, empty_cb, NULL);
-+ err = PTR_ERR(to_free);
-+ if (IS_ERR(to_free))
-+ goto out;
-+
-+ err = test_file_busy(sb, br_id, to_free, opened);
-+ if (unlikely(err)) {
-+ AuVerbose(verbose, "%llu file(s) opened\n", opened);
-+ goto out;
-+ }
-+ }
-+
-+ wbr = br->br_wbr;
-+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
-+ if (do_wh) {
-+ /* instead of WbrWhMustWriteLock(wbr) */
-+ SiMustWriteLock(sb);
-+ for (i = 0; i < AuBrWh_Last; i++) {
-+ dput(wbr->wbr_wh[i]);
-+ wbr->wbr_wh[i] = NULL;
-+ }
-+ }
-+
-+ err = test_children_busy(root, bindex, verbose);
-+ if (unlikely(err)) {
-+ if (do_wh)
-+ goto out_wh;
-+ goto out;
-+ }
-+
-+ err = 0;
-+ if (to_free) {
-+ /*
-+ * now we confirmed the branch is deletable.
-+ * let's free the remaining opened dirs on the branch.
-+ */
-+ di_write_unlock(root);
-+ br_del_file(to_free, opened, br_id);
-+ di_write_lock_child(root);
-+ }
-+
-+ if (!remount)
-+ au_br_do_del(sb, bindex, br);
-+ else {
-+ sysaufs_brs_del(sb, bindex);
-+ au_br_do_del(sb, bindex, br);
-+ sysaufs_brs_add(sb, bindex);
-+ }
-+
-+ if (!bindex) {
-+ au_cpup_attr_all(root->d_inode, /*force*/1);
-+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
-+ } else
-+ au_sub_nlink(root->d_inode, del->h_path.dentry->d_inode);
-+ if (au_opt_test(mnt_flags, PLINK))
-+ au_plink_half_refresh(sb, br_id);
-+
-+ if (au_xino_brid(sb) == br_id)
-+ au_xino_brid_set(sb, -1);