Support bootoptions ethdevice and ethdevice-timeout for specifying from which device...
[live-boot-grml.git] / scripts / live
index 9baf5a9..bae9193 100755 (executable)
@@ -100,6 +100,16 @@ Arguments ()
                                export DEVICE
                                ;;
 
+                       ethdevice=*)
+                               ETHDEVICE="${ARGUMENT#ethdevice=}"
+                               export ETHDEVICE
+                               ;;
+
+                       ethdevice-timeout=*)
+                               ETHDEV_TIMEOUT="${ARGUMENT#ethdevice-timeout=}"
+                               export ETHDEV_TIMEOUT
+                               ;;
+
                        fetch=*)
                                 FETCH="${ARGUMENT#fetch=}"
                                 export FETCH
@@ -762,18 +772,51 @@ do_netmount ()
 
        modprobe -q af_packet # For DHCP
 
-       if [ -x /sbin/udevadm ]
-       then
-               # lenny
-               udevadm trigger
-               udevadm settle
-       else
-               # etch
-               udevtrigger
-               udevsettle
+       udevadm trigger
+       udevadm settle
+
+       # 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)
+       if [ -z "$ETHDEVICE" ] ; then
+               echo "If you want to boot from a specific device use bootoption ethdevice=..."
+               for device in /sys/class/net/*; do
+                       dev=${device##*/} ;
+                       if [ "$dev" != "lo" ] ; then
+                               ETHDEVICE="$ETHDEVICE $dev"
+                       fi
+               done
        fi
 
-       ipconfig ${DEVICE} | tee /netboot.config
+       # split args of ethdevice=eth0,eth1 into "eth0 eth1"
+       for device in $(echo $ETHDEVICE | sed 's/,/ /g') ; do
+               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
+       for dev in $devlist $devlist $devlist ; do
+               echo "Executing ipconfig -t $ETHDEV_TIMEOUT $dev"
+               ipconfig -t "$ETHDEV_TIMEOUT" $dev | tee -a /netboot.config &
+               jobid=$!
+               sleep "$ETHDEV_TIMEOUT" ; sleep 1
+               if [ -r /proc/"$jobid"/status ] ; then
+                       echo "Killing job $jobid for device $dev as ipconfig ran into recursion..."
+                       kill -9 $jobid
+               fi
+
+               # if configuration of device worked we should have an assigned
+               # IP address, iff so let's use the according as $DEVICE for later usage
+               # simple and primitive approach which seems to work fine
+               if ifconfig $dev | grep -q 'inet.*addr:' ; then
+                       export DEVICE="$dev"
+                       break
+               fi
+       done
 
        # source relevant ipconfig output
        OLDHOSTNAME=${HOSTNAME}
@@ -782,7 +825,8 @@ do_netmount ()
        export HOSTNAME
 
        # Check if we have a network device at all
-       if ! ls /sys/class/net/eth0 > /dev/null 2>&1 && \
+       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
@@ -996,7 +1040,7 @@ find_snap ()
        if [ "${PERSISTENT}" != "nofiles" ]
        then
                # search for image files
-               snapdata=$(find_files "${snap_label}.squashfs ${snap_label}.cpio.gz ${snap_label}.ext2 ${snap_label}.ext3 ${snap_label}.ext4 ${snap_label}.jffs2")
+               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}" ]
@@ -1094,7 +1138,25 @@ setup_unionfs ()
        image_directory="${1}"
        rootmnt="${2}"
         addimage_directory="${3}"
-       modprobe -q -b ${UNIONTYPE}
+
+       case ${UNIONTYPE} in
+               aufs|unionfs)
+                       modprobe -q -b ${UNIONTYPE}
+
+                       if ! cut -f2 /proc/filesystems | grep -q "^${UNIONTYPE}\$" && [ -x /bin/unionfs-fuse ]
+                       then
+                               echo "${UNIONTYPE} not available, falling back to unionfs-fuse."
+                               echo "This might be really slow."
+
+                               UNIONTYPE="unionfs-fuse"
+                       fi
+                       ;;
+       esac
+
+       if [ "${UNIONTYPE}" = unionfs-fuse ]
+       then
+               modprobe fuse
+       fi
 
        # run-init can't deal with images in a subdir, but we're going to
        # move all of these away before it runs anyway.  No, we're not,
@@ -1109,7 +1171,11 @@ setup_unionfs ()
 
        if [ "${UNIONTYPE}" = "aufs" ]
        then
-               roopt="rr,xino=/tmp/aufs.xino"
+               roopt="rr"
+               noxino_opt="noxino,"
+       elif [ "${UNIONTYPE}" = "unionfs-fuse" ]
+       then
+               roopt="RO"
        else
                roopt="ro"
        fi
@@ -1232,16 +1298,8 @@ setup_unionfs ()
                                modprobe -q -b ${module}
                        done
 
-                       if [ -x /sbin/udevadm ]
-                       then
-                               # lenny
-                               udevadm trigger
-                               udevadm settle
-                       else
-                               # etch
-                               udevtrigger
-                               udevsettle
-                       fi
+                       udevadm trigger
+                       udevadm settle
 
                        # For some reason, udevsettle does not block in this scenario,
                        # so we sleep for a little while.
@@ -1357,16 +1415,27 @@ setup_unionfs ()
 
                for dir in ${cow_dirs}; do
                        mkdir -p /cow${dir}
-                       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"
+
+                       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}")
+                                       ;;
+
+                               *)
+                                       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
-               mount -t ${UNIONTYPE} -o noatime,dirs=/cow=rw:${rofsstring} \
-                       ${UNIONTYPE} "${rootmnt}" || panic "mount ${UNIONTYPE} on \
-                       ${rootmnt} failed with option noatime,dirs=/cow=rw:${rofsstring}"
+               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}")
+                               ;;
+
+                       *)
+                               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}"
+                               ;;
+               esac
        fi
 
        # Correct the permissions of /:
@@ -1409,7 +1478,15 @@ setup_unionfs ()
                                        ;;
 
                                *)
-                                       mount -o move "${d}" "${rootmnt}/live/${d##*/}"
+                                       case "${UNIONTYPE}" in
+                                               unionfs-fuse)
+                                                       mount -o bind "${d}" "${rootmnt}/live/${d##*/}"
+                                                       ;;
+
+                                               *)
+                                                       mount -o move "${d}" "${rootmnt}/live/${d##*/}"
+                                                       ;;
+                                       esac
                                        ;;
                        esac
                done
@@ -1730,12 +1807,24 @@ mountroot ()
 
        log_end_msg
 
+       # unionfs-fuse needs /dev to be bind-mounted for the duration of
+       # live-bottom; udev's init script will take care of things after that
+       if [ "${UNIONTYPE}" = unionfs-fuse ]
+       then
+               mount -n -o bind /dev "${rootmnt}/dev"
+       fi
+
        maybe_break live-bottom
        log_begin_msg "Running /scripts/live-bottom\n"
 
        run_scripts /scripts/live-bottom
        log_end_msg
 
+       if [ "${UNIONFS}" = unionfs-fuse ]
+       then
+               umount "${rootmnt}/dev"
+       fi
+
        exec 1>&6 6>&-
        exec 2>&7 7>&-
        kill ${tailpid}