diff options
author | 2013-05-08 22:24:51 -0400 | |
---|---|---|
committer | 2015-04-29 13:31:44 -0400 | |
commit | 7149888e45e8ef7471ebb1461f3edb568bdd8b94 (patch) | |
tree | 673b63a9a787750f0181e13081ed66120db94087 | |
parent | set DEFAULT_MAKEOPTS to what portage uses (diff) | |
download | genkernel-7149888e45e8ef7471ebb1461f3edb568bdd8b94.tar.gz genkernel-7149888e45e8ef7471ebb1461f3edb568bdd8b94.tar.bz2 genkernel-7149888e45e8ef7471ebb1461f3edb568bdd8b94.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-x | defaults/initrd.defaults | 1 | ||||
-rw-r--r-- | defaults/initrd.scripts | 180 | ||||
-rw-r--r-- | defaults/linuxrc | 194 |
3 files changed, 321 insertions, 54 deletions
diff --git a/defaults/initrd.defaults b/defaults/initrd.defaults index 69be5160..a0176427 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 153c3790..1bae2761 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 6401614f..e2e1b6f5 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}" |