Archivi tag: linu

Defrag_icon

Deframmentare Linux ?

Non vogliamo tirarla lunga con un articolo accademico sulla frammentazione e sulle tecniche implementate per minimizzarla sui filesystem della famiglia ext*.

Vogliamo solo farvi giocare concretamente con questo concetto/problema che sfugge all’attenzione degli utenti (e sistemisti Linux) per un assunto ben poco esatto ma comunque in concreto valido: “Linux non soffre di problemi di frammentazione”.

In realtà questo, come abbiamo detto, non è “esattamente” vero (e non vogliamo tediarvi con questioni tecniche), ma è altrettanto vero che il filesystem ext2 (e successori) ha dei buoni anticorpi per risolvere l’influenza della deframmentazione.

Il primo giocattolo per poter cominciare a saggiare con mano l’esistenza di questa realtà è il comando filefrag. Questo è disponibile nel pacchetto e2fsprogs (disponibile sia su distribuzioni RedHat like che Debian like).

Questo comando è capace di rilevare la frammentazione di un file indicato, in numero e identità dei blocchi di indirezione (extents).

A partire da questo e considerando che tra gli artifici del filesystem ext2 (e successori) per evitare la framentazione vi è la tecnica di allocare sequenzialmente i blocchi di un file in fase di creazione, possiamo porre le basi per un nuovo giocattolo.

Prendiamo ora il seguente nuovo assunto: “per deframmentare un file basta copiarlo”.
La nuova copia (per via del modo di allocazione blocchi) sarà “probabilmente” deframmentato. Il “probabilmente” è dovuto al fatto che i blocchi contigui devono essere disponibili. Ecco perché nell’implementazione provvediamo a copiare il file su un filesystem di appoggio (di base /tmp), liberiamo spazio sul filesystem sorgente (per aumentare la probabilità di trovare blocchi consecutivi) e ricopiamo nuovamente il file.

Dato che “repetita iuvant”, ripetere questa operazione quando la deframmentazione non è stata pienamente possibile potrà renderla possibile (a patto che il filesystem sia nel frattempo mutato rendendo disponibile nuove sequenze di blocchi contigui).

Ed ecco il nostro defrag per Linux:

#!/bin/bash
#
#
[ "$USER" != "root" ] && echo Must be root && exit 1

TEMPFILE=`mktemp`
trap 'rm -f $TEMPFILE' EXIT 1 15

echo -n "Raccolgo elenco file(s) ... "
find ${1:-.} -type f 2>/dev/null | grep -v $TEMPFILE >$TEMPFILE
echo fatto
NFILES=`cat $TEMPFILE | wc -l`
echo "Trovati $NFILES file(s)"

exec 3<> $TEMPFILE
declare -i i
declare -i defrag

i=0
defrag=0
read <&3
while [ -n "$REPLY" ]
do
EXTENTS=`filefrag "$REPLY" | cut -d: -f2 | awk '{ print $1 }'`
if [ ${EXTENTS:-0} -gt 2 ] 2>/dev/null; then
# Usare mktemp -p /altrodisco (se server più spazio)
TEMP=`mktemp`
cp -dp $REPLY $TEMP
rm -f $REPLY
cp $TEMP $REPLY
rm -f $TEMP
defrag=$(( defrag + 1 ))
fi
i=$((i + 1))
echo -en "\r$i/$NFILES ($(( 100 * i / NFILES ))%)"
read <&3
done
echo
exec 3>&-
echo "Processati $i file(s)"
echo "Deframmentati $defrag file(s)"
trap '' 1 15
exit 0

Ovviamente, in quanto giocattolo, non possiamo chiedervi di provarlo in ambienti di produzione. Pur essendo (crediamo) esente da problemi, non è consigliato soprattutto per il suo tempo di esecuzione, che è legato proporzionalmente alla dimensione e numero dei files da ottimizzare.

Non è il migliore degli approcci, ma è capace di ottenere il suo scopo. Soprattutto è capace di mostrarci il motivo nascosto del perché in Linux abbiamo pochi problemi di frammentazione (la copia dei file che ogni tanto avviene o la creazione degli stessi sono alla base della deframmentazione che avviene fuori dal nostro sguardo)

A noi bastava fornire una fascinazione riguardo il problema.