Por Jonathan Corbet, traducción de Ángel Ortega. Artículo original: http://lwn.net/Articles/313682/
El sistema de ficheros Btrfs lleva en desarrollo más o menos desde el último año; durante casi todo este tiempo ha sido denominado como el «sistema de ficheros de nueva generación» de Linux. Pero, antes de ser merecedor de reclamar este título, debe estabilizarse e incorporarse al núcleo principal. Su desarrollador Chris Mason lleva un tiempo diciendo que el desarrollo irá más rápido si se incluye en el núcleo lo antes posible, incluso aunque no esté listo todavía para su uso en producción. La experiencia parece apoyar esta postura: el código en el árbol principal obtiene más pruebas, revisiones y arreglos que el que está fuera de él. Por tanto, la comunidad de desarrolladores ha apoyado una inclusión relativamente temprana de Btrfs.
En nuestro anterior episodio, Andrew Morton sugirió la versión 2.6.29 como objetivo para su inclusión. Chris quiere que esto ocurra y ha publicado una versión de Btrfs para que sea tenida en cuenta. Como era de esperar, esto ya ha atraído la atención hacia el código, con el resultado de que Chris tiene una lista de cosas pendientes de arreglar. La mayoría ya han sido tenidas en cuenta, pero quedan unos cuantos asuntos que podrían impedir su inclusión en este ciclo de desarrollo. Este artículo se centrará en estudiar estos posibles obstáculos.
Uno de ellos es el API del espacio de usuario. Btrfs trae todo un grupo de llamadas ioctl(), ninguna de las cuales ha sido especialmente revisada ni documentada. Estas llamadas hacen cosas como crear «snapshots», iniciar la defragmentación, crear o redimensionar subvolúmenes, añadir volúmenes a un conjunto, etc. Curiosamente, no ha habido objeciones significativas a las capacidades de gestión de volúmenes de Btrfs, pero el interfaz necesita un serio escrutinio; normalmente, las APIs de espacio de usuario no pueden ser cambiadas una vez publicadas. Ha habido conversaciones sobre hacer una excepción para Btrfs, ya que hay pocas posibilidades de que un sistema se haga dependiente de ellas antes de que Btrfs se considere como listo para producción.
De cualquier forma, una vez que las distribuciones comiencen a incluir las herramientas de Btrfs - aunque sólo sea para contribuir a que la gente las pruebe - un cambio en las APIs sería doloroso, y Linux podría acabar estancado con una versión demasiado inmadura. Dado que al menos un desarrollador estima que este API necesita una seria reescritura, el tema podría convertirse en un obstáculo serio.
Por otra parte están las primitivas de bloqueo diseñadas específicamente para Btrfs. Para comprender profundamente el tema, merece la pena echar un ojo a su función de bloqueo:
int btrfs_tree_lock(struct extent_buffer *eb) { int i; if (mutex_trylock(&eb->mutex)) return 0; for (i = 0; i < 512; i++) { cpu_relax(); if (mutex_trylock(&eb->mutex)) return 0; } cpu_relax(); mutex_lock_nested(&eb->mutex, BTRFS_MAX_LEVEL - btrfs_header_level(eb)); return 0; }
El cerrojo en cuestión es un «mutex» (cerrojo de exclusión mutua) normal, pero el bloqueo se efectúa de una forma peculiar: si otro proceso tiene bloqueado el cerrojo, esta función intentará bloquearlo activamente hasta 512 veces sin dormir, con la esperanza de que sea liberado rápidamente. Si esto ocurre, el bloqueo se puede conseguir sin que el proceso se pare. Si después de estos 512 intentos no lo consigue, la función se rinde y se echa a dormir.
Chris justifica este comportamiento:
"Btrfs usa cerrojos de exclusión mutua para proteger los bloques de «btrees», y en estas búsquedas a menudo se encuentran nodos que ya están en el caché. Para estos nodos, los intentos activos funcionan mucho más rápido, pero btrfs también tiene que ser capaz de dormir con los cerrojos bloqueados de forma que pueda leer del disco y hacer otras operaciones más complejas.
Para btrfs, el test de dbench 50 dobla su rendimiento con este método, fundamentalmente porque casi todo está en RAM. Para 50 procesos creando ficheros de 4k en paralelo, es de un 30 a un 50% más rápido. Esta carga de trabajo está repartida entre disco y CPU."
Esta mejora de rendimiento parece merecer la pena. De hecho, refleja un fenómeno observado en otras situaciones: incluso usando cerrojos en los que el proceso se echa a dormir, el rendimiento mejora si el procesador hace unos intentos activos durante un tiempo con la esperanza de que el cerrojo se libere pronto. Si el bloqueo se consigue, se evita la sobrecarga de poner al proceso a dormir para despertarlo inmediatamente después. Además, el proceso que espera obtener el bloqueo está probablemente en la caché de la CPU. Permitir al proceso continuar sin dormir sin duda redunda en una mejora significativa del rendimiento.
Por esta misma razón se desarrolló el parche de cerrojos adaptativos en tiempo real, aunque nunca llegó a incluirse en el núcleo principal. En respuesta a la discusión sobre Btrfs, Peter Zijlstra propuso el parche «spinning mutex», el cual pretende obtener las mismas ventajas que el bloqueo especial de Btrfs pero para uso general y sin añadir constantes «mágicas». En el parche de Peter se hacen sucesivos intentos activos de obtener un bloqueo mientras el proceso que tiene el cerrojo está ejecutándose en una de las CPUs. Si el propietario del cerrojo se echa a dormir, el resto de los procesos que estén tratando de obtenerlo también se echarán a dormir. La heurística parece tener sentido, aunque no se han publicado estudios estadísticos. El parche ha sido recibido bastante bien, aunque Linus ha insistido en que se hagan algunos cambios.
Por tanto, puede que acabe haciéndose un cambio genérico en los «mutex». No obstante, no queda claro si será en la versión 2.6.29. A los desarrolladores les suele gustar que sus primitivas de bloqueo estén razonablemente bien probadas; algo que ha sido desarrollado al final de un ciclo de aceptación de cambios no suele ser fácil de vender. Hasta que algo de esto pase, Chris no tiene intención de quitar su función especial de bloqueo:
"Pero, si alguien que esté trabajando en bloqueos de exclusión mutua adaptativos está buscando alguien que ayude a programar, probar o medir su esquema de bloqueos, levanto mi mano. Hasta entonces, éste es mi bucle, hay muchos como él, pero éste es mío."
Finalmente, está el tema del nombre. Algunos han sugerido que el sistema de ficheros debería incorporarse con un nombre que indique claramente que no está listo aún para usarse en producción, por ejemplo «btrfsdev». Chris es reticente a esto, ya que, a diferencia de los sistemas de ficheros ya existentes, de Btrfs se sabe que es nuevo y no tiene ninguna reputación de estabilidad que mantener. No obstante, si se estima necesario, está dispuesto a hacer ese cambio. Bruce Fields ha manifestado que llamarlo «btrfs» desde el principio puede quemar a futuros desarrolladores que arranquen un kernel antiguo (con un Btrfs no apto para producción) después de cambiarse a un Btrfs definitivo.
Todo esto apunta a un destino incierto para Btrfs en 2.6.29; hay demasiados interrogantes y la fecha de cierre de aceptación de nuevas funcionalidades está cerca. Por supuesto, Btrfs podría incorporarse después de 2.6.29-rc1; como es un sistema nuevo, no causará regresiones. Pero si Linus decide que hay demasiados asuntos pendientes, podría esperar al siguiente ciclo de desarrollo. Por tanto, nadie duda de su inclusión, pero el cuándo es lo que permanece una incógnita.