diff options
39 files changed, 64476 insertions, 70 deletions
@@ -1,6 +1,4 @@ -- cleanup dots in menu (script is in test phase) - rpm package backend -- ALSA updates - port htop software - stripping of kernel is not working for all targets - implement a non-interactive allmodconfig for different targets diff --git a/package/Depends.mk b/package/Depends.mk index 96d25a34a..db7aaeb4d 100644 --- a/package/Depends.mk +++ b/package/Depends.mk @@ -2,6 +2,7 @@ # material, please see the LICENCE file in the top-level directory. aircrack-ng-compile: openssl-compile libpcap-compile +alsa-utils-compile: alsa-lib-compile apr-util-compile: expat-compile apr-compile arpd-compile: libpcap-compile libdnet-compile libevent-compile arpwatch-compile: libpcap-compile diff --git a/package/Makefile b/package/Makefile index 424c7493b..60fc52a25 100644 --- a/package/Makefile +++ b/package/Makefile @@ -200,7 +200,7 @@ package-$(ADK_PACKAGE_LIBPCAP) += libpcap package-$(ADK_PACKAGE_LIBPCIACCESS) += libpciaccess package-$(ADK_PACKAGE_LIBPNG) += libpng package-$(ADK_PACKAGE_LIBPRI) += libpri -ifeq (${ADK_NATIVE},n) +ifneq (${ADK_NATIVE},y) package-$(ADK_PACKAGE_LIBPTHREAD) += libpthread endif package-$(ADK_COMPILE_LIBSHOUT) += libshout diff --git a/package/alsa-lib/Makefile b/package/alsa-lib/Makefile index 01f97a8b8..78d0b08df 100644 --- a/package/alsa-lib/Makefile +++ b/package/alsa-lib/Makefile @@ -4,9 +4,9 @@ include ${TOPDIR}/rules.mk PKG_NAME:= alsa-lib -PKG_VERSION:= 1.0.20 +PKG_VERSION:= 1.0.21a PKG_RELEASE:= 1 -PKG_MD5SUM:= 6e9080ba1faa5d3739d14dd76c62d8dc +PKG_MD5SUM:= 914685deb8c23cb4b940a4173cf8efe4 PKG_DESCR:= ALSA sound library PKG_SECTION:= libs PKG_URL:= http://www.alsa-project.org @@ -17,12 +17,12 @@ DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.bz2 include ${TOPDIR}/mk/package.mk -$(eval $(call PKG_template,ALSA_LIB,alsa-lib,${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) +$(eval $(call PKG_template,ALSA_LIB,${PKG_NAME},${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) -CONFIGURE_STYLE= gnu +CONFIGURE_STYLE:= gnu CONFIGURE_ARGS+= --disable-python -BUILD_STYLE= auto -INSTALL_STYLE= auto +BUILD_STYLE:= auto +INSTALL_STYLE:= auto post-install: ${INSTALL_DIR} ${IDIR_ALSA_LIB}/usr/lib ${IDIR_ALSA_LIB}/usr/share/alsa diff --git a/package/alsa-utils/Config.in b/package/alsa-utils/Config.in index 64fc5ab94..0c5982c40 100644 --- a/package/alsa-utils/Config.in +++ b/package/alsa-utils/Config.in @@ -2,6 +2,7 @@ config ADK_PACKAGE_ALSA_UTILS prompt "alsa-utils........................ ALSA utilities / mixer" tristate default n + select ADK_PACKAGE_ALSA_LIB + select ADK_PACKAGE_LIBPTHREAD help - http://www.alsa-project.org/ diff --git a/package/alsa-utils/Makefile b/package/alsa-utils/Makefile index 1b0dc7eee..6cbc92509 100644 --- a/package/alsa-utils/Makefile +++ b/package/alsa-utils/Makefile @@ -4,11 +4,11 @@ include ${TOPDIR}/rules.mk PKG_NAME:= alsa-utils -PKG_VERSION:= 1.0.20 +PKG_VERSION:= 1.0.21 PKG_RELEASE:= 1 -PKG_MD5SUM:= 6837e673ef19da96d8bd2f9e18cd9574 +PKG_MD5SUM:= 3672287c2608040d111ce45495ba7602 PKG_DESCR:= ALSA mixer utility -PKG_SECTION:= libs +PKG_SECTION:= utils PKG_URL:= http://www.alsa-project.org PKG_SITES:= ftp://ftp.task.gda.pl/pub/linux/misc/alsa/utils/ \ ftp://ftp.alsa-project.org/pub/utils/ @@ -19,10 +19,10 @@ include ${TOPDIR}/mk/package.mk $(eval $(call PKG_template,ALSA_UTILS,${PKG_NAME},${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) -CONFIGURE_STYLE= gnu +CONFIGURE_STYLE:= gnu CONFIGURE_ARGS+= --disable-alsamixer -BUILD_STYLE= auto -INSTALL_STYLE= auto +BUILD_STYLE:= auto +INSTALL_STYLE:= auto post-install: ${INSTALL_DIR} ${IDIR_ALSA_UTILS}/usr/bin diff --git a/package/dnsmasq/Makefile b/package/dnsmasq/Makefile index 0cfa55f25..711a575fc 100644 --- a/package/dnsmasq/Makefile +++ b/package/dnsmasq/Makefile @@ -4,9 +4,9 @@ include ${TOPDIR}/rules.mk PKG_NAME:= dnsmasq -PKG_VERSION:= 2.49 +PKG_VERSION:= 2.51 PKG_RELEASE:= 1 -PKG_MD5SUM:= 7ccc861d8a733474f9c0a0a127006ee9 +PKG_MD5SUM:= 97465261a6de5258a3c3edfe51ca16a4 PKG_DESCR:= A lightweight DNS and DHCP server PKG_SECTION:= net PKG_URL:= http://thekelleys.org.uk/dnsmasq @@ -17,7 +17,6 @@ include ${TOPDIR}/mk/package.mk $(eval $(call PKG_template,DNSMASQ,${PKG_NAME},${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) BUILD_STYLE:= auto -INSTALL_STYLE= manual MAKE_FLAGS+= BINDIR=/usr/sbin MANDIR=/usr/man COPTS="${TCFLAGS}" ifneq ($(ADK_IPV6),y) MAKE_FLAGS+= COPTS="${TCFLAGS} -DNO_IPV6" diff --git a/package/dropbear/files/dropbear.init b/package/dropbear/files/dropbear.init index b1623c919..09eea25e4 100644 --- a/package/dropbear/files/dropbear.init +++ b/package/dropbear/files/dropbear.init @@ -10,7 +10,7 @@ bothlog() { case $1 in autostop) ;; autostart) - [[ $dropbear_flags = NO ]] && exit 0 + [[ "$dropbear_flags" = "NO" ]] && exit 0 exec sh $0 start ;; start) diff --git a/target/alix1c/device.mk b/target/alix1c/device.mk index fb0f58477..fc3479ab4 100644 --- a/target/alix1c/device.mk +++ b/target/alix1c/device.mk @@ -1,6 +1,6 @@ ARCH:= x86 CPU_ARCH:= i586 -KERNEL_VERSION:= 2.6.30.5 +KERNEL_VERSION:= 2.6.31.4 KERNEL_RELEASE:= 1 KERNEL_MD5SUM:= be9c3a697a54ac099c910d068ff0dc03 TARGET_OPTIMIZATION:= -Os -pipe diff --git a/target/foxboard/device.mk b/target/foxboard/device.mk index e9be810b6..b2eb19f57 100644 --- a/target/foxboard/device.mk +++ b/target/foxboard/device.mk @@ -1,6 +1,6 @@ ARCH:= cris CPU_ARCH:= cris -KERNEL_VERSION:= 2.6.30.5 +KERNEL_VERSION:= 2.6.31.4 KERNEL_RELEASE:= 1 KERNEL_MD5SUM:= be9c3a697a54ac099c910d068ff0dc03 TARGET_OPTIMIZATION:= -Os -pipe -fno-peephole2 diff --git a/target/g1/device.mk b/target/g1/device.mk index 1d5c2cd72..933c74e18 100644 --- a/target/g1/device.mk +++ b/target/g1/device.mk @@ -1,6 +1,6 @@ ARCH:= arm CPU_ARCH:= armel -KERNEL_VERSION:= 2.6.30.5 +KERNEL_VERSION:= 2.6.31.4 KERNEL_RELEASE:= 1 KERNEL_MD5SUM:= be9c3a697a54ac099c910d068ff0dc03 TARGET_OPTIMIZATION:= -Os -pipe diff --git a/target/lemote/device.mk b/target/lemote/device.mk index 52cc097fc..a9037d8ed 100644 --- a/target/lemote/device.mk +++ b/target/lemote/device.mk @@ -1,6 +1,6 @@ ARCH:= mips CPU_ARCH:= mips64el -KERNEL_VERSION:= 2.6.30.5 +KERNEL_VERSION:= 2.6.31.4 KERNEL_RELEASE:= 1 KERNEL_MD5SUM:= be9c3a697a54ac099c910d068ff0dc03 TARGET_OPTIMIZATION:= -Os -pipe diff --git a/target/linux/patches/2.6.31.4/aufs2.patch b/target/linux/patches/2.6.31.4/aufs2.patch new file mode 100644 index 000000000..7a6d3bac6 --- /dev/null +++ b/target/linux/patches/2.6.31.4/aufs2.patch @@ -0,0 +1,24453 @@ +diff -Nur linux-2.6.31.4.orig/Documentation/ABI/testing/debugfs-aufs linux-2.6.31.4/Documentation/ABI/testing/debugfs-aufs +--- linux-2.6.31.4.orig/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.31.4/Documentation/ABI/testing/debugfs-aufs 2009-10-18 11:26:01.000000000 +0200 +@@ -0,0 +1,40 @@ ++What: /debug/aufs/si_<id>/ ++Date: March 2009 ++Contact: J. R. Okajima <hooanon05@yahoo.co.jp> ++Description: ++ Under /debug/aufs, a directory named si_<id> is created ++ per aufs mount, where <id> is a unique id generated ++ internally. ++ ++What: /debug/aufs/si_<id>/xib ++Date: March 2009 ++Contact: J. R. Okajima <hooanon05@yahoo.co.jp> ++Description: ++ It shows the consumed blocks by xib (External Inode Number ++ Bitmap), its block size and file size. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see ++ Documentation/filesystems/aufs/aufs.5 in detail. ++ ++What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN ++Date: March 2009 ++Contact: J. R. Okajima <hooanon05@yahoo.co.jp> ++Description: ++ It shows the consumed blocks by xino (External Inode Number ++ Translation Table), its link count, block size and file ++ size. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see ++ Documentation/filesystems/aufs/aufs.5 in detail. ++ ++What: /debug/aufs/si_<id>/xigen ++Date: March 2009 ++Contact: J. R. Okajima <hooanon05@yahoo.co.jp> ++Description: ++ It shows the consumed blocks by xigen (External Inode ++ Generation Table), its block size and file size. ++ If CONFIG_AUFS_EXPORT is disabled, this entry will not ++ be created. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see ++ Documentation/filesystems/aufs/aufs.5 in detail. +diff -Nur linux-2.6.31.4.orig/Documentation/ABI/testing/sysfs-aufs linux-2.6.31.4/Documentation/ABI/testing/sysfs-aufs +--- linux-2.6.31.4.orig/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.31.4/Documentation/ABI/testing/sysfs-aufs 2009-10-18 11:26:01.000000000 +0200 +@@ -0,0 +1,25 @@ ++What: /sys/fs/aufs/si_<id>/ ++Date: March 2009 ++Contact: J. R. Okajima <hooanon05@yahoo.co.jp> ++Description: ++ Under /sys/fs/aufs, a directory named si_<id> is created ++ per aufs mount, where <id> is a unique id generated ++ internally. ++ ++What: /sys/fs/aufs/si_<id>/br0, br1 ... brN ++Date: March 2009 ++Contact: J. R. Okajima <hooanon05@yahoo.co.jp> ++Description: ++ It shows the abolute path of a member directory (which ++ is called branch) in aufs, and its permission. ++ ++What: /sys/fs/aufs/si_<id>/xi_path ++Date: March 2009 ++Contact: J. R. Okajima <hooanon05@yahoo.co.jp> ++Description: ++ It shows the abolute path of XINO (External Inode Number ++ Bitmap, Translation Table and Generation Table) file ++ even if it is the default path. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see ++ Documentation/filesystems/aufs/aufs.5 in detail. +diff -Nur linux-2.6.31.4.orig/fs/aufs/aufs.h linux-2.6.31.4/fs/aufs/aufs.h +--- linux-2.6.31.4.orig/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.31.4/fs/aufs/aufs.h 2009-10-18 11:26:01.000000000 +0200 +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2005-2009 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 ++ */ ++ ++/* ++ * all header files ++ */ ++ ++#ifndef __AUFS_H__ ++#define __AUFS_H__ ++ ++#ifdef __KERNEL__ ++ ++#include "debug.h" ++ ++#include "branch.h" ++#include "cpup.h" ++#include "dcsub.h" ++#include "dbgaufs.h" ++#include "dentry.h" ++#include "dir.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-2.6.31.4.orig/fs/aufs/branch.c linux-2.6.31.4/fs/aufs/branch.c +--- linux-2.6.31.4.orig/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.31.4/fs/aufs/branch.c 2009-10-18 11:26:01.000000000 +0200 +@@ -0,0 +1,974 @@ ++/* ++ * Copyright (C) 2005-2009 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 ++ */ ++ ++/* ++ * branch management ++ */ ++ ++#include <linux/file.h> ++#include "aufs.h" ++ ++/* ++ * free a single branch ++ */ ++static void au_br_do_free(struct au_branch *br) ++{ ++ int i; ++ struct au_wbr *wbr; ++ ++ 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); ++ } ++ ++ /* some filesystems acquire extra lock */ ++ lockdep_off(); ++ mntput(br->br_mnt); ++ 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_d1, ++ struct dentry *h_d2) ++{ ++ if (unlikely(h_d1 == h_d2)) ++ return 1; ++ return !!au_test_subdir(h_d1, h_d2) ++ || !!au_test_subdir(h_d2, h_d1) ++ || au_test_loopback_overlap(sb, h_d1, h_d2) ++ || au_test_loopback_overlap(sb, h_d2, h_d1); ++} ++ ++/* ++ * 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; ++ ++ root = sb->s_root; ++ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS); ++ if (unlikely(!add_branch)) ++ goto out; ++ ++ 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_br; ++ } ++ ++ if (unlikely(au_sbr_realloc(au_sbi(sb), new_nbranch) ++ || au_di_realloc(au_di(root), new_nbranch) ++ || au_ii_realloc(au_ii(root->d_inode), new_nbranch))) ++ goto out_wbr; ++ return add_branch; /* success */ ++ ++ out_wbr: ++ kfree(add_branch->br_wbr); ++ out_br: ++ kfree(add_branch); ++ out: ++ return ERR_PTR(-ENOMEM); ++} ++ ++/* ++ * test if the branch permission is legal or not. ++ */ ++static int test_br(struct inode *inode, int brperm, char *path) ++{ ++ int err; ++ ++ err = 0; ++ if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) { ++ AuErr("write permission for readonly mount or inode, %s\n", ++ path); ++ err = -EINVAL; ++ } ++ ++ 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; ++ AuErr("%s duplicated\n", add->pathname); ++ } ++ goto out; ++ } ++ ++ err = -ENOSPC; /* -E2BIG; */ ++ if (unlikely(AUFS_BRANCH_MAX <= add->bindex ++ || AUFS_BRANCH_MAX - 1 <= bend)) { ++ AuErr("number of branches exceeded %s\n", add->pathname); ++ goto out; ++ } ++ ++ err = -EDOM; ++ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) { ++ AuErr("bad index %d\n", add->bindex); ++ goto out; ++ } ++ ++ inode = add->path.dentry->d_inode; ++ err = -ENOENT; ++ if (unlikely(!inode->i_nlink)) { ++ AuErr("no existence %s\n", add->pathname); ++ goto out; ++ } ++ ++ err = -EINVAL; ++ if (unlikely(inode->i_sb == sb)) { ++ AuErr("%s must be outside\n", add->pathname); ++ goto out; ++ } ++ ++ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) { ++ AuErr("unsupported filesystem, %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)))) { ++ AuErr("%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) ++ || h_inode->i_uid != inode->i_uid ++ || h_inode->i_gid != inode->i_gid) ++ AuWarn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", ++ add->pathname, ++ inode->i_uid, inode->i_gid, ++ (inode->i_mode & S_IALLUGO), ++ h_inode->i_uid, h_inode->i_gid, ++ (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, struct dentry *h_root) ++{ ++ int err, old_perm; ++ aufs_bindex_t bindex; ++ struct mutex *h_mtx; ++ struct au_wbr *wbr; ++ struct au_hinode *hdir; ++ ++ 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_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT); ++ } else { ++ h_mtx = &h_root->d_inode->i_mutex; ++ mutex_lock_nested(h_mtx, AuLsc_I_PARENT); ++ } ++ if (!wbr) ++ err = au_wh_init(h_root, br, sb); ++ else { ++ wbr_wh_write_lock(wbr); ++ err = au_wh_init(h_root, br, sb); ++ wbr_wh_write_unlock(wbr); ++ } ++ if (hdir) ++ au_hin_imtx_unlock(hdir); ++ else ++ mutex_unlock(h_mtx); ++ br->br_perm = old_perm; ++ ++ if (!err && wbr && !au_br_writable(new_perm)) { ++ kfree(wbr); ++ br->br_wbr = NULL; ++ } ++ ++ return err; ++} ++ ++static int au_wbr_init(struct au_branch *br, struct super_block *sb, ++ int perm, struct path *path) ++{ ++ int err; ++ 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; ++ ++ err = au_br_init_wh(sb, br, perm, path->dentry); ++ ++ return err; ++} ++ ++/* intialize 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_mnt = add->path.mnt; /* set first, mntget() later */ ++ atomic_set(&br->br_count, 0); ++ br->br_xino_upper = AUFS_XINO_TRUNC_INIT; ++ atomic_set(&br->br_xino_running, 0); ++ br->br_id = au_new_br_id(sb); ++ ++ if (au_br_writable(add->perm)) { ++ err = au_wbr_init(br, sb, add->perm, &add->path); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ 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; ++ } ++ } ++ ++ sysaufs_br_init(br); ++ mntget(add->path.mnt); ++ ++ 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_hin_init(hip, NULL); ++ iinfo->ii_bend++; ++ if (unlikely(bend < 0)) ++ iinfo->ii_bstart = 0; ++} ++ ++static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry, ++ struct au_branch *br, aufs_bindex_t bindex) ++{ ++ struct dentry *root; ++ struct inode *root_inode; ++ aufs_bindex_t bend, amount; ++ ++ root = sb->s_root; ++ root_inode = root->d_inode; ++ au_plink_block_maintain(sb); ++ bend = au_sbend(sb); ++ amount = bend + 1 - bindex; ++ 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); ++} ++ ++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount) ++{ ++ int err; ++ unsigned long long maxb; ++ 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; ++ h_dentry = add->path.dentry; ++ if (!remount) ++ au_br_do_add(sb, h_dentry, add_branch, add_bindex); ++ else { ++ sysaufs_brs_del(sb, add_bindex); ++ au_br_do_add(sb, h_dentry, add_branch, add_bindex); ++ sysaufs_brs_add(sb, add_bindex); ++ } ++ ++ if (!add_bindex) ++ au_cpup_attr_all(root_inode, /*force*/1); ++ else ++ au_add_nlink(root_inode, h_dentry->d_inode); ++ maxb = h_dentry->d_sb->s_maxbytes; ++ if (sb->s_maxbytes < maxb) ++ sb->s_maxbytes = maxb; ++ ++ /* ++ * this test/set prevents aufs from handling unnecesary inotify events ++ * of xino files, in a 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 |