25 de julio de 2016

Las novedades de Linux 4.7

Ya se ha anunciado la versión 4.7 de Linux. Esta versión añade soporte para las recientemente puestas en venta GPUs Radeon RX 480 'Polaris', soporte para búsquedas de rutas de archivo paralelas en el mismo directorio, un nuevo gobernador de frecuencia experimental "schedutils" que debería ser más rápido y veloz que otros gobernadores, soporte para el mecanismo EFI "Capsule" que facilita las actualizaciones de firmware, soporte de controladores virtuales USB en la funcionalidad USB/IP para que los emuladores de teléfonos puedan funcionar como dispositivos USB reales, un módulo de seguridad llamado "LoadPin" que asegura que los módulos del kernel sólo se puedan cargar desde un sistema de archivos determinado, soporte para construir histogramas de eventos en la interfaz de trazado ftrace, soporte para asociar programas BPF a tracepoints del kernel, soporte para callchains en la utilidad perf trace, y soporte estable para la funcionalidad sync_file de Android. También se han incluido drivers nuevos y muchas otras mejoras y pequeños cambios. La lista completa de cambios, en inglés, puede encontrarse aquí, como siempre.



· Soporte para GPUs Radeon RX 480 'Polaris'

Como resultado de la nueva política de drivers libres de AMD, esta versión incluye soporte en el driver amdgpu para las recientísimamente puestas en venta GPUs Polaris, la nueva generación de  GPUs Radeon RX 480. El soporte está al mismo nivel que el resto de dispositivos del driver.



· Búsquedas de ruta de archivo paralelas en el mismo directorio

El caché de directorio (conocido como "dcache") es una de las partes más críticas del kernel, se trata de un caché de las rutas de los sistema de archivos, lo cual permite agilizar enormemente ciertas operaciones; por ejemplo, permite determinar si cierto archivo o directorio existe o no sin tener que leer datos del disco. Este cache usa un mutex para serializar las búsquedas de rutas en el mismo directorio.

Esta versión permite hacer búsquedas de rutas en el mismo directorio; el mutex serializador ha sido sustituido por un semáforo de lectura-escritura. Esta mejora no se notará en la vastísima mayoría de casos, porque las búsquedas en el caché de directorios son muy rápidas y es muy raro que se convierta en un punto de contención. Pero para algunas cargas específicas que utilizan la búsqueda de rutas muy intensivamente, verán una mejora del rendimiento porque a partir de ahora podrán hacerse en paralelo. La mayor parte  de los sistemas de archivos han sido convertidos para utilizar esta característica.


· Nuevo gobernador de frecuencia experimental 'schedutils'

Esta versión incorpora un nuevo gobernador para el subsistema de escalado de frecuencias (cpufreq). Hay dos grandes diferencias entre este nuevo gobernador y los existentes. Primero, schedutils utiliza información proporcionada directamente por el planificador de procesos. Segundo, puede invocar los drivers cpufreq y cambiar la frecuencia más rápidamente.

Lo que esto significa es que el tiempo que tarda el gobernador en hacer cambios de frecuencia y la calidad de las decisiones tomadas mejora respecto a anteriores gobernadores. Nótese que este nuevo gobernador es muy simple, y está considerado como una base sobre la que fundar futuros cambios que mejoren la integración entre el planificador de procesos y la gestión de energía. Sin embargo, funciona y los resultados preliminares son prometedores. Este gobernador comparte algunos valores tuneables con los otros gobernadores.


· Soporte para construir histogramas de eventos en la interfaz de trazado ftrace

Los "Hist triggers" son una funcionalidad que se incorpora a ftrace, la infraestructura de trazado de Linux disponible desde 2.6.27 que está embebida en el kernel y disponible en /sys/kernel/debug/tracing. Esta versión añade el comando "hist" a ftrace, que permite construir "histogramas" de eventos, agregando el número de eventos en una tabla hash. Como ejemplo, vamos a suponer que un usuario quiere conseguir una lista de bytes leídos por cada proceso en el sistema. Se puede hacer con el comando "hist" de la siguiente manera:

# echo 'hist:key=common_pid.execname:val=count:sort=count.descending' > /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/trigger

Lo que hace este extraño comando es escribir un comando al archivo trigger del evento sys_enter_read (el evento que corresponde a entrar en la llamada al sistema read(), es decir, intentar leer un archivo). Cuando se produzca el evento, se ejecutará un comando hist (hist:) que significa lo siguiente: cada vez que se dispare el evento, leer el PID (common_pid - puedes ver todos los campos posibles del evento en el archivo /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/format) y convertirlo a nombre de proceso (sufijo .execname); esto será usado como clave (key=) en el histograma. El parámetro val=count hace que se lea también el campo count, que en el evento sys_enter_read se refiere al número de bytes leídos. Finalmente, tras el separador :, el parámetro sort=count.descending hace que el comando ordene el resultado por el campo count en orden descendiente. La salida resultante es esta:


Esta salida muestra qué procesos han leído archivos, cuantos bytes (count), y con cuanta frecuencia (hitcount, que no fue especificado en el comando pero se incluye por defecto).

Como se puede observar, esta pequeña herramienta permite hacer análisis muy útiles del sistema, y si bien ftrace no puede competir (ni lo pretende) con herramientas de trazado más potentes como LTTng, perf o SystemTap, puede ser una herramienta muy conveniente. Para más información, puedes ver la documentación sobre hist triggers, or leer este post recomendado de Brendan Egg: Hist Triggers in Linux 4.7. Para más documentation sobre ftrace, ver Documentation/trace/ftrace.txt


· Soporte para callchains en la utilidad perf trace

En esta versión, perf trace añade la habilidad de mostrar callchains cada vez que el proceso a trazar encuentra una llamada al sistema. Puedes probarlo con comandos como # perf trace --call dwarf ping 127.0.0.1. Puedes mostrar callchains para los eventos deseados: # perf trace --event sched:sched_switch/call-graph=fp/ -a sleep 1. El trazado de fallos de página (options -F/--pf) también lo soportan, por ejemplo, para trazar las llamadas a write() y los fallos de página con callchains mientras se inicia firefox, puede hacerse con # perf trace -e write --pf maj --max-stack 5 firefox. Una análisis de perf trace con callchains de todos los procesos de un sistema completo puede encontrarse aquí.


· Permitir que los programas BPF usen tracepoints

Los tracepoints son una suerte de printf()s dinámicos que los desarrolladores introducen en su código para que puedan ser utilizados más tarde para analizar el comportamiento del sistema. Los Tracepoints pueden ser utilizados por muchas utilidades: LTTng, perf, SystemTap, ftrace...pero no podían ser utilizados por programas BPF

Esta versión añade un nuevo tipo de programa BPF (BPF_PROG_TYPE_TRACEPOINT) que puede usarse para construir programas BPF que puedan recoger datos de los tracepoints y procesarlos dentro del programa BPF. Esta alternativa puede ser más rápida que acceder a los tracepoints mediante kprobes, puede hacer las interfaces de los programas de trazado más estable, y permite la construcción de herramientas de trazado más complejas.


· Soporte para el mecanismo 'Capsule' de EFI

Esta versión añade soporte para el mecanismo 'Capsule' de EFI, que permite pasar a EFI archivos de datos. EFI los valida y toma decisiones de acuerdo con sus contenidos. El uso más común para este mecanismo es incluir actualizaciones de firmware en una Capsule para que EFI haga la actualización en el próximo reinicio. Los usuarios pueden subir datos a Capsule escribiendo el firmware en el dispositivo /dev/efi_capsule_loader device.


· Soporte para controladores de USB virtuales en USB/IP

USB/IP permite compartir dispositivos USB sobre la red. Los dispositivos a compartir necesitan, sin emabrgo, ser reales. Esta versión soporte la capacidad de crear dispositivos USB virtuales sin necesidad de tener un dispositivo USB físico, tal sólo utilizando el subsistema de USB gadgets.

Esta característica tiene varios usos; el más obvio (el que ha motivado su desarrollo) es la mejora de la emulación de teléfonos en los entornos de desarrollo. Los teléfonos emulados pueden ahora conectarse a la máquina del desarrollador, o a una virtual, mediante USB/IP, y así utilizarlos como si fuera un teléfono físico. También es útil, por razones obvias, para pruebas y experimentos.


· El mecanismo de fencing de Android, sync_file, se considera estable

En esta versión, el código sync_file que estaba en el directorio de pruebas staging/, ha sido movido al kernel principal. Sync_file es una API desarrollada para Android para cubrir las deficiencias del mecanismo de fencing de Linux; para los interesados se pueden encontrar más detalles en la documentación oficial, Documentation/sync_file.txt.


· LoadPin, un módulo de seguridad para restringir el origen de los módulos del kernel 

LoadPin es un módulo de seguridad que se asegura de que todos los archivos cargados por el kernel (módulos del kernel, firmware, imágenes kexec, políticas de seguridad, etc) tengan origen en un mismo sistema de archivos. Las expectativas son que ese sistema de archivos sea de sólo lectura, como por ejemplo un DVD o dm-verity (esta característica viene de ChromeOS, donde el sistema principal está verificado criptográficamente con dm-verity). Los sistemas con este tipo de sistemas de archivos podrán con este sistema forzar las restricciones citadas sin tener que recurrir a firmar criptográficamente los módulos (algo que Linux también soporta), lo cual es obviamente beneficioso para la seguridad


Estas son las novedades principales de este kernel. Como siempre, pueden encontrar la lista completa, y en inglés, en esta página.

14 de junio de 2016

Apple ya tiene su ZFS: APFS

ZFS fue una revolución en el mundo de los sistemas operativos de propósito general, hasta el punto que se puede afirmar tajantemente que el sistema operativo que no tenga un sistema de archivos inspirado en él, está obsoleto. En Apple no son tontos y en seguida se interesaron al menos en facilitar el uso de ZFS, pero acabaron abandonando la idea por problemas de licencia. Aun así, surgieron rumores de que Apple estaba desarrollando un sustituto de HFS+, sin que llegaran nunca a nada.

Hoy, en su conferencia para desarrolladores, Apple ha anunciado su nuevo sistema de archivos APFS. No se han dado muchos detalles, pero no se diferencia en nada de lo que se podría esperar de un clon de ZFS. Habrá que esperar hasta el año que viene para que den más detalles y publiquen el código fuente: APFS está tan verde, que ni tan siquiera garantizan la estabilidad del formato de disco.

Sorprende que Apple, con sus inacabables recursos monetarios, se haya tomado tanto tiempo en crear un clon de ZFS: todos sus sistemas usan aun HFS+ (prueba de que, como se ha sugerido en el pasado en este blog, una implementación rápida y estable de un sistema de archivos es mucho más importante en la práctica que las campanitas y luces de colores de un formato de disco nuevo). Un servidor esperaba a APFS años mucho antes; hace cuatro años predecía, erróneamente, que veríamos un ZFS de Apple antes de ver ReFS -el ZFS de Microsoft, recuerden- en los Windows de escritorio.

Pero sobre todo, lo que esperaba de Apple es que se atreviese a ir más allá de los sistemas de archivo jerárquicos. Tras haber contratado al desarrollador del sistema de archivos de BeOS, uno se esperaba que se atreverían a copiar su implementación de atributos extendidos, pero no parece haber ninguna innovación en ese frente. No pierdo la esperanza de que lo tengan reservado para el futuro.

2 de junio de 2016

Las novedades de Linux 4.3

(Tras un larguísimo retraso, esta es la lista de cambios de Linux 4.3)

Ya se ha anunciado la versión 4.6 de Linux. Esta versión elimina el sistema de archivos Ext3 (a partir de ahora los sistemas de archivo Ext3 se tendrán que montar con Ext4, que siempre los ha soportado). También añade la llamada al sistema userfaultfd() para gestionar fallos de páginas desde espacio de usuario; la llamada al sistema membarrier() para enviar barreras de memoria a un conjunto de hilos; un controlador de PIDs para limitar el número de PIDs que puede haber en un cgroup; "ambient" capabilities para hacer el sistema de capabilities menos difícil de usar; un sistema para conseguir mejores estadísticas sobre la memoria que está siendo utilizada por un proceso; soporte para Identifier Locator Addressing de IPv6, que permite implementar túneles o virtualización de redes sin encapsulación; soporte para Virtual Routing and Forwarding Lite, túneles de red ligeros, y muchas otras mejoras y nuevos controladores. La lista completa de cambios, en inglés, puede encontrarse aquí, como siempre.


· Eliminación del sistema de archivos Ext3
Se ha eliminado el sistema de archivos Ext3. La motivación es que los sistemas de archivo Ext3 siempre han estado soportados por Ext4, que de hecho Ext4 se creó pensando en sustituir Ext3, y que las principales distribuciones llevan ya mucho tiempo utilizando Ext4 para montar sistemas de archivos Ext3. Ahora que Ext4 es bastante estable, los mantenedores creen adecuado librarse de él.

· userfaultfd(), una llamada al sistema para gestionar fallos de página en espacio de usuario

Un fallo de página es algo que ocurre cuando un proceso que tiene alguna cosa mapeada en su espacio de direcciones, por ejemplo, un archivo, pero ese archivo no está en la memoria RAM: al tratar de acceder al archivo, se produce un fallo de pagina. El kernel es quien, normalmente, se ocupa de gestionar ese fallo de página: carga la porción del archivo en memoria.


En esta versión, Linux añade soporte para gestionar fallos de página en espacio de usuario a través de una nueva llamada al sistema: userfaultfd(). La ventaja de esta llamada al sistema comparada con las operaciones de gestión de memoria habituales como mremap()/mprotect() es que es mucho más ligera.

El principal usuario de esta llamada al sistema es QEMU, que puede usar esta llamada al sistema para implementar migración en vivo post-copia: se migran las VMs de un host a otro sin migrar su memoria, lo cual hace que la migración sea mucho más rápida, y una vez migrada la VM, QEMU utiliza userfaultfd() para ir transfiriendo la memoria al nuevo host a medida que ocurren fallos de página.

· membarrier(), una llamada al sistema para enviar barreras de memoria a un conjunto de hilos 

Esta versión añade una nueva llamada al sistema, membarrier(2), que ayuda a distribuir los costes de las barreras de memoria en espacio de usuario utilizadas para ordenar los accesos a memoria en sistemas multicore, y lo logra transformando parejas de barreras de memoria en parejas consistentes en membarrier(2) y una barrera de compilador. Para las primitivas de sincronización que distinguen entre el lado de lectura y el de escritura (por ejemplo, RCU, read-write locks), el lado de la lectura puede acelerarse significativamente con esta llamada al sistema, ya que se mueve la sobrecarga de la barrera de memoria al lado de la escritura. La idea fundamental es hacer que las CPUs ejecuten las barreras solamente cuando se requiere sincronización por parte del hilo que modifica datos, a diferencia de ejecutar las barreras antes y después toda vez que se acceden los datos desde un hilo de lectura.

· Nuevo controlador de PIDs para limitar el número de PIDs en los cgroups.

Esta versión añade un controlador de PIDs que permite limitar el número de procesos que pueden crearse dentro de un cgroup. Los PIDs son un recurso fundamentalmente global, porque es bastante fácil acabar con todos los PIDs posibles antes de alcanzar otros límites de recursos. Como resultado, es posible paralizar el sistema. El controlador de PIDs está diseñado para prevenir estos abusos.


Esencialmente, se trata de una implementación del límite RLIMIT_NPROC, sólo que se aplica a un cgroup en lugar de a un árbol de procesos. Sin embargo, hay que notar que las operaciones de añadir PIDs a un cgroup manualmente no están afectadas por el límite, sólo están limitados los procesos creados a través de fork().

Para usar este controlador de PIDs, hay que configurar el número máximo de tareas en pid.max. El número de procesos disponibles en el cgroup es proporcionado por pids.current. Para que el cgroup no tenga límite de procesos, se puede configurar pid.max a "max".

· Ambient capabilities

En Linux, hay un número de capabilities ("capacidades") definidas por el kernel. Para ejecutar varias operaciones privilegiadas, los procesos pueden ejercer las capacidades que tengan asignadas. Cada proceso tiene cuatro máscaras de capacidades: "effective", "permitted", "inheritable", y "bounding set". Cuando el kernel comprueba la validez de las capacidades comprueba la máscara "effective", el resto de máscaras sirven para modificar las capacidades que pueden estar en "effective"

Debido a los defectos de diseño de las capacidades de Linux (artículo de LWN recomendado al respecto: Inheriting capabilities), la herencia de capacidades no es muy útil. Para resolver los problemas, esta versión añade una quinta máscara llamada máscara "ambient". Esta máscara hace lo que la mayor parte de la gente esperaría que hiciera la máscara "inheritable". No se puede cambiar ningún bit de capacidades en "ambient" si no está previamente en "inheritable" y "permitted". Eliminar un bit de "permitted" o "inheritable" elimina ese bit de "ambient". Esto asegura que los programas que quieran intentar desprenderse de capacidades pueden hacerlo, sin complicaciones. Como la herencia de capacidades en Linux actualmente es tan chapucera, configurar prctl(PR_SET_KEEPCAPS,...), usar setresuid() para cambiarse a una uid no-root, y después llamar a execve(), tiene como efecto que se desactivan las capabilities. Por lo tanto, setresuid() de root a no-root limpia la máscara "ambient" al menos que no esté activada SECBIT_NO_SETUID_FIXUP.

Si eres no-root pero tienes una capacidad, puedes añadirla a "ambient". Si lo haces, tus hijos también tendrán esa capacidad en "ambient", "permitted" y "effective". Por ejemplo, puedes configurar CAP_NET_BIND_SERVICE en "ambient", y tus hijos podrán, automáticamente, hacer bind() a puertos con números bajos. Los usuarios sin privilegios pueden crear espacios de nombres de usuario, mapearse ellos mismos a una uid no-cero, y crear árboles de procesos privilegiados y no privilegiados (relativos a su espacio de nombres).


· page tracking, una manera más precisa de medir la memoria utilizada por las aplicaciones
Saber qué páginas de memoria están siendo accedidas por una carga determinada y cuáles es útil para saber el tamaño de trabajo de la carga, lo cual es útil para configurar la aplicación, decidir en qué nodo debe ejecutarse, o configurar límites de memoria. Actualmente, la única manera de estimar la cantidad de memoria que no está siendo usada es /proc/PID/clear_refs y /proc/PID/smaps: el usuario puede eliminar el bit de acceso de todas las páginas de un determinado proceso escribiendo "1" al archivo clear_refs, esperar un tiempo, y contar la memoria que está siendo utilizada en la sección "Referenced" del archivo smaps. Sin embargo, este método tiene dos inconvenientes serios: 1) no puede contar las memoria de archivo que no está mapeada (ej, los archivos no mapeados, accedidos mediante read()/write()) 2) limpiar el bit de acceso de las páginas distorsiona la gestión de memoria.

Para resolver esos problemas, esta versión introduce una nueva manera de analizar el uso de memoria. Para estimar la cantidad de páginas que no están siendo usadas por una aplicación, se deben seguir los siguientes procesos:
  · Marcar todas las páginas de la tarea en cuestión, configurando los bits correspondientes en /mm/page_idle/bitmap (este archivo implementa un bitmap donde cada bit representa una página de memoria). Las páginas a ser marcadas pueden encontrase en /proc/PID/pagemap, si se trata de un proceso, o /proc/kpagecgroup (un nuevo archivo) si se trata de una carga ubicada en un cgroup.
  · Esperar a que la carga en cuestión haga su trabajo
  · Leer /sys/kernel/mm/page_idle/bitmap y contar el número de bits que han cambiado

· Soporte para IPv6 Identifier Locator Addressing

Esta versión añade soporte para Identifier Locator Addressing, un mecanismo diseñado para permitir la implementación de túneles o virtualización de redes sin encapsulación. El concepto básico de ILA es que una dirección IPv6 es dividida en dos partes de 64 bits: localizador e identificador. El identificador es la identidad de la entidad que se comunica ("quien"); el localizador expresa la localización de la entidad ("dónde"). Las aplicaciones usan direcciones visibles externamente que contienen el identificador. Cuando se envía un paquete, se hace una traducción que sobreescribe los primeros 64 bits de la dirección con el localizador. El paquete puede entonces ser redirigido por la red al host donde esté ubicada la entidad. El receptor hace la traducción inversa de manera que la aplicación vea la dirección original, sin traducir.

Esta característica se configura con el comando "ip -6 route", usando la opción "encap ila ", donde es el valor a configurar en el localizador de destino del paquete, ej. ip -6 route add 3333:0:0:1:5555:0:1:0/128 encap ila 2001:0:0:1 via 2401:db00:20:911a:face:0:25:0 configurará una ruta donde 333:0:0:1 será sobreescrito por 2001:0:0:1

· Túneles de red ligeros

Esta versión proporciona infraestructura para soportar túneles ligeros tales como túneles ip sobre MPLS. Permite una encapsulación escalable sin la sobrecarga de un netdevice completo. Para más información, leer este artículo de LWN Identifier locator addressing, o estas diapositivas netconf2015Herbert-ILA.pdf

iproute2 ha sido extendido con dos nuevos casos: VXLAN: ip route add 40.1.1.1/32 encap vxlan id 10 dst 50.1.1.2 dev vxlan0; MPLS: ip route add 10.1.1.0/30 encap mpls 200 via inet 10.1.1.1 dev swp1

·  Soporte de Virtual Routing and Forwarding (Lite)

 
Esta versión añade soporte de Virtual Routing and Forwarding (VRF), que, combinado con reglas ip, proporciona la abilidad de crear enrutados virtuales y dominios de reenvío (VRFs, o más bien VRF-lite para ser más específico). Para más información, leer la documentación en Documentation/networking/vrf.txt 


Estas son las novedades principales de este kernel. Como siempre, pueden encontrar la lista completa, y en inglés, en esta página.

16 de mayo de 2016

Las novedades de Linux 4.6

Ya se ha anunciado la versión 4.6 de Linux. Esta versión añade soporte para USB 3.1 SuperSpeedPlus (10 Gbps), un nuevo sistema de archivos distribuido OrangeFS, una implementación del "OOM killer" más fiable, soporte para una característica de CPUs Intel llamada "memory protection keys", un sistema para implementar más fácilmente protocolos de capa de aplicación (nivel 7 OSI), soporte para cifrado a nivel de MAC 802.1AE (conocido como MACsec), soporte para la versión V del protocolo BATMAN, un chequeador de inodos online en OCFS2, soporte de diferentes espacios de nombre en los cgroups, soporte del layout SCSI en pNFS, y muchas otras mejoras y nuevos controladores. La lista completa de cambios, en inglés, puede encontrarse aquí, como siempre.


· Soporte de USB 3.1 SuperSpeedPlus (10Gbps)
La especificación de USB 3.1 incluye un nuevo protocolo SuperSpeedPlus que soporta velocidades de hasta 10 Gbps. Los dispositivos que utilizan este nuevo protocolo son apodados como dispositivos USB 3.1 Gen2 (nótese que SuperSpeedPlus no es lo mismo que Type-C)

Esta versión añade soporte de la velocidad de 10 Gbps de USB 3.1 SuperSpeedPlus para el subsistema USB y el controlador host xHCI, lo cual significa que un dispositivo de almacenamiento USB 3.1 conectado a un host xHCI USB 3.1 debería poder alcanzar la velocidad de 10 Gbps.

· Mejora de la fiabilidad del asesino OOM

En anteriores versiones, el asesino OOM (que intenta matar un proceso cuando el sistema se queda sin memoria) intentaba matar un proceso con la esperanza de que acabase en un tiempo razonable y liberase su memoria. En la práctica, se ha demostrado que es fácil crear situaciones en las que esa asunción sea errónea, y el proceso elegido para ser eliminado tarde mucho tiempo porque ha sido bloqueado por otro proceso que está, a su vez, esperando a que se libere memoria. Esta versión añade un thread de kernel especializado, oom_reaper, que intenta liberar memoria librándose por adelantado de la memoria anónima o enviada al swap de la víctima, bajo la asunción de que esa memoria no será utilizada posteriormente.

· Soporte de Intel Memory Protection keys

Esta versión añade soporte para una característica de hardware para la protección de memoria, que estará disponible en futuras CPUs Intel: protection keys. Protection keys permite insertar en las entradas de la tabla de páginas una serie de máscaras de protección configurables. En lugar de tener en la tabla de páginas una protección fija para una página determinada (que requiere una llamada al sistema y debe cambiar los permisos una vez por cada página), el usuario puede definir unas pocas áreas de memoria. Luego, el espacio de usuario puede manipular un nuevo registro (PKRU, individual para cada proceso/thread) donde se pueden asignar a cada área de memoria dos bits separados: Desactivar Acceso y Desactivar Escritura. De ese modo, con la sola escritura en ese registro, se puede cambiar la protección de enormes porciones de memoria, sin tener que cambiar los permisos de cada una de las páginas.

También permite un control más preciso de los permisos de la MMU: Por ejemplo, el bit para desactivar la ejecución es distinto del bit para desactivar la lectura. Esta versión añade soporte para cambiar esos bits, y además añade una API para poder hacer uso de las protection keys. Si un programa en espacio de usuario hace la llamada mmap (..., PROT_EXEC) o mprotect(ptr, sz, PROT_EXEC), (nótese el PROT_EXEC sólo, sin PROT_READ/WRITE), el kernel notará este caso especial, y activará una protection key en este rango de memoria, y cambiará el contenido del registro PKRU. De ese modo, con las protection keys el kernel puede implementar un "verdadero" PROT_EXEC: código que puede ser ejecutado, pero no leído, lo cual es una pequeña ventaja de seguridad (pero téngase en cuenta que el código malicioso también puede manipular el registro PKRU). En el futuro, habrá mejoras en la implementación de esta caraterística y nuevas APIs de más alto nivel.

· OrangeFS, un nuevo sistema de archivos distribuido

OrangeFS es un sistema de almacenamiento paralelo, originalmente llamado PVFS y desarrollado en 1993 como parte de una beca de la NASA para estudiar los patrones de E/S de programas paralelos. Es ideal para solucionar los problemas de gran almacenamiento que se encuentran en entornos de HPC, BigData, Streaming de Video, Genómica, Bioinformática. OrangeFS puede ser accedido a través de utilidades del sistema, librerías, MPI-IO y puede ser utilizado por el ecosistema Hadoop como alternativa al sistema de archivos HDFS.

Las aplicaciones a menudo no requieren que OrangeFS esté montado en el VFS, pero el cliente del kernel de OrangeFS permite montarlos. El cliente del kernel se comunica con un demonio en espacio de usuario que a su vez se comunica con el demonio-servidor de OrangeFS que implementa el sistema de archivos. El demonio-servidor no tiene por qué estar ejecutándose en el mismo sistema que el cliente del kernel. Los sistemas de archivo OrangeFS también pueden montarse con FUSE.

· Multiplexor de conexiones del kernel, una herramienta para acelerar protocolos de capa de aplicación 

Esta versión añade el "Kernel Connection Multiplexor" o KCM, un sistema que proporciona una interfaz basada en mensajes sobre TCP para acelerar protocolos de la capa de aplicación. La motivación que tiene procede de la observación de que aunque TCP es un protocolo de transporte orientado a los streams de bytes, sin concepto de límites entre mensajes, un caso de uso común es la implementación de protocolos en la capa de aplicación dividido en mensajes, que se ejecuta sobre TCP. La mayor parte de pilas TCP ofrecen APIs de streams de bytes, lo cual fuerza a las aplicaciones a gestionar la delineación de mensajes, la atomicidad del envío y recepción de los mensajes, y balanceo de carga.

Con KCM una aplicación puede enviar y recibir eficientemente mensajes de un protocolo de la capa de aplicación sobre TCP. EL kernel proporciona la seguridad necesaria de que el mensaje será recibido y enviado atómicamente. Esto libera a la aplicación de buena parte del tedio de tener que mapear un protocolo basado en mensajes a un stream TCP. Para delinear el límite de los mensajes en el stream TCP, el kernel implementa un parseador de mensajes basado en BPF. Casi todos los protocolos de aplicación son parseables de esta manera, de modo que KCM debería ser usable por un amplio rango de aplicaciones.

· Cifrado a nivel de MAC 802.1AE (MACsec)

Esta versión añade soporte para MACsec IEEE 802.1AE, un estandar que proporciona cifrado sobre ethernet. Cifra y autentifica todo el tráfico en una red LAN con GCM-AES-128. Puede proteger el tráfico DHCP y las VLANs y prevenir la manipulación de cabeceras de ethernet. MACSex está diseñado para ser utilizado con la extensión al protocolo 802.1X MACsec Key Agreement, que proporciona un mecanismo para la distribución de claves a los nodos, pero también puede utilizarse con claves estáticas configuradas manualmente por el administrador.

· Soporte para el protocolo V de BATMAN

B.A.T.M.A.N. (Better Approach To Mobile Adhoc Networking) añade en esta versión soporte para el  protocolo V, sucesor del protocolo IV. El nuevo protocolo divide el protocolo OGM en dos subcomponentes: ELP (Echo Location Protocol), que se ocupa del descubrimiento de nuevos nodos y estimación de la calidad de los enlaces; y un nuevo protocolo OGM, OGMv2, que implementa el algoritmo que difunde las métricas a lo largo de la red y computa las rutas óptimas. El cambio más importante introducido en esta versión del protocolo es la nueva métrica: Ya no se basará en la pérdida de paquetes, sino en la estimación del ancho de banda.

· dma-buf: una nueva ioctl para gestionar la coherencia entre la GPU y la CPU

Los programas pueden necesitar algún tipo de mecanismo de gestión de la coherencia cuando tanto la CPU como la GPU están accediendo a recursos dma-buf simultáneamente. Para resolver este problema se ha añadido la ioctl DMA_BUF_IOCTL_SYNC, que permite manejar esos problemas de coherencia.

· Chequeador de inodos online para OCFS2

OCFS2 a menudo es utilizado en sistemas de alta disponibilidad. OCFS2 suele remontar automáticamente el sistema de archivos al modo sólo-lectura cuando se encuentra un error, pero esta acción disminuye la disponibilidad, y no siempre es necesario. Existe una opción de montaje (errors=continue) que permite evitar ese montaje a sólo-lectura: sólo se devuelve -EIO al proceso que causó el error y se reporta el número de inodo problemático en el dmesg. Esta versión añade un chequeador de inodos muy simple en el kernel que puede utilizarse para comprobar y resetear el inodo. Nótese que esta característica está dirigida para problemas muy pequeños que puedan entorpecer las operaciones diarias de un cluster, no está dirigido a comprobaciones complejas, que deben seguir utilizando el fsck offline.

· Soporte para diferentes espacios de nombre en los cgroups

Esta versión añade soporte para diferentes espacios de nombre en los cgroups, lo cual proporciona un mecanismo para virtualizar el contenido del archivo /proc/$PID/cgroup y de los montajes de cgroups. Se ha añadido una nueva bandera a clone(2) y unshare(2), CLONE_NEWCGROUP, que permite crear un nuevo espacio de nombres de cgroup. Para un contenedor correctamente configurado, esto permite a las herramientas de contenedores (libcontainer, lxc, lmctfy, etc) crear contenedores virtualizados que no revelen información crítica sobre otras jerarquías cgroup del sistema.

· Soporte del layout SCSI para pNFS

Esta versión añade soporte en pNFS (parallel NFS, disponible en NFS v4.1) para layouts SCSI en el servidor NFS de Linux. Con los layouts SCSI, el servidor NFS actua como un Servidor de Metadatos para pNFS, que además de gestionar todo el acceso a metadatos de la exportación NFS, también ofrece layouts al cliente de manera que los clientes puedan acceder los LUNs SCSI. Para más detalles ver draft-ietf-nfsv4-scsi-layout

Estas son las novedades principales de este kernel. Como siempre, pueden encontrar la lista completa, y en inglés, en esta página.

1 de abril de 2016

Las novedades de Linux 4.1

(Nota: aunque con un retraso enorme, aquí va este post)

Ya se ha anunciado la versión 4.1 de Linux. Esta versión añade soporte de cifrado integrado en Ext4, soporte experimental de arrays RAID compartidos en clúster, un nuevo target del device mapper que permite mantener un registro de todas las escrituras hechas a un dispositivo y que permite reproducirlas, un driver que convierte la memoria de sistemas con memoria persistente en un dispositivo de bloques, posibilidad de desactivar el soporte multiusuario, soporte para el Multiprotocol Label Switching que permite enrutar paquetes basándose en etiquetas de ruta en lugar de direcciones de red, capacidad de asociar programas BPF a sondas kprobes, soporte de ACPI en la arquitectura ARM64, y un driver GEM virtual que permite construir mejores rasterizadores por software. También hay nuevos drivers y muchas pequeñas mejoras. La lista completa de cambios, en inglés, puede encontrarse aquí, como siempre.


· Soporte de cifrado en Ext4

Linux ya proporciona sistemas para cifrar archivos, tales como dm-crypt o ecryptfs, pero tienen ciertos costes de rendimiento y consumo de memoria. En esta versión, el sistema de archivos Ext4 añade soporte nativo para cifrado: tanto los datos como los nombres de los archivos pueden ser cifrados con una clave proporcionada por el usuario. La clave se utiliza para los archivos de un directorio y todos sus subdirectorios. Cuando haya que leer un archivo, si no se ha proporcionado previamente una clave válida, sólo se podrá leer los nombres de archivo cifrados, pero pero no los descifrados, y los datos cifrados no se podrán leer.

Para usar esta característica, se necesitan e2fsprogs versión 1.43 y el software keyutils. Aquí hay un pequeño howto. Para detalles sobre el diseño interno, ver aquí. Artículo de LWN recomendado: Ext4 encryption

· Soporte experimental de clustering en MD

Esta versión añade soporte experimental de clústering en MD (Linux software RAID). Un Cluster MDes un dispositivo compartido RAID para un clúster. Permite bloqueos y sincronización a través de múltiples sistemas de un clúster, de modo que todos los nodos del clúster pueden acceder al dispositivo MD simultáneamente, proporcionando la redundancia (y uptime) del RAID a todos los nodos del clúster. En esta versión, la implementación está limitada a RAID1, pero en el futuro podría extenderse a otros niveles RAID. El código en esta versión es altamente experimental. Howto: howto

· Device mapper: nuevo target que guarda un registro de las escrituras

En esta versión, el device mapper introduce un nuevo target que permite hacer un registro de todas las operaciones de escritura, y guardar ese registro en un dispositivo separado, de modo que puedan reproducirse las operaciones a posteriori. La motivación de esta funcionalidad es proporcionar a los desarrolladores una herramienta para verificar el sistema de archivos en varios puntos de la vida de un sistema de archivos, permitiéndoles reproducir el registro hasta un punto concreto.

· Soporte de monousuario

Puede parecer extraño que un sistema multi-usuario como Linux quiera adoptar una funcionalidad que es una regresión al pasado, tal y como lo es la eliminación de la protección multi-usuario. Pero resulta que los dispositivos embebidos quieren hacer Linux lo más pequeño que sea posible, y no necesitan las capacidades multi-usuario. En esta versión, es posible configurar el kernel para que el UID y GID de todos los procesos sean cero (root) en todos los casos. Con esto, se ahorra la compilación de 25 KB de código en una configuración defconfig. Artículo LWN recomendado: Linux as a single-user system

 · Driver virtual GEM para implementar mejores rasterizadores por software

El driver vGEM proporciona un GEM (graphics memory manager) que puede ser utilizado por el renderizador por software de la librería MESA para mejorar el rendimiento.

· Dispositivo de bloques para memoria persistente

Hay nuevos tipos de memoria que pueden ser accedidas casi tan rápido como la RAM, pero que no pierden los datos cuando se apaga el equipo. Este tipo de memoria se llama memoria persistente. En esta versión, Linux incluye PMEM, un driver que representa un rango de memoria reservado como un dispositivo de bloques, que puede ser utilizado posteriormente por sistemas de archivo. Artículo recomendado de LWN: Persistent memory support progress

· Multiprotocol Label Switching

Esta versión añade soporte para Multiprotocol Label Switching (MPLS). MPLS es un transporte de red escalable e independiente de protocolo, que dirige los datos de un nodo al siguiente basándose en etiquetas cortas en lugar de direcciones de red, de modo que se evitan las búsquedas complejas en la tabla de enrutado, porque las decisiones sobre el redireccionamiento de paquetes se toman en base de los contenidos de una etiqueta, sin necesidad de examinar el paquete. Las etiquetas identifican enlaces virtuales (rutas) entre nodos distantes, en lugar de destinos. MPLS puede encapsular paquetes de varios protocolos de red.

· Los programas BPF pueden ser asociados a sondas kprobes

En esta versión, Linux permite asociar pequeños programas BPF a sondas kprobes, proporcionando de este modo una manera segura de ejecutar programas BPF, sin riesgos para la seguridad o la estabilidad. Esto permite construir, en un kernel en ejecución, instrumentación definida por el usuario que no puede colgar o interferir con el kernel. En esta versión, sólo se permite el uso por root.

· Soporte de ACPI para la arquitectura ARM64

Durante mucho tiempo, ACPI ha sido una característica exclusiva de sistemas x86 (e Itanium). A pesar de las controversias, algunas partes del mundo ARM han empezado a utilizar el estándar ACPI. Esta versión añade soporte preliminar de ACPI 5.1 a la arquitectura arm64.



Estas son las novedades principales de este kernel. Como siempre, pueden encontrar la lista completa, y en inglés, en esta página.

31 de marzo de 2016

Las novedades de Linux 4.2

(Nota: aunque con un retraso enorme de medio año, aquí va este post)

Ya se ha anunciado la versión 4.2 de Linux. Esta versión añade el driver amdgpu para GPUs de AMD, un driver virtio para la virtualización de GPU, la nueva API gráfica "atomic modesetting" ya es estable, soporte para usar más de un módulo de seguridad al mismo tiempo, una implementación de spinlock más rápida y escalable, soporte de control de writeback dentro de los cgroups, y la reintroducción del soporte para la arquitectura H3/800. También se han incluido drivers nuevos y muchas otras mejoras y pequeños cambios. La lista completa de cambios, en inglés, puede encontrarse aquí, como siempre.


· Nuevo driver amdgpu para hardware AMD Radeon moderno

Esta versión incluye el driver amdgpu, un nuevo driver para asics AMD VI+. Actualmente soporta Tonga, Iceland y Carrizo, y también contiene una opción para soportar experimentalmente partes CI. Toda la funcionalidad importante está soportada. La gestión energética funciona en Carrizo, pero todavía está en desarrollo para Tonga e Iceland.

Este driver es un punto de partida de cero de AMD para centrar en él su nueva estrategia de apuesta por el software libre: Su propósito es que el único driver para gráficos AMD sea éste; la funcionalidad privativa que existe actualmente en el driver Catalyst será portada al driver o se ejecutará como un binario que se ejecute en espacio de usuario e interactúe con el driver.

· Driver virtio para GPUs
Los drivers virtio son "falsos" drivers diseñados para hacer la comunicación entre huéspedes y anfitriones de virtualización más eficiente. Emular el hardware real es complejo e ineficiente, estos drivers en cambio son conscientes de estar ejecutándose en entornos virtualizados, y ofrecen canales para el intercambio de datos simples y rápidos.

En esta versión se incluye un driver para GPUs virtuales. Puede ser utilizado en máquinas virtuales de QEMU. Por ahora sólo soporta kernel-modesetting; el driver modesetting de X.org es capaz de gestionar el dispositivo perfectamente, y también está disponible el framebuffer para fbcon. Los parches para el soporte en QEMU están siendo revisados. La versión inicial sólo tiene soporta para 2D; el soporte 3D requiere más trabajo en QEMU y será añadido más tarde.

· La API atomic modesetting activada por defecto

Esta versión por fin completa la nueva API atomic modesetting, y la activa por defecto (hasta ahora era experimental y requería ser activada manualmente). Esta API es necesaria para implementar mejor los sistemas gráficos modernos; para más detalles sobre esta API y por qué es necesaria, se recomienda leer estos artículos de LWN: Atomic mode setting design overview, parte 1, y parte 2

· Apilado de módulos de seguridad

Hay varios módulos de seguridad disponibles en Linux, pero sólo se puede usar uno al mismo tiempo. Durante muchísimo tiempo, ha habido desarrolladores que han querido poder utilizar más de un módulo de seguridad al mismo tiempo ("stacking", es decir "apilando" otro módulo tras el primero). Esta versión añade soporte para el "apilado" de módulos de seguridad. Para más detalles, léase Progress in security module stacking

· Una nueva implementación de spinlocks

Esta versión añade soporte en la arquitectura x86 para un nuevo tipo de spinlocks basados en una cola. Esta nueva implementación es capaz de reemplazar la actual implementación por defecto de spinlocks basado en "tickets", sin incrementar el tamaño de la estructura de datos del spinlock.

Este nuevo spinlock tiene un rendimiento ligeramente lejor que el "ticket" en caso de que no haya contención, y su rendimiento puede ser mucho mejor cuando hay contención moderada o alta. Es especialmente útil para máquinas NUMA con al menos 2 sockets; aunque incluso con sólo 2 sockets puede haber mejoras significativas, dependiendo del trabajo a realizar. También puede mejorar el rendimiento de un test de estrés intensivo de E/S e interrupciones hasta un 20%. Para más detalles, leer MCS locks and qspinlocks.

· Soporte de control de writeback dentro de un cgroup

Linux es capaz de limitar a los procesos que están intentando escribir muchas páginas de memoria al disco (writeback). Pero este control es global, y no permite un control personalizado en los cgroups. Esta versión añade soporte para control de writeback a los procesos de un cgroup. Para más detalles, ver Writeback and control groups

· Reintroducción de la arquitectura H8/300

Linux añadió soporte para la arquitectura H8/300 en Linux 2.5.68. Pero fue eliminada en Linux 3.13 por falta de mantenimiento.

En esta versión, se ha vuelto a implementar el soporte para esta arquitectura.



Estas son las novedades principales de este kernel. Como siempre, pueden encontrar la lista completa, y en inglés, en esta página

14 de marzo de 2016

Las novedades de Linux 4.5

Ya se ha anunciado la versión 4.5 de Linux. Esta versión añade una nueva llamada al sistema, copy_file_range(2), que permite copiar archivos sin el coste de transferir los datos a través del espacio de usuario; soporte experimental de la gestión de energía Powerplay en GPUs Radeon modernas; mejoras de escalabilidad en la gestión del espacio libre de Btrfs; soporte para el Undefined Behavior Sanitizer de GCC (-fsanitize=undefined); soporte para Forwarded Error Correction en el objetivo verity del device-mapper, soporte para la bandera MADV_FREE en madvise(); la nueva jerarquía unificada de cgroup ya se considera estable; mejoras de escalabilidad en sockets UDP que hacen uso de SO_REUSEPORT; y mejoras de escalabilidad para epoll. También se han incluido drivers nuevos y muchas otras mejoras y pequeños cambios. La lista completa de cambios, en inglés, puede encontrarse aquí, como siempre.


· Copias más rápidas con la llamada al sistema copy_file_range(2)

Copiar un archivo consiste en leer datos de un archivo a la memoria de un proceso, y luego copiar los datos de esa memoria al archivo destino. No hay nada malo con esta manera de hacer las cosas, pero requiere hacer copias extra de los datos al copiarlos a/desde la memoria del proceso. En esta versión Linux añade una nueva llamada al sistema, copy_file_range(2), que permite copiar un rango de datos de un archivo a otro, evitando el coste mencionado de transferir los datos del kernel al proceso y luego de nuevo al kernel.

Esta llamada al sistema sólo es ligeramente más rápida que cp, porque el coste de hacer las copias apenas es nada, comparado con el tiempo que toma hacer la E/S, pero hay algunos casos en los que puede ayudar mucho. En sistemas de archivos de red, como NFS, copiar los datos implica enviar los datos del servidor al cliente a través de la red, y luego enviarlos de nuevo del cliente al nuevo archivo en el servidor. Pero con copy_file_range(2), el cliente puede ordenar al servidor NFS que copie un rango de datos específico de un archivo a otro, sin transferir los datos a través de la red (para NFS, esto requiere también el soporte de la característica "copia del lado del servidor, presente en el próximo NFSv4.2, y también soportado experimentalmente en esta versión). En próximas versiones, los sistemas de archivos locales como Btrfs, o algunos dispositivos de almacenamiento especializados, podrían usar esta llamada al sistema para optimizar la copia de datos, o se podrían eliminar algunas de las limitaciones actuales (la copia de datos está limitada a archivos que se encuentren en la misma montura y superbloque, y que las copias no sean entre partes del mismo archivo)

· Gestión de energía PowerPlay experimental en el driver amdgpu

Las GPUs modernas arrancan en modo de bajo consumo y rendimiento, y necesitan alterar dinámicamente su frecuencia para funcionar en los modos que proporcionan el mejor rendimiento. Pero eso no puede hacerse sin gestión de energía. Esta versión incorpora soporte de Powerplay en el driver amdgpu para GPUs Tonga y Fiji, y APUs integradas Carrizo y Stoney.

Powerplay es el nombre dado por AMD al sistema de gestión de energía presente en varias de sus GPUs y APUs y soportado en el driver propietario Catalyst, y ahora aspira a reemplazar la actual gestión de energía del driver amdgpu. En las GPUs soportadas el rendimiento será mucho más alto.

Powerplay no está activado por defecto en todos los tipos de hardware soportado debido a su carácter experimental, en esos casos puede intentar forzarse su uso con la opción del kernel "amdgpu.powerplay=1".

· Mejoras de escalabilidad en la gestión del espacio libre de Btrfs

Los sistemas de archivos necesitan mantener un registro de los bloques que están en uso y de los que no. También necesitan almacenar información sobre el espacio libre en algún lado, porque regenerarlo de cero cuesta demasiado. Btrfs ha tenido la capacidad de almacenar un caché del espacio libre desde 2.6.37, pero la implementación se ha convertido en un cuello de botella de escalabilidad en los sistemas de archivos grandes (+30T) y ocupados.

Esta versión incluye una nueva y experimental implementación del caché de espacio libre, que es más ligero y resuelve los problemas de escalabilidad citados. Este nuevo sistema es experimental, y no está activado por defecto. Puede ser activado con la opción de montaje -o space_cache=v2. La primera vez que se utilice esta opción, se creará el nuevo caché de espacio libre y se activará una bandera de sólo lectura (los kernels antiguos podrán leer, pero no escribir, al sistema de archivos). Es posible revertir el cambio y volver al caché antiguo (y eliminar la bandera de sólo lectura) utilizando la opción de montaje -o clear_cache,space_cache=v1.


· Soporte para el Undefined Behaviour Sanitizer de GCC (-fsanitize=undefined)

UBSAN (Undefined Behaviour SANitizer) es una herramienta de depuración disponible en GCC a partir de la versión 4.9 (ver -fsanitize=undefined documentation). Se trata de una funcionalidad que inserta código durante la compilación que hace comprobaciones en tiempo de ejecución para detectar situaciones que podrían causar comportamientos indefinidos. Comportamiento indefinido significa que las semánticas de ciertas operaciones no están definidas y el compilador asume que esas operaciones no se dan y que el programador se preocupará de evitarlas, pero de ocurrir la aplicación puede producir resultados equivocados, estrellarse, o incluso producir agujeros de seguridad; ejemplos de comportamientos indefinidos son el uso de una variable no estática antes de ser inicializada, división de un entero por cero, desbordamiento de enteros con signo, desreferenciación de punteros NULL, etc.


En esta versión, Linux soporte la posibilidad de compilar el kernel con la funcionalidad Undefined Behavior Sanitizer activada, con las opciones de -fsanitize: shift, integer-divide-by-zero, unreachable, vla-bound, null, signed-integer-overflow, bounds, object-size, returns-nonnull-attribute, bool, enum y, opcionalmente, alignment. La mayor parte del trabajo lo hace el compilador, el kernel se limita a mostrar los errores.

· Soporte de Forwarded Error Correction en el target verity del device-mapper

El target "verity" del device-mapper, utilizado por plataformas populares como Android o Netflix, fue incluido en Linux 3.4, y permite comprobar que un sistema de archivos no ha sido modificado, comprobando cada lectura del sistema de archivos con una lista de hashes criptográficos.

Esta versión añade soporte de Forward Error Correction para el target verity. Esta característica hace posible recuperarse de varios bloques de datos corrompidos, utilizando unos bloques pre-generados de correción de errores, que no ocupan demasiado espacio y pueden ser utilizados para reconstruir los bloques dañados. Esta técnica, utilizada en DVDs, discos duros o transmisiones satélite, permitirá seguir utilizando un sistema de archivos de un target verity que esté ubicado en un medio de almacenamiento que esté ligeramente dañado.

· Añadir la bandera MADV_FREE a madvise(2)

madvise(2) es una llamada al sistema utilizada por los procesos para decirle al kernel cómo van a utilizar su memoria, permitiendo al kernel, de ese modo, optimizar la gestión de memoria de acuerdo con las pistas proporcionadas, para alcanzar un mejor rendimiento del sistema.

Cuando una aplicación quiere decir al kernel que no va a utilizar un rango de memoria en un futuro cercano, puede usar la bandera MADV_DONTNEED, de manera que el kernel puede liberar los recursos de memoria asociados a ese rango. Los accesos subsiguientes tendrán éxito, pero sus consecuencia serán o bien recargar la memoria con datos del archivo mapeado, o páginas puestas a cero para los mapeados que no estén respaldados por archivos. Pero hay algunos tipos de aplicaciones (notablemente, asignadores de memoria de librerías) que pueden reusar ese rango de memoria, y MADV_DONTNEED fuerza a que incurran en el coste de hacer un fallo de página, asignación de una página, rellenarla con ceros, etc. Para evitar esa sobrecarga, otros sistemas operativos como los BSDs han soportado MADV_FREE, que simplemente marca las páginas como disponibles para ser liberadas, pero sin liberarlos inmediatamente, y por lo tanto permitiendo reusar la memoria en un corto espacio de tiempo sin incurrir en el coste de un fallo de página.

· Mejor escalabilidad multihilo en epoll

Cuando se añaden múltiples descriptores de archivo de epoll a una sóla fuente de eventos compartida entre todos, se añaden de modo que un evento puede despertar a todos los descriptores de archivo de epoll, lo cual crea un problema de escalabilidad cuando se utilizan muchísimos descriptores de archivo desde muchos hilos.

Esta versión añade una nueva bandera, EPOLLEXCLUSIVE, que puede pasarse como parte del argumento 'event' durante una operación EPOLL_CTL_ADD con epoll_ctl(2). Esta nueva bandera permite que las notificaciones de eventos no despierten a todos los descriptores de archivo. En una versión modificada de Enduro/X, el uso de la bandera 'EPOLLEXCLUSIVE' redujo la longitud de esta carga particular de 860s a 24s.

· La jerarquía unificada de cgroup se considera estable

cgroups, o grupos de control, son una característica introducida en Linux 2.6.24 que permite asignar recursos (como tiempo de CPU, memoria, ancho de banda) entre grupos de procesos definidos por el usuario. En su primera implementatión, los cgroups permitían un número arbitrario de jerarquías de procesos y cada jerarquía podía albergar cualquier número de controladores. Este modo de operar proporcionaba mucha flexibilidad, pero en la práctica tenía una serie de problemas, así que en Linux 3.16 se incluyó una uneva jerarquía unificada, pero experimental, y sólo disponible con la opción de montaje -o __DEVEL__sane_behavior.

En esta versión, la jerarquía unificada ya se considera estable, y ya no se esconde tras esa opción de montaje especial. Puede ser montada con el tipo de archivo cgroup2 (desgraciadamente, el controlador de cpu no ha llegado a ser incluído en esta versión, sólo los controladores de memoria y E/S están disponibles). Para mas detalles sobre cgroup2 y una justificación detallada sobre la migración a la jerarquía unificada, ver la documentación de cgroup2.

· Mejoras de rendimiento para sockets UDP que usen SO_REUSEPORT

SO_REUSEPORT es una opción de socket disponible desde Linux 3.9 que permite que múltiples sockets de escucha se "enganchen" al mismo puerto. La motivación tras el desarrollo de SO_REUSEPORT serían casos de uso tales como un servidor web escuchando en el puerto 80, y ejecutando múltiples hilos, cada uno con su propio socket.

En esta versión, Linux incluye dos optimizaciones para SO_REUSEPORT (en esta versión, sólo para sockets UDP):
  · Hay dos nuevas opciones de socket para sockets SO_REUSEPORT: SO_ATTACH_REUSEPORT_CBPF y SO_ATTACH_REUSEPORT_EBPF. Esas opciones permiten definir un programa BPF clásico o extendido, que defina cómo los paquetes se asignan a los sockets que están esperando en el grupo de sockets SO_REUSEPORT.
  · Búsqueda más rápida al seleccionar un socket SO_REUSEPORT para un paquete entrante. Anteriormente, el proceso de búsqueda necesitaba iterar por todos los sockets, en esta versión se puede encontrar un candidato mucho más rápido.

· Mejor gestión del uso de memoria de los sockets en el controlador de memoria

En anteriores versiones, los buffers de los sockets se contaban en el controlador de memoria de los cgroup por separado, sin ninguna presión que igualara entre la memoria anónima, el caché de páginas, y los buffers de sockets. Cuando se acababa la memoria de la reserva de buffers de socket, las asignaciones de buffers fallaban y el rendimiento de la red se hundía, al margen de que aun hubiera memoria disponible en el grupo o no. Del mismo modo, la memoria anónima u otros caches no podían hacer uso de la reserva para buffers de sockets que no estuviese siendo usada. Por esta razón, esta característica no podía ser usada con fiabilidad en muchas aplicaciones de la vida real.

En esta versión, el nuevo controlador de memoria unificado tendrá en cuenta todos los tipos de memoria a su cargo. Cuando haya poca memoria, la VM reclamará y reducirá y presionará en cualquier consumidor de memoria. Cuando la VM tenga problemas liberando memoria, la pila de red detendrá los incrementos en los "transmit windows" del cgroup. Para evitar la gestión de memoria de los sockets de buffer, es posible usar la opción del kernel cgroup.memory=nosocket.



Estas son las novedades principales de este kernel. Como siempre, pueden encontrar la lista completa, y en inglés, en esta página.

19 de enero de 2016

Las novedades de Linux 4.4

Ya se ha anunciado la versión 4.4 de Linux. Esta versión añade soporte 3D para el driver de la GPU virtual, que permite usar la aceleración 3D de hardware en sistemas virtualizados; se añade también soporte de E/S directo y asíncrono en el dispositivo loop, lo cual ahorra memoria y mejora el rendimiento; se añade soporte para discos SSDs Open-Channel, que son SSDs que intentan compartir con el sistema operativo la responsabilidad de la FTL; la gestión de los "TCP listener" se hace ahora sin ningún tipo de bloqueo y permite que los servidores TCP sean más rápidos y mucho más escalables; journaling de RAID5 en la capa MD que permite solucionar el llamado "write hole"; los programas eBFP pueden ahora ser ejecutados por usuarios sin privilegios, pueden hacerse permanentes tras el fin de un proceso, y la utilidad perf ha añadido soporte para eBFP también; una nueva llamada de sistema mlock2() que permite bloquear la memoria añadida desde los fallos de página; y soporte de polling en dispositivos de bloques que mejora el rendimiento en los dispositivos de muy alto rendimiento. También se han incluido drivers nuevos y muchas otras mejoras y pequeños cambios. La lista completa de cambios, en inglés, puede encontrarse aquí, como siempre.


· Dispositivo loop más rápido y ligero con E/S Directa y Asíncrona

  Esta versión incorpora soporte de E/S directa y asíncrona en el dispositivo de bloques loop. Esto tiene varias ventajas: se mejora el consumo de memoria porque se evita mantener un cache duplicado; y se mejora el rendimiento al evitarse cambios de contexto

· Soporte en el driver de GPU virtual

  virtio-gpu es un driver para huéspedes de virtualización que permite utilizar las capacidades gráficas del anfitrión eficientemente. En esta versión, se permite que el huésped utilice las capacidades de la GPU del anfitrión para acelerar los gráficos 3D. En la práctica, esto significa que un huésped virtualizado Linux puede ejecutar juegos OpenGL utilizando la GPU, como se muestra aquí o aquí. Se requiere el uso de QEMU 2.5 o superior.

· LightNVM añade soporte para SSDs Open-Channel

  Los SSDs Open-Channel son dispositivos que comparten con el sistema operativo la responsabilidad de implementar y mantener las características que los SSDs implementan típicamente en el firmware, tales como la Flash Translation Layer (FTL), la gestión de bloques dañados, y unidades del hardware como el controlador flash, el controlador de la interfaz, y muchos chips flash. De este modo, los SSDs Open-Channel exponen un acceso directo al almacenamiento físico flash.

LightNVM es una especificación que da soporte a SSDs Open-Channel. LightNVM permite al sistema gestionar la ubicación de los datos, la recolección de memoria y el paralelismo, mientras que otras características permanecen en control del hardware. Esta versión de Linux añade soporte para lightnvm y para NVMe.

· Gestión de TCP listeners sin bloqueos

  En esta versión, y como resultado de un esfuerzo que empezó hace dos años, la implementación TCP ha sido reescrita para que no haya ningún bloqueo en las rutas más comunes del código que gestiona a los programas que hacen escuchas TCP. En pruebas, un servidor fue capaz de procesar 3.500.000 de paquetes SYN por segundo en un sólo listener y sin llegar a ocupar todo el tiempo de CPU, esto representa entre 2 y 3 órdenes de magnitud de lo que era posible previamente. SO_REUSEPORT también ha sido extendido para añadir afinidades de CPU/NUMA.

· Soporte de journalled RAID5 en MD

  Esta versión añade soporte de RAID 5 journalled en la capa MD (RAID/LVM). Con un dispositivo de journal configurado (típicamente NVRAM o SSD), los datos y la paridad de un array RAID se escriben primero al journal, y luego al array. Si el sistema se bloquea, se pueden recuperar datos del log. Esto puede acelerar la resincronización RAID y resuelve el problema del "write hole" de RAID5 - un cuelgue durante el modo degradado no resultará en corrupción de datos. En futuras versión el journal será utilizado también para mejorar el rendimiento y la latencia.

· Programas eBPF sin privilegios + programas eBPF persistentes

  Programas eBPF sin privilegios
  Los programas eBPF consiguieron su propia llamada al sistema en Linux 3.18, pero hasta ahora su uso había estado restringido a root, porque estos programas son peligrosos para la seguridad. Sin embargo, los programas eBPF son validados por el kernel, y en esta versión el verificador de programas eBPF ha sido mejorado y como resultado los usuarios sin privilegios pueden hacer uso de ellos (aunque sólo podrán construir programas tipo filtro de sockets, los programas que usen funciones de trazado o del control de tráfico de red requerirán root). esta característica puede ser desactivada con la sysctl kernel.unprivileged_bpf_disabled (una vez desactivada sólo root podrá usar programas eBPF, y la sysctl no podrá volver a cambiarse)

  Programas eBPF persistentes
  Esta versión añade soporte para mapas/programas eBPF "persistentes". El término "persistente" ha de entenderse como un mecanismo que permite que sobrevivan al fin del proceso que los crea. Hay usuarios eBPF que desean este tipo de comportamientos, por ejemplo el clasificador de tráfico tc(8). Cuando tc hace uso de un objecto eBPF, nuevas invocaciones de tc no podrán reutilizarlo.

  Para solucionar ese problema, se ha añadido un sistema de archivos virtual que puede almacenar programas y mapas eBPF en /sys/fs/bpf/. Los objetos eBPF son creados mediante la llamada al sistema bpf() junto con una ruta y dos nuevos comandos (BPF_OBJ_PIN/BPF_OBJ_GET) que crean los archivos correspondientes en el sistema de archivos. Estos archivos pueden ser reutilizados posteriormente por otros procesos, a través también de bpf(2).

· Integración de perf y eBPF

  En esta versión, los programas eBPF han sido integrados en perf. Cuando se pasa a perf un archivo .c eBPF (o uno .o compilado con el target "bpf" de clang) será compilado automáticamente, validado y cargado en el kernel, pudiendo ser utilizado posterioemente por perf trace y otras herramientas.

  Los usuarios pueden hacer uso de un filtro eBPF con comandos como: # perf record --event ./hello_world.o ls; y el programa eBPF será conectado a un evento perf que puede ser utilizado por el resto de herramientas.

· Soporte de polling para dispositivos de bloque

  Esta versión añade soporte básico para hacer polling para que una petición de E/S concreta se complete, lo cual puede mejorar la latencia y el rendimiento en dispositivos muy rápidos. De momento, se soportan escrituras y lecturas síncronas con O_DIRECT. Este soporte es preliminar y sólo debe ser utilizado para pruebas, en próximas versiones se utilizarán estadísticas para hacer uso de este modo automáticamente. De momento, se añade un archivo en sysfs (io_poll) que controla si el polling está activado o no.

· Llamada al sistema mlock2() que permite a los usuarios bloquear memoria en fallos de página

  mlock() permite a un usuario bloquear la memoria de un programa en la RAM, pero esto tiene como coste la necesidad de incluir en la RAM toda la memoria de una vez. Este comportamiento no es muy adecuado cuando se necesita usar mlock() con mapeados de archivos muy grandes: Por ejemplo, las aplicaciones sensibles con la seguridad que usan mlock() pueden verse forzadas a bloquear un búfer demasiado grande. O quizás un modelo gráfico gigantesco donde la ruta de un grafo no es conocida hasta el tiempo de ejecución, en lugar de bloquear en memoria sólo las partes utilizadas están forzadas a bloquear todo el grafo o ir bloqueando página tras página a medida que van siendo utilizadas.

Esta nueva llamada al sistema, mlock2(), trata de conseguir una solución intermedia. Las páginas de la memoria no son bloqueadas en memoria inmediatamente, sino que se van bloqueando aquellas que van siendo mapeadas en memoria.

Estas son las novedades principales de este kernel. Como siempre, pueden encontrar la lista completa, y en inglés, en esta página.