# mountare rootfs con unionfs (linuxrc)

## tonyputi

Salve a tutti ragazzi.

E' da tempo ormai che cerco di risolvere un problema che a qualcuno potrebbe sembrare interessante.

In pratica ho un pc di tipo mini itx equipaggiato di una compact flash al posto del normale comune hd. Questa CF ha una capacità di 2 GB e per via del mio morboso attaccamento a gentoo e del poco spazio a mia disposizione, mi sono chiesto come fosse possibile installare su questa macchina un completo sistema funzionante utile per i più disparati scopi salvaguardando comunque un bel po di spazio.

La risposta più ovvia è quella di utilizzare squashfs e unionfs in modo da avere una root compressa dove però sia possibile anche installare o rimuovere programmi in maniera del tutto trasparente.

L'idea viene dall'ottimo howto presente su wiki che spiega come usare questi due componenti per avere un portage di circa 22 Mb in rw.

http://gentoo-wiki.com/HOWTO_VERY_small_Portage_Tree_with_SquashFS_and_UnionFS

Dunque dopo aver studiato un bel po sono riuscito a coprendere che il risultato migliore al minor tempo lo si può ottenere modificando o creando a mestiere lo script di init (linuxrc) utilizzato da genkernel.

Questo ottimo link mostra, tra le altre cose, come effettuare un completo carotaggio dell'initramfs e comprenderne alcuni aspetti interessanti

http://wiki.gentoo-italia.net/index.php/Initramfs:_La_cowboy_way_e_i_segreti_di_genkernel

La mia idea quindi è quella di modificare in maniera minima questo file di init in maniera che riesca a montare uno squashfs ed una partizione da 1GB della mia compact flash per avere un unico file system aggiornabile.

Per effettuare i miei esperimenti mi sono basato sul seguente howto:

http://gentoo-wiki.com/HOWTO_build_a_LiveCD_from_scratch

che spiega come creare un livecd da zero. L'unica pecca di tale howto è quello di non spiegare come montare la root del livecd in modo che sia anche scrivibile, ovvero quello che voglio fare io sulla mia CF.

Dunque mi chiedevo se qualcuno di voi ha esperienza in merito o se conosce qualche soluzione migliore al mio problema.

Qui di seguito riporto il mio init (linuxrc) modificato da dare in pasto a genkernel.

Tale script funzionicchia ovvero monta la root in unionfs e la rende modificabile in modo trasparente, ma cmq per altri versi da qualche problemino tra cui i più evidenti sono:

1. eseguento il comando "df" ricevo un messaggio di errore in quanto in etc/mtab ho ancora listati alcuni fs che non dovrebbero esserci dopo il pivot_root e quindi il chroot

2. durante lo shutdown o il reboot ricevo un errore sull'umountig dei fs ausiliari (loop0, hda1, union) che non vengono smonanti in quanto occupati.

```

#!/bin/sh

# Copyright 2003-2006 Gentoo Foundation 

# Distributed under the terms of the GNU General Public License v2

. /etc/initrd.defaults

. /etc/initrd.scripts

splash() {

   return 0

}

[ -e /etc/initrd.splash ] && . /etc/initrd.splash

# Clean input/output

exec >${CONSOLE} <${CONSOLE} 2>&1

if [ "$$" != '1' ]

then

   echo '/linuxrc has to be run as the init process as the one'

   echo 'with a PID of 1. Try adding init="/linuxrc" to the'

   echo 'kernel command line or running "exec /linuxrc".'

   exit 1

fi

mount -t proc proc /proc >/dev/null 2>&1

mount -o remount,rw / >/dev/null 2>&1

# Set up symlinks

if [ "$0" = '/init' ]

then

   /bin/busybox --install -s

   [ -e /linuxrc ] && rm /linuxrc

    

   if [ -e /bin/lvm ]

   then

      ln -s /bin/lvm /bin/vgscan

      ln -s /bin/lvm /bin/vgchange

   fi

fi

quiet_kmsg

CMDLINE="`cat /proc/cmdline`"

# Scan CMDLINE for any specified real_root= or cdroot arguments

REAL_ROOT=''

FAKE_ROOT=''

REAL_ROOTFLAGS=''

for x in ${CMDLINE}

do

   case "${x}" in

      real_root\=*)

         REAL_ROOT=`parse_opt "${x}"`

      ;;

      root\=*)

         FAKE_ROOT=`parse_opt "${x}"`

      ;;

      subdir\=*)

         SUBDIR=`parse_opt "${x}"`

      ;;

      real_init\=*)

         REAL_INIT=`parse_opt "${x}"`

      ;;

      init_opts\=*)

         INIT_OPTS=`parse_opt "${x}"`

      ;;

      # Livecd options

      cdroot)

         CDROOT=1

      ;;

      cdroot\=*)

         CDROOT=1

         CDROOT_DEV=`parse_opt "${x}"`

      ;;

      # Start livecd loop and looptype options

      loop\=*)

         LOOP=`parse_opt "${x}"`

      ;;

      looptype\=*)

         LOOPTYPE=`parse_opt "${x}"`

      ;;

      # Start Device Manager options 

      devfs)

         USE_DEVFS_NORMAL=1

         USE_UDEV_NORMAL=0

      ;;

      udev)

         USE_DEVFS_NORMAL=0

         USE_UDEV_NORMAL=1

      ;;

      unionfs)

         if [ ! -x /sbin/unionctl ]

         then

            USE_UNIONFS_NORMAL=0

            bad_msg 'Unionctl not found: aborting use of unionfs!'

         else

            USE_UNIONFS_NORMAL=1

         fi

      ;;

      unionfs\=*)

         if [ ! -x /sbin/unionctl ]

         then

            USE_UNIONFS_NORMAL=0

            bad_msg 'Unionctl not found: aborting use of unionfs!'

         else

            USE_UNIONFS_NORMAL=1

            CMD_UNIONFS=`parse_opt "${x}"`

            echo ${CMD_UNIONFS}|grep , >/dev/null 2>&1

            if [ "$?" -eq '0' ]

            then

               UID=`echo ${CMD_UNIONFS#*,}`

               UNIONFS=`echo ${CMD_UNIONFS%,*}`

            else

               UNIONFS=${CMD_UNIONFS}

            fi

         fi

      ;;

      # Start Volume manager options 

      dolvm2)

         USE_LVM2_NORMAL=1

      ;;

      dodmraid)

         USE_DMRAID_NORMAL=1

      ;;

      dodmraid\=*)

         DMRAID_OPTS=`parse_opt "${x}"`

         USE_DMRAID_NORMAL=1

      ;;

      doevms2)

         USE_EVMS2_NORMAL=1

      ;;

      # Debug Options

      debug)

         DEBUG='yes'

      ;;

       # Scan delay options 

      scandelay\=*)

         SDELAY=`parse_opt "${x}"`

      ;;

      scandelay)

         SDELAY=10

      ;;

      # Module no-loads

      doload\=*)

         MDOLIST=`parse_opt "${x}"`

         MDOLIST="`echo ${MDOLIST} | sed -e \"s/,/ /g\"`"

      ;;

      nodetect)

         NODETECT=1

      ;;

      noload\=*)

         MLIST=`parse_opt "${x}"`

         MLIST="`echo ${MLIST} | sed -e \"s/,/ /g\"`"

         export MLIST

      ;;

      # Redirect output to a specific tty

      CONSOLE\=*)

         CONSOLE=`parse_opt "${x}"`

         exec >${CONSOLE} <${CONSOLE} 2>&1

      ;;

      # /dev/md

      lvmraid\=*)

         RAID_DEVICES="`parse_opt ${x}`"

         RAID_DEVICES="`echo ${RAID_DEVICES} | sed -e 's/,/ /g'`"

      ;;

      part\=*)

         MDPART=`parse_opt "${x}"`

      ;;

      # NFS

      ip\=*)

         IP=`parse_opt "${x}"`

      ;;

      nfsroot\=*)

         NFSROOT=`parse_opt "${x}"`

      ;;

      crypt_root\=*)

         LUKS_ROOT=`parse_opt "${x}"`

      ;;

      crypt_swap\=*)

         LUKS_SWAP=`parse_opt "${x}"`

      ;;

      real_rootflags\=*)

         REAL_ROOTFLAGS=`parse_opt "${x}"`

      ;;

   esac

done

if [ -z "${REAL_ROOT}" -a \( "${CDROOT}" -eq 0 \)  -a \( "${FAKE_ROOT}" != "/dev/ram0" \) ]

then

   REAL_ROOT="${FAKE_ROOT}"   

fi

splash 'init'

detect_sbp2_devices

cmdline_hwopts

# Load modules listed in MY_HWOPTS if /lib/modules exists

if [ -d '/lib/modules' ]

then

   good_msg 'Loading modules'

   # Load appropriate kernel modules

   if [ "${NODETECT}" -ne '1' ]

   then

      for modules in $MY_HWOPTS

      do

         modules_scan $modules

         eval DO_`echo $modules | sed 's/-//'`=1

      done

   fi

   # Always eval doload=...

   modules_load $MDOLIST

else

   for modules in $MY_HWOPTS

   do

      eval DO_`echo $modules | sed 's/-//'`=1

   done

   good_msg 'Skipping module load; no modules in the initrd!'

fi

# Mount sysfs

mount_sysfs

# Delay if needed for USB hardware

sdelay

# Start udev/devfs

start_dev_mgr

# Setup md device nodes if they dont exist

setup_md_device

# Scan volumes

startVolumes

# Initialize LUKS root device

startLUKS

# Set up unionfs

mkdir -p ${NEW_ROOT}

setup_unionfs

if [ "${USE_UNIONFS_NORMAL}" -eq '1' ]

then

   CHROOT=${UNION}

else

   CHROOT=${NEW_ROOT}

fi

# Run debug shell if requested

rundebugshell

suspend_resume

suspend2_resume

if [ "${CDROOT}" -eq '1' ]

then

   if [ ! "${USE_UNIONFS_NORMAL}" -eq '1' ]

   then

      good_msg "Making tmpfs for ${NEW_ROOT}"

      mount -t tmpfs tmpfs ${NEW_ROOT}

   fi

   

   for i in dev mnt mnt/cdrom mnt/livecd mnt/dynamic mnt/static 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

   # For SGI LiveCDs ...

   if [ "${LOOPTYPE}" = "sgimips" ]

   then

      [ ! -e ${NEW_ROOT}/dev/sr0 ] && mknod ${NEW_ROOT}/dev/sr0 b 11 0

      [ ! -e ${NEW_ROOT}/dev/loop0 ] && mknod ${NEW_ROOT}/dev/loop0 b 7 0

   fi

   # Required for gensplash to work.  Not an issue with the initrd as this

   # device isnt created there and is not needed.

   if [ -e /dev/tty1 ]

   then

      [ ! -e ${NEW_ROOT}/dev/tty1 ] && mknod ${NEW_ROOT}/dev/tty1 c 4 1

   fi

   if [ "${REAL_ROOT}" != "/dev/nfs" ] && [ "${LOOPTYPE}" != "sgimips" ]

   then

      bootstrapCD

   fi

   if [ "${REAL_ROOT}" = '' ]

   then

      echo -n -e "${WARN}>>${NORMAL}${BOLD} No bootable medium found. Waiting for new devices"

      

      COUNTER=0

      while [ $COUNTER -lt 3 ]; do

         sleep 3

         echo -n '.'

         let COUNTER=$COUNTER+1

      done   

      

      sleep 1

      echo -e "${NORMAL}"

      bootstrapCD

   fi

   if [ "${REAL_ROOT}" = '' ]

   then

      # Undo stuff

      umount  ${NEW_ROOT}/dev 2>/dev/null

      umount  ${NEW_ROOT}/sys 2>/dev/null

      umount /sys 2>/dev/null

      umount  ${NEW_ROOT}

      rm -rf  ${NEW_ROOT}/*

      bad_msg 'Could not find CD to boot, something else needed!'

      CDROOT=0

   fi

fi

setup_keymap

# Determine root device

good_msg 'Determining root device...'

while true

do

   while [ "${got_good_root}" != '1' ]

   do

      case "${REAL_ROOT}" in

         LABEL\=*|UUID\=*)

         

            ROOT_DEV=""

            retval=1

            

            if [ "${retval}" -ne '0' ]; then

               ROOT_DEV=`findfs "${REAL_ROOT}" 2>/dev/null`

               retval=$?

            fi

            

            if [ "$retval" -ne '0' ]; then

               ROOT_DEV=`busybox findfs "${REAL_ROOT}" 2>/dev/null`

               retval=$?

            fi

            

            if [ "${retval}" -ne '0' ]; then

               ROOT_DEV=`blkid -t "${REAL_ROOT}" | cut -d ":" -f 1 2>/dev/null`

               retval=$?

            fi

            

            if [ "${retval}" -eq '0' ] && [ -n "${ROOT_DEV}" ]; then

               good_msg "Detected real_root=${ROOT_DEV}"

               REAL_ROOT="${ROOT_DEV}"

            else

               bad_msg "Could not find root block device: ${REAL_ROOT}"

               echo '   Please specify a device to boot, or "shell" for a shell...'

               echo -n 'boot() :: '

               read REAL_ROOT

               got_good_root=0

               continue

            fi

            ;;

      esac

            

      if [ "${REAL_ROOT}" = 'shell' ]

      then

         run_shell

         REAL_ROOT=''

         got_good_root=0

         continue

      

      elif [ "${REAL_ROOT}" = '' ]

      then

         # No REAL_ROOT determined/specified. Prompt user for root block device.

         bad_msg "The root block device is unspecified or not detected."

         echo '   Please specify a device to boot, or "shell" for a shell...'

         echo -n 'boot() :: '

         read REAL_ROOT

         got_good_root=0

      # Check for a block device or /dev/nfs

      elif [ -b "${REAL_ROOT}" ] || [ "${REAL_ROOT}" = "/dev/nfs" ]

      then

         got_good_root=1

      else

         bad_msg "Block device ${REAL_ROOT} is not a valid root device..."

         REAL_ROOT=""

         got_good_root=0

      fi

   done

   if [ "${CDROOT}" -eq '1' -a "${got_good_root}" = '1' -a "${REAL_ROOT}" != "/dev/nfs" ]

   then

      # CD already mounted; no further checks necessary

      break

   elif [ "${LOOPTYPE}" = "sgimips" ]

   then

      # sgimips mounts the livecd root partition directly

      # there is no isofs filesystem to worry about

      break

   else

      good_msg "Mounting root..."

      # Try to mount the device as ${NEW_ROOT}

      if [ "${REAL_ROOT}" = '/dev/nfs' ]; then

         findnfsmount

      else

         # mount ro so fsck doesn't barf later

#         REAL_ROOT_TYPE=`vol_id -t ${REAL_ROOT}`

#         mount -t ${REAL_ROOT_TYPE} -o ro ${REAL_ROOT} ${NEW_ROOT}

         if [ "${REAL_ROOTFLAGS}" = '' ]; then

            mount -o ro ${REAL_ROOT} ${NEW_ROOT}

         else

            good_msg "Using mount -o ro,${REAL_ROOTFLAGS}"

            mount -o ro,${REAL_ROOTFLAGS} ${REAL_ROOT} ${NEW_ROOT}

         fi

      fi

      

      # If mount is successful break out of the loop 

      # else not a good root and start over.

      if [ "$?" = '0' ]

      then

         break

      else

         bad_msg "Could not mount specified ROOT, try again"

         got_good_root=0

         REAL_ROOT=''

      fi

   fi

done

# End determine root device

#verbose_kmsg

# If cdroot is set determine the looptype to boot

if [ "${CDROOT}" = '1' ]

then

   good_msg 'Determining looptype ...'

   cd ${NEW_ROOT}

   # Find loop and looptype if we have NFS-mounted a livecd

   if  [ "${LOOP}" = '' ] && [ "${REAL_ROOT}" = '/dev/nfs' ]

   then

      if [ -e "${NEW_ROOT}/mnt/cdrom/livecd.loop" ]; then

         LOOP='/livecd.loop'

         LOOPTYPE='normal'

            elif [ -e "${NEW_ROOT}/mnt/cdrom/zisofs" ]; then

         LOOP='/zisofs'

         LOOPTYPE='zisofs'

            elif [ -e "${NEW_ROOT}/mnt/cdrom/livecd.squashfs" ]; then

         LOOP='/livecd.squashfs'

         LOOPTYPE='squashfs'

            elif [ -e "${NEW_ROOT}/mnt/cdrom/image.squashfs" ]; then

         LOOP='/image.squashfs'

         LOOPTYPE='squashfs'

            elif [ -e "${NEW_ROOT}/mnt/cdrom/livecd.gcloop" ]; then

         LOOP='/livecd.gcloop'

         LOOPTYPE='gcloop'

            else

         LOOPTYPE='noloop'

      fi

   fi

   # Failsafe the loop type wasn't set

   if [ "${LOOPTYPE}" = '' ]

   then

      warn_msg 'Warning: loop type unspecified!'

      if [ "${LOOP}" = '/livecd.loop' ]

      then

         LOOPTYPE='normal'

      elif [ "${LOOP}" = '/zisofs' ]

      then

         LOOPTYPE='zisofs'

      elif [ "${LOOP}" = '/livecd.squashfs' ]

      then

         LOOPTYPE='squashfs'

      elif [ "${LOOP}" = '/image.squashfs' ]

      then

         LOOPTYPE='squashfs'

      elif [ "${LOOP}" = '/livecd.gcloop' ]

      then

         LOOPTYPE='gcloop'

      else

         LOOPTYPE='noloop'

      fi

   fi

   cache_cd_contents

   # Setup the loopback mounts

   if [ "${LOOPTYPE}" = 'normal' ]

   then

      good_msg 'Mounting loop filesystem'

      mount -t ext2 -o loop,ro ${NEW_ROOT}/mnt/cdrom/${LOOPEXT}${LOOP} ${NEW_ROOT}/mnt/livecd

      test_success 'Mount filesystem'

      FS_LOCATION='mnt/livecd'

   elif [ "${LOOPTYPE}" = 'squashfs' ]

   then

      good_msg 'Mounting squashfs filesystem'

      #mount -t squashfs -o loop,ro ${NEW_ROOT}/mnt/cdrom/${LOOPEXT}${LOOP} ${NEW_ROOT}/mnt/livecd

      

      mount -t squashfs -o loop,ro ${NEW_ROOT}/mnt/cdrom/${LOOPEXT}${LOOP} ${NEW_ROOT}/mnt/static

      #mount -t tmpfs -o size=300M none ${NEW_ROOT}/mnt/dynamic

      mount -t xfs /dev/hda1 ${NEW_ROOT}/mnt/dynamic

      mount -t unionfs -o dirs=${NEW_ROOT}/mnt/dynamic=rw:${NEW_ROOT}/mnt/static=ro unionfs ${NEW_ROOT}/mnt/livecd

      

      test_success 'Mount filesystem'

      FS_LOCATION='mnt/livecd'

   fi

#

# End cdrom looptype determination and mounting if necessary

#

   

   if [ ! "${USE_UNIONFS_NORMAL}" -eq '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})

      # Now we do the links.

      for x in ${ROOT_LINKS}

      do

         if [ -L "${NEW_ROOT}/${FS_LOCATION}/${x}" ]

         then

            ln -s "`readlink ${NEW_ROOT}/${FS_LOCATION}/${x}`" "${x}" 2>/dev/null

         else

            # List all subdirectories of x

            for directory in `find "${NEW_ROOT}/${FS_LOCATION}/${x}" -type d 2>/dev/null`

            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 [ "${curent_parrent}" != '' ]; then

                  var=`echo "${directory}" | grep "^${curent_parrent}"`

                  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

         fi

      done

      if [ "${DO_slowusb}" ] || [ "${FORCE_slowusb}" ]

      then

         sleep 10

      fi

      mkdir initrd proc tmp sys 2>/dev/null

      chmod 1777 tmp

   fi

   

   # Let Init scripts know that we booted from CD

   export CDBOOT

   CDBOOT=1

   if [ "${DO_slowusb}" ] || [ "${FORCE_slowusb}" ]

   then

      sleep 10

   fi

else

   if [ "${USE_UNIONFS_NORMAL}" -eq '1' ]

   then

      union_insert_dir ${UNION} ${NEW_ROOT}

      mkdir -p ${UNION}/tmp/.initrd

   fi

fi

# Execute script on the cdrom just before boot to update things if necessary

#cdupdate

if [ "${SUBDIR}" != '' -a -e "${CHROOT}/${SUBDIR}" ]

then

   good_msg "Entering ${SUBDIR} to boot"

   CHROOT=${CHROOT}/${SUBDIR}

fi

verbose_kmsg

# Move the /memory mount point to what will be the system root so that 

# init scripts will be able to unmount it properly at next reboot

#

# Eventually, all "unions over /" mounts should go in that /.unions/

if [ "${USE_UNIONFS_NORMAL}" -eq '1' ]

then

   mkdir -p /${CHROOT}/.unions/memory 2>/dev/null

   mount -o move /memory /${CHROOT}/.unions/memory || echo '*: Failed to move unionfs /memory into the system root!'

fi

if [ "$0" = '/linuxrc' ] || [ "$0" = 'linuxrc' ]

then

   [ ! -e ${CHROOT}/dev/console ] && mknod ${CHROOT}/dev/console c 5 1

   echo -ne "${GOOD}>>${NORMAL}${BOLD} Booting"

   cd ${CHROOT}

   mkdir ${CHROOT}/proc ${CHROOT}/sys 2>/dev/null

   pivot_root . tmp/.initrd

   if [ "${DO_slowusb}" ] || [ "${FORCE_slowusb}" ]

   then

      sleep 10

   fi

   echo -n '.'

   if /tmp/.initrd/bin/[ "${USE_DEVFS_NORMAL}" -eq '1' -a "${CDROOT}" -eq '0' ]

   then

      umount /tmp/.initrd/proc || echo '*: Failed to unmount the initrd /proc!'

      mount -n --move /tmp/.initrd/dev dev || echo '*: Failed to move over the /dev tree!'

      rm -rf /tmp/.initrd/dev || echo '*: Failed to remove the initrd /dev!'

   elif /tmp/.initrd/bin/[ "${USE_UDEV_NORMAL}" -eq '1' ]

   then

      /tmp/.initrd/bin/[ -e /tmp/.initrd/dev/fd ] && rm /tmp/.initrd/dev/fd

      /tmp/.initrd/bin/[ -e /tmp/.initrd/dev/stdin ] && rm /tmp/.initrd/dev/stdin

      /tmp/.initrd/bin/[ -e /tmp/.initrd/dev/stdout ] && rm /tmp/.initrd/dev/stdout

      /tmp/.initrd/bin/[ -e /tmp/.initrd/dev/stderr ] && rm /tmp/.initrd/dev/stderr

      /tmp/.initrd/bin/[ -e /tmp/.initrd/dev/core ] && rm /tmp/.initrd/dev/core 

      umount /tmp/.initrd/dev || echo '*: Failed to unmount the initrd /dev!'

      umount /tmp/.initrd/proc || echo '*: Failed to unmount the initrd /proc!'

      umount /tmp/.initrd/sys || echo '*: Failed to unmount the initrd /sys!'

   elif /tmp/.initrd/bin/[ "${CDROOT}" -eq '1' ]

   then

      umount /tmp/.initrd/proc || echo "*: Failed to unmount the initrd /proc!"

      umount /dev 2>/dev/null

      mount -n --move /tmp/.initrd/dev dev 2>/dev/null

      rm -rf /tmp/.initrd/dev || echo '*: Failed to remove the initrd /dev!'

      umount /sys 2>/dev/null

      umount /tmp/.initrd/sys 2>/dev/null

   fi

   echo -n '.'

   # /usr/src/linux/Documentation/initrd.txt:

   #   exec chroot . /sbin/init </dev/console >/dev/console 2>&1

   exec <dev/console >dev/console 2>&1

   echo '.'

   exec chroot . /bin/sh <<- EOF

      umount /tmp/.initrd || echo "*: Failed to unmount the initrd!"

      /sbin/blockdev --flushbufs /dev/ram0 >/dev/null 2>&1

      exec ${REAL_INIT:-/sbin/init} ${INIT_OPTS}

EOF

elif [ "$0" = '/init' ]

then

   [ ! -e ${CHROOT}/dev/console ] && mknod ${CHROOT}/dev/console c 5 1

   [ ! -e ${CHROOT}/dev/tty1 ] && mknod ${CHROOT}/dev/tty1 c 4 1

   echo -ne "${GOOD}>>${NORMAL}${BOLD} Booting (initramfs)"

   cd ${CHROOT}

   mkdir ${CHROOT}/proc ${CHROOT}/sys 2>/dev/null

   echo -n '.'

      umount /sys || echo '*: Failed to unmount the initrd /sys!'

      umount /proc || echo '*: Failed to unmount the initrd /proc!'

   echo -n '.'

   

   CHROOT=${NEW_ROOT}/mnt/livecd

   exec switch_root -c "/dev/console" "${CHROOT}" ${REAL_INIT:-/sbin/init} ${INIT_OPTS}

fi

splash 'verbose'

echo 'A fatal error has probably occured since /sbin/init did not'

echo 'boot correctly. Trying to open a shell...'

echo

exec /bin/bash

exec /bin/sh

exec /bin/ash

exec sh

```

So che magari qualche concetto non è chiaro ma sono pronto a chiarire ogni domanda o a fare qualunque test mi si proponga e sopratutto a documentare bene ognisingolo successo.

Grazie a tutti

----------

## randomaze

Direi che per adesso si tratta di una discussione... ma confidiamo di vedere presto l'howto in documentazione  :Wink: 

Moved from Forum italiano (Italian) to Forum di discussione italiano.

----------

## Frez

Io non uso genkernel, ne squashfs, ne unionfs  :Very Happy: 

Non uso squashfs perche' lo spazio sulla CF mi e' sufficiente e non voglio sovraccarichi di cpu (scarsa) per la decompressione (e magari posso mappare in ram i file senza tenerli fisicamente nella RAM che e' poca. questa affermazione va cmq presa con le molle)

Non uso unionfs perche' non prevedo di installare/rimuovere programmi (altrimenti avrei messo un HD)

Ho modificato qualche script per montare il filesystem in sola lettura, in particolare:

```
/etc/mtab
```

e' un link a /proc/mounts

```
/etc/init.d/localmount
```

dove ho aggiunto -n alle opzioni di mount per impedisce a mount di aggiornare /etc/mtab

```
/etc/init.d/checkroot
```

per montare in ram alcune cosette tipo /var

Sa un po' di porcata, ma vorrei lavorarci nei ritagli di tempo, che ultimamente sono azzerati  :Neutral: 

A casa dovrei avere un paio di link, vedo di editare piu' tardi il messaggio.

----------

## tonyputi

Grazie molte ragazzi per il supporto,

Cmq l'idea di avere un filesystem compresso in rw è dato dal fatto che se voglio che questo mini itx diventi un web server con php e mysql dovrò pure aggiornarlo alla presenza di nume versioni senza troppi sbattimenti, cosa che sarebbe impossibile in caso di fs in sola lettura.

A maggior ragione se volessi vendere tale pc a terzi garantendogli aggiornamenti nel tempo.

Ciao

----------

## cloc3

 *tonyputi wrote:*   

> 
> 
> Tale script funzionicchia ovvero monta la root in unionfs e la rende modificabile in modo trasparente, ma cmq per altri versi da qualche problemino tra cui i più evidenti sono:
> 
> 1. eseguento il comando "df" ricevo un messaggio di errore in quanto in etc/mtab ho ancora listati alcuni fs che non dovrebbero esserci dopo il pivot_root e quindi il chroot
> ...

 

non ho ancora letto tutto, e comunque ritego che il complesso del problema sia un po' sopra alle mie capacità.

tuttavia, sui problemini che hai segnalato, un'opinione la posso dare.

secondo me, /etc/mtab può essere ripulita preventivamente negli script di init, magari con un avviso nei log in caso di segnalazioni inopportune. non mi piace molto invece l'idea del link a /proc/mounts perché ne snatura del tutto la funzione. /etc/mtab non è un file virtuale. tanto varrebbe farne a meno.

l'errore allo shutdown probabilmente è inevitabile. ne ricevo uno sistematico anche io in una configurazione di raid software con problemi analoghi. di certo male non fa. penso  che per eliminarlo bisognerebbe cambiare gli script di shutdown, che evidentemente non contemplano situazioni del genere. ma sarebbe cosa tanto faticosa quanto inutile.

se dici che l'impianto funziona, vale proprio la pena postarlo in documentazione o, ancor meglio sui wiki (italiano e inglese).

----------

## djinnZ

 *cloc3 wrote:*   

> secondo me, /etc/mtab può essere ripulita preventivamente negli script di init, magari con un avviso nei log in caso di segnalazioni inopportune. non mi piace molto invece l'idea del link a /proc/mounts perché ne snatura del tutto la funzione. /etc/mtab non è un file virtuale. tanto varrebbe farne a meno.

 

prima dell'avvento degli fs virtuali serviva a registrare i mount, oggi non serve praticamente più a nulla.

----------

## cloc3

 *djinnZ wrote:*   

> 
> 
> prima dell'avvento degli fs virtuali serviva a registrare i mount, oggi non serve praticamente più a nulla.

 

può essere. anche a me sembra una doppia copia di informazioni che si possono ricavare per altre strade.

ma finché lo lasciano, un motivo ci [b[può[/b] essere.

non sarà lì solo per nostalgia.

----------

## djinnZ

è solo per retrocompatibilità e perchè lo standard posix è quello che è.

----------

## tonyputi

Parte della documentazione o perlo meno la parte più sostanziale la trovate qui 

http://gentoo-wiki.com/Talk:HOWTO_build_a_LiveCD_from_scratch#Making_.2F_rw_with_unionfs.28or_something_better.3F.29

Non è completa è scritta in un inglese molto scadente e sopratutto l'ho scrittaio. Purtroppo non ho molto tempo in sti giorni per sistemare il wiki ma non appena avrò un attimo di tempo giuro che lo sistemo.

Ciao

----------

## cloc3

 *tonyputi wrote:*   

> 
> 
> or_something_better
> 
> 

 

infatti, sembra che aufs sia riconosciuto come alternativa competitiva.

ultimamente, ho sostituito aufs ad unionfs nel mio sistema perché ogni tanto unionfs mi tirava dei pacchi (si piantava), di cui non capivo bene il motivo.

una volta installato aufs, la sintassi non cambia per l'utente finale. inoltre aufs offre un'opzione per garantire la compatibilità con unionfs.

knoppix usa aufs.

----------

## tonyputi

Grazie del consiglio è la prima cosa che proverò !

----------

## tonyputi

Ciao a tutti ragazzi sto provando aufs al posto di unionfs dentro l'initramfs ma ho qualche problemino.

In pratica io ho la mia compact flash così partizionata:

 /dev/sda1  /boot (16M) [ext2]

 /dev/sda2  / (752M) [xfs]

 /dev/sda3  none (256M) [swap]

Nella partizione 2 ovvero /dev/sda2 ho creato una direcotry "/.squashfs" dove al suo interno risiede la mia root originale compressa in squashfs dal nome "root.squashfs"

Adesso nel mio init, finalmente completato, voglio sostituire unionfs con aufs:

```

do_realroot() {

   verbose "Mounting $REALROOT on $NEWROOT"

   DISK="/.overlay"   # Rappresenta la partizione /dev/sda2 in xfs che per comodità monto qua

   SQUASH="/.squashfs"   # Rappresenta il file montato /.overlay/.squashfs/root.squashfs

        NEWROOT="/newroot"   # Ovvero dove verrà montato aufs

        [ ! -d $DISK ] && mkdir $DISK

   [ ! -d $SQUASH ] && mkdir $SQUASH

   [ ! -d $NEWROOT ] && mkdir $NEWROOT

        # monto /dev/sda2 /.overlay

   mount $REALROOT $DISK

        # monto /.overlay/.squashfs/root.squashfs /.squashfs

   mount $DISK/.squashfs/root.squashfs $SQUASH $ARGS_ROOT_MOUNT

        # Questo è quello che facevo quando usavo unionfs ed andava!

   # mount -t unionfs -o dirs=$DISK=rw:$SQUASH=ro unionfs $NEWROOT

  

       # Questo è quello che faccio adesso per aufs ma ricevendo un errore

   mount -t aufs -o br:$DISK=rw:$SQUASH=ro aufs $NEWROOT

   exec /bin/sh

   return $?

}

```

Con questo non voglio dire che aufs ha un bug ma che semplicemente non riesco a montare lo squashfs perchè is overlapped.

Riporto dal sito ufficiale di aufs la seguente informazione rigurado all'utilizzo dell'opzione "br:":

http://aufs.sourceforge.net/aufs.html

 *Quote:*   

> 
> 
> br:BRANCH[:BRANCH ...] (dirs=BRANCH[:BRANCH ...])
> 
> Adds new branches. (cf. Branch Syntax).
> ...

 

Non so come venirne a capo

 *Quote:*   

> 
> 
> / # mount -t aufs -o br:$DISK=rw:$SQUASH=ro aufs $NEWROOT
> 
> aufs test_add:393:mount[792]: /.squashfs is overlapped
> ...

 

Se qualcuno avesse un idea?

Grazie ciao

----------

## cloc3

 *tonyputi wrote:*   

> 
> 
>  *Quote:*   
> 
> Adds new branches. (cf. Branch Syntax).
> ...

 

non capisco io. che bisogno hai di aggiungere un nuovo ramo?

 *tonyputi wrote:*   

> 
> 
>        # Questo è quello che facevo quando usavo unionfs ed andava! 
> 
>     # mount -t unionfs -o dirs=$DISK=rw:$SQUASH=ro unionfs $NEWROOT 
> ...

 

e io mi aspetterei di fare semplicemente così:

```

mount -t aufs -o dirs=$DISK=rw:$SQUASH=ro aufs $NEWROOT 

```

ci sono complicazioni che non vedo?

----------

## tonyputi

Ciao ho provato quella che mi hai detto:

```
/ # mount -t aufs -o dirs=$DISK=rw:$SQUASH=ro aufs $NEWROOT 
```

Ma con lo stesso identico errore di prima

aufs test_add:393:mount[797]: /.squashfs is overlapped

munt: Mounting aufs on /newroot failed: ivalid argument 

Ho provato a montare un tmpfs

```

/ # mkdir /tmpfs

/ # mount -t tmpfs tmpfs /tmpfs

/ # mount -t aufs -o dirs=/tmpfs=rw:$SQUASH=ro aufs $NEWROOT 

```

e così tutto sembra funzionare.

Il problema è che cerco di fare l'unione di un disco e di uno squashfs che risiede come file dentro il disco stesso, purtroppo non posso usare ulteriori partizioni per tenere li il mio squashfs e non avere problemi.

Grazie comunque

----------

## cloc3

 *tonyputi wrote:*   

> 
> 
> ```
> 
> do_realroot() {
> ...

 

mi sfugge del tutto il perché unionfs funzioni mentre aufs no.

tuttavia vorrei farti delle domande sull'impianto che usi per preparare il chroot.

hai scritto una initrd di una lunghezza incredibile che non riesco a seguire nei dettagli.

da questo pezzettino di codice, tuttavia, mi sorge il sospetto che le cartelle .squashfs, .overlay e newroot corrispondano a nodi fisici contenuti dentro la chiavetta /dev/sda2 .

se questo è vero, perché non provi a creare a priori i nodi dentro la initrd, e ti ciaccarutti dopo in newroot?

qui avevo studiato una cosa analoga per un diskless. non la ho mai testata con aufs, ma dicono che funzioni.

----------

## tonyputi

 *Quote:*   

> mi sfugge del tutto il perché unionfs funzioni mentre aufs no.

 

Sono riuscito a risolvere il rpoblema di aufs. In pratica aufs ti dice che non puoi unire due branch in cui uno dei due è padre o figlio rispetto all'altro.

In pratica la mia compactflash è così strutturata:

```

/           partizione della compactflash formattata con xfs

/.squasfs/disk.squashfs           è una direcotry all'intero della partizione al cui interno risiede lo squashfs

```

Io cercavo di unire in /aufs il branch / (ovvero la root di sda) e /tmp (ovvero dove ho montato l'immagine squash), ma per via della roblematica di cui parlavo aufs non per lo permette, ritornandoti un errore is overlapped.

Per risolvere il problema ho dunque cambiato la struttura della mia CF in questo modo

```

/           partizione della compactflash formattata con xfs

/.squasfs/disk.squashfs           è una direcotry all'intero della partizione al cui interno risiede lo squashfs

/.overlay (branch utilizzato da aufs non overlapped in quanto non è nel figlio ne padre di disk.squashfs)

```

E tutto funziona a meraviglia

 *Quote:*   

> tuttavia vorrei farti delle domande sull'impianto che usi per preparare il chroot.

 

Spara

 *Quote:*   

> hai scritto una initrd di una lunghezza incredibile che non riesco a seguire nei dettagli.

 

non l'ho scritto io l'ho trovato su internet e non ricordo dove. Io l'ho solamente adattato a quello che mi serve.

P.S. l'initrd che usa genkernel di default è molto ma molto più esteso circa 800 righe di codice alle quali ho dato una lettura.

----------

## cloc3

 *tonyputi wrote:*   

> 
> 
> E tutto funziona a meraviglia
> 
> 

 

 :Smile: 

ottimo. mi pare che ti sei mosso nella direzione a cui mi riferivo, togliendo la sovrapposizione superflua dei rami di unione.

non me la sentivo di giurare che quello fosse il problema perché il tuo script era troppo complesso e aveva parti che avrebbero potuto sfuggire facilmente (sopratutto a me, che scrivo pochissimo codice).

Il fatto è che non puoi confrontare la lettura di 800 linee di genkernel, per il proposito determinato di impararare qualcosa, alla lettura di un codice in cui, per fare un mount unionfs, si trovano check di controllo su raid, udev, devfs e compagnia.

quando chiedi, qualcosa, devi prima circoscrivere il problema a quello che ti interessa strettamente.

adesso riassumi e fai un report completo su un wiki. magari anche un confronto tra unionfs ed aufs, se ti sembra possibile.

meglio se italiano.

----------

## tonyputi

con piacere solo vi chiedo qualche giorno di tempo, ho un paio di esami per l'uni da passare.

Comunque le questioni non sono terminate ed anzi ve ne proporrò una interesante nei prossimi giorni

----------

