As you may know, the /lib directory is now a sym-link pointing to /usr/lib (see http://www.archlinux.org/news/the-lib-d … -symlink/). Squashing the /usr directory the way described here causes problems when update the kernel for example (because /usr/lib/modules/ is not mounted during early userspace, the modules for the new kernel are missing even if one had kept the former /usr/lib on the root partition).
Here is a hook for mkinitcpio to mount the squashed /usr directory soon enough to avoid those issues. It has been inspired by the "usr" and the "rootaufs" hooks. Here is the /usr/lib/initcpio/hooks/aufsusr file:
#!/usr/bin/ash
run_latehook () {
#check if wanted
if [ "x${aufsusr}" = "x" ]; then
return
fi
#defaults
if [ "${aufsusr}" == "y" ]; then
aufsusr="/squashed/usr"
fi
if [ "x${squashedusr}" = "x" ]; then
squashedusr="$aufsusr/usr.sfs"
fi
#load modules
/sbin/modprobe aufs
if [ $? != 0 ]; then
msg ":: aufsusr: Could NOT load aufs module, bailing out"
launch_interactive_shell
return
fi
/sbin/modprobe loop
/sbin/modprobe squashfs
#fs tree
squashedusr_nr="/new_root/$squashedusr"
aufs_ro="/new_root/$aufsusr/ro"
aufs_rw="/new_root/$aufsusr/rw"
#mount "ro":
msg ":: Mounting squashed ro usr directory..."
if [ ! -f "$squashedusr_nr" ]; then
msg ":: aufsusr: $squashedusr does not exist, bailing out"
launch_interactive_shell
return
fi
mkdir -p "$aufs_ro"
/bin/mount -t squashfs -o loop,ro "$squashedusr_nr" "$aufs_ro"
#mount "aufs"
msg ":: Mounting aufs usr..."
mkdir -p "$aufs_rw"
/bin/mount -t aufs -o br:"$aufs_rw"=ro:"$aufs_ro"=rr usr /new_root/usr
}
# vim: set ft=sh ts=4 sw=4 et:
together with an installation file /usr/lib/initcpio/install/aufsusr
# vim:set ft=sh:
build ()
{
add_module aufs
add_module squashfs
add_module loop
add_runscript
}
In order to use it, one need to re-mkinitcpio the kernel after having added "aufsusr" and "shutdown" at the end of the hook list in /etc/mkinitcpio.conf
One moreover need to have an aufs-friendly kernel and aufs3 installed, both of which can be found on the AUR.
Now assuming the /squashed/usr/usr.sfs have been build as before and that /squashed/usr/rw and /squashed/usr/ro do exist, one would need to adapt the corresponding menuentry in /boot/grub/grub.cfg by adding the aufsusr option to the linux command.
linux /vmlinuz-linux-aufs_friendly root=[...] ro quiet aufsusr
The hook also allows you to override the /squashed/usr/ by setting aufsusr=/path/to/where/you/wanna/be and to override the path to your squashfs file by adding squashedusr=/path/to/the/squashfs/file.sfs
Finally, remember to add the proper lines to your /etc/fstab file. As explained in the above posts, we are to add two lines to this file:
/squashed/usr/usr.sfs /squashed/usr/ro squashfs loop,ro 0 0
usr /usr aufs br:/squashed/usr/rw=rw:/squashed/usr/ro=rr 0 0
There is though a little something to change. Because the aufs /usr is already mounted by the hook in READ-ONLY mode, we need to change this mode to READ-WRITE. The br option is thus replaced by a mod option (see man aufs for details) and the squashfs line is not needed anymore:
#/squashed/usr/usr.sfs /squashed/usr/ro squashfs loop,ro 0 0
usr /usr aufs mod:/squashed/usr/rw=rw 0 0
I still have a few remarks about it:
When running mkinitcpio, you can have some error looking like "fsck.aufs does not exist". This comes from the fact that aufs is not a real file system. To avoid it, I added a symlink /sbin/fsck.aufs pointing to /bin/true This is a bit coarse and there must be a better way.
Another thing is the udba=reval mount option which we can see in the gentoo script. This option is setting some security against aufs problems when modifying files directly in /squashed/usr/rw/. Keeping the option causes some error, I don't really understand why because this option works when mounting something after boot. The result is: DO NOT MODIFY THE /squashed/usr/rw/ CONTENT.
A last remark will of course be: USING ALL THIS IS YOUR RESPONSABILITY...
I would be thankful if someone has some comments and/or improvements.
EDIT: Added the part about /etc/fstab.
EDIT2: Some weird bug happened at shutdown after a while. Even though having it working back is possible, this whole thing may deserve being deleted...
]]>Are the upgraded packages going to be there when I reboot? Do I have to recompress /usr after every upgrade? I realize that they at least wont be compressed, but I just don't understand what is happening.
The directory /squashed/usr/rw is overlayed over /usr so any packages added/removed use this instead of /usr (read only).
Data written is uncompressed and is persistent. For example, you upgrade pacman on a system with a newly compressed /usr and files will need to go into
/usr/bin, /usr/include, /usr/lib and /usr/share
but instead those directories will now be in
/squashed/usr/rw/bin, /squashed/usr/rw/include, /squashed/usr/rw/lib and /squashed/usr/rw/share
When you recompress /usr, these changes are included into the new squashed image. This includes any packages removed from the system as well.
How often you recompress /usr is up to you. After doing pacman -Syu a few times you'll find /squashed/usr/rw starts to fill in size.
]]>What happens when we do an upgrade while the compressed /usr is mounted?
Are the upgraded packages going to be there when I reboot? Do I have to recompress /usr after every upgrade? I realize that they at least wont be compressed, but I just don't understand what is happening.
]]>Is there any clue to solve this problem?
EDIT:
-=solved=-
]]>#!/bin/bash
#This script comes with ABSOLUTELY NO WARRANTY use it at your own risk!
#cron job to rebuild the squashfs image of /usr
if [[ -e /var/lib/pacman/db.lck ]]; then
exit
fi
touch /var/lib/pacman/db.lck
mksquashfs /usr /squashed/usr/usr_tmp.sfs -b 65536 || return 1
umount -l /usr
umount -l /squashed/usr/ro
rm /squashed/usr/usr.sfs
mv /squashed/usr/usr_tmp.sfs /squashed/usr/usr.sfs
rm -rf /squashed/usr/rw/*
mount /squashed/usr/ro
mount /usr
rm /var/lib/pacman/db.lck
Is the script I now use.
]]>#!/bin/bash
#This script comes with ABSOLUTELY NO WARRANTY use it at your own risk!
#cron job to rebuild the squashfs image of /usr
if [[ -e /var/lib/pacman/db.lck ]]; then
exit
fi
mksquashfs /usr /squashed/usr/usr_tmp.sfs -b 65536 || exit 1
umount -l /usr
umount -l /squashed/usr/ro
rm /squashed/usr/usr.sfs
mv /squashed/usr/usr_tmp.sfs /squashed/usr/usr.sfs
rm -rf /squashed/usr/rw/*
mount /squashed/usr/ro
mount /usr
#!/bin/bash #This script comes with ABSOLUTELY NO WARRANTY use it at your own risk! #cron job to rebuild the squashfs image of /usr if [[ -e /var/lib/pacman/db.lck ]]; then exit fi mksquashfs /usr /squashed/usr/usr_tmp.sfs -b 65536 umount -l /usr umount -l /squashed/usr/ro rm /squashed/usr/usr.sfs mv /squashed/usr/usr_tmp.sfs /squashed/usr/usr.sfs rm -rf /squashed/usr/rw/* mount /squashed/usr/ro mount /usr
I would add touch /var/lib/pacman/db.lck and rm /var/lib/pacman/db.lck before mksquashfs and after mount to prevent the user from doing anything stupid
]]>mksquashfs /usr /squashed/usr/usr_tmp.sfs -b 65536
...
mv /squashed/usr/usr_temp.sfs /squashed/usr/usr.sfs
I think there might be some use for more error checking, although I'm not sure where yet. I don't know what happened exactly, but when I woke up I didn't have any usr.sfs or usr_tmp.sfs (so nothing in /usr, and nothing to put there). I'm assuming it ran as a cron job, since I don't what else would mess with it.
Once I've finished getting /usr back to normal I'll try this again and see if I can figure out what I did. Cool script, though.
]]>echo "umount -l /usr"
echo "umount -l /squashed/usr/ro"
shouldn't
/bin/umount -a -r -t noramfs,notmpfs,nosysfs,noproc -O no_netdev
do the job already?
]]>#checks to see if the user is root
if [[ $UID != "0" ]];then
exit
#next
would be more the Arch way rather than covering the whole script with if-fi clause.
Also, in the rebuild script it is not necessary to have an else-clause since it wouldn't be executed once it exits
#move the /usr folder instead of deleting it
sudo mv /usr /usr.old
sudo mkdir /usrA little problem.
You can't sudo after you moved sudo.
Got it working though
Good catch I didn't think of that. I added an if statement that will only continue running the program if the user is root.
edit: I just started using this and I don't think I'm going to continue using it since I tend to install and uninstall stuff a lot and that would mean a lot of image recreations :-/
]]>