#!/bin/bash #/** #@file Cache.lib #@brief Librería o clase Cache #@class Cache #@brief Funciones para gestión de la caché local de disco. #@version 1.1.1 #@warning License: GNU GPLv3+ #*/ #/** # ogCreateCache [int_ndisk] int_partsize #@brief Define la caché local, por defecto en partición 4 del disco 1. #@param int_ndisk numero de disco donde crear la cache, si no se indica es el 1 por defecto #@param int_npart número de partición (opcional, 4 por defecto) #@param int_partsize tamaño de la partición (en KB) #@return (nada, por determinar) #@exception OG_ERR_FORMAT formato incorrecto. #@note Requisitos: sfdisk, parted, awk, sed #@warning El tamaño de caché debe estar entre 50 MB y la mitad del disco. #@warning La caché no puede solaparse con las particiones de datos. #@version 0.9.1 - Definición de caché local. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2010/03/09 #@version 0.9.2 - Corrección definición de límites. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2010/06/01 #@version 1.0.4 - Soporte para discos GPT. #@author Universidad de Huelva #@date 2012/03/13 #@version 1.0.5 - Posibilidad de crear la cache en cualquier disco duro #@author Universidad de Huelva #@date 2012/09/18 #@version 1.1.0 - Posibilidad de crear la caché en cualquier partición. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2016/05/25 #@version 1.1.0 - Soporte discos con sectores de 4k #@date 2017/01/09 #@version 1.0.6b - Al crear las particiones ordenamos los dispositivos en el fichero auxiliar. #@author Irina Gomez, ETSII Universidad de Sevilla #@date 2017/01/09 #*/ ## function ogCreateCache () { # Variables locales. local FINDCACHE IOSIZE NDSK SIZECACHE PART DISK START END ENDPREVPART SIZE MINSIZE MAXSIZE local PTTYPE ID TMPFILE NVME_PREFIX # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then ogHelp "$FUNCNAME" "$FUNCNAME [int_ndisk [int_npart]] int_partsize" \ "$FUNCNAME 10000000" "$FUNCNAME 1 10000000" "$FUNCNAME 1 4 10000000" return fi # Si se recibe un parametro, sera el tamano de la cache case $# in 1) # Error, si no es un entero positivo [[ $1 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$1" || return $? NDSK=1 PART=4 SIZECACHE=$1 ;; 2) # Error, si no son enteros positivos [[ $1 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$1" || return $? [[ $2 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$2" || return $? NDSK=$1 PART=4 SIZECACHE=$2 ;; 3) # Error, si no son enteros positivos [[ $1 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$1" || return $? [[ $2 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$2" || return $? [[ $3 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$3" || return $? NDSK=$1 PART=$2 SIZECACHE=$3 ;; *) ogRaiseError $OG_ERR_FORMAT return $? ;; esac TMPFILE=/tmp/sfdisk$$ DISK=$(ogDiskToDev $NDSK) || return $? # PATCH Para discos nvme la particion debe ser p1, p2, etc...en lugar de 1,2, sino falla sfdisk NVME_PREFIX="" if [[ $DISK == *"nvme"* ]]; then NVME_PREFIX="p" fi END=$[$(ogGetLastSector $NDSK 2>/dev/null)] # Sector final del disco. SIZE=$[$SIZECACHE*2] # Tamaño en sectores de 512 B. # Inicio partición cache según el disco tenga sectores de 4k o menores IOSIZE=$(fdisk -l $DISK | awk '/I\/O/ {print $4}') if [ $IOSIZE -eq 4096 ]; then END=$[$END-8192] START=$[END-SIZE+2048-(END-SIZE)%2048] else START=$[END-SIZE+1] fi ENDPREVPART=$[$(ogGetLastSector $NDSK $[PART-1] 2>/dev/null)] # Error si tamaño no está entre límites permitidos o si se solapa con la partición anterior. MINSIZE=25000 # Error de formateo si tamaño < 50 MB. MAXSIZE=$END # Para restringir tamaño > mitad del disco: MAXSIZE=$[END/2] if [ $SIZE -lt $MINSIZE -o $SIZE -gt $MAXSIZE -o $START -le $ENDPREVPART ]; then ogRaiseError $OG_ERR_FORMAT "$1" || return $? fi # Desmontar todos los sistemas de archivos del disco. ogUnmountAll $NDSK 2>/dev/null # Definir particiones y notificar al kernel. # En el caso de ser disco GPT, de momento se borra la particion y se vuelve a crear, # por lo que se pierden los datos. PTTYPE=$(ogGetPartitionTableType $NDSK) if [ -z "$PTTYPE" ]; then PTTYPE="MSDOS" # Por defecto para discos vacíos. ogCreatePartitionTable $NDSK $PTTYPE fi case "$(ogGetPartitionTableType $NDSK)" in GPT) # Si la tabla de particiones no es valida, volver a generarla. [ ! $(sgdisk -p $DISK &>/dev/null) ] || echo -e "2\nw\nY\n" | gdisk $DISK # Si existe la cache se borra previamente [ -n "$(ogFindCache)" ] && ogDeleteCache # Capturamos el codigo de particion GPT para cache # PATCH - Cuando es GPT, la particion con codigo CACHE (CA00) no existe y no puede crearse, se cambia por LINUX (8300) ID=$(ogTypeToId LINUX GPT) sgdisk $DISK -n$PART:$START:$END -c$PART:CACHE -t$PART:$ID 2>/dev/null ;; MSDOS) # Si la tabla de particiones no es valida, volver a generarla. parted -s $DISK print &>/dev/null || fdisk $DISK <<< "w" # Definir particiones y notificar al kernel. ID=$(ogTypeToId CACHE MSDOS) # Salvamos la configuración de las particiones e incluimos la cache. trap "rm -f $TMPFILE" 1 2 3 9 15 sfdisk --dump $DISK | grep -v $DISK$PART > $TMPFILE echo "$DISK$NVME_PREFIX$PART : start= $START, size= $SIZE, Id=$ID" >> $TMPFILE # Ordenamos las líneas de los dispositivos UNIT=$(grep unit $TMPFILE) grep ^/dev $TMPFILE|sort -o $TMPFILE sed -i "1i $UNIT\n" $TMPFILE # Guardamos nueva configuración en el disco. sfdisk --no-reread $DISK < $TMPFILE rm -f $TMPFILE ;; esac # Actualiza la tabla de particiones en el kernel. ogUpdatePartitionTable } #/** # ogDeleteCache #@brief Elimina la partición de caché local. #@return (nada, por determinar) #@exception OG_ERR_FORMAT formato incorrecto. #@note Requisitos: fdisk, sgdisk, partprobe #@version 0.91 - Definición de caché local. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2010/03/11 #@version 1.0.4 - Soporte para discos GPT. #@author Universidad de Huelva #@date 2012/03/13 #@version 1.0.6b - llamada correcta a ogUpdatePartitionTable #@author Antonio Doblas Universidad de Málaga #@date 2016/11/16 #@version 1.1.0 - Sustituir "sfdisk" por "fdisk" para discos MSDOS. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2016/05/25 #*/ ## function ogDeleteCache () { # Variables locales. local NDISK NPART DISK # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then ogHelp "$FUNCNAME" "$FUNCNAME" return fi # Error si no se encuentra partición de caché. read NDISK NPART <<<"$(ogFindCache)" [ -n "$NDISK" -a -n "$NPART" ] || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? DISK=$(ogDiskToDev $NDISK) # Desmontar todos los sistemas de archivos del disco. ogUnmountAll $NDISK 2>/dev/null case "$(ogGetPartitionTableType $NDISK)" in GPT) # Si la tabla de particiones no es valida, volver a generarla. [ ! $(sgdisk -p $DISK 2>&1 >/dev/null) ] || echo -e "2\nw\nY\n" | gdisk $DISK sgdisk $DISK -d$NPART 2>/dev/null ;; MSDOS) # Si la tabla de particiones no es valida, volver a generarla. parted -s $DISK print &>/dev/null || fdisk $DISK <<< "w" # Eliminar la partición de caché. echo -e "d\n$NPART\nw" | fdisk $DISK 2>/dev/null ;; esac # Borrar etiqueta de la caché. rm -f /dev/disk/by-label/CACHE #Actualiza la tabla de particiones en el kernel. ogUpdatePartitionTable $NDISK } #/** # ogFindCache #@brief Detecta la partición caché local. #@param No requiere parametros #@return int_ndisk int_npart - devuelve el par nº de disco-nº de partición . #@warning Si no hay cache no devuelve nada #@version 0.1 - Integracion para Opengnsys - EAC: FindCache() en ATA.lib - HIDRA: DetectarCache.sh #@author Ramon Gomez, ETSII Universidad de Sevilla #@Date 2008/06/19 #@author Antonio J. Doblas Viso. Universidad de Malaga #@Date 2008/10/27 #@version 0.91 - Adaptacion a la cache local de OpenGnSys. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2010/03/16 #@version 1.0.5 - Obtener caché en discos GPT. #@author Alberto García, Universidad de Málaga y Ramon Gomez, ETSII Universidad de Sevilla #@date 2014/05/28 #*/ ## function ogFindCache () { # Variables locales local DISK PART # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 1 4" return fi # Obtener el dispositivo del sistema de archivos etiquetado como "CACHE". PART=$(blkid -L "CACHE") # En discos nvme con particiones GPT la partición se detecta usando el tag PARTLABEL PART=${PART:-$(blkid -t PARTLABEL=CACHE | awk -F: '{print $1}')} # Si no se detecta, obtener particiones marcadas de tipo caché en discos MSDOS. PART=${PART:-$(sfdisk -l 2>/dev/null | awk '$6~/ca|a7/ {print $1}')} # Por último revisar todos los discos GPT y obtener las particiones etiquetadas como caché. if [ -z "$PART" ]; then for DISK in $(ogDiskToDev); do # Nota: se añade espacio separador solo si existe valor previo. PART="${PART:+"$PART "}$(sgdisk -p $DISK 2>/dev/null | awk -v d=$DISK '$7~/CACHE/ {printf "%s%s",d,$1;}')" done fi # Devolver número de disco y número de partición de la 1ª partición encontrada. ogDevToDisk ${PART%% *} 2>/dev/null } #/** # ogFormatCache #@brief Formatea el sistema de ficheros para la caché local. #@return (por determinar) #@warning Prueba con formato Reiser. #@attention #@note El sistema de archivos de la caché se queda montado. #@version 0.1 - Integracion para Opengnsys - EAC: FormatCache() en ATA.lib #@author Antonio J. Doblas Viso. Universidad de Malaga #@date 2008/10/27 #@version 0.91 - Creacion cache local. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2010-03-11 #@version 1.1.0 - llamada a updateBootCache. #@author Antonio J. Doblas Viso. Universidad de Malaga #@date 2018-01-21 #*/ ## function ogFormatCache () { # Variables locales. local DEV MNTDIR # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then ogHelp "$FUNCNAME" "$FUNCNAME" return fi # Error si no hay definida partición de caché. DEV=$(ogFindCache) || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? DEV=$(ogDiskToDev $DEV) || return $? # Formatear sistema de ficheros. ogUnmountCache 2>/dev/null mkfs.ext4 -q -F $DEV -L "CACHE" -O extent,large_file 2>/dev/null || ogRaiseError $OG_ERR_PARTITION "CACHE" || return $? # Crear estructura básica. MNTDIR=$(ogMountCache) mkdir -p $MNTDIR/$OGIMG # Incluir kernel e Initrd del ogLive updateBootCache 2>&1>/dev/null } #/** # ogGetCacheSize #@brief Devuelve el tamaño definido para la partición de caché. #@return int_partsize tamaño de la partición (en KB) #@exception OG_ERR_PARTITION No existe partición de caché. #@version 0.1 - Integracion para Opengnsys - EAC: InfoCache() en FileSystem.lib #@author Antonio J. Doblas Viso. Universidad de Malaga #@date 2008/10/27 #@version 0.91 - Definicion de cache local. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2010/03/09 #*/ ## function ogGetCacheSize () { # Variables locales local PART # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 10000000" return fi # Error si no se encuentra partición de caché. PART=$(ogFindCache) || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? # Devuelve tamaño de la partición de caché. ogGetPartitionSize $PART } #/** # ogGetCacheSpace #@brief Devuelve el espacio de disco disponible para la partición de caché. #@return int_size tamaño disponible (en KB) #@note El espacio disponible es el que hay entre el límite superior de la partición 3 del disco 1 y el final de dicho disco, y no puede ser superior a la mitad de dicho disco. #@version 0.1 - Integracion para Opengnsys - EAC: InfoCache() en FileSystem.lib #@author Antonio J. Doblas Viso. Universidad de Malaga #@date 2008/10/27 #@version 0.91 - Definicion de cache local. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2010/03/09 #@version 1.0.5 - Uso de ogFindCache para detectar disco y particion #@author Universidad de Huelva #@date 2012/09/18 #*/ ## function ogGetCacheSpace () { # Variables locales. local NDISK DISK NPART SECTORS CYLS ENDPART3 # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 23165386" return fi # Parche UHU para usar ogFindCache en lugar de 1 # Error si no se encuentra partición de caché. read NDISK NPART <<<"$(ogFindCache)" [ -n "$NDISK" -a -n "$NPART" ] || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? DISK=$(ogDiskToDev $NDISK) || return $? SECTORS=$(awk -v D=${DISK#/dev/} '{if ($4==D) {print $3*2}}' /proc/partitions) CYLS=$(sfdisk -g $DISK | cut -f2 -d" ") SECTORS=$[SECTORS/CYLS*CYLS-1] ENDPART3=$(sfdisk -uS -l $DISK | awk -v P="${DISK}3" '{if ($1==P) print $3}') # Mostrar espacio libre en KB (1 KB = 2 sectores) if [ $ENDPART3 -gt $[SECTORS/2] ]; then echo $[(SECTORS-ENDPART3)/2] else echo $[SECTORS/4] fi } #/** # ogMountCache #@brief Monta la partición Cache y exporta la variable $OGCAC #@param sin parametros #@return path_mountpoint - Punto de montaje del sistema de archivos de cache. #@warning Salidas de errores no determinada #@version 0.1 - Integracion para Opengnsys - EAC: MountCache() en FileSystem.lib - HIDRA: MontarCache.sh #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2008/06/19 #@author Antonio J. Doblas Viso. Universidad de Malaga #@Date 2008/10/27 #@version 0.91 - Adaptacion a la cache local de OpenGnSys. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2010/03/16 #@version 1.0 - Correccion multiples montajes de cache. #@author Antonio J. Doblas Viso, Universidad de Malaga #@date 2011/02/24 #*/ ## function ogMountCache () { # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME ==> /mnt/sda4" return fi ogMountFs $(ogFindCache) 2>/dev/null || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? } #/** # ogUnmountCache #@brief Desmonta la particion Cache y elimina la variable $OGCAC #@param sin parametros #@return nada #@warning Salidas de errores no determinada #@version 0.1 - Integracion para Opengnsys - EAC: UmountCache() en FileSystem.lib #@author Antonio J. Doblas Viso. Universidad de Malaga #@Date 2008/10/27 #@version 0.91 - Adaptacion a la cache local de OpenGnSys. #@author Ramon Gomez, ETSII Universidad de Sevilla #@date 2010/03/16 #@version 1.0 - Correccion multiples montajes de cache. #@author Antonio J. Doblas Viso, Universidad de Malaga #@date 2011/02/24 #*/ ## function ogUnmountCache () { # Variables locales. local CACHE # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then ogHelp "$FUNCNAME" "$FUNCNAME" return fi CACHE=$(ogFindCache) || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" ogIsMounted $CACHE || return 0 ogUnmountFs $CACHE # Borrar enlace simbólico de /mnt/ParticiónCache. rm -f $(ogDiskToDev $CACHE | sed 's/dev/mnt/') }