Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Portage in 20MB (create-portage-squash)
View unanswered posts
View posts from last 24 hours
View posts from last 7 days

 
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German) Deutsche Dokumentation
View previous topic :: View next topic  
Author Message
sirro
Veteran
Veteran


Joined: 20 Jul 2003
Posts: 1472
Location: aachen.nrw.de.eu

PostPosted: Thu Oct 21, 2004 4:50 pm    Post subject: Portage in 20MB (create-portage-squash) Reply with quote

Einleitung
Vor einiger Zeit [1] wurde hier das Thema Groesse des Portage, insbesondere auf kleinen Platten, angeprochen. Neben Rsync_excludes [2] (evtl. recht wenig Einsparung) und einem ISO mit besonders kleiner Blockgroesse (unflexibel, da groesse vorgplant werden muss) wurde dort auch die Moeglichkeit eines komprimierten Dateisystems angesprochen. Entscheidender Nachteil dieser Loesung ist, dass alle mir bekannten komprimierenden Dateisysteme (cloop, squashfs etc.) read-only sind, ein emerge sync auf einem solchen also unmoeglich. Also heisst es sich immer ein neues .iso zu erstellen.

Motivation
Nachdem meine geliebten hardened-dev-sources im neuen Release squashfs [4] mit drin hatte, war es fuer mich an der Zeit soetwas einmal auszuprobieren. Als fauler User habe ich natuerlich erstmal ein Skript (um)geschrieben, das mir die Sache extrem vereinfacht und dieses moechte ich nun mit euch teilen ;-)

Credits
Mein Dank geht dabei an Karl Trygve Kalleberg (karltk) fuer das uespruengliche Skript, an Christian Hartmann (Ian) fuer die modifizierte Version [3] (hauptsaechlich in der fetch_snapshot() zu finden) und an www.gentoo.de fuer die Snapshots (sorry fuer die paar MB mehr heute ;-)).

Disclaimer
Eins vorweg: Anregungen, Kritik, Verbesserungen und Fehler koennen gerne hier im Thread diskutiert werden oder mir per PN geschickt werden.

Installation
  • Kernel mit squashfs-Unterstuetzung kompilieren und installieren
  • Skript downloaden (z.B.: /root/bin/create-portage-squash)
  • Datei ausfuehrbar machen (z.B.: chmod u+x /root/bin/create-portage-squash)
  • Skript starten
  • Datei mounten (z.B.: mount -o loop,ro,nodev,nosuid -t squashfs /root/portage.iso)
  • Datei in /etc/fstab eintragen. Altes Portage natuerlich loeschen, sonst spart es nix ;-)

Bedienung
  • ein einfaches create-portage-squash erzeugt aus dem aktuellen Portage (in $PORTDIR) ein squashfs in /root/portage.iso
  • create-portage-squash -f laedt einen kompletten Portage-Snapshot (ca. 16MB) mit dem bereits erwaehnten emerge-websync-de Code [3] und wandelt diesen in ein squashfs in /root/portage.iso
  • mit dem Parameter -o stellt man die Ausgabedatei um
  • -e bestimmt eine Excludes-Datei, die alle in der Datei gelisteten Dateien und Verzeichnisse auschliesst. (oder default: /etc/portage/squash_excludes)
  • weitere Parameter bringt der Aufruf create-portage-squash -h"

Skript
Code:
#!/bin/sh
# Copyright 1999-2003 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2

# Author: Karl Trygve Kalleberg <karltk  'at` gentoo 'dot` org>
# Rewritten from the old, Perl-based emerge-webrsync script
#
# Changelog:
# emerge-webrsync for hourly snapshots at http://www.gentoo.de/pub/gentoo/snapshots/
# Christian Hartmann <ian 'at` gentoo 'dot` org>
#
# create-portage-squash-0.1 (21 Oct 2004) for creating a squashfs portage based
# on PORTDIR or the latest hourly snapshot from gentoo.de
# sirro <sirro 'at` nurfuerspam 'dot`de>

init_variables() {
        SYNCPATH="/var/tmp/emerge-webrsync"
        GENTOO_MIRRORS="http://www.gentoo.de/pub/gentoo"
        PORTDIR="$(/usr/lib/portage/bin/portageq portdir)"

        #some create-portage-squash specific settings
        if [ -r "/etc/portage/squash_excludes" ]; then
                SQUASH_EXCLUDEFROM="/etc/portage/squash_excludes"
        else
                SQUASH_EXCLUDEFROM="/dev/null"
        fi
        PORTAGE_ISO="/root/portage.iso"
        REMOVE_SNAPSHOT=true
        VERBOSE="size"

        if ! which mksquashfs &>/dev/null; then
                echo " !!! mksquashfs not found, please install sys-fs/squashfs-tools"
                exit 1
        fi
}

fetch_snapshot() {
        local attempts=0
        local wgetops=

        if [ ! -d ${SYNCPATH} ]; then mkdir -p ${SYNCPATH}; fi
        cd ${SYNCPATH}
        echo " *** Fetching most recent snapshot"

        while (( ${attempts} <  40 )) ; do
                day=`date -d "-${attempts} day" +"%d"`
                month=`date -d "-${attempts} day" +"%m"`
                year=`date -d "-${attempts} day" +"%Y"`

                attemptsHour=0
                while (( ${attemptsHour} < 24 )) ; do

                        hour=`date -d "-${attemptsHour} hour" +"%H"`
                        SNAPSHOT_FILE="portage-${year}${month}${day}-${hour}.tar.bz2"

                        echo "Trying ${SNAPSHOT_FILE}"

                        if [ -s ${SNAPSHOT_FILE} ]; then
                                return 0
                        fi

                        for i in ${GENTOO_MIRRORS} ; do
                                url="${i}/snapshots/${SNAPSHOT_FILE}"
                                if (wget ${wgetops} ${url}) \
                                                && [ -s ${SNAPSHOT_FILE} ] ; then
                                        echo " *** The snapshot-date (YYMMDD-HH): ${year}${month}${day}-${hour}"
                                        cd - &>/dev/null
                                        return 0
                                fi
                        done
                        attemptsHour=$[attemptsHour+1]

                done
                attempts=$[attempts+1]
        done

        cd - &>/dev/null
        return 1
}

unpack_snapshot() {
        cd ${SYNCPATH}
        echo " *** Extracting compressed portage... (This may take a while)"
        tar --exclude-from ${SQUASH_EXCLUDEFROM} -xjf ${SNAPSHOT_FILE}
        if ${REMOVE_SNAPSHOT}; then
                rm -f ${SNAPSHOT_FILE};
        else
                echo " *** ${REMOVE_SNAPSHOT} is still in ${SYNCPATH}"
        fi
        # Make sure user and group file ownership is root
        chown -R root:root portage
        cd - &>/dev/null
}

cleanup() {
        echo " *** Cleaning up..."
        if [ -d "${SYNCPATH}/portage" ]; then rm -rf "${SYNCPATH}/portage"; fi
        if [ -f "${SYNCPATH}/${SNAPSHOT_FILE}" ] && ${REMOVE_SNAPSHOT}; then
                rm -f "${SYNCPATH}/${SNAPSHOT_FILE}";
        fi
}

diplay_help() {
        local SCRIPT_NAME=$(basename ${0})
        echo "SYNTAX: ${SCRIPT_NAME} [options]"
        echo "Options are:"
        echo -e "\t-e file\t exclude files listed in \"file\" (* wildcard allowed)"
        echo -e "\t-f\t fetch and use snapshot from gentoo.de for the squashfs"
        echo -e "\t-h\t display this help"
        echo -e "\t-k\t keep snapshots in tempdir"
        echo -e "\t-o file\t use \"file\" as outputfile (defaults to ${PORTAGE_ISO})"
        echo -e "\t-t dir\t use \"dir\" as tempdir (defaults to ${SYNCPATH})"
        echo -e "\t-v\t be verbose"
        echo
        echo "This script generates a squashfs-portage either from your PORTDIR or from"
        echo "a recent snapshot file downloaded from gentoo.de (see options above)."
        echo
        echo "Config files:"
        echo -e "/etc/portage/squash_excludes\tfiles/dirs listed in this file will be"
        echo -e "\t\t\t\texluded from squashfs (see also: option -e)"
}


######### main starts here #########

#catch some signals
trap 'cleanup; exit 1' TERM INT

init_variables

while getopts hko:e:t:fv opt; do
        case $opt in
        #fetch
        f)      if fetch_snapshot; then
                        unpack_snapshot
                        PORTDIR="${SYNCPATH}/portage"
                else
                        echo " !!! Failed fetching a recent snapshot"
                        cleanup
                        exit 1
                fi ;;
        #help
        h)      diplay_help
                exit 0 ;;
        #keep snapshots
        k)  REMOVE_SNAPSHOT=false;;
        #output-file
        o)      PORTAGE_ISO="${OPTARG}" ;;
        #exclude-file
        e)      if [ -r "${OPTARG}" ]; then
                        SQUASH_EXCLUDEFROM="${OPTARG}";
                else
                        echo " !!! Could not read ${OPTARG}"
                        exit 1
                fi ;;
        #temp-file
        t)      SYNCPATH="${OPTARG}" ;;
        #verbose
        v)      VERBOSE="^" ;;
        esac
done

if [ ! -d ${SYNCPATH} ]; then mkdir -p ${SYNCPATH}; fi

#the local rsync is a workaround to get the squashexcludes working.
#mksquashfs seems to ignore files from my scrip without any obvious reason :(
#on commandline it is working fine...
if [ ! -d "${SYNCPATH}/portage" ]; then
        echo " *** Creating a temp copy of your portage (without the specified excludes)"
        mkdir -p "${SYNCPATH}/portage"
        rsync -a --exclude-from=${SQUASH_EXCLUDEFROM} --exclude='distfiles' \
                --exclude='packages' ${PORTDIR%%/} "${SYNCPATH}"
fi

echo " *** Building squashed portage file system to ${PORTAGE_ISO}"
if ! mksquashfs ${SYNCPATH}/portage/* ${PORTAGE_ISO} -noappend \
                | grep ${VERBOSE}; then

        if [ -f ${PORTAGE_ISO} ]; then rm -f ${PORTAGE_ISO}; fi
        echo " !!! Failed to build squashed portage file"
fi

cleanup
exit 0


Ergebnis
Bei einem kompletten Portage ist mir eine Einsparung von ca. 95% auf 20MB moeglich. Mit den excludes bekomme ich es fuer meinen Laptop sogar auf 11MB.
Natuerlich ist das ganze nur da sinnvoll wo Plattenplatz knapp ist, da die Dekomprimiererei natuerlich zu Lasten der Performance geht...

Quellen
[1] https://forums.gentoo.org/viewtopic.php?t=225745
[2] https://forums.gentoo.org/viewtopic.php?t=173433
[3] https://forums.gentoo.org/viewtopic.php?p=969443#969443
[4] http://squashfs.sourceforge.net

Changelog
2006/01/14: Das Skript in den Text gepackt.


Last edited by sirro on Sat Jan 14, 2006 12:27 pm; edited 1 time in total
Back to top
View user's profile Send private message
lolli78
Apprentice
Apprentice


Joined: 14 Jan 2004
Posts: 162
Location: Europe

PostPosted: Thu Oct 21, 2004 5:20 pm    Post subject: Reply with quote

hallo sirro,
danke dafür. ich hab mir sowas auch mal überlegt, aber ich wusste nicht, how to... demnächst muss ich mal squashfs installieren.

hast du zufällig auch so eine lösung für /var/db/pkg? bei mir liegen da 74mb drin, die sich sicher auch gut komprimieren lassen.

danke,
lorenz
_________________
frag' doch deinadmin.de
Back to top
View user's profile Send private message
sirro
Veteran
Veteran


Joined: 20 Jul 2003
Posts: 1472
Location: aachen.nrw.de.eu

PostPosted: Thu Oct 21, 2004 5:23 pm    Post subject: Reply with quote

lolli78 wrote:
hast du zufällig auch so eine lösung für /var/db/pkg? bei mir liegen da 74mb drin, die sich sicher auch gut komprimieren lassen.

Da /var/db ja recht dynamisch bleiben muss, ist squashfs keine geeignete Loesung. Es sein dann man will auf jegliches Installieren verzichten 8)

Die IMO beste Moeglichkeit ist IMO ein ext2 .iso mit ganz kleiner Blockgroesse zu erzeugen und das zu mounten. So grosse Einsparungen wie mit squashfs sind damit natuerlich nicht moeglich, aber bei vielen kleinen Dateien sind auch schonmal 50% drin und man bleibt recht flexibel. (siehe auch [1])


[1] https://forums.gentoo.org/viewtopic.php?p=1567001#1567001
Back to top
View user's profile Send private message
c07
Veteran
Veteran


Joined: 25 Oct 2002
Posts: 1091

PostPosted: Tue Dec 14, 2004 7:33 am    Post subject: Reply with quote

sirro wrote:
Die IMO beste Moeglichkeit ist IMO ein ext2 .iso mit ganz kleiner Blockgroesse zu erzeugen und das zu mounten.

Allerdings kann ext2 keine kleinen Blockgrößen (Minimum ist 1024) und braucht für 1 Byte (was hier sehr häufig ist) mindestens 1152 Bytes (inkl. Inode).

Ich hab es aber mal mit ein paar Dateisystemen ausprobiert. Zunächst die Daten (Ausgaben gekürzt):
Code:
~ # dd if=/dev/zero of=/tmp/pkg bs=64M count=1
~ # losetup /dev/loop0 /tmp/pkg
~ # du -sk /var/db/pkg
32972   /var/db/pkg

~ # mkfs.ext2 -b4096 -m0 -i6144 /dev/loop0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
~ # df /mnt/tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/loop0               64152     62056      2096  97% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck -f /dev/loop0
/dev/loop0: 10277/10944 files (0.0% non-contiguous), 15860/16384 blocks

~ # mkfs.ext2 -b1024 -m0 -i6144 /dev/loop0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
~ # df /mnt/tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/loop0               64141     32983     31158  52% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck -f /dev/loop0
/dev/loop0: 10277/10944 files (0.1% non-contiguous), 34378/65536 blocks

~ # mkfs.minix -i10944 -v /dev/loop0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
(35 Dateien und 1 Ordner (gut 57 KB) wegen zu langem Namen gescheitert)
~ # df /mnt/tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/loop0               64840     33123     31717  52% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck -fv /dev/loop0
 10231 inodes used (93%)
 33819 zones used (51%)

~ # mkfs.vfat -F32 -s1 -f1 -r160 -v /dev/loop0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
~ # df /mnt/tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/loop0               65012     27976     37037  44% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck /dev/loop0
/dev/loop0: 10266 files, 55951/130024 clusters

~ # mkfs.reiserfs -qb1024 -s513 /dev/loop0
~ # mount -treiserfs /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg/* /mnt/tmp
~ # df /mnt/tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/loop0               65527     25875     39652  40% /mnt/tmp
~ # umount /mnt/tmp
~ # fsck.reiserfs /dev/loop0
        Leaves 2048
        Internal nodes 54
        Directories 427
        Other files 9840
        Data block pointers 23196 (0 of them are zero)
        Safe links 0

Inodes hab ich äußerst knapp vergeben, dafür bei FAT auch nur 1 FAT. Bei ext2 spart eine Blockgröße von 1024 Bytes gegenüber den geläufigen 4096 fast die Hälfte. Allerdings muss man bei einem Loop-Device natürlich etwas Reserve einrechnen.

Bei Minix ist die maximale Länge der Dateinamen ein Problem. Die alte Version ist noch ein bisschen sparsamer, aber bei 64 MB am Limit. Ähnlich wär bei FAT bis 32 MB noch FAT16 mit 512-Byte-Clustern möglich, was auch etwas sparsamer ist. Reiser (3.6) ist von den getesteten Systemen am sparsamsten. Womöglich würden 512-Byte-Blocks noch was bringen, aber die funktionieren nicht.

Beim Kopieren in das frische Loop-Dateisystem ist der Geschwindigkeitsverlust gegenüber normalem Kopieren nicht groß, wobei Reiser deutlich langsamer als die Anderen ist und dabei auch noch mehr CPU braucht. 1024er-ext2 ist spürbar schneller, aber das könnte auch dran liegen, dass 1024 meine echte Blockgröße ist.

JFS und XFS hab ich nicht im Kernel, aber für diesen Zweck könnten sie durchaus interessant sein, weil sie sehr kleine Dateien direkt im Inode speichern können. Der ist bei JFS allerdings schon 512 Bytes groß, bei XFS einstellbar ab 256 Bytes.

Eigentlich bräuchte man aber ein spezialisiertes Dateisystem, das auch seine Größe dynamisch ändern kann, was aber wahrscheinlich gar nicht über ein normales Loop-Device möglich ist.
Back to top
View user's profile Send private message
moe
Veteran
Veteran


Joined: 28 Mar 2003
Posts: 1289
Location: Potsdam / Germany

PostPosted: Tue Dec 14, 2004 9:31 am    Post subject: Reply with quote

Habs mal mit xfs probiert, wusste allerdings nicht mit den ganzen Optionen etwas anzufangen:
Code:

# du -sk /var/db/pkg
137884  /var/db/pkg
# dd if=/dev/zero of=vardbpkg bs=150M count=1
# mkfs.xfs -b size=512 vardbpkg
# cp -a /var/db/pkg/* /mnt/floppy
# df
/root/vardbpkg          151128     69331     81797  46% /mnt/floppy


aber das mit dem Squashfs ist wirklich nicht schlecht, und readonly ist zwar etwas umständlicher beim syncen, dafür aber zusätzliche Sicherheit im laufenden Betrieb..

Gruss Maurice
Back to top
View user's profile Send private message
c07
Veteran
Veteran


Joined: 25 Oct 2002
Posts: 1091

PostPosted: Tue Dec 14, 2004 5:13 pm    Post subject: Reply with quote

Ich hab es jetzt auch noch mal mit JFS und XFS probiert. Die Werte sind zu den obigen vergleichbar, weil ich /var/db/pck gesichert hab, vor ich jfsutils und xfsprogs emergt hab.

JFS war für diesen Zweck ein Griff ins Klo. Lässt sich freiwillig nur mit 4KB-Blöcken formatieren und passt dann nicht mehr in die 64 MB (braucht ungefähr 70 MB). Zwar ist mkfs.jfs auf die Blockgrößeneinstellung vorbereitet (2-Zeilen-Patch), aber mit 512 Bytes lässt es sich nicht mehr mounten. Da ist scheinbar der Support im Kernel noch nicht vorhanden.

Bei XFS kann man an sehr vielen Stellen schrauben, wobei die Auswirkungen enorm sind. Ich hab eigentlich nur alle Blockgrößen auf das Minimum gedreht:
Code:
~ # mkfs.xfs -fbsize=512 -isize=256 -lsize=927b -nsize=512 /dev/loop0
meta-data=/dev/loop0             isize=256    agcount=4, agsize=32768 blks
         =                       sectsz=512
data     =                       bsize=512    blocks=131072, imaxpct=25
         =                       sunit=0      swidth=0 blks, unwritten=1
naming   =version 2              bsize=512
log      =internal log           bsize=512    blocks=927, version=1
         =                       sectsz=512   sunit=0 blks
realtime =none                   extsz=65536  blocks=0, rtextents=0
~ # mount /dev/loop0 /mnt/tmp
~ # cp -a /var/db/pkg-old/* /mnt/tmp
~ # df /mnt/tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/loop0               65073     30662     34411  48% /mnt/tmp

Das ist auch ziemlich platzsparend, aber die Performance lässt sehr zu wünschen übrig (braucht für das Kopieren ungefähr dreimal so lang wie 1024er-ext2 und doppelt so lang wie Reiser). Wobei natürlich die Performance im laufenden Betrieb ganz anders ausschaun könnte. Theoretisch kann man noch das Journal mit "norecovery" abschalten, aber praktisch lehnt das mount ab.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German) Deutsche Dokumentation All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum