X-Git-Url: http://git.grml.org/?a=blobdiff_plain;f=scripts%2Flive;h=584193e223bdec9219d72a91609993b3d055d6a4;hb=6ac1aac5fcd96ce1e986e64884bd8c16a7aa9ea8;hp=7ee3e7f39098eb77e7f5c0b75b1d070bf8310019;hpb=cbdc09bc4b5bfe6c1fe803965e6431c14b018697;p=live-boot-grml.git diff --git a/scripts/live b/scripts/live index 7ee3e7f..584193e 100755 --- a/scripts/live +++ b/scripts/live @@ -51,14 +51,11 @@ Arguments () case "${ARGUMENT}" in skipconfig) NOACCESSIBILITY="Yes" - NOAUTOLOGIN="Yes" - NOCONSOLEKEYBOARD="Yes" NOFASTBOOT="Yes" NOFSTAB="Yes" NONETWORKING="Yes" - NOXAUTOCONFIG="Yes" - export NOACCESSIBILITY NOAUTOLOGIN NOCONSOLEKEYBOARD NOFASTBOOT NOFSTAB NONETWORKING NOXAUTOCONFIG + export NOACCESSIBILITY NOFASTBOOT NOFSTAB NONETWORKING ;; access=*) @@ -71,6 +68,10 @@ Arguments () export DEFCONSOLE ;; + BOOTIF=*) + BOOTIF="${x#BOOTIF=}" + ;; + debug) DEBUG="Yes" export DEBUG @@ -91,12 +92,8 @@ Arguments () ethdevice=*) DEVICE="${ARGUMENT#ethdevice=}" - export DEVICE - ;; - - ethdevice=*) - ETHDEVICE="${ARGUMENT#ethdevice=}" - export ETHDEVICE + ETHDEVICE="${DEVICE}" + export DEVICE ETHDEVICE ;; ethdevice-timeout=*) @@ -105,9 +102,9 @@ Arguments () ;; fetch=*) - FETCH="${ARGUMENT#fetch=}" - export FETCH - ;; + FETCH="${ARGUMENT#fetch=}" + export FETCH + ;; forcepersistentfsck) FORCEPERSISTENTFSCK="Yes" @@ -124,6 +121,19 @@ Arguments () export HTTPFS ;; + iscsi=*) + ISCSI="${ARGUMENT#iscsi=}" + #ip:port - separated by ; + ISCSI_PORTAL="${ISCSI%;*}" + if echo "${ISCSI_PORTAL}" | grep -q , ; then + ISCSI_SERVER="${ISCSI_PORTAL%,*}" + ISCSI_PORT="${ISCSI_PORTAL#*,}" + fi + #target name + ISCSI_TARGET="${ISCSI#*;}" + export ISCSI ISCSI_PORTAL ISCSI_TARGET ISCSI_SERVER ISCSI_PORT + ;; + isofrom=*|fromiso=*) FROMISO="${ARGUMENT#*=}" export FROMISO @@ -205,11 +215,6 @@ Arguments () export NOACCESSIBILITY ;; - noautologin) - NOAUTOLOGIN="Yes" - export NOAUTOLOGIN - ;; - nofastboot) NOFASTBOOT="Yes" export NOFASTBOOT @@ -225,34 +230,47 @@ Arguments () export NONETWORKING ;; + ramdisk-size=*) + ramdisk_size="${ARGUMENT#ramdisk-size=}" + ;; + swapon) SWAPON="Yes" export SWAPON ;; - noxautoconfig) - NOXAUTOCONFIG="Yes" - export NOXAUTOCONFIG - ;; - persistent) PERSISTENT="Yes" export PERSISTENT ;; - persistent=*) - PERSISTENT="${ARGUMENT#persistent=}" - if [ -z "${PERSISTENT}" ] - then - PERSISTENT="Yes" - fi - export PERSISTENT + persistent-encryption=*) + PERSISTENT_ENCRYPTION="${ARGUMENT#*=}" + export PERSISTENT_ENCRYPTION + ;; + + persistent-media=*) + PERSISTENT_MEDIA="${ARGUMENT#*=}" + export PERSISTENT_MEDIA + ;; + persistent-method=*) + PERSISTENT_METHOD="${ARGUMENT#*=}" + export PERSISTENT_METHOD ;; persistent-path=*) PERSISTENT_PATH="${ARGUMENT#persistent-path=}" export PERSISTENT_PATH ;; + persistent-read-only) + PERSISTENT_READONLY="Yes" + export PERSISTENT_READONLY + ;; + + persistent-storage=*) + PERSISTENT_STORAGE="${ARGUMENT#persistent-storage=}" + export PERSISTENT_STORAGE + ;; persistent-subtext=*) root_persistence="${root_persistence}-${ARGUMENT#persistent-subtext=}" @@ -266,6 +284,16 @@ Arguments () export NOPERSISTENT ;; + noprompt) + NOPROMPT="Yes" + export NOPROMPT + ;; + + noprompt=*) + NOPROMPT="${ARGUMENT#noprompt=}" + export NOPROMPT + ;; + quickusbmodules) QUICKUSBMODULES="Yes" export QUICKUSBMODULES @@ -325,9 +353,9 @@ Arguments () ;; skipunion) - SKIP_UNION_MOUNTS="Yes" - export SKIP_UNION_MOUNTS - ;; + SKIP_UNION_MOUNTS="Yes" + export SKIP_UNION_MOUNTS + ;; root=*) ROOT="${ARGUMENT#root=}" @@ -338,21 +366,6 @@ Arguments () UNIONTYPE="${ARGUMENT#union=}" export UNIONTYPE ;; - - xdebconf) - XDEBCONF="Yes" - export XDEBCONF - ;; - - xdriver=*) - XDRIVER="${ARGUMENT#xdriver=}" - export XDRIVER - ;; - - xvideomode=*) - XVIDEOMODE="${ARGUMENT#xvideomode=}" - export XVIDEOMODE - ;; esac done @@ -381,6 +394,39 @@ Arguments () UNIONTYPE="aufs" export UNIONTYPE fi + + if [ -z "${PERSISTENT_ENCRYPTION}" ] + then + PERSISTENT_ENCRYPTION="none" + export PERSISTENT_ENCRYPTION + elif echo ${PERSISTENT_ENCRYPTION} | grep -qe "\" + then + if ! modprobe dm-crypt + then + log_warning_msg "Unable to load module dm-crypt" + PERSISTENT_ENCRYPTION=$(echo ${PERSISTENT_ENCRYPTION} | sed -e 's/\= 174) + PATH_ID="/sbin/udevadm test-builtin path_id" + fi + + if ${PATH_ID} "${sysfs_path}" | egrep -q "ID_PATH=(usb|pci-[^-]*-(ide|sas|scsi|usb|virtio)|platform-sata_mv|platform-orion-ehci|platform-mmc|platform-mxsdhci)" then return 0 elif echo "${sysfs_path}" | grep -q '^/block/vd[a-z]$' @@ -490,6 +545,9 @@ is_nice_device () elif echo ${sysfs_path} | grep -q "^/block/dm-" then return 0 + elif echo ${sysfs_path} | grep -q "^/block/mtdblock" + then + return 0 fi return 1 @@ -544,6 +602,13 @@ copy_live_to () return 1 fi + # Custom ramdisk size + if [ -z "${mount_options}" ] && [ -n "${ramdisk_size}" ] + then + # FIXME: should check for wrong values + mount_options="-o size=${ramdisk_size}" + fi + # begin copying (or uncompressing) mkdir "${copyto}" log_begin_msg "mount -t ${fstype} ${mount_options} ${dev} ${copyto}" @@ -589,17 +654,68 @@ copy_live_to () return 0 } -do_netmount () +do_netsetup () { modprobe -q af_packet # For DHCP udevadm trigger udevadm settle + [ -n "$ETHDEV_TIMEOUT" ] || ETHDEV_TIMEOUT=15 + echo "Using timeout of $ETHDEV_TIMEOUT seconds for network configuration." + if [ -z "${NETBOOT}" ] && [ -z "${FETCH}" ] && \ [ -z "${HTTPFS}" ] && [ -z "${FTPFS}" ] then + + # support for Syslinux IPAPPEND parameter + # it sets the BOOTIF variable on the kernel parameter + + if [ -n "${BOOTIF}" ] + then + # pxelinux sets BOOTIF to a value based on the mac address of the + # network card used to PXE boot, so use this value for DEVICE rather + # than a hard-coded device name from initramfs.conf. this facilitates + # network booting when machines may have multiple network cards. + # pxelinux sets BOOTIF to 01-$mac_address + + # strip off the leading "01-", which isn't part of the mac + # address + temp_mac=${BOOTIF#*-} + + # convert to typical mac address format by replacing "-" with ":" + bootif_mac="" + IFS='-' + for x in $temp_mac + do + if [ -z "$bootif_mac" ] + then + bootif_mac="$x" + else + bootif_mac="$bootif_mac:$x" + fi + done + unset IFS + + # look for devices with matching mac address, and set DEVICE to + # appropriate value if match is found. + + for device in /sys/class/net/* + do + if [ -f "$device/address" ] + then + current_mac=$(cat "$device/address") + + if [ "$bootif_mac" = "$current_mac" ] + then + DEVICE=${device##*/} + break + fi + fi + done + fi + # if ethdevice was not specified on the kernel command line # make sure we try to get a working network configuration # for *every* present network device (except for loopback of course) @@ -618,9 +734,6 @@ do_netmount () devlist="$devlist $device" done - [ -n "$ETHDEV_TIMEOUT" ] || ETHDEV_TIMEOUT=15 - echo "Using timeout of $ETHDEV_TIMEOUT seconds for network configuration." - # this is tricky (and ugly) because ipconfig sometimes just hangs/runs into # an endless loop; iff execution fails give it two further tries, that's # why we use '$devlist $devlist $devlist' for the other for loop @@ -644,24 +757,62 @@ do_netmount () done else - ipconfig ${DEVICE} | tee /netboot.config + for interface in ${DEVICE}; do + ipconfig -t "$ETHDEV_TIMEOUT" ${interface} | tee /netboot-${interface}.config + [ -e /tmp/net-${interface}.conf ] && . /tmp/net-${interface}.conf + if [ "$IPV4ADDR" != "0.0.0.0" ] + then + break + fi + done fi - # source relevant ipconfig output - OLDHOSTNAME=${HOSTNAME} - . /tmp/net-${DEVICE}.conf - [ -z ${HOSTNAME} ] && HOSTNAME=${OLDHOSTNAME} - export HOSTNAME + for interface in ${DEVICE}; do + # source relevant ipconfig output + OLDHOSTNAME=${HOSTNAME} + [ -e /tmp/net-${interface}.conf ] && . /tmp/net-${interface}.conf + [ -z ${HOSTNAME} ] && HOSTNAME=${OLDHOSTNAME} + export HOSTNAME - # Check if we have a network device at all - if ! ls /sys/class/net/"$DEVICE" > /dev/null 2>&1 && \ - ! ls /sys/class/net/eth0 > /dev/null 2>&1 && \ - ! ls /sys/class/net/wlan0 > /dev/null 2>&1 && \ - ! ls /sys/class/net/ath0 > /dev/null 2>&1 && \ - ! ls /sys/class/net/ra0 > /dev/null 2>&1 - then - panic "No supported network device found, maybe a non-mainline driver is required." - fi + if [ -n "${interface}" ] + then + HWADDR="$(cat /sys/class/net/${interface}/address)" + fi + + if [ ! -e "/etc/resolv.conf" ] + then + echo "Creating /etc/resolv.conf" + + if [ -n "${DNSDOMAIN}" ] + then + echo "domain ${DNSDOMAIN}" > /etc/resolv.conf + echo "search ${DNSDOMAIN}" >> /etc/resolv.conf + fi + + for i in ${IPV4DNS0} ${IPV4DNS1} ${IPV4DNS1} + do + if [ -n "$i" ] && [ "$i" != 0.0.0.0 ] + then + echo "nameserver $i" >> /etc/resolv.conf + fi + done + fi + + # Check if we have a network device at all + if ! ls /sys/class/net/"$interface" > /dev/null 2>&1 && \ + ! ls /sys/class/net/eth0 > /dev/null 2>&1 && \ + ! ls /sys/class/net/wlan0 > /dev/null 2>&1 && \ + ! ls /sys/class/net/ath0 > /dev/null 2>&1 && \ + ! ls /sys/class/net/ra0 > /dev/null 2>&1 + then + panic "No supported network device found, maybe a non-mainline driver is required." + fi + done +} + +do_netmount() +{ + do_netsetup if [ "${NFSROOT}" = "auto" ] then @@ -697,6 +848,54 @@ do_netmount () return ${rc} } +do_iscsi() +{ + do_netsetup + #modprobe ib_iser + modprobe iscsi_tcp + local debugopt="" + [ "${DEBUG}" == "Yes" ] && debugopt="-d 8" + #FIXME this name is supposed to be unique - some date + ifconfig hash? + ISCSI_INITIATORNAME="iqn.1993-08.org.debian.live:01:$(echo "${HWADDR}" | sed -e s/://g)" + export ISCSI_INITIATORNAME + if [ -n "${ISCSI_SERVER}" ] ; then + iscsistart $debugopt -i "${ISCSI_INITIATORNAME}" -t "${ISCSI_TARGET}" -g 1 -a "${ISCSI_SERVER}" -p "${ISCSI_PORT}" + else + iscsistart $debugopt -i "${ISCSI_INITIATORNAME}" -t "${ISCSI_TARGET}" -g 1 -a "${ISCSI_PORTAL}" -p 3260 + fi + if [ $? != 0 ] + then + panic "Failed to log into iscsi target" + fi + local host="$(ls -d /sys/class/scsi_host/host*/device/iscsi_host:host* \ + /sys/class/scsi_host/host*/device/iscsi_host/host* | sed -e 's:/device.*::' -e 's:.*host::')" + if [ -n "${host}" ] + then + local devices="" + local i=0 + while [ -z "${devices}" -a $i -lt 60 ] + do + sleep 1 + devices="$(ls -d /sys/class/scsi_device/${host}*/device/block:* \ + /sys/class/scsi_device/${host}*/device/block/* | sed -e 's!.*[:/]!!')" + i=$(expr $i + 1) + echo -ne $i\\r + done + for dev in $devices + do + if check_dev "null" "/dev/$dev" + then + NETBOOT="iscsi" + export NETBOOT + return 0; + fi + done + panic "Failed to locate a live device on iSCSI devices (tried: $devices)." + else + panic "Failed to locate iSCSI host in /sys" + fi +} + do_httpmount () { rc=1 @@ -746,7 +945,7 @@ do_httpmount () fi modprobe fuse $FUSE_MOUNT "${url}" "${dest}" - FUSE_PID="$(minips h -C "$FUSE_MOUNT" | { read x y ; echo "$x" ; } )" + ROOT_PID="$(minips h -C "$FUSE_MOUNT" | { read x y ; echo "$x" ; } )" fi [ ${?} -eq 0 ] && rc=0 [ "${extension}" = "tgz" ] && live_dest="ram" @@ -777,9 +976,6 @@ do_httpmount () elif [ "${webfile}" != "FETCH" ] ; then NETBOOT="${webfile}" export NETBOOT - if [ -n "${FUSE_PID}" ] ; then - echo "${FUSE_PID}" > ${mountpoint}/root.pid - fi fi return ${rc} @@ -844,6 +1040,8 @@ do_snap_copy () if [ -b "${fromdev}" ] then + log_success_msg "Copying snapshot ${fromdev} to ${todir}..." + # look for free mem if [ -n "${HOMEMOUNTED}" -a "${snap_type}" = "HOME" ] then @@ -881,38 +1079,29 @@ do_snap_copy () return 0 else - return 1 - log_warning_msg "Unable to find the snapshot ${snap_type} medium" + return 1 fi } -find_snap () -{ - # Look for ${snap_label}.* in block devices - snap_label="${1}" - - if [ "${PERSISTENT}" != "nofiles" ] - then - # search for image files - snapdata=$(find_files "${PERSISTENT_PATH}${snap_label}.squashfs ${PERSISTENT_PATH}${snap_label}.cpio.gz ${PERSISTENT_PATH}${snap_label}.ext2 ${PERSISTENT_PATH}${snap_label}.ext3 ${PERSISTENT_PATH}${snap_label}.ext4 ${PERSISTENT_PATH}${snap_label}.jffs2") - fi - - if [ -z "${snapdata}" ] - then - snapdata=$(find_cow_device "${snap_label}") - fi - echo "${snapdata}" -} - try_snap () { - # copy the contents of previously found snapshot to ${snap_mount} + # copy the contents of previously found snapshot to ${snap_mount} # and remember the device and filename for resync on exit in live-boot.init snapdata="${1}" snap_mount="${2}" snap_type="${3}" + snap_relpath="${4}" + + if [ -z "${snap_relpath}" ] + then + # root snapshot, default usage + snap_relpath="/" + else + # relative snapshot (actually used just for "/home" snapshots) + snap_mount="${2}${snap_relpath}" + fi if [ -n "${snapdata}" ] && [ ! -b "${snapdata}" ] then @@ -921,19 +1110,20 @@ try_snap () snapback="$(echo ${snapdata} | cut -f2 -d ' ')" snapfile="$(echo ${snapdata} | cut -f3 -d ' ')" - RES="" if ! try_mount "${snapdev}" "${snapback}" "ro" then break fi + RES="0" + if echo "${snapfile}" | grep -qs '\(squashfs\|ext2\|ext3\|ext4\|jffs2\)' then # squashfs, jffs2 or ext2/ext3/ext4 snapshot dev=$(get_backing_device "${snapback}/${snapfile}") do_snap_copy "${dev}" "${snap_mount}" "${snap_type}" - RES=$? + RES="$?" else # cpio.gz snapshot @@ -949,9 +1139,20 @@ try_snap () cpioargs='--unconditional --make-directories' fi - if ! (cd "${snap_mount}" && zcat "${snapback}/${snapfile}" | cpio $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse 2>/dev/null) + if [ -s "${snapback}/${snapfile}" ] + then + BEFOREDIR="$(pwd)" + cd "${snap_mount}" && zcat "${snapback}/${snapfile}" | $cpiopath $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse 2>/dev/null + RES="$?" + cd "${BEFOREDIR}" + else + log_warning_msg "${snapback}/${snapfile} is empty, adding it for sync on reboot." + RES="0" + fi + + if [ "${RES}" != "0" ] then - log_warning_msg "failure to \"zcat ${snapback}/${snapfile} | cpio $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse\"" + log_warning_msg "failure to \"zcat ${snapback}/${snapfile} | $cpiopath $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse\"" fi fi @@ -979,7 +1180,7 @@ try_snap () if ! do_snap_copy "${dev}" "${snap_mount}" "${snap_type}" then - log_warning_msg "Impossible to include the ${snap_type} Snapshot" + log_warning_msg "Impossible to include the ${snap_type} Snapshot (i)" return 1 else if [ -n "${snapfile}" ] @@ -989,11 +1190,14 @@ try_snap () fi fi else - log_warning_msg "Impossible to include the ${snap_type} Snapshot" + log_warning_msg "Impossible to include the ${snap_type} Snapshot (o)" return 1 fi - echo "export ${snap_type}SNAP="/cow${snap_mount#$rootmnt}":${snapdev}:${snapfile}" >> /etc/live.conf # for resync on reboot/halt + if [ -z ${PERSISTENT_READONLY} ] + then + echo "export ${snap_type}SNAP=${snap_relpath}:${snapdev}:${snapfile}" >> snapshot.conf # for resync on reboot/halt + fi return 0 } @@ -1001,7 +1205,7 @@ setup_unionfs () { image_directory="${1}" rootmnt="${2}" - addimage_directory="${3}" + addimage_directory="${3}" case ${UNIONTYPE} in aufs|unionfs) @@ -1030,12 +1234,11 @@ setup_unionfs () croot="/" # Let's just mount the read-only file systems first - rofsstring="" rofslist="" if [ "${UNIONTYPE}" = "aufs" ] then - roopt="rr" + roopt="rr+wh" noxino_opt="noxino," elif [ "${UNIONTYPE}" = "unionfs-fuse" ] then @@ -1090,7 +1293,7 @@ setup_unionfs () image_string="$(echo ${image_string} | sed -e 's/ /\n/g' | sort )" fi - [ -n "${MODULETORAMFILE}" ] && image_string="${image_directory}/$(basename ${MODULETORAMFILE})" + [ -n "${MODULETORAMFILE}" ] && image_string="${image_directory}/$(basename ${MODULETORAMFILE})" mkdir -p "${croot}" @@ -1107,7 +1310,6 @@ setup_unionfs () if [ -d "${image}" ] then # it is a plain directory: do nothing - rofsstring="${image}=${roopt}:${rofsstring}" rofslist="${image} ${rofslist}" elif [ -f "${image}" ] then @@ -1130,9 +1332,17 @@ setup_unionfs () log_warning_msg "Unknown file system type on ${backdev} (${image}), assuming ${fstype}." fi - mkdir -p "${croot}/${imagename}" - log_begin_msg "Mounting \"${image}\" on \"${croot}${imagename}\" via \"${backdev}\"" - mount -t "${fstype}" -o ro,noatime "${backdev}" "${croot}/${imagename}" || panic "Can not mount ${backdev} (${image}) on ${croot}/${imagename}" && rofsstring="${croot}/${imagename}=${roopt}:${rofsstring}" && rofslist="${croot}/${imagename} ${rofslist}" + if [ "${UNIONTYPE}" != "unionmount" ] + then + mpoint="${croot}/${imagename}" + rofslist="${mpoint} ${rofslist}" + else + mpoint="${rootmnt}" + rofslist="${rootmnt} ${rofslist}" + fi + mkdir -p "${mpoint}" + log_begin_msg "Mounting \"${image}\" on \"${mpoint}\" via \"${backdev}\"" + mount -t "${fstype}" -o ro,noatime "${backdev}" "${mpoint}" || panic "Can not mount ${backdev} (${image}) on ${mpoint}" log_end_msg fi done @@ -1140,19 +1350,20 @@ setup_unionfs () # we have a plain root system mkdir -p "${croot}/filesystem" log_begin_msg "Mounting \"${image_directory}\" on \"${croot}/filesystem\"" - mount -t $(get_fstype "${image_directory}") -o ro,noatime "${image_directory}" "${croot}/filesystem" || panic "Can not mount ${image_directory} on ${croot}/filesystem" && rofsstring="${croot}/filesystem=${roopt}:${rofsstring}" && rofslist="${croot}/filesystem ${rofslist}" + mount -t $(get_fstype "${image_directory}") -o ro,noatime "${image_directory}" "${croot}/filesystem" || \ + panic "Can not mount ${image_directory} on ${croot}/filesystem" && \ + rofslist="${croot}/filesystem ${rofslist}" # probably broken: mount -o bind ${croot}/filesystem $mountpoint log_end_msg fi - rofsstring=${rofsstring%:} - mkdir -p /cow # Looking for "${root_persistence}" device or file if [ -n "${PERSISTENT}" ] && [ -z "${NOPERSISTENT}" ] then + if [ -z "${QUICKUSBMODULES}" ] then # Load USB modules @@ -1180,46 +1391,74 @@ setup_unionfs () done fi - # search for label and files (this could be hugely optimized) - cowprobe=$(find_cow_device "${root_persistence}") - if [ -b "${cowprobe}" ] + case "${PERSISTENT_MEDIA}" in + removable) + whitelistdev="$(removable_dev)" + ;; + removable-usb) + whitelistdev="$(removable_usb_dev)" + ;; + *) + whitelistdev="" + ;; + esac + + if echo ${PERSISTENT_METHOD} | grep -qe "\" then - # Blacklist /cow device, to avoid inconsistent setups for overlapping snapshots - # makes sense to have both persistence for /cow and /home mounted, maybe also with - # snapshots to be sure to really store some e.g key config files, - # but not on the same media - blacklistdev="${cowprobe}" - PERSISTENCE_IS_ON="1" - export PERSISTENCE_IS_ON + overlays="${root_persistence} ${home_persistence}" fi - # homecow just mount something on /home, this should be generalized some way - homecow=$(find_cow_device "${home_persistence}" "${blacklistdev}") - if [ -b "${homecow}" ] + + if echo ${PERSISTENT_METHOD} | grep -qe "\" + then + snapshots="${root_snapshot_label} ${home_snapshot_label}" + fi + + + for media in $(find_persistent_media "${overlays}" "${snapshots}" "${blacklistdev}" "${whitelistdev}") + do + media="$(echo ${media} | tr ":" " ")" + case ${media} in + ${root_persistence}=*) + cowprobe="${media#*=}" + ;; + ${home_persistence}=*) + homecow="${media#*=}" + ;; + ${root_snapshot_label}=*) + root_snapdata="${media#*=}" + ;; + ${home_snapshot_label}=*) + # This second type should be removed when snapshot will get smarter, + # hence when "/etc/live-snapshot*list" will be supported also by + # ext2|ext3|ext4|jffs2 snapshot types. + home_snapdata="${media#*=}" + ;; + *) + ;; + esac + done + + if [ -b "${cowprobe}" ] || [ -b "${homecow}" ] then PERSISTENCE_IS_ON="1" export PERSISTENCE_IS_ON fi - root_snapdata=$(find_snap "${root_snapshot_label}" "${blacklistdev}") - # This second type should be removed when snapshot will get smarter, - # hence when "/etc/live-snapshot*list" will be supported also by - # ext2|ext3|ext4|jffs2 snapshot types. - home_snapdata=$(find_snap "${home_snapshot_label}" "${blacklistdev}") if [ -b "${cowprobe}" ] then cowdevice=${cowprobe} cow_fstype=$(get_fstype "${cowprobe}") - cow_mountopt="rw,noatime" + if [ -z "${PERSISTENT_READONLY}" ] + then + cow_mountopt="rw,noatime" + else + cow_mountopt="ro,noatime" + fi if [ "${FORCEPERSISTENTFSCK}" = "Yes" ] then fsck -y ${cowdevice} fi - else - log_warning_msg "Unable to find the persistent medium" - cowdevice="tmpfs" - cow_fstype="tmpfs" - cow_mountopt="rw,noatime,mode=755" fi elif [ -n "${NFS_COW}" ] && [ -z "${NOPERSISTENT}" ] then @@ -1232,6 +1471,12 @@ setup_unionfs () nfs_cow_opts="-o nolock" nfs_cow=${NFS_COW} fi + + if [ -n "${PERSISTENT_READONLY}" ] + then + nfs_cow_opts="${nfs_cow_opts},nocto,ro" + fi + mac="$(get_mac)" if [ -n "${mac}" ] then @@ -1240,35 +1485,49 @@ setup_unionfs () else panic "unable to determine mac address" fi - else + fi + + if [ -z "${cowdevice}" ] + then cowdevice="tmpfs" cow_fstype="tmpfs" cow_mountopt="rw,noatime,mode=755" fi - if [ "${cow_fstype}" = "nfs" ] + if [ "${UNIONTYPE}" != "unionmount" ] then - log_begin_msg \ - "Trying nfsmount ${nfs_cow_opts} ${cowdevice} /cow" - nfsmount ${nfs_cow_opts} ${cowdevice} /cow || \ - panic "Can not mount ${cowdevice} (n: ${cow_fstype}) on /cow" - else - mount -t ${cow_fstype} -o ${cow_mountopt} ${cowdevice} /cow || \ - panic "Can not mount ${cowdevice} (o: ${cow_fstype}) on /cow" + if [ -n "${PERSISTENT_READONLY}" ] + then + persistent_root="/$(basename ${cowdevice})-backing" + mkdir -p ${persistent_root} + else + persistent_root="/cow" + fi + + if [ "${cow_fstype}" = "nfs" ] + then + log_begin_msg \ + "Trying nfsmount ${nfs_cow_opts} ${cowdevice} ${persistent_root}" + nfsmount ${nfs_cow_opts} ${cowdevice} ${persistent_root} || \ + panic "Can not mount ${cowdevice} (n: ${cow_fstype}) on ${persistent_root}" + else + mount -t ${cow_fstype} -o ${cow_mountopt} ${cowdevice} ${persistent_root} || \ + panic "Can not mount ${cowdevice} (o: ${cow_fstype}) on ${persistent_root}" + fi fi rofscount=$(echo ${rofslist} |wc -w) - if [ -n "${EXPOSED_ROOT}" ] + if [ ${rofscount} -ne 1 ] then - if [ ${rofscount} -ne 1 ] - then - panic "only one RO file system supported with exposedroot: ${rofslist}" - fi - exposedrootfs=${rofslist%% } + panic "only one RO file system supported with exposedroot: ${rofslist}" + fi + rofs=${rofslist%% } - mount --bind ${exposedrootfs} ${rootmnt} || \ - panic "bind mount of ${exposedrootfs} failed" + if [ -n "${EXPOSED_ROOT}" ] + then + mount --bind ${rofs} ${rootmnt} || \ + panic "bind mount of ${rofs} failed" if [ -z "${SKIP_UNION_MOUNTS}" ] then @@ -1276,35 +1535,55 @@ setup_unionfs () else cow_dirs='' fi + else + cow_dirs="/" + fi - for dir in ${cow_dirs}; do - mkdir -p /cow${dir} + if [ "${cow_fstype}" != "tmpfs" ] && [ "${cow_dirs}" != "/" ] && [ "${UNIONTYPE}" = "unionmount" ] + then + true # FIXME: Maybe it does, I don't really know. + #panic "unionmount does not support subunions (${cow_dirs})." + fi - case "${UNIONTYPE}" in - unionfs-fuse) - (ulimit -n 16384; unionfs-fuse -o cow -o noinitgroups -o default_permissions -o allow_other -o use_ino -o suid /cow=RW:${exposedrootfs}${dir} "${rootmnt}${dir}" || panic "mount ${UNIONTYPE} on ${rootmnt}${dir} failed with option cow,noinitgroups,default_permissions,allow_other,use_ino,suid=/cow=RW:${exposedrootfs}${dir}") - mkdir -p /dev/.initramfs/varrun - pidof unionfs-fuse >> /dev/.initramfs/varrun/sendsigs.omit || true - ;; + unionmountopts="" + unionmountpoint="" - *) - mount -t ${UNIONTYPE} -o rw,noatime,dirs=/cow${dir}=rw:${exposedrootfs}${dir}=ro ${UNIONTYPE} "${rootmnt}${dir}" || panic "mount ${UNIONTYPE} on ${rootmnt}${dir} failed with option rw,noatime,dirs=/cow${dir}=rw:${exposedrootfs}${dir}=ro" - ;; - esac - done - else + for dir in ${cow_dirs}; do + mkdir -p /cow${dir} + + unionmountpoint="${rootmnt}${dir}" + unionrw="/cow${dir}" + unionro="${rofs}${dir}" + # We don't handle spaces and other junk gracefully here, hopefully not needed. case "${UNIONTYPE}" in unionfs-fuse) - (ulimit -n 16384; unionfs-fuse -o cow -o noinitgroups -o default_permissions -o allow_other -o use_ino -o suid /cow=RW:${rofsstring} "${rootmnt}" || panic "mount ${UNIONTYPE} on ${rootmnt} failed with option cow,noinitgroups,default_permissions,allow_other,use_ino,suid=/cow:RW:${rofsstring}") - mkdir -p /dev/.initramfs/varrun - pidof unionfs-fuse >> /dev/.initramfs/varrun/sendsigs.omit || true + unionmountopts="-o cow -o noinitgroups -o default_permissions -o allow_other -o use_ino -o suid" + unionmountopts="${unionmountopts} ${unionrw}=RW:${unionro}=RO" + ( sysctl -w fs.file-max=391524 ; ulimit -HSn 16384 + unionfs-fuse ${unionmountopts} "${unionmountpoint}" ) && \ + ( mkdir -p /run/sendsigs.omit.d + pidof unionfs-fuse >> /run/sendsigs.omit.d/unionfs-fuse || true ) + ;; + + unionmount) + unionmountopts="-t ${cow_fstype} -o noatime,union,${cow_mountopt} ${cowdevice}" + mount_full $unionmountopts "${unionmountpoint}" ;; + *) - mount -t ${UNIONTYPE} -o noatime,${noxino_opt}dirs=/cow=rw:${rofsstring} ${UNIONTYPE} "${rootmnt}" || panic "mount ${UNIONTYPE} on ${rootmnt} failed with option noatime,${noxino_opt}dirs=/cow=rw:${rofsstring}" + if [ -n "${PERSISTENT_READONLY}" ] + then + mount -t tmpfs -o rw,noatime,mode=755 tmpfs "${unionrw}" + unionmountopts="-o noatime,${noxino_opt}dirs=${unionrw}=rw:${persistent_root}=${roopt}:${unionro}=${roopt}" + else + unionmountopts="-o noatime,${noxino_opt}dirs=${unionrw}=rw:${unionro}=${roopt}" + fi + mount -t ${UNIONTYPE} ${unionmountopts} ${UNIONTYPE} "${unionmountpoint}" ;; - esac - fi + esac || \ + panic "mount ${UNIONTYPE} on ${unionmountpoint} failed with option ${unionmountopts}" + done # Correct the permissions of /: chmod 0755 "${rootmnt}" @@ -1322,7 +1601,17 @@ setup_unionfs () if [ -b "${homecow}" ] then - mount -t $(get_fstype "${homecow}") -o rw,noatime "${homecow}" "${rootmnt}/home" + if [ -z "${PERSISTENT_READONLY}" ] + then + mount -t $(get_fstype "${homecow}") -o rw,noatime "${homecow}" "${rootmnt}/home" + else + homerw="/cow/home" + homero="/$(basename ${homecow})-backing" + homemountpoint="${rootmnt}/home" + mkdir -p ${homerw} ${homero} ${homemountpoint} + mount -t $(get_fstype "${homecow}") -o ro "${homecow}" "${homero}" + mount -t "${UNIONTYPE}" -o "noatime,${noxino_opt}dirs=${homerw}=rw:${homero}=${roopt}" "${UNIONTYPE}" "${homemountpoint}" + fi export HOMEMOUNTED=1 # used to proper calculate free space in do_snap_copy() else log_warning_msg "Unable to find the persistent home medium" @@ -1331,7 +1620,7 @@ setup_unionfs () # Look for other snapshots to copy in try_snap "${root_snapdata}" "${rootmnt}" "ROOT" # This second type should be removed when snapshot grow smarter - try_snap "${home_snapdata}" "${rootmnt}/home" "HOME" + try_snap "${home_snapdata}" "${rootmnt}" "HOME" "/home" fi if [ -n "${SHOWMOUNTS}" ] @@ -1391,13 +1680,19 @@ check_dev () if [ "$ISO_DEVICE" = "/" ] then - echo "Warning: device for bootoption isofrom= ($FROMISO) not found.">>/live.log + echo "Warning: device for bootoption isofrom= ($FROMISO) not found.">>/live-boot.log else - mkdir /isofrom - mount "$ISO_DEVICE" /isofrom - ISO_NAME="$(echo $FROMISO | sed "s|$ISO_DEVICE||")" - loopdevname=$(setup_loop "/isofrom/${ISO_NAME}" "loop" "/sys/block/loop*" "" '') - devname="${loopdevname}" + fs_type=$(get_fstype "${ISO_DEVICE}") + if is_supported_fs ${fs_type} + then + mkdir /isofrom + mount -t $fs_type "$ISO_DEVICE" /isofrom + ISO_NAME="$(echo $FROMISO | sed "s|$ISO_DEVICE||")" + loopdevname=$(setup_loop "/isofrom/${ISO_NAME}" "loop" "/sys/block/loop*" "" '') + devname="${loopdevname}" + else + echo "Warning: unable to mount $ISO_DEVICE." >>/live-boot.log + fi fi fi @@ -1418,6 +1713,35 @@ check_dev () umount $mountpoint fi fi + + IFS="," + for device in ${devname} + do + case "$device" in + *mapper*) + # Adding lvm support + if [ -x /scripts/local-top/lvm2 ] + then + ROOT="$device" resume="" /scripts/local-top/lvm2 + fi + ;; + + /dev/md*) + # Adding raid support + if [ -x /scripts/local-top/mdadm ] + then + cp /conf/conf.d/md /conf/conf.d/md.orig + echo "MD_DEVS=$device " >> /conf/conf.d/md + /scripts/local-top/mdadm + mv /conf/conf.d/md.orig /conf/conf.d/md + fi + ;; + esac + done + unset IFS + + [ -n "$device" ] && devname="$device" + [ -e "$devname" ] || continue if [ -n "${LIVE_MEDIA_OFFSET}" ] @@ -1441,7 +1765,7 @@ check_dev () echo ${mountpoint} return 0 else - umount ${mountpoint} + umount ${mountpoint} 2>/dev/null fi fi @@ -1469,39 +1793,29 @@ find_livefs () # first look at the one specified in the command line case "${LIVE_MEDIA}" in removable-usb) - for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)") + for sysblock in $(removable_usb_dev "sys") do - if [ "$(cat ${sysblock}/removable)" = "1" ] - then - if readlink ${sysblock} | grep -q usb || - readlink ${sysblock}/device | grep -q usb # linux < 2.6.29 + for dev in $(subdevices "${sysblock}") + do + if check_dev "${dev}" then - for dev in $(subdevices "${sysblock}") - do - if check_dev "${dev}" - then - return 0 - fi - done + return 0 fi - fi + done done return 1 ;; removable) - for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)") + for sysblock in $(removable_dev "sys") do - if [ "$(cat ${sysblock}/removable)" = "1" ] - then - for dev in $(subdevices "${sysblock}") - do - if check_dev "${dev}" - then - return 0 - fi - done - fi + for dev in $(subdevices "${sysblock}") + do + if check_dev "${dev}" + then + return 0 + fi + done done return 1 ;; @@ -1519,16 +1833,7 @@ find_livefs () # or do the scan of block devices # prefer removable devices over non-removable devices, so scan them first - for sysblock in $(echo /sys/block/* | tr ' ' '\n' | egrep -v "/(loop|ram|dm-|fd)") - do - if [ "$(cat ${sysblock}/removable)" = "1" ] - then - removable_devices_to_scan="$removable_devices_to_scan $sysblock" - else - nonremovable_devices_to_scan="$nonremovable_devices_to_scan $sysblock" - fi - done - devices_to_scan="$removable_devices_to_scan $nonremovable_devices_to_scan" + devices_to_scan="$(removable_dev 'sys') $(non_removable_dev 'sys')" for sysblock in $devices_to_scan do @@ -1552,6 +1857,7 @@ find_livefs () fi done elif [ "${fstype}" = "squashfs" -o \ + "${fstype}" = "btrfs" -o \ "${fstype}" = "ext2" -o \ "${fstype}" = "ext3" -o \ "${fstype}" = "ext4" -o \ @@ -1569,16 +1875,6 @@ find_livefs () return 1 } -set_usplash_timeout () -{ - if [ -x /sbin/usplash_write ] - then - /sbin/usplash_write "TIMEOUT 120" - else if [ -x /sbin/splashy_update ] ; then - /sbin/splashy_update "TIMEOUT 120" - fi ; fi -} - integrity_check () { media_mountpoint="${1}" @@ -1605,25 +1901,17 @@ integrity_check () fi } -start_usplash_pulse () -{ - if [ -x /sbin/usplash_write ] - then - /sbin/usplash_write "PULSELOGO" - fi -} - mountroot () { - if [ -x /scripts/local-top/cryptroot ]; then + if [ -x /scripts/local-top/cryptroot ]; then /scripts/local-top/cryptroot fi exec 6>&1 exec 7>&2 - exec > live.log + exec > live-boot.log exec 2>&1 - tail -f live.log >&7 & + tail -f live-boot.log >&7 & tailpid="${!}" # Ensure 'panic' function is overridden @@ -1631,9 +1919,6 @@ mountroot () Arguments - set_usplash_timeout - start_usplash_pulse - maybe_break live-premount log_begin_msg "Running /scripts/live-premount" run_scripts /scripts/live-premount @@ -1642,8 +1927,6 @@ mountroot () # Needed here too because some things (*cough* udev *cough*) # changes the timeout - set_usplash_timeout - if [ ! -z "${NETBOOT}" ] || [ ! -z "${FETCH}" ] || [ ! -z "${HTTPFS}" ] || [ ! -z "${FTPFS}" ] then if do_netmount @@ -1653,11 +1936,29 @@ mountroot () panic "Unable to find a live file system on the network" fi else - if [ -n "${PLAIN_ROOT}" ] && [ -n "${ROOT}" ] + if [ -n "${ISCSI_PORTAL}" ] + then + do_iscsi && livefs_root="${mountpoint}" + elif [ -n "${PLAIN_ROOT}" ] && [ -n "${ROOT}" ] then # Do a local boot from hd livefs_root=${ROOT} else + if [ -x /usr/bin/memdiskfind ] + then + MEMDISK=$(/usr/bin/memdiskfind) + + if [ $? -eq 0 ] + then + # We found a memdisk, set up phram + modprobe phram phram=memdisk,${MEMDISK} + modprobe phram phram=memdisk,${MEMDISK} + + # Load mtdblock, the memdisk will be /dev/mtdblock0 + modprobe mtdblock + fi + fi + # Scan local devices for the image i=0 while [ "$i" -lt 60 ] @@ -1718,6 +2019,11 @@ mountroot () mount_images_in_directory "${livefs_root}" "${rootmnt}" "${mac}" fi + + if [ -n "${ROOT_PID}" ] ; then + echo "${ROOT_PID}" > "${rootmnt}"/live/root.pid + fi + log_end_msg # unionfs-fuse needs /dev to be bind-mounted for the duration of @@ -1734,6 +2040,31 @@ mountroot () mount --move /live/image /root/live/image fi + # aufs2 in kernel versions around 2.6.33 has a regression: + # directories can't be accessed when read for the first the time, + # causing a failure for example when accessing /var/lib/fai + # when booting FAI, this simple workaround solves it + ls /root/* >/dev/null 2>&1 + + # copy snapshot configuration if exists + if [ -f snapshot.conf ] + then + log_begin_msg "Copying snapshot.conf to ${rootmnt}/etc/live/boot.d" + if [ ! -d "${rootmnt}/etc/live/boot.d" ] + then + mkdir -p "${rootmnt}/etc/live/boot.d" + fi + cp snapshot.conf "${rootmnt}/etc/live/boot.d/" + log_end_msg + fi + + if [ -f /etc/resolv.conf ] && [ ! -s ${rootmnt}/etc/resolv.conf ] + then + log_begin_msg "Copying /etc/resolv.conf to ${rootmnt}/etc/resolv.conf" + cp -v /etc/resolv.conf ${rootmnt}/etc/resolv.conf + log_end_msg + fi + maybe_break live-bottom log_begin_msg "Running /scripts/live-bottom\n" @@ -1748,5 +2079,5 @@ mountroot () exec 1>&6 6>&- exec 2>&7 7>&- kill ${tailpid} - [ -w "${rootmnt}/var/log/" ] && cp live.log "${rootmnt}/var/log/" 2>/dev/null + [ -w "${rootmnt}/var/log/" ] && cp live-boot.log "${rootmnt}/var/log/" 2>/dev/null }