From old wiki http://en.gentoo-wiki.com/wiki/Squashed_Portage_Tree
This article describes how to reduce the Portage tree, using a squashfs image, to 30-40MB. A good alternative to having the portage tree on a separate partition. For a list of publicly available copies please see the bottom of this article.
Prerequisites¶
Required Packages¶
You will need sys-fs/squashfs-tools which provides mksquashfs,
emerge -av squashfs-tools
And of course the aufs module:
emerge -av aufs3
Note: If you are using kernel 2.6 then emerge sys-fs/aufs2 instead. In case aufs2 complains about missing Symbols related to inotify, you can remove inotify-useflag from aufs as a workaround.
Note: Alternative you can use the “live” ebuild, aufs2-9999 or a kernel source package that includes aufs, like sys-kernel/zen-sources.
Kernel Configuration¶
Kernels based on sys-kernel/gentoo-sources include SquashFS by default.
# Linux Kernel Configuration: SquashFS Kernel Config
Device Drivers --->
Block Devices --->
<M> Loopback device support
File systems --->
Miscellaneous Filesystems --->
<M> SquashFS
It is of course possible to have these built-in, but we avoid a reboot when building these as modules.
Single tree¶
Preparation¶
For a single squashed tree, you will need to move anything not part of the portage tree out of PORTDIR( /usr/portage ). This usally includes DISTDIR and laymans storage. Modify /etc/make.conf,
# File: /etc/make.conf
...
DISTDIR="/var/portage/distfiles"
...
Remove /usr/portage/distfiles,
rm /usr/portage/distfiles -rf
Note: The following step is only needed if you are using a layman version older than 1.2.0
Layman’s configuration file is /etc/layman/layman.cfg. Here we move layman’s storage directory to /var/portage, same directory as DISTDIR,
# File: /etc/layman/layman.cfg
...
storage : /var/portage/layman
...
Move the layman storage directory to our new location,
mv /usr/portage/local/layman /var/portage/layman
init.d/squash_portage¶
Paste this into /etc/init.d/squash_portage,
File: /etc/init.d/squash_portage
#!/sbin/runscript
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
#
# /etc/init.d/squash_portage allows efficient compression of
# Gentoo portage arborescence
#
# It requires support for the loop device and squashfs enabled in the kernel,
# module autoloading is also *highly* recommended.
# sys-fs/squashfs and sys-fs/aufs are necessary for read-write support.
#
# Author: Mathias Laurin <mathias_laurin@users.sourceforge.net>
# 2006-11-28, v.0.1.5(4)
# 2009-02-24, v.0.1.6(1) Weedy <weedy2887@gmail.com>
# 2009-03-20, v.0.1.7(1) j0inty <j0inty@stollfuss.net>
# 2009-07-10, v.0.1.8(1) j0inty
# 2009-09-01. v.0.1.9(1) nall <soir@fuzzysock.net>
extra_started_commands="sync"
source /usr/share/portage/config/make.globals
source /etc/make.conf
SQFS_CUR="$SQFS_DIRNAME/portage.sqfs"
SQFS_NEW="$SQFS_DIRNAME/portage-current.sqfs"
SQFS_OLD="$SQFS_DIRNAME/portage-old.sqfs"
DEF_RW="/dev/shm/.portage-rw"
SQFS_OPTS="-force-uid portage -force-gid portage -no-duplicates"
depend() {
need localmount modules
}
check_support() {
if ! [ -x /usr/bin/mksquashfs ] ; then
eerror "ERROR: sys-fs/squashfs-tools is not installed."
return 1
fi
if ! [ -w /dev/loop0 ] ; then
eerror "ERROR: loopback support is not available."
return 1
fi
if ! [[ $(grep -s $'\taufs$' /proc/filesystems) ]] ; then
eerror "ERROR: aufs filesystem support is not available."
return 1
fi
if ! [[ $(grep -s $'\tsquashfs$' /proc/filesystems) ]] ; then
eerror "ERROR: squashfs filesystem support is not available."
return 1
fi
return 0
}
makeImage() {
mksquashfs $PORTDIR $SQFS_NEW $SQFS_OPTS # 2>/dev/null
retval=$?
ln -sf $SQFS_NEW $SQFS_CUR
eend $retval
}
sync() {
ebegin "Syncing portage tree"
eval $SYNC_CMDS
#svc_stop; svc_start
stop
start
eend 0
}
start() {
check_support || return 1
if [ -f "$SQFS_CUR" ]; then
ebegin "SQFS-PORTAGE: Mounting read-only squashfs image"
mount -rt squashfs -o loop,nodev,noexec $SQFS_CUR $PORTDIR
retval=$?
[ $retval -ne 0 ] && return $retval
else
if [ ! -f "/usr/portage/metadata/timestamp.chk" ]; then
ebegin "SQFS-PORTAGE: $PORTDIR looks empty or corrupted, syncing"
eval $SYNC_CMDS
fi
einfo " $SQFS_CUR does not exist, creating"
mkdir -p $SQFS_DIRNAME
makeImage
[ $? -ne 0 ] && eerror "ERROR: failed to create initial tree image"
einfo "Clearing ${PORTDIR}"
rm -r ${PORTDIR}
mkdir ${PORTDIR}
start
eend 0
fi
ebegin "Mounting read-write with aufs"
if [ ! $PORTAGE_RW ] ; then
einfo " mounted in tmpfs (RAM)"
PORTAGE_RW="${DEF_RW}"
fi
[ -d $PORTAGE_RW ] || mkdir -p $PORTAGE_RW
chmod 0750 $PORTAGE_RW
chown portage:portage $PORTAGE_RW
mount -t aufs -o nodev,noexec,br=$PORTAGE_RW=rw:$PORTDIR=ro aufs $PORTDIR
eend $?
if [ "$DISTDIR" == "/usr/portage/distfiles" ]; then
mkdir -p /usr/local/distfiles
mount -o bind /usr/local/distfiles /usr/portage/distfiles
ewarn "DISTDIR is currently inside the portage tree. It has been bind
mounted to keep the SquashFS image small."
fi
}
stop() {
ebegin "SQFS-PORTAGE: Stopping and unmounting"
[ ! $PORTAGE_RW ] && PORTAGE_RW="${DEF_RW}"
if [ $(du -s --exclude=.w* $PORTAGE_RW | cut -f 1) -gt 4 ]; then
einfo " Changes detected, updating image."
mv -f $SQFS_NEW $SQFS_OLD
makeImage
rm -f $SQFS_OLD
else
einfo " No changes detected, skipping update."
eend 0
fi
if [ "$DISTDIR" == "/usr/portage/distfiles" ]; then
einfo " Unmounting distfiles"
umount /usr/local/distfiles
fi;
einfo " Unmounting the tree"
umount -t aufs $PORTDIR
umount -t squashfs $PORTDIR
rm -rf $PORTAGE_RW
eend 0
}
Make it executable,
chmod 755 /etc/init.d/squash_portage
conf.d/squash_portage¶
Paste this in the corresponding configuration file /etc/conf.d/squash_portage,
# File: /etc/conf.d/squash_portage
# /etc/conf.d/squash_portage
# SQFS_DIRNAME points to the directory that will contain the sqfs
# images, recommended value is /var/portage
SQFS_DIRNAME="/var/portage"
# Leave PORTAGE_RW empty for use with tmpfs, a ram-based filesystem,
# This is recommended unless you are short of RAM
PORTAGE_RW=""
# If you need more then just emerge --sync, or are using another
# package manager add them here. Example SYNC_CMDS="/usr/bin/layman -S; /usr/bin/eix-sync"
SYNC_CMDS="emerge --sync"
Usage¶
To make sure you always have a mounted portage tree:
rc-update add squash_portage default
Now it is time to initialize the tree. Simply start the service.
/etc/init.d/squash_portage start
Multiple trees¶
Note: The following option is only recommended if you know exactly what you intend to do.
Preparation¶
For multiple squashed trees, you probably want to move DISTDIR (usually /usr/portage/distfiles) out of PORTDIR (usually /usr/portage), or else it’ll take a very long time to create a portage sqfs image, without any significant size reduction.
What we’ll describe here is an example configuration, for three trees, each of located in /var/portage/{portage,layman,local}, with it’s original locations being /usr/portage, /usr/local/portage/layman and /usr/local/portage. One could achieve the same with only two trees by merging local with layman. But this would side effect you dependent of layman for your local tree, and our script configuration, to work without modifications.
First we make sure that /var/portage and sub-dirs does exist.
mkdir -p /var/portage/{portage,layman,local}
Remember that we want every tree in /var/portage, and, we also need layman to write it’s overlays to /etc/make.overlays, instead of /usr/local/layman/make.conf. So, modify /etc/make.conf,
Note: Remember to remove the old “source /usr/local/portage/layman/make.conf” before entering the new one
# File: /etc/make.conf
source /etc/make.overlays
...
PORTDIR=/var/portage/portage
LOCALDIR="/var/portage/local"
DISTDIR="/var/portage/distfiles"
...
and /etc/layman/layman.cfg,
# File: /etc/layman/layman.cfg
...
storage : /var/portage/layman
...
make_conf : /etc/make.overlays
...
Move /usr/portage/distfiles,
mv /usr/portage/distfiles /var/portage/distfiles
Or remove /usr/portage/distfiles,
rm /usr/portage/distfiles -rf
Move /usr/local/layman/make.conf,
mv /usr/local/layman/make.conf /etc/make.overlays
Modify /etc/make.overlays overlays to /var/portage/,
Note: Example configuration, you have to adapt your configuration
File: /etc/make.overlays
PORTDIR_OVERLAY="
/var/portage/layman/sunrise
/var/portage/layman/gentoo-china
/var/portage/layman/devnull
/var/portage/layman/kde-testing
/var/portage/layman/mozilla
/var/portage/layman/qting-edge
$PORTDIR_OVERLAY
/var/portage/local"
Before we create the images we need to split layman from local, doing:
mv /usr/local/portage/layman/ /usr/local/layman/
Now we have to create the sqfs images, since our script expect the images to be at /var/portage/, named as sqfs.${TREE}-current.sqfs, we proceed as following:
mksquashfs /usr/portage/ sqfs.portage-current.sqfs
mksquashfs /usr/local/portage/ sqfs.local-current.sqfs
mksquashfs /usr/local/layman/ sqfs.layman-current.sqfs
Since some system files need files at /usr/portage/, we have to symlink after we remove them.
It’s safer to move:
mv /usr/portage/eclass /usr/portage/eclass.old
mv /usr/portage/profiles /usr/portage/profiles.old
After we symlink:
ln -fs /var/portage/portage/eclass/ /usr/portage/eclass
ln -fs /var/portage/portage/profiles/ /usr/portage/profiles
Init script¶
You can now create and configure /etc/init.d/squash_portage, first of all create it:
File: /etc/init.d/squash_portage
#!/sbin/runscript
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
#
# /etc/init.d/squash_portage allows efficient compression of
# Gentoo portage arborescence
#
# It requires support for the loop device and squashfs enabled in the kernel,
# module autoloading is also *highly* recommended.
# sys-fs/squashfs, sys-fs/squashfs-tools and sys-fs/aufs
# or sys-fs/aufs2 (recommended) are necessary for read-write support.
#
# Author: Mathias Laurin <mathias_laurin@users.sourceforge.net>
# 2006-11-28, v.0.1.5(4)
# 2009-02-24, v.0.1.6(1) Weedy <weedy2887@gmail.com>
# 2009-03-20, v.0.1.7(1) j0inty <j0inty@stollfuss.net>
# 2009-07-10, v.0.1.8(1) j0inty
# 2009-08-14, v.0.1.9(1) morris <mauricioarozi@gmail.com>
# 2009-09-01. v.0.1.9(1) nall <soir@fuzzysock.net>
# 2009-11-22, v.0.2.0(3) morris <mauricioarozi@gmail.com>
opts="sync"
depend() {
need localmount modules
}
retuval() {
retval=${1}
eend ${retval}
[ ${retval} -ne 0 ] && \
ewarn "${2}" && \
return 1
}
check_support() {
if ! [ -x /usr/bin/mksquashfs ] ; then
eerror "ERROR: sys-fs/squashfs-tools is not installed."
return 1
fi
if ! [ -w /dev/loop0 ] ; then
eerror "ERROR: loopback support is not available."
return 1
fi
if ! [[ $(grep -s aufs /proc/filesystems) ]] ; then
eerror "ERROR: aufs filesystem support is not available."
return 1
fi
if ! [[ $(grep -s squashfs /proc/filesystems) ]] ; then
eerror "ERROR: squashfs filesystem support is not available."
return 1
fi
}
sync() {
source /etc/make.globals # MUST source inside function, causes initramfs errors otherwise
source /etc/make.conf
ebegin "Syncing portage tree"
if [ ${SYNC_CMD} ]; then
eval ${SYNC_CMD}
else
[ -x '/usr/bin/emerge' ] && local SYNC_CMD='command emerge --sync'
[ -x '/usr/bin/paludis' ] && local SYNC_CMD='command paludis --sync'
[ -x '/usr/bin/eix' ] && local SYNC_CMD='command eix-sync'
# make eix-sync work with layman overlays shound't be default
# [ -x '/usr/bin/eix' ] && [ -x '/usr/bin/layman' ] && [ ! -f /etc/eix-sync.conf ] && `/bin/echo '*' > /etc/eix-sync.conf`
eval "${SYNC_CMD}"
fi
retuval ${?} "Error: ${SYNC_CMD}"
stop
start
eend 0
}
start() {
source /etc/make.globals # MUST source inside function
source /etc/make.conf
ebegin "Mounting read-only squashfs image(s)"
check_support
if [ ! -d "${SQFS_DIRNAME}" ]; then
einfo "${SQFS_DIRNAME} does not exist, creating"
mkdir -p "${SQFS_DIRNAME}"
retuval ${?} "Error: mkdir -p ${SQFS_DIRNAME}"
fi
for i in ${SQFSS[@]}; do
einfo "Mounting ${i}"
mount -rt squashfs -o loop,nodev,noexec "${SQFS_DIRNAME}/sqfs.${i}-current.sqfs" "${SQFS_DIRNAME}/${i}"
retuval ${?} "Error: mount -rt squashfs -o loop,nodev,noexec \"${SQFS_DIRNAME}/sqfs.${i}-current.sqfs\" \"${SQFS_DIRNAME}/${i}\""
[ "${SQFS_DIST}" ] || \
if [ `echo ${DISTDIR} | grep "${SQFS_DIRNAME}/${i}"` ]; then
mkdir -p /usr/local/distfiles
retuval ${?} "Error: mkdir -p /usr/local/distfiles"
mount -o bind "/usr/local/distfiles" "${DISTDIR}"
retuval ${?} "Error: mount -o bind /usr/local/distfiles ${DISTDIR}"
ewarn "DISTDIR is currently inside of ${SQFS_DIRNAME}/${i} tree.
It has been bind mounted to keep the SquashFS image small."
fi
done; unset i rw
einfo "Mounting read-write with aufs"
for i in `seq 0 $[${#FSRW[@]}-1]`; do
local RW=${FSRW[${i}]:-"/dev/shm/.${SQFSS[${i}]}-rw"}
[ -d "${RW}" ] || einfo "Creating ${RW}" && mkdir -p "${RW}"
retuval ${?} "Error: mkdir -p \"${RW}\""
chmod 0750 "${RW}"
retuval ${?} "Error: chmod 0750 \"${RW}\""
chown portage:portage "${RW}"
retuval ${?} "Error: chown portage:portage \"${RW}\""
done; unset a i rw
for i in ${SQFSS[@]}; do
[ ${a} ] && a=$[${a}+1] || local a=0
local RW=${FSRW[${a}]:-"/dev/shm/.${i}-rw"}
einfo "${RW}"
mount -t aufs -o "nodev,noexec,br:${RW}=rw:${SQFS_DIRNAME}/${i}=ro" aufs "${SQFS_DIRNAME}/${i}"
retuval ${?} "Error: mount -t aufs -o \"nodev,noexec,br:${RW}=rw:${SQFS_DIRNAME}/${i}=ro\" aufs \"${SQFS_DIRNAME}/${i}\""
einfo "${SQFSS[${a}]} mounted in ${RW}"
done; unset a i rw
eend ${?}
}
stop() {
source /etc/make.globals # MUST source inside function
source /etc/make.conf
check_support
if [ "$RC_RUNLEVEL" != shutdown ]; then # OpenRC timeout doesn't allow this kind of thing
ebegin "Updating portage tree"
for i in `seq 0 $[${#FSRW[@]}-1]`; do
local RW=${FSRW[${i}]:-"/dev/shm/.${SQFSS[${i}]}-rw"}
einfo "Syncing the tree ${SQFSS[${i}]}"
if [ ! -z "`/bin/ls -A "${RW}" | /bin/grep -v .wh.`" ]; then
einfo "Syncing..."
local SOLD="${SQFS_DIRNAME}/sqfs.${SQFSS[${i}]}-old.sqfs"
local SNEW="${SQFS_DIRNAME}/sqfs.${SQFSS[${i}]}-current.sqfs"
local SS="${SQFS_DIRNAME}/sqfs.${SQFSS[${i}]}.sqfs"
mv -f "${SNEW}" "${SOLD}"
retuval ${?} "Error: mv -f \"${SNEW}\" \"${SOLD}\""
[ -w "${SQFS_DIRNAME}" ] && \
/usr/bin/mksquashfs "${SQFS_DIRNAME}/${SQFSS[${i}]}" "${SNEW}" ${SQFS_OPTS}
retuval ${?} "Error: /usr/bin/mksquashfs \"${SQFS_DIRNAME}/${SQFSS[${i}]}\" \"${SNEW}\" ${SQFS_OPTS}"
/bin/ln -fs "${SNEW}" "${SS}"
retuval ${?} "Error: /bin/ln -fs \"${SNEW}\" \"${SS}\""
else
einfo "Nothing to do"
fi
done; unset a i retval
fi
ebegin "Unmounting the tree(s)"
for i in ${SQFSS[@]}; do
[ ${a} ] && a=$[${a}+1] || local a=0
local RW=${FSRW[${a}]:-"/dev/shm/.${i}-rw"}
umount -f -l -t aufs "${SQFS_DIRNAME}/${i}"
retuval ${?} "Error: umount -f -l -t aufs \"${SQFS_DIRNAME}/${i}\""
umount -f -l -t squashfs "${SQFS_DIRNAME}/${i}"
retuval ${?} "Error: umount -f -l -t squashfs \"${SQFS_DIRNAME}/${i}\""
/bin/rm -fr "${RW}"
retuval ${?} "Error: /bin/rm -fr \"${RW}\""
done; unset i retval
eend 0
}
Make it executable,
chmod 755 /etc/init.d/squash_portage
Now to configure, create and edit the corresponding configuration file /etc/conf.d/squash_portage,
Note: Configuration file for example setup, remember to change it!
# File: /etc/conf.d/squash_portage
# /etc/conf.d/squash_portage
# Fill SQFS_DIST with anything if you don't mind to squash your distfiles
# It is recommended to leave blank
SQFS_DIST=""
# SQFS_DIRNAME points to the directory that will contain the sqfs images
SQFS_DIRNAME="/var/portage"
# Options used for ALL image creations
# Do not change unless you know what you are doing
SQFS_OPTS="-force-uid portage -force-gid portage -no-duplicates"
# Populate FSRW array with nulls ("", '', 0...) to use tmpfs, a ram-based filesystem,
# This is recommended unless you are short of RAM
FSRW=('' '' '')
# FS mount array, used in substitution: ${SQFS_DIRNAME}/${SQFSS[@]}
SQFSS=("portage" "local" "layman")
# If you need more than just emerge --sync, or are using another
# package manager add them here. Example SYNC_CMDS="/usr/bin/layman -S; /usr/bin/eix-sync"
SYNC_CMD="eix-sync"
# Note: eix-sync can run `layman -S` automatically if you run `echo '*' > /etc/eix-sync.conf` once
Check your initial setup running the script once.
/etc/init.d/squash_portage start
Now complete your setup restarting it, so it will create necessary symlinks while stopping.
/etc/init.d/squash_portage restart
To make sure you always have a mounted portage tree:
rc-update add squash_portage default
If everything went alright, you can now delete the all old trees content but /usr/portage/eclass and /usr/portage/profiles links from /usr/ if you want.
Usage¶
You can sync the trees with:
/etc/init.d/squash_portage sync
You can also start, stop, and restart it:
/etc/init.d/squash_portage start
/etc/init.d/squash_portage stop
/etc/init.d/squash_portage restart
Note: Restart is useful if you synced trees manually, and want to sync just the sqfs images automatically
Comments