Hace algunos días tuve que de hacer un manejo algo turbio sobre una tabla de particiones MBR. Necesitaba que una partición lógica, dentro de una partición MBR extendida, pase a ser una partición primaria, por razones que no vienen al caso.

Como muchos veteranos saben, las tablas de particiones DOS sólo soportan 4 particiones, que pueden ser primarias o extendidas. Las particiones primarias presumiblemente contienen un sistema de archivos, mientras que las particiones extendidas son particiones que contienen subparticiones internas, llamadas "lógicas". Esto permite que un disco posea más de 4 particiones, y es lo que se utilizó tradicionalmente en sistemas Windows y GNU/Linux hasta la adopción de GPT.

Mi problema era que necesitaba deshacerme de toda partición "lógica" en la tabla de particiones uno de mis discos rígidos, por cuestiones de compatibilidad. Y para empeorar las cosas, una de las particiones utilizada para almacenar datos (la más valiosa) era justamente una partición lógica, y a su vez la de mayor tamaño (ocupando un 70% del espacio total del disco rígido). Esta situación me imposibilitaba mover su contenido hacia otras particiones para poder borrar la partición extendida (junto con todas sus particiones lógicas), para luego crearla como primaria.

La solución fácil hubiera sido conseguir un disco adicional para mover todos los datos y crear una nueva tabla GPT en el disco (hacer borrón y cuenta nueva). Pero en lugar de eso, y como buen sysadmin, opté por una solución más elegante: convertir la gigantesca partición lógica en primaria (desechando las restantes particiones lógicas dentro de la misma extendida), poniendo en juego unos 350 GB de datos. Mentira, en realidad no tenía un disco de 500 GB a mano, por eso decidí arriesgarme.



Escenario

Al convertir una partición lógica en primaria, estamos automáticamente desechando el resto de las particiones lógicas dentro de la misma partición extendida (suponiendo que hemos agotado las cuatro particiones primarias, es decir tenemos tres primarias y una extendida). Por ello, antes de comenzar a toquetear la tabla de particiones, he movido los datos de las particiones lógicas restantes a otras particiones.

El escenario actual es una tabla de particiones que posee dos particiones primarias (sda1 y sda3) y una extendida, que a su vez posee una única partición lógica (sda5, de aproximadamente 350 GB):

                           cfdisk (util-linux 2.21.2)

                              Disk Drive: /dev/sda
                       Size: 500107862016 bytes, 500.1 GB
             Heads: 255   Sectors per Track: 63   Cylinders: 60801

    Name        Flags      Part Type  FS Type          [Label]        Size (MB)
 ------------------------------------------------------------------------------
    sda1        Boot        Primary   ext4                             21500.89
    sda3                    Primary   ext4                             51202.37
                            Pri/Log   Free Space                       65539.04
    sda5                    Logical   ext4                            361862.97 
                            Pri/Log   Free Space                           2.62*

El plan es convertir la partición lógica sda5 en la partición primaria sda4, sin perder datos durante el proceso.

Manos a la obra

Iniciar con un Live CD o DVD de cualquier distribución GNU/Linux, por ejemplo SliTaz (una distribución minimalista que ocupa unos 35 MB).

Sólo es necesario iniciar desde un Live CD si el sistema operativo está instalado en el disco en cuestión, ya que no deben haber particiones montadas para realizar la tarea (el disco no puede estar siendo utilizado al momento de "reparticionar").

Cambiar a superusuario (en el Live CD de SliTaz el password de root es "root"):

bash-4.2$ sudo su

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

Password:
bash-4.2#

Antes de comenzar, montar la partición extendida para examinar su contenido. Para ello, crear un directorio donde montar la partición:

bash-4.2# mkdir /data

Montar el sistema de archivos ext4 de la partición lógica /dev/sda5 en /data:

bash-4.2# mount /dev/sda5 /data/

El contenido del filesystem es el siguiente:

bash-4.2# ls /data/
Dropbox                              fotos
FreeBSD-10.1-RELEASE-amd64-dvd1.iso  lost+found
ISO                                  manuales
mp3                                  owncloud
VM                                   packages
books                                soft
ffmpeg.txt

Luego de examinar el contenido, desmontar el filesystem:

bash-4.2# umount /data/

Para manipular la tabla de particiones a bajo nivel, es necesario utilizar la herramienta sfdisk provista por el paquete util-linux.

sfdisk provee la funcionalidad necesaria para listar el tamaño de una partición, listar las particiones de un dispositivo, verificar las particiones de un dispositivo, y reparticionar ("muy peligroso" según el manual) un dispositivo. Esta herramienta funciona sólo con tablas MBR, no soporta el formato GPT.

Al ejecutar sfdisk se listan las opciones disponibles:

bash-4.2# sfdisk

Usage:
 sfdisk [options] <device> [...]

Options:
 -s, --show-size           list size of a partition
 -c, --id                  change or print partition Id
     --change-id           change Id
     --print-id            print Id
 -l, --list                list partitions of each device
 -d, --dump                idem, but in a format suitable for later input
 -i, --increment           number cylinders etc. from 1 instead of from 0
 -u, --unit <letter>       units to be used; <letter> can be one of
                             S (sectors), C (cylinders), B (blocks), or M (MB)
 -1, --one-only            reserved option that does nothing currently
 -T, --list-types          list the known partition types
 -D, --DOS                 for DOS-compatibility: waste a little space
 -E, --DOS-extended        DOS extended partition compatibility
 -R, --re-read             make the kernel reread the partition table
 -N <number>               change only the partition with this <number>
 -n                        do not actually write to disk
 -O <file>                 save the sectors that will be overwritten to <file>
 -I <file>                 restore sectors from <file>
 -V, --verify              check that the listed partitions are reasonable
 -v, --version             display version information and exit
 -h, --help                display this help text and exit

Dangerous options:
 -f, --force               disable all consistency checking
     --no-reread           do not check whether the partition is in use
 -q, --quiet               suppress warning messages
 -L, --Linux               do not complain about things irrelevant for Linux
 -g, --show-geometry       print the kernel's idea of the geometry
 -G, --show-pt-geometry    print geometry guessed from the partition table
 -A, --activate[=<device>] activate bootable flag
 -U, --unhide[=<dev>]      set partition unhidden
 -x, --show-extended       also list extended partitions in the output,
                             or expect descriptors for them in the input
     --leave-last          do not allocate the last cylinder
     --IBM                 same as --leave-last
     --in-order            partitions are in order
     --not-in-order        partitions are not in order
     --inside-outer        all logicals inside outermost extended
     --not-inside-outer    not all logicals inside outermost extended
     --nested              every partition is disjoint from all others
     --chained             like nested, but extended partitions may lie outside
     --onesector           partitions are mutually disjoint

Override the detected geometry using:
 -C, --cylinders <number>>  set the number of cylinders to use
 -H, --heads <number>      set the number of heads to use
 -S, --sectors <number>    set the number of sectors to use

Para mayor información, consultar la página del manual (altamente recomendable antes de realizar acciones tan peligrosas):

man sfdisk

Tal como explica la ayuda, la opción -d permite volcar el contenido de la tabla de particiones en un formato apto para ser utilizado luego como entrada.

De acuerdo a la salida de fdisk, el estado actual de la tabla de particiones es el siguiente:

bash-4.2# fdisk -l

Disk /dev/sda: 500.1 GB, 500107862016 bytes
255 heads, 63 sectors/track, 60801 cylinders, total 976773168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000efc5a

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *          63    41993909    20996923+  83  Linux
/dev/sda3        41993910   141998534    50002312+  83  Linux
/dev/sda4       270004455   976768064   353381805    5  Extended
/dev/sda5       270004518   976768064   353381773+  83  Linux

Es posible verificar que la tabla sea correcta ejecutando sfdisk -V:

bash-4.2# sfdisk -V
/dev/sda: OK

La tabla de particiones en el dispositivo /dev/sda parece consistente, por lo tanto es posible proceder con el volcado de la misma a un archivo de texto plano:

bash-4.2# sfdisk -d /dev/sda > particiones.txt

El volcado de la tabla es el siguiente:

# partition table of /dev/sda
unit: sectors

/dev/sda1 : start=       63, size= 41993847, Id=83, bootable
/dev/sda2 : start=        0, size=        0, Id= 0
/dev/sda3 : start= 41993910, size=100004625, Id=83
/dev/sda4 : start=270004455, size=706763610, Id= 5
/dev/sda5 : start=270004518, size=706763547, Id=83

Antes de proceder con las modificaciones, crear una copia del archivo, para que éste quede como copia de seguridad. Así, en caso de que algo falle, podremos recuperar la tabla de particiones a su estado original.

bash-4.2# cp particiones.txt particiones-nuevas.txt

Editar la copia con cualquier editor de texto, por ejemplo nano:

bash-4.2# nano particiones-nuevas.txt

Para transformar la partición sda5 en partición primaria, basta con eliminar la entrada correspondiente a la partición extendida sda4 y luego renombrar sda5 a sda4. Así de simple.

Advertencia: no alterar ningún número de bloque de inicio, o tamaño en bloques, de ninguna partición.

La nueva tabla de particiones debería quedar así:

# partition table of /dev/sda
unit: sectors

/dev/sda1 : start=       63, size= 41993847, Id=83, bootable
/dev/sda2 : start=        0, size=        0, Id= 0
/dev/sda3 : start= 41993910, size=100004625, Id=83
/dev/sda4 : start=270004518, size=706763547, Id=83

Ahora llegó el momento de aplicar en disco los cambios hechos en el archivo. Esta operación es destructiva, y si se han cometido errores durante la edición se puede provocar la pérdida o destrucción total o parcial de los datos en el disco.

Iniciar el reparticionado:

bash-4.2# sfdisk --force /dev/sda < particiones-nuevas.txt 
Checking that no-one is using this disk right now ...
BLKRRPART: Device or resource busy
sfdisk: 
This disk is currently in use - repartitioning is probably a bad idea.
Umount all file systems, and swapoff all swap partitions on this disk.
Use the --no-reread flag to suppress this check.


Disk /dev/sda: 60801 cylinders, 255 heads, 63 sectors/track
Old situation:
Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/sda1   *      0+   2613    2614-  20996923+  83  Linux
/dev/sda2          0       -       0          0    0  Empty
/dev/sda3       2614    8838    6225   50002312+  83  Linux
/dev/sda4      16807   60800   43994  353381805    5  Extended
/dev/sda5      16807+  60800   43994- 353381773+  83  Linux
New situation:
Units = sectors of 512 bytes, counting from 0

   Device Boot    Start       End   #sectors  Id  System
/dev/sda1   *        63  41993909   41993847  83  Linux
/dev/sda2             0         -          0   0  Empty
/dev/sda3      41993910 141998534  100004625  83  Linux
/dev/sda4     270004518 976768064  706763547  83  Linux
Warning: partition 4 does not start at a cylinder boundary
Successfully wrote the new partition table

Re-reading the partition table ...
BLKRRPART: Device or resource busy
sfdisk: The command to re-read the partition table failed.
Run partprobe(8), kpartx(8) or reboot your system now,
before using mkfs

If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes:  dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)

La operación es breve y en la salida se muestra el estado anterior y el estado actual de la tabla de particiones.

Si no hubo errores, notificar al kernel Linux acerca de los cambios en la tabla de particiones:

bash-4.2# partprobe

A continuación, listar la nueva tabla de particiones del dispositivo /dev/sda:

bash-4.2# fdisk -l

Disk /dev/sda: 500.1 GB, 500107862016 bytes
255 heads, 63 sectors/track, 60801 cylinders, total 976773168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000efc5a

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *          63    41993909    20996923+  83  Linux
/dev/sda3        41993910   141998534    50002312+  83  Linux
/dev/sda4       270004518   976768064   353381773+  83  Linux

Montar la partición sda4 (ex sda5):

bash-4.2# mount /dev/sda4 /data/

Verificar su contenido mediante un listado:

bash-4.2# ls /data/
Dropbox                              fotos
FreeBSD-10.1-RELEASE-amd64-dvd1.iso  lost+found
ISO                                  manuales
mp3                                  owncloud
VM                                   packages
books                                soft
ffmpeg.txt

¡Éxito! Se ha convertido exitosamente a la partición lógica sda5 en la partición primaria sda4.

Obviamente ha quedado espacio sin utilizar, correspondiente al resto de las particiones lógicas en la partición extendida que se ha eliminado. Es posible aprovechar este espacio expandiendo la partición primaria que precede al espacio libre. Para ello se debe aplicar el mismo procedimiento, editando cuidadosamente la tabla de particiones y expandiendo luego el filesystem involucrado.


Tal vez pueda interesarte


Compartí este artículo