commit: 6df308a1f51e423d7378147610562459538249ec
Author: Rick Farina (Zero_Chaos) <zerochaos <AT> gentoo <DOT> org>
AuthorDate: Thu May 9 02:24:51 2013 +0000
Commit: Richard Farina <zerochaos <AT> gentoo <DOT> org>
CommitDate: Thu May 22 20:03:46 2014 +0000
URL:
http://git.overlays.gentoo.org/gitweb/?p=proj/genkernel.git;a=commit;h=6df308a1
Proper AUFS support
This patch is what we have been using for the Pentoo LiveCDs for about 5
years with the changes suggested by lxnay merged in. As much as
possible has been addressed (with the exception of the man page
documentation). Please review this code as the next version will likely
be suggested for inclusion (once I write the documentation for the new
features).
Signed-off-by: Rick Farina (Zero_Chaos) <zerochaos <AT> gentoo.org>
---
defaults/initrd.defaults | 1 +
defaults/initrd.scripts | 180 +++++++++++++++++++++++++++++++++++++++++++
defaults/linuxrc | 194 ++++++++++++++++++++++++++++++++++-------------
3 files changed, 321 insertions(+), 54 deletions(-)
diff --git a/defaults/initrd.defaults b/defaults/initrd.defaults
index cbf18f3..3d6fe7e 100755
--- a/defaults/initrd.defaults
+++ b/defaults/initrd.defaults
@@ -65,6 +65,7 @@ CDROOT_PATH='/mnt/cdrom'
# This is the file that the cdroot will be checked for as a
# marker. It must exist RELATIVE to the cdroot.
CDROOT_MARKER='/livecd'
+AUFS_CHANGESFILE=livecd.aufs
LOOPS='/livecd.loop /zisofs /livecd.squashfs /image.squashfs /livecd.gcloop'
diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts
index 5ef5d0b..6b31095 100644
--- a/defaults/initrd.scripts
+++ b/defaults/initrd.scripts
@@ -234,6 +234,186 @@ mount_sysfs() {
[ ${ret} -eq 0 ] || bad_msg "Failed to mount /sys!"
}
+# Insert a directory tree ${2} to an union specified by ${1}
+# Top-level read-write branch is specified by it's index 0
+# ${1} = union absolute path (starting with /)
+# ${2} = path to data directory
+#
+union_insert_dir() {
+ # Always mount it over the precedent (add:1:)
+ mount -n -o remount,add:1:${2}=rr aufs ${1}
+ if [ $? = '0' ]
+ then
+ good_msg "Addition of ${2} to ${1} successful"
+ fi
+}
+
+# Insert all modules found in $1, usually ${CDROOT_PATH}
+# added to allow users to add their own apps.
+union_insert_modules() {
+ for module in $(ls ${NEW_ROOT}/${1}/modules/*.mo 2>/dev/null| sort)
+ do
+ mkdir -p ${MEMORY}/modules/$(basename ${module} .mo)
+ union_insert_dir $UNION ${MEMORY}/modules/$(basename ${module}
.mo)
+ done
+ for module in $(ls ${NEW_ROOT}/${1}/modules/*.lzm 2>/dev/null| sort)
+ do
+ mkdir -p ${MEMORY}/modules/$(basename ${module} .lzm)
+ mount -o loop,ro ${module} ${MEMORY}/modules/$(basename
${module} .lzm)
+ union_insert_dir $UNION ${MEMORY}/modules/$(basename ${module}
.lzm)
+ done
+}
+
+# Function to create an ext2 fs on $CHANGESDEV, $CHANGESMNT mountpoint
+create_changefs() {
+ local size
+ while [ 1 ]
+ do
+ read -p '<< Size of file (Enter for default 256 Mb): ' size
+ if [ -z "${size}" ]; then
+ let size=256
+ fi
+ let size="${size}"
+ if [ ${size} -lt 16 ]
+ then
+ bad_msg "Please give a size of at least 16 Mb"
+ else
+ dd if=/dev/zero of=${CHANGESMNT}/${AUFS_CHANGESFILE}
bs=1M count=${size}
+ if [ $? = '0' ]
+ then
+ good_msg "Creation of ${AUFS_CHANGESFILE},
${size} Mb on ${CHANGESDEV} successful, formatting it ext2"
+ mke2fs -F ${CHANGESMNT}/${AUFS_CHANGESFILE}
+ break
+ else
+ rm -f ${CHANGESMNT}/${AUFS_CHANGESFILE}
+ bad_msg "Unable to create ${AUFS_CHANGESFILE}
on ${CHANGESDEV} of ${size} Mb"
+ bad_msg "Please give a size of at least 16 Mb"
+ bad_msg "Also check if your disk is full or
read-only ?"
+ read -p '<< Type "a" to abort, anything else to
continue : ' doabort
+ if [ "${doabort}" = "a" ]; then
+ return 1
+ fi
+ fi
+ fi
+ done
+ return 0
+}
+
+setup_aufs() {
+ if [ "${USE_AUFS_NORMAL}" -eq '1' ]
+ then
+ # Directory used for rw changes in union mount filesystem
+ UNION=/union
+ MEMORY=/memory
+ # Mountpoint for the changesdev
+ CHANGESMNT=${NEW_ROOT}/mnt/changesdev
+ if [ -z "$UID" ]
+ then
+ CHANGES=${MEMORY}/aufs_changes/default
+ else
+ CHANGES=${MEMORY}/aufs_changes/${UID}
+ fi
+
+ mkdir -p ${MEMORY}
+ mkdir -p ${UNION}
+ mkdir -p ${CHANGESMNT}
+ for i in dev mnt ${CDROOT_PATH} mnt/livecd mnt/key tmp
tmp/.initrd mnt/gentoo sys
+ do
+ mkdir -p "${NEW_ROOT}/${i}"
+ chmod 755 "${NEW_ROOT}/${i}"
+ done
+ [ ! -e "${NEW_ROOT}/dev/null" ] && mknod "${NEW_ROOT}"/dev/null
c 1 3
+ [ ! -e "${NEW_ROOT}/dev/console" ] && mknod
"${NEW_ROOT}"/dev/console c 5 1
+
+ bootstrapCD
+ if [ -n "${AUFS}" ]
+ then
+ if [ "${AUFS}" = "detect" ]
+ then
+ CHANGESMNT="${NEW_ROOT}${CDROOT_PATH}"
+ CHANGESDEV=${REAL_ROOT}
+ else
+ CHANGESDEV=${AUFS}
+ good_msg "mounting ${CHANGESDEV} to ${MEMORY}
for aufs support"
+ mount -t auto ${CHANGESDEV} ${CHANGESMNT}
+ ret=$?
+ if [ "${ret}" -ne 0 ]
+ then
+ bad_msg "mount of ${CHANGESDEV} failed,
falling back to ramdisk based aufs"
+ unset AUFS
+ fi
+ fi
+ # Check and attempt to create the changesfile
+ if [ ! -e ${CHANGESMNT}/${AUFS_CHANGESFILE} ] && [ -n
"${AUFS}" ]
+ then
+ create_changefs
+ mount -t auto ${CHANGESMNT}/${AUFS_CHANGESFILE}
${MEMORY}
+ elif [ -n "${AUFS}" ]
+ then
+ local nbpass=0
+ while [ 1 ]
+ do
+ mount -t auto
${CHANGESMNT}/${AUFS_CHANGESFILE} ${MEMORY}
+ ret=$?
+ if [ "${ret}" -ne 0 ]
+ then
+ if [ ${nbpass} -eq 0 ]
+ then
+ bad_msg "mounting of
changes file failed, Running e2fsck"
+ e2fsck
${CHANGESMNT}/${AUFS_CHANGESFILE}
+ nbpass=$((${nbpass} +
1))
+ else
+ bad_msg "mount of
${CHANGESDEV} failed, falling back to ramdisk based aufs"
+ bad_msg "your
${AUFS_CHANGESFILE} might be messed up, and I couldn't fix it"
+ bad_msg "moving
${AUFS_CHANGESFILE} to ${AUFS_CHANGESFILE}.bad"
+ mv
${CHANGESMNT}/${AUFS_CHANGESFILE} ${CHANGESMNT}/${AUFS_CHANGESFILE}.bad
+ bad_msg "try to fix it
yourself with e2fsck later on, sorry for disturbing"
+ break
+ fi
+ else
+ if [ ${nbpass} -eq 1 ]
+ then
+ good_msg "e2fsck ran
successfully. Please check your files after bootup"
+ fi
+ break
+ fi
+ done
+ fi
+ # mount tmpfs only in the case when changes= boot
parameter was
+ # empty or we were not able to mount the storage device
+ if [ "${CDROOT}" -eq '1' -a ! -f
${CHANGESMNT}/${AUFS_CHANGESFILE} ]
+ then
+ umount ${MEMORY}
+ bad_msg "failed to find ${AUFS_CHANGESFILE}
file on ${CHANGESDEV}"
+ bad_msg "create an ext2 ${AUFS_CHANGESFILE}
file on this device if you wish to use it for aufs"
+ bad_msg "falling back to ramdisk based aufs for
safety"
+ mount -t tmpfs tmpfs ${MEMORY}
+ XINO=${MEMORY}
+ else
+ XINO=${MEMORY}/xino
+ mkdir -p ${XINO}
+ mount -t tmpfs tmpfs ${XINO}
+ fi
+ else
+ good_msg "Mounting ramdisk to $MEMORY for aufs
support..."
+ mount -t tmpfs tmpfs ${MEMORY}
+ XINO=${MEMORY}
+ fi
+
+ mkdir -p ${CHANGES}
+ mount -t aufs -n -o
nowarn_perm,udba=none,xino=${XINO}/.aufs.xino,br:${CHANGES}=rw aufs ${UNION}
+ ret=$?
+ if [ "${ret}" -ne 0 ]
+ then
+ bad_msg "Can't setup union ${UNION} in directory!"
+ USE_AUFS_NORMAL=0
+ fi
+ else
+ USE_AUFS_NORMAL=0
+ fi
+}
+
+
findnfsmount() {
if [ "${IP}" != '' ] || busybox udhcpc -n -T 15 -q
then
diff --git a/defaults/linuxrc b/defaults/linuxrc
index 6401614..e2e1b6f 100644
--- a/defaults/linuxrc
+++ b/defaults/linuxrc
@@ -253,6 +253,38 @@ do
aufs)
USE_AUFS_NORMAL=1
;;
+ aufs\=*)
+ USE_AUFS_NORMAL=1
+ CMD_AUFS=$(parse_opt "${x}")
+ echo ${CMD_AUFS}|grep , >/dev/null 2>&1
+ if [ "$?" -eq '0' ]
+ then
+ UID=$(echo ${CMD_AUFS#*,})
+ AUFS=$(echo ${CMD_AUFS%,*})
+ else
+ AUFS=${CMD_AUFS}
+ fi
+ ;;
+ aufs.changes\=*)
+ USE_AUFS_NORMAL=1
+ CMD_AUFS=$(parse_opt "${x}")
+ echo ${CMD_AUFS}|grep , >/dev/null 2>&1
+ if [ "$?" -eq '0' ]
+ then
+ UID=$(echo ${CMD_AUFS#*,})
+ AUFS=$(echo ${CMD_AUFS%,*})
+ else
+ AUFS=${CMD_AUFS}
+ fi
+ ;;
+ aufs.persistent)
+ USE_AUFS_NORMAL=1
+ AUFS="detect"
+ ;;
+ # Allow user to specify the modules location
+ aufs.modules\=*)
+ MODULESD=$(parse_opt "${x}")
+ ;;
unionfs)
if [ ! -x /sbin/unionfs ]
then
@@ -425,19 +457,26 @@ rundebugshell "before setting up the root filesystem"
if [ "${CDROOT}" = '1' ]
then
- good_msg "Making tmpfs for ${NEW_ROOT}"
- mount -n -t tmpfs tmpfs "${NEW_ROOT}"
+ setup_aufs
+ if [ "${USE_AUFS_NORMAL}" -eq '1' ]
+ then
+ CHROOT=${UNION}
+ else
+ CHROOT=${NEW_ROOT}
+ good_msg "Making tmpfs for ${NEW_ROOT}"
+ mount -n -t tmpfs tmpfs ${NEW_ROOT}
- for i in dev mnt proc run sys tmp mnt/livecd mnt/key tmp/.initrd
mnt/gentoo
- do
- mkdir -p "${NEW_ROOT}/${i}"
- chmod 755 "${NEW_ROOT}/${i}"
- done
- [ ! -d "${CDROOT_PATH}" ] && mkdir -p "${CDROOT_PATH}"
- [ ! -e "${NEW_ROOT}/dev/null" ] && mknod -m 660 "${NEW_ROOT}"/dev/null
c 1 3
- [ ! -e "${NEW_ROOT}/dev/zero" ] && mknod -m 660 "${NEW_ROOT}"/dev/zero
c 1 5
- [ ! -e "${NEW_ROOT}/dev/console" ] && mknod -m 660
"${NEW_ROOT}"/dev/console c 5 1
- [ ! -e "${NEW_ROOT}/dev/ttyS0" ] && mknod -m 600
"${NEW_ROOT}"/dev/ttyS0 c 4 64
+ for i in dev mnt ${CDROOT_PATH} proc run mnt/livecd mnt/key tmp
tmp/.initrd mnt/gentoo sys
+ do
+ mkdir -p "${NEW_ROOT}/${i}"
+ chmod 755 "${NEW_ROOT}/${i}"
+ done
+ [ ! -d "${CDROOT_PATH}" ] && mkdir -p "${CDROOT_PATH}"
+ [ ! -e "${NEW_ROOT}/dev/null" ] && mknod -m 666
"${NEW_ROOT}"/dev/null c 1 3
+ [ ! -e "${NEW_ROOT}/dev/zero" ] && mknod -m 666
"${NEW_ROOT}"/dev/zero c 1 5
+ [ ! -e "${NEW_ROOT}/dev/console" ] && mknod -m 600
"${NEW_ROOT}"/dev/console c 5 1
+ [ ! -e "${NEW_ROOT}/dev/ttyS0" ] && mknod -m 660
"${NEW_ROOT}"/dev/ttyS0 c 4 64
+ fi
# For SGI LiveCDs ...
if [ "${LOOPTYPE}" = "sgimips" ]
@@ -452,7 +491,7 @@ then
[ ! -e "${NEW_ROOT}/dev/$minor" ] && mknod -m 600
"${NEW_ROOT}/dev/tty$minor" c 4 $minor
done
- if [ "${REAL_ROOT}" != "/dev/nfs" ] && [ "${LOOPTYPE}" != "sgimips" ]
+ if [ "${REAL_ROOT}" != "/dev/nfs" ] && [ "${LOOPTYPE}" != "sgimips" ]
&& [ "${USE_AUFS_NORMAL}" != '1' ]
then
bootstrapCD
fi
@@ -764,7 +803,23 @@ then
fi
fi
+ if [ "${USE_AUFS_NORMAL}" -eq '1' ]
+ then
+ union_insert_dir ${UNION} ${NEW_ROOT}/${FS_LOCATION}
+ # Make sure fstab notes livecd is mounted ro. Makes system
skip remount which fails on aufs dirs.
+ sed -e 's|\(.*\s/\s*tmpfs\s*\)defaults\(.*\)|\1defaults,ro\2|'
/${UNION}/etc/fstab > /${UNION}/etc/fstab.new
+ mv /${UNION}/etc/fstab.new /${UNION}/etc/fstab
+ warn_msg "Adding all modules in $MODULESD/modules/"
+ if [ -z "${MODULESD}" ]
+ then
+ union_insert_modules ${CDROOT_PATH}
+ else
+ mkdir ${NEW_ROOT}/mnt/modulesd
+ mount "${MODULESD}" ${NEW_ROOT}/mnt/modulesd
+ union_insert_modules ${NEW_ROOT}/mnt/modulesd
+ fi
+ fi
# Unpacking additional packages from NFS mount
# This is useful for adding kernel modules to /lib
@@ -787,56 +842,60 @@ then
then
setup_unionfs ${NEW_ROOT} /${FS_LOCATION}
CHROOT=/union
- elif [ "${USE_AUFS_NORMAL}" != '1' ]; then
-
- good_msg "Copying read-write image contents to tmpfs"
- # Copy over stuff that should be writable
- (cd "${NEW_ROOT}/${FS_LOCATION}"; cp -a ${ROOT_TREES} "${NEW_ROOT}") ||
{
- bad_msg "Copying failed, dropping into a shell."
- do_rundebugshell
- }
-
- # Now we do the links.
- for x in ${ROOT_LINKS}
- do
- if [ -L "${NEW_ROOT}/${FS_LOCATION}/${x}" ]
+ else
+ #XXX Note to potential reviewers. diff formats this section very very
oddly. Be sure to review this hunk after applied, do NOT simply read the diff
+ if [ ! "${USE_AUFS_NORMAL}" -eq '1' ]
then
- ln -s "$(readlink ${NEW_ROOT}/${FS_LOCATION}/${x})"
"${x}" 2>/dev/null
- else
- # List all subdirectories of x
- find "${NEW_ROOT}/${FS_LOCATION}/${x}" -type d
2>/dev/null | while read directory
+ good_msg "Copying read-write image contents to tmpfs"
+ # Copy over stuff that should be writable
+ (cd "${NEW_ROOT}/${FS_LOCATION}"; cp -a ${ROOT_TREES}
"${NEW_ROOT}") || {
+ bad_msg "Copying failed, dropping into a shell."
+ do_rundebugshell
+ }
+
+ # Now we do the links.
+ for x in ${ROOT_LINKS}
do
- # Strip the prefix of the FS_LOCATION
-
directory="${directory#${NEW_ROOT}/${FS_LOCATION}/}"
-
- # Skip this directory if we already linked a
parent directory
- if [ "${current_parent}" != '' ]; then
- var=$(echo "${directory}" | grep
"^${current_parent}")
- if [ "${var}" != '' ]; then
- continue
- fi
- fi
- # Test if the directory exists already
- if [ -e "/${NEW_ROOT}/${directory}" ]
+ if [ -L "${NEW_ROOT}/${FS_LOCATION}/${x}" ]
then
- # It does exist, link all the
individual files
- for file in $(ls
/${NEW_ROOT}/${FS_LOCATION}/${directory})
+ ln -s "$(readlink
${NEW_ROOT}/${FS_LOCATION}/${x})" "${x}" 2>/dev/null
+ else
+ # List all subdirectories of x
+ find "${NEW_ROOT}/${FS_LOCATION}/${x}"
-type d 2>/dev/null | while read directory
do
- if [ ! -d
"/${NEW_ROOT}/${FS_LOCATION}/${directory}/${file}" ] && [ ! -e
"${NEW_ROOT}/${directory}/${file}" ]; then
- ln -s
"/${FS_LOCATION}/${directory}/${file}" "${directory}/${file}" 2> /dev/null
+ # Strip the prefix of the
FS_LOCATION
+
directory="${directory#${NEW_ROOT}/${FS_LOCATION}/}"
+
+ # Skip this directory if we
already linked a parent directory
+ if [ "${current_parent}" != ''
]; then
+ var=$(echo
"${directory}" | grep "^${current_parent}")
+ if [ "${var}" != '' ];
then
+ continue
+ fi
+ fi
+ # Test if the directory exists
already
+ if [ -e
"/${NEW_ROOT}/${directory}" ]
+ then
+ # It does exist, link
all the individual files
+ for file in $(ls
/${NEW_ROOT}/${FS_LOCATION}/${directory})
+ do
+ if [ ! -d
"/${NEW_ROOT}/${FS_LOCATION}/${directory}/${file}" ] && [ ! -e
"${NEW_ROOT}/${directory}/${file}" ]; then
+ ln -s
"/${FS_LOCATION}/${directory}/${file}" "${directory}/${file}" 2> /dev/null
+ fi
+ done
+ else
+ # It does not exist,
make a link to the livecd
+ ln -s
"/${FS_LOCATION}/${directory}" "${directory}" 2>/dev/null
+
current_parent="${directory}"
fi
done
- else
- # It does not exist, make a link to the
livecd
- ln -s "/${FS_LOCATION}/${directory}"
"${directory}" 2>/dev/null
- current_parent="${directory}"
fi
done
- fi
- done
+ mkdir initramfs proc tmp sys 2>/dev/null
+ chmod 1777 tmp
- mkdir initramfs proc tmp sys run 2>/dev/null
- chmod 1777 tmp
+ fi
+ #XXX: end extremely confusing hunk
# have handy /mnt/cdrom (CDROOT_PATH) as well
_new_cdroot="${NEW_ROOT}${CDROOT_PATH}"
@@ -863,6 +922,12 @@ else
setup_unionfs /union_changes ${NEW_ROOT}
mkdir -p ${UNION}/tmp/.initrd
fi
+ if [ "${USE_AUFS_NORMAL}" -eq '1' ]
+ then
+ union_insert_dir ${UNION} ${NEW_ROOT}
+ mkdir -p ${UNION}/tmp/.initrd
+ fi
+
fi
# Mount the additional things as required by udev & systemd
@@ -907,6 +972,27 @@ fi
verbose_kmsg
+if [ "${USE_AUFS_NORMAL}" -eq '1' ]
+then
+ mkdir -p /${CHROOT}/.unions/memory 2>/dev/null
+ mount -o move /memory /${CHROOT}/.unions/memory || echo '*: Failed to
move aufs /memory into the system root!'
+ for i in tmp var/tmp mnt/gentoo mnt/livecd
+ do
+ mkdir -p ${CHROOT}/$i
+ chmod 755 ${CHROOT}/$i
+ done
+ # This will prevent from putting junk on the CHANGESDEV
+ mkdir -p ${CHROOT}/usr/portage/distfiles
+ mount -t tmpfs tmpfs ${CHROOT}/var/tmp
+ mount -t tmpfs tmpfs ${CHROOT}/tmp
+ mount -t tmpfs tmpfs ${CHROOT}/usr/portage/distfiles
+ warn_msg "/tmp /var/tmp /usr/portage/distfiles are mounted in ram"
+ warn_msg "consider saving important files elsewhere..."
+ read -t 3 UNUSEDVAL
+ mount --bind ${NEW_ROOT}${CDROOT_PATH} ${CHROOT}${CDROOT_PATH}
+ mount --bind ${NEW_ROOT}/mnt/livecd ${CHROOT}/mnt/livecd
+fi
+
good_msg "Booting (initramfs)"
cd "${CHROOT}"