aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Farina (Zero_Chaos) <zerochaos@gentoo.org>2013-05-08 22:24:51 -0400
committerRichard Yao <ryao@gentoo.org>2014-03-17 14:56:32 -0400
commitd0992f5207bb483dde0a8c8f437a1d240422222f (patch)
tree13711b835e34134babb907b8f3cc227358123573
parentBump version to 3.4.49 (diff)
downloadgenkernel-d0992f5207bb483dde0a8c8f437a1d240422222f.tar.gz
genkernel-d0992f5207bb483dde0a8c8f437a1d240422222f.tar.bz2
genkernel-d0992f5207bb483dde0a8c8f437a1d240422222f.zip
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@gentoo.org>
-rwxr-xr-xdefaults/initrd.defaults1
-rw-r--r--defaults/initrd.scripts180
-rw-r--r--defaults/linuxrc190
3 files changed, 319 insertions, 52 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 ed808e4..c8f06d0 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,17 +457,24 @@ 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 "${NEW_ROOT}"/dev/null c 1 3
- [ ! -e "${NEW_ROOT}/dev/console" ] && mknod "${NEW_ROOT}"/dev/console c 5 1
+ 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
+ [ ! -d "${CDROOT_PATH}" ] && mkdir -p "${CDROOT_PATH}"
+ [ ! -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
+ fi
# For SGI LiveCDs ...
if [ "${LOOPTYPE}" = "sgimips" ]
@@ -451,7 +490,7 @@ then
[ ! -e "${NEW_ROOT}/dev/tty1" ] && mknod "${NEW_ROOT}/dev/tty1" c 4 1
fi
- if [ "${REAL_ROOT}" != "/dev/nfs" ] && [ "${LOOPTYPE}" != "sgimips" ]
+ if [ "${REAL_ROOT}" != "/dev/nfs" ] && [ "${LOOPTYPE}" != "sgimips" ] && [ "${USE_AUFS_NORMAL}" != '1' ]
then
bootstrapCD
fi
@@ -763,7 +802,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
@@ -786,56 +841,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}"
@@ -862,6 +921,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
@@ -906,6 +971,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}"