Fixed mount paths for other partitions than root

New features which should be implemented in Porteus; suggestions are welcome. All questions or problems with testing releases (alpha, beta, or rc) should go in their relevant thread here, rather than the Bug Reports section.
Gele
White ninja
White ninja
Posts: 5
Joined: 06 Jan 2011, 01:18
Location: bulgaria

Fixed mount paths for other partitions than root

Post#1 by Gele » 06 Jan 2011, 01:48

Now it`s implemented only for the root file system (it`s always at "/" ). AFAIK it`s done by placing a .sgn file in one of the subdirectories (typ. /slax), which is searched for during the boot process.
Other partitions are mount under /mnt with device name which isn`t very user friendly or app friendly (my Virtualbox VM config looses it`s disk images). In Ubuntu (for ex.), partitions are mounted with their label (if any) which makes more sense (you can get the same path across different hardware in most of the cases).
What I think about is a quick fix - to create a .sgn file for each partition with information about the desired mount path and slightly modify the automount script(s) to scan first level of subdirs for sgn`s (slow?).
Or make it work like Ubuntu - read the label (if any) and use it, if already used - add a digit to the label, if there is not label - think out one.
Maybe (didn`t test it) for the filesystems that support UUIDS (ext3/4) it could be done by the user ( me:) ) by making entries with UUIDS in fstab.
Last edited by Gele on 27 Aug 2014, 12:30, edited 1 time in total.

User avatar
fanthom
Moderator Team
Moderator Team
Posts: 5666
Joined: 28 Dec 2010, 02:42
Distribution: Porteus Kiosk
Location: Poland
Contact:

Re: Fixed mount paths for other partitions than root

Post#2 by fanthom » 06 Jan 2011, 05:37

yes - i was thinking about it before, when some user on slax forum started complaining about random letters assigned to his pendrives. It could be a solution to this problem :)
This feature (reading UUID's instead of /dev/sdx*) requires modification in linuxrc (inside initrd) and should be quite easy to implement. Anyway - if you want to take this challenge, i would be very happy to assign you to this task. ( i would like to have more people here who are familiar with my LLS implementation).

If you want to start working on this - please do, and dont hesitate to ask about anything linuxrc/initrd related.
Cheers
Please add [Solved] to your thread title if the solution was found.

Gele
White ninja
White ninja
Posts: 5
Joined: 06 Jan 2011, 01:18
Location: bulgaria

Re: Fixed mount paths for other partitions than root

Post#3 by Gele » 26 Aug 2014, 18:59

Well, I felt unprepared to do it and had hope that somebody will fix it for me :oops: The shell script syntax is a nightmare for me.
But this did not happen, so today I .. tried. The boot process is somwhat unclear to me.
I decided to keep the mount points under /mnt, just modifying their names. To do so, I need to find where the partitions get mounted by init.
I found this line in linuxrc:

Code: Select all

...
# Create /etc/fstab and mount devices:
fstab
.........................
So i went to line 44 "# Device Functions" and modified the fstab() function, assuming that this will do what's needed. But it didn't - I ended with probably "properly" created fstab, mtab but the folders under /mnt were not present and instead the old device-named folders appeared. The partitions were mounted, but not at /mnt. They left mounted at /mnt/live/mnt/
So probably i need to rewrite more functions, but I don't know which. The modified fstab() (w lots ot echo" DBG:...) so far looks like this:

Code: Select all

fstab() { rm -f /tmp/devices
param nocd || for x in /dev/sr*; do blkid $x >>/tmp/devices; done
param nohd || blkid | egrep -v '/dev/sr|/dev/loop|/dev/mapper' >>/tmp/devices
dev=`egrep -v 'TYPE="sw|TYPE="LVM|TYPE=".*_raid_member"' /tmp/devices 2>/dev/null | cut -d: -f1 | cut -d/ -f3 | sort | uniq`
cat > /etc/fstab << EOF
# Do not edit this file as fstab is recreated automatically during every boot.
# Please use /etc/rc.d/rc.local or sysvinit scripts if you want to mount/unmount
# drive, filesystem or network share.

# System mounts:
aufs / aufs defaults 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devtmpfs /dev devtmpfs defaults 0 0
devpts /dev/pts devpts rw,mode=0620,gid=5 0 0

# Device partitions:
EOF
# set mountpoint names:
mpts="" #initial
for d in $dev; do
  bi=`blkid /dev/$d` # cache blkid output
  r=`echo $bi | cut -f2 -d":" | cut -f1 -d"=" | sed 's/[[:space:]]//g'` # has label ?
  is_cd=`echo $d | egrep -o 'sr|scd|cdrom'`
  echo "DBG: r=$r bi=$bi"
  if  [ "$r" = "LABEL" ] && [ "$is_cd" = "" ]; then
    #m=`echo $bi | egrep -o ' LABEL=[^ ]+' | cut -d'"' -f2` # take the label
    m=`echo $bi |sed 's/^.*LABEL="//' | cut -d'"' -f1 |sed 's/[[:space:]]/_/g' ` #take the label, replace spaces w underline
    echo "The device $d is not a cdrom, has label $m"
  else
    echo "The device $d left $d "
    m=$d
  fi
  # test if the new mountpoint is unique, fix if not
  r=`echo $mpts | egrep -o "$m" | sed 's/[[:space:]]//g'`; # sed here used to trim any spaces
  #r="sda1"; # to test  
  i=0 
  nm=$m; # we preserve the orig. value in m
  while [ "$r" != "" ]
  do
    i=$(($i+1)) #i++
    nm=$m"$i"
    #echo "new m=$nm"
    r=`echo $mpts | egrep -o "$nm" | sed 's/[[:space:]]//g'`; #test again
  done 
  echo "DBG_l: I want to mount dev=$d at /mnt/$nm " 
  if [ "$mpts" = "" ]; then mpts=$nm; else mpts=$mpts" $nm"; fi # add the generated mount point
  echo 'DBG_l: mpts='$mpts
done
echo "DBG: dev=$d, mpts=$mpts"
for d in $dev; do
    fs=`grep -w /dev/$d /tmp/devices | egrep -o ' TYPE=[^ ]+' | cut -d'"' -f2`
    mp=`echo $mpts | cut -d' ' -f1` # get the first word (mountpoint)
    echo "DBG: Trying to mount /dev/$d at /mnt/$mp fstype=$fs"
    [ $fs = "vfat" ] && echo "/dev/$d /mnt/$mp vfat $MOPT,umask=0,check=s,utf8 0 0" >>/etc/fstab || echo "/dev/$d /mnt/$mp $fs $MOPT 0 0" >>/etc/fstab
    if [ ! -d /mnt/$mp ]; then
	mkdir /mnt/$mp
	if [ $fs = "ntfs" ]; then
	    ntfs-3g /dev/$d /mnt/$mp -o $MOPT 2>/dev/null || { sed -i "/$mp /d" /etc/fstab; rmdir /mnt/$mp; } # on failure removes the mountpoint from fstab and /mnt/
	else
	    mount -n /mnt/$mp 2>/dev/null || { modprobe $fs 2>/dev/null && mount -n /mnt/$mp 2>/dev/null || { sed -i "/$mp /d" /etc/fstab; rmdir /mnt/$mp; }; }
	fi
    fi
    if [ ! -d /mnt/$mp ]; then
     echo "DBG: mount /dev/$d at /mnt/$mp failed, cmd='mount -n /mnt/$mp'"
    else
     echo "DBG: mount /dev/$d at /mnt/$mp succeeded"
    fi
    mpts=`echo $mpts | sed 's/[^ ]* //'` # remove the first mountpoint ( word ) (everything before the first space)
done

if [ -z "`egrep -o " noswap( |\$)" /proc/cmdline`" -a -e /tmp/devices ]; then
	echo -e "\n# Swap partitions:" >>/etc/fstab
	for x in `grep 'TYPE="swap"' /tmp/devices | cut -d: -f1`; do echo "$x none swap sw,pri=1 0 0" >>/etc/fstab; done
fi }
What it does ? It tries to get the partition labels, then calculates the new mountpoint names where labels are present. Where the labels absent, it retains the device name as mountpoint. It avoids duplicate mountpoint names (when 2 names match it appends a number to the name). The spaces within the label names are converted to underlines. This may improve later.
Last edited by Gele on 28 Aug 2014, 07:06, edited 6 times in total.

Gele
White ninja
White ninja
Posts: 5
Joined: 06 Jan 2011, 01:18
Location: bulgaria

Re: Fixed mount paths for other partitions than root

Post#4 by Gele » 27 Aug 2014, 12:43

Should I continue ?
It turned out that at step "0changing root directory" it fails. So we need to fix this...
Well, it turned out that at this step it parses the fstab, gets partition names from there and moves the mountpoints to /union/mnt/.
To fix this behavior, we can parse the fstab to get the previous calculated mountpoints of devices (instead of device names) which makes more sense. So we change the related code segment to look like this (w old code commented out):

Code: Select all

echo $i"-changing root directory"
mpts=`grep /mnt/ /etc/fstab | cut -d/ -f5 | cut -d' ' -f1`
if param noauto; then
    #echo "DBG: param noauto -  Do not mount any devices during startup"
    #for x in `grep /mnt/ /etc/fstab | cut -d/ -f3`; do mkdir -p /union/mnt/$x; umount -n /mnt/$x 2>/dev/null && rmdir /mnt/$x; done
    for mp in $mpts; do mkdir -p /union/mnt/$mp; umount -n /mnt/$mp 2>/dev/null && rmdir /mnt/$mp; done
else
    #echo "DBG: param noauto off - auto mount the partitions & devices"
    grep /mnt/ /etc/fstab >> /union/etc/mtab # combine into the new mtab
    #for x in `grep /mnt/ /etc/fstab | cut -d/ -f3`; do mkdir -p /union/mnt/$x; mount -n --move /mnt/$x /union/mnt/$x; rmdir /mnt/$x; done
    for mp in $mpts; do mkdir -p /union/mnt/$mp; mount -n --move /mnt/$mp /union/mnt/$mp; rmdir /mnt/$mp; done
fi

User avatar
fanthom
Moderator Team
Moderator Team
Posts: 5666
Joined: 28 Dec 2010, 02:42
Distribution: Porteus Kiosk
Location: Poland
Contact:

Re: Fixed mount paths for other partitions than root

Post#5 by fanthom » 27 Aug 2014, 14:06

yes - you have to update fstab function and tweak the code where partitions are remounted to /union.
Please add [Solved] to your thread title if the solution was found.

Gele
White ninja
White ninja
Posts: 5
Joined: 06 Jan 2011, 01:18
Location: bulgaria

Re: Fixed mount paths for other partitions than root

Post#6 by Gele » 27 Aug 2014, 14:13

O.K. Now I found I need a new global variable to store the mount points, because I don't want to parse the fstab.
let declare it as g_pmpts - global partition mount points:

Code: Select all

...
livedbg=/var/log/livedbg
g_pmpts="" # global variable - partition mount points, filled in fstab(), used in "changing root directory" step 
...
Now, the code of fstab() looks like this:

Code: Select all

# Device Functions:
fstab() { rm -f /tmp/devices
param nocd || for x in /dev/sr*; do blkid $x >>/tmp/devices; done
param nohd || blkid | egrep -v '/dev/sr|/dev/loop|/dev/mapper' >>/tmp/devices
dev=`egrep -v 'TYPE="sw|TYPE="LVM|TYPE=".*_raid_member"' /tmp/devices 2>/dev/null | cut -d: -f1 | cut -d/ -f3 | sort | uniq`
cat > /etc/fstab << EOF
# Do not edit this file as fstab is recreated automatically during every boot.
# Please use /etc/rc.d/rc.local or sysvinit scripts if you want to mount/unmount
# drive, filesystem or network share.

# System mounts:
aufs / aufs defaults 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devtmpfs /dev devtmpfs defaults 0 0
devpts /dev/pts devpts rw,mode=0620,gid=5 0 0

# Device partitions:
EOF
# set mountpoint names:
mpts="" #initial
sep="/" # separator
for d in $dev; do
  #bi=`blkid /dev/$d` # cache blkid output
  bi=`blkid -o export /dev/$d | grep LABEL` # cache blkid output
  #r=`echo $bi | cut -f2 -d":" | cut -f1 -d"=" | sed 's/[[:space:]]//g'` # has label ?
  r=`echo $bi | cut -f1 -d"=" | sed 's/[[:space:]]//g'`  # has label ?
  is_cd=`echo $d | egrep -o 'sr|scd|cdrom'`
  #echo "DBG_l: r='$r' bi=$bi" ls -l /dev/disk/by-label | grep ../sda5
  if  [ "$r" = "LABEL" ] && [ "$is_cd" = "" ]; then
    #mp=`echo $bi |sed 's/^.*LABEL="//' |sed -E 's/(([^UUID=]+ ){1}).*/\1/' |sed 's/[[:space:]]/_/g' ` #take the label, replace spaces w underline
    #mp=`echo $bi | sed 's/.*LABEL="\(.*\)"[[:space:]]UUID=.*/\1/' ` #take the label
    #mp=`echo $bi |sed 's/^.*LABEL="//' |sed -E 's/(([^UUID=]+ ){2}).*/\1/'`
    mp=`echo $bi | cut -f2 -d"="`
    #mp1=` ls -l /dev/disk/by-label | grep ../../$d | cut -d">" -f1 | cut -d" " -f9 `
    echo "The device $d is not a cdrom, has label mp=\"$mp\""
    mp=`echo $mp | sed -e "s/[^@{},A-Za-z0-9._-]/_/g"` # fix it to form a valid filename    
    # we replace the spaces w underline, because we didn't implement mtab & fstab compliant escaping
  else
    echo "The device $d left $d "
    mp=$d
  fi
  # test if the new mountpoint is unique, fix if not
  #r=`echo $mpts | egrep -o "$mp" | sed 's/[[:space:]]//g'`; # sed here used to trim any spaces
  r=`echo $mpts | egrep -o "$mp" `; 
  #r="sda1"; # to test, sda1 has not label  
  i=0;nm=$mp; # we preserve the orig. value in mp
  while [ "$r" != "" ]
  do
    i=$(($i+1)) #i++
    nm=$mp"$i"
    echo "new m=$nm"
    r=`echo $mpts | egrep -o "$nm" `; #test again
  done 
  if [ "$mpts" = "" ]; then mpts=$nm; else mpts=$mpts$sep$nm; fi # add the generated mount point
  echo "DBG_l: I want to mount dev=$d at \"/mnt/$nm\" " 
done
g_pmpts=$mpts # save in a global for later use in "changing root directory" step
echo "DBG: dev='$dev', mpts='$mpts'"
for d in $dev; do
    fs=`grep -w /dev/$d /tmp/devices | egrep -o ' TYPE=[^ ]+' | cut -d'"' -f2`
    mp=`echo $mpts | cut -d"$sep" -f1` # get first word using our separator
    echo "DBG: Trying to mount /dev/$d at /mnt/$mp fstype=$fs"
    # fstab escaping is different than mtab escaping; but no spaces in mountpoint names
    [ $fs = "vfat" ] && echo "/dev/$d /mnt/$mp vfat $MOPT,umask=0,check=s,utf8 0 0" >>/etc/fstab || echo "/dev/$d /mnt/$mp $fs $MOPT 0 0" >>/etc/fstab
    if [ ! -d /mnt/$mp ]; then
	mkdir /mnt/$mp
	if [ $fs = "ntfs" ]; then
	    ntfs-3g /dev/$d /mnt/$mp -o $MOPT 2>/dev/null || { sed -i "/$mp /d" /etc/fstab; rmdir /mnt/$mp; } # on failure removes the mountpoint from fstab and /mnt/
	else
	    mount -n /mnt/$mp 2>/dev/null || { modprobe $fs 2>/dev/null && mount -n /mnt/$mp 2>/dev/null || { sed -i "/$mp /d" /etc/fstab; rmdir /mnt/$mp; }; }
	fi
    fi
    if [ ! -d /mnt/$mp ]; then
     echo "DBG: mount /dev/$d at /mnt/$mp failed, cmd='mount -n /mnt/$mp'"
    else
     echo "DBG: mount /dev/$d at /mnt/$mp succeeded"
    fi
    mpts=`echo $mpts | cut -d"$sep" -f2-` # remove the first word (everything before the first sep)
done

if [ -z "`egrep -o " noswap( |\$)" /proc/cmdline`" -a -e /tmp/devices ]; then
	echo -e "\n# Swap partitions:" >>/etc/fstab
	for x in `grep 'TYPE="swap"' /tmp/devices | cut -d: -f1`; do echo "$x none swap sw,pri=1 0 0" >>/etc/fstab; done
fi }
We are going to tweak the code where partitions are remounted to /union to use our global g_pmpts array to move the mountpoints. It's located just under the "changing root directory" string:

Code: Select all

echo $i'-changing root directory'
mpts=$g_pmpts; sep='/' # separator
if param noauto; then
    #echo "DBG: param noauto -  Do not mount any devices during startup"
    #sh # run a shell
    #for x in `grep /mnt/ /etc/fstab | cut -d/ -f3`; do mkdir -p /union/mnt/$x; umount -n /mnt/$x 2>/dev/null && rmdir /mnt/$x; done
    while [ "$mpts" != "$mp" ]; do
	mp=`echo $mpts | cut -d"$sep" -f1` # get first word using our separator
	mpts=`echo $mpts | cut -d"$sep" -f2-` # remove the first word (everything before the first sep)
	echo "umounting /mnt/$mp"
	mkdir -p /union/mnt/$mp; umount -n /mnt/$mp 2>/dev/null && rmdir /mnt/$mp;
    done 
else
    #echo "DBG: param noauto off - auto mount the partitions & devices"
    #grep /mnt/ /etc/fstab >> /union/etc/mtab # combine into the new mtab
    grep /mnt/ /proc/mounts >> /union/etc/mtab # combine into the new mtab
    #for x in `grep /mnt/ /etc/fstab | cut -d/ -f3`; do mkdir -p /union/mnt/$x; mount -n --move /mnt/$x /union/mnt/$x; rmdir /mnt/$x; done
    #sh # run a shell
    while [ "$mpts" != "$mp" ]; do
	mp=`echo $mpts | cut -d"$sep" -f1` # get first word using our separator
	mpts=`echo $mpts | cut -d"$sep" -f2-` # remove the first word (everything before the first sep)
	echo "mounting --move \"/mnt/$mp\""
	mkdir -p /union/mnt/$mp; mount -n --move /mnt/$mp /union/mnt/$mp; rmdir /mnt/$mp;
    done
    #echo 'DBG: $g_pmpts='$g_pmpts
fi
And we're done :Yahoo!:

I can ensure You, I broke something
Todo: test test test.
The code works for me. I expect suggestions, bugreports, bugfixes.
Last edited by Gele on 28 Aug 2014, 21:37, edited 9 times in total.

Gele
White ninja
White ninja
Posts: 5
Joined: 06 Jan 2011, 01:18
Location: bulgaria

Re: Fixed mount paths for other partitions than root

Post#7 by Gele » 28 Aug 2014, 07:36

If anybody wants to try this, here's quick how-to for newbies:
1. make an empty folder to extract the initrd image, for example porteus:
mkdir -p ~/A_work/porteus
Do this on a filesystem which supports eXecutable flags to preserve the script flags
2. Copy there your boot/syslinux/initrd.xz file. To extract the cpio image, as per Modify Default Files, etc., use the xz de/compressor and pipe it's output to cpio:
xz -d < initrd.xz | cpio -i
rm initrd.xz
# remove the used archive
3. Edit the linuxrc script.
4. Pack it back:
find | cpio -H newc -o | xz --check=crc32 --x86 --lzma2 > ../initrd.xz
Now move the archive back to boot/syslinux/

Post Reply