LLA y LNKLST: liberar una librería para poder borrarla
Antes de tocar la LNKLST de forma dinámica, lee la nota de IBM Using the dynamic LNKLST facility safely and properly: qué es seguro hacer, qué no (UNALLOCATE, parar LLA y renombrar) y los riesgos de SETPROG LNKLST,UPDATE.
Quieres borrar (o renombrar) una LOADLIB y no te deja: «Data set in use». Lo tienen XCFAS y LLA. Veremos por qué, cómo se añade una librería a LLA y a la LNKLST (y para qué), y cómo liberarla bien. Todo con una librería de prueba.
Por ejemplo, elijo una librería de la LNKLST y ejecuto el siguiente comando:
D GRS,RES=(*,NETVW64.SCNMLNK1)
Veremos que está en uso por XCFAS y LLA. Por lo tanto, no podremos renombrarla ni borrarla.

Qué hace LLA
- Rendimiento. Cada vez que se carga un programa, el sistema busca el miembro en el directorio de la librería: sin LLA es una E/S a disco.
- LLA guarda una copia de los directorios en su propio espacio de direcciones: la búsqueda se hace en memoria.
- Cuando LLA se usa con VLF, guarda en memoria los módulos más usados («staging»), elegidos por tamaño y número de cargas. Sin VLF, LLA solo ahorra la búsqueda en el directorio.
- Por defecto LLA gestiona las librerías de la LNKLST. Las demás (por ejemplo, la loadlib de una aplicación que cientos de jobs usan en STEPLIB) hay que añadirlas en CSVLLAxx.
- Las librerías gestionadas por LLA tienen que estar catalogadas (y seguir catalogadas mientras LLA las gestione).
En el miembro COFVLFxx de PARMLIB vemos que tiene definida la clase CSVLLA.

En el PROC de la tarea VLF podemos confirmar que usa el miembro de parámetros 00 (COFVLF00).

FREEZE y NOFREEZE
Al añadir una librería a LLA, tenemos la opción de configurarla como FREEZE o NOFREEZE:
- FREEZE: LLA usa su copia del directorio. Rápido, pero si cambias un programa se sigue ejecutando el anterior hasta refrescar LLA (F LLA,REFRESH o F LLA,UPDATE=xx).
- NOFREEZE: se lee el directorio del disco. Los cambios se ven al momento, pero se pierde la ventaja.
- Una librería de la LNKLST, cuando se usa a través de la LNKLST, se comporta siempre como FREEZE, aunque esté en NOFREEZE. Si esa misma librería se usa por otro camino (por ejemplo en un STEPLIB), sí cuenta su FREEZE o NOFREEZE.
- Las que añades con LIBRARIES están en NOFREEZE por defecto: hay que poner FREEZE explícitamente (IBM lo recomienda).

📖 Using the FREEZE|NOFREEZE option
📖 Statements and parameters for CSVLLAxx
Librería de prueba
Vamos a crear una librería PDS de módulos (RECFM=U) con un programa que solo escribe un mensaje, para ver qué versión se ejecuta.
//ALLOCLIB JOB (ACCT),'ALLOC LOADLIB',CLASS=A,MSGCLASS=X
//ALLOC EXEC PGM=IEFBR14
//LOADLIB DD DSN=IBMUSER.TEST.LOADLIB,DISP=(NEW,CATLG),
// UNIT=SYSDA,SPACE=(CYL,(1,1,10)),
// DSORG=PO,RECFM=U,LRECL=0,BLKSIZE=32760
Tendremos la librería creada.

Vamos a ensamblar este programa de prueba (escribe un WTO con la versión: 'HELLOV VERSION 1'):
//ASMHELLO JOB (ACCT),'ASSEMBLE HELLOV',CLASS=A,MSGCLASS=X
//* Assemble and link HELLOV into the test load library
//ASM EXEC ASMACL
//C.SYSIN DD *
HELLOV CSECT
STM 14,12,12(13)
BALR 12,0
USING *,12
WTO 'HELLOV VERSION 1'
LM 14,12,12(13)
SR 15,15
BR 14
END
/*
//L.SYSLMOD DD DSN=IBMUSER.TEST.LOADLIB(HELLOV),DISP=SHR
Terminará correctamente.


Ahora vamos a ejecutarlo:
//RUNHELLO JOB (ACCT),'RUN HELLOV',CLASS=A,MSGCLASS=X
//RUN EXEC PGM=HELLOV
//STEPLIB DD DSN=IBMUSER.TEST.LOADLIB,DISP=SHRVemos que muestra el mensaje “HELLOV VERSION 1”.

Primera prueba: añadir la librería a LLA (LIBRARIES y FREEZE)
Para añadir librerías a LLA se usa un miembro de PARMLIB (CSVLLAxx) con LIBRARIES y, para congelarla, FREEZE.
Se aplica con el comando:
F LLA,UPDATE=xxAntes y después de aplicar el cambio, podemos usar el comando de display para comprobar que se añade:
D LLACrearé el miembro CSVLLA01 en una PARMLIB de mi sistema (las PARMLIB disponibles se ven con el comando D PARMLIB):
LIBRARIES(IBMUSER.TEST.LOADLIB)
FREEZE(IBMUSER.TEST.LOADLIB)
F LLA,UPDATE=01
D LLA
Vemos que la librería se ha añadido, con la columna “F” marcada (FREEZE).

Ahora vamos a modificar el programa para que muestre “VERSION 2” y ensamblarlo en la misma librería (IBMUSER.TEST.LOADLIB). Volveremos a ejecutar RUNHELLO para ver el resultado.


Confirmamos que el módulo se ha reemplazado.

Un detalle interesante es que, aunque el módulo se ha reemplazado, al consultarlo sigue mostrando VERSION 1. Es por el FREEZE: LLA usa su copia del directorio, que sigue apuntando al módulo antiguo, y en una PDS el módulo antiguo sigue en el disco hasta que se comprime.

Si lo ejecutamos, también obtenemos el mensaje “VERSION 1”.

Ahora vamos a refrescar LLA. Se puede hacer con el siguiente comando para refrescar todas las librerías:
F LLA,REFRESHPero también se puede hacer de forma individual para un módulo concreto:
📖 Identifying members for selective refreshes
Definir en PARMLIB el miembro CSVLLA02:
LIBRARIES(IBMUSER.TEST.LOADLIB)
MEMBERS(HELLOV)
F LLA,UPDATE=02
Ahora el módulo sí muestra “VERSION 2”.

Si lo ejecutamos, aparece el mensaje “VERSION 2”.

Como tenemos la librería en LLA, si intentamos borrarla, aparecerá el mensaje “Data set in use”.

Si pulsamos F1 dos veces, veremos que está en uso por LLA.

Segunda prueba: añadirla a la LNKLST de forma dinámica
Para poder mostrar cómo quitar una librería de la LNKLST, primero voy a añadir nuestra librería de prueba.
📖 Syntax format of the LNKLST statements (PROGxx)
La LNKLST activa no se puede modificar: se define una nueva copiando la actual, se le añade la librería y se activa. Los jobs y STC que ya estaban corriendo siguen con la LNKLST anterior.
Al activar la nueva LNKLST, LLA empieza a gestionar sola las librerías nuevas. Y al usarla desde la LNKLST se comporta como FREEZE.
Además, modificaremos el job que ejecuta el programa HELLOV para quitar la STEPLIB (porque ya no es necesaria).
D PROG,LNKLST
SETPROG LNKLST,DEFINE,NAME=LNKTEST,COPYFROM=CURRENT
SETPROG LNKLST,ADD,NAME=LNKTEST,DSNAME=IBMUSER.TEST.LOADLIB
SETPROG LNKLST,ACTIVATE,NAME=LNKTEST
D PROG,LNKLST
D LLA
Vemos que ya tenemos la librería en la LNKLST.

Ahora, en el display de LLA, vemos que tiene rellena la columna “L”, que indica que está en la LNKLST.

Vemos que el job ya no tiene STEPLIB y sigue mostrando VERSION 2.

Si volvemos a intentar borrar la librería, mostrará el mensaje “Data set in use”.

Tras pulsar F1 dos veces, veremos que ahora está en uso por LLA y XCFAS.

Si preferimos usar un comando para ver quién la tiene en uso (no sea que hagamos la prueba de borrar, no la tenga nadie y la borremos de verdad…), podemos usar:
D GRS,RES=(SYSDSN,IBMUSER.TEST.LOADLIB)O también:
D GRS,RES=(*,IBMUSER.TEST.LOADLIB)
Liberar el ENQ de XCFAS: sacarla de la LNKLST
📖 Removing or compressing a data set in an active LNKLST set
📖 Updating LNKLST concatenations (SETPROG LNKLST)
Como la LNKLST activa no se puede modificar, para quitar la librería hacemos lo mismo que para añadirla: definimos una LNKLST nueva copiando la actual, le quitamos la librería y la activamos.
SETPROG LNKLST,DEFINE,NAME=LNKCLEAN,COPYFROM=CURRENT
SETPROG LNKLST,DELETE,NAME=LNKCLEAN,DSNAME=IBMUSER.TEST.LOADLIB
SETPROG LNKLST,ACTIVATE,NAME=LNKCLEAN
D PROG,LNKLST
Vemos que la LNKLST activa ya es LNKCLEAN y que la librería no aparece.

Pero XCFAS no suelta la librería mientras algún job siga usando la LNKLST anterior (LNKTEST): cada job se queda con la LNKLST que estaba activa cuando arrancó. Para ver quién sigue con una LNKLST que no es la actual:
D PROG,LNKLST,USERS,NOTCURRENTVemos que muchas tareas siguen apuntando a LNKLST antiguas. Casi todas estarán en la LNKLST original, que no tiene la librería: solo nos afectan las que usan LNKTEST.

También es posible mover los jobs a la LNKLST nueva sin pararlos.
Pero hay que tener cuidado: si un job está cargando un programa justo en ese momento, la carga puede fallar o coger una copia equivocada del módulo (ver la nota de IBM del principio: en producción, solo en emergencias).
SETPROG LNKLST,UPDATE,JOB=*,DELAY=10Después volvemos a comprobar:
D PROG,LNKLST,USERS,NOTCURRENTAparecerá el mensaje:
CSV483I ALL LNKLST USERS ARE USING THE CURRENT LNKLST SET
Si ahora ejecutamos el job sin STEPLIB, ya no encuentra HELLOV (abend S806): los jobs nuevos usan LNKCLEAN, que ya no tiene la librería.

Volvemos a mirar quién tiene la librería:
D GRS,RES=(SYSDSN,IBMUSER.TEST.LOADLIB)XCFAS ya no aparece: solo queda LLA.

Liberar el ENQ de LLA: REMOVE
📖 CSVLLAxx (library lookaside list)
Podríamos pensar que basta con refrescar LLA (F LLA,REFRESH), pero no: una librería que se ha quitado de la LNKLST sigue gestionada por LLA hasta que se lo decimos expresamente. IBM lo explica en esta nota: How to remove the LLA enqueue on a library. En nuestro caso, además, la habíamos añadido nosotros con LIBRARIES en CSVLLA01.
Para quitarla de LLA, creo el miembro CSVLLA03 en la PARMLIB con el parámetro REMOVE:
REMOVE(IBMUSER.TEST.LOADLIB)
Y lo aplicamos:
F LLA,UPDATE=03
D LLAVemos que la librería ya no aparece en la lista de LLA.

Comprobamos que ya no la tiene nadie:
D GRS,RES=(SYSDSN,IBMUSER.TEST.LOADLIB)
Y ahora sí, podemos borrarla.

Otra opción sería parar y arrancar LLA (P LLA y S LLA,SUB=MSTR), pero mientras LLA está parada se pierde su ventaja en todo el sistema. No lo haría salvo que no quede otra.
Resumen
Quién tiene la librería y cómo se libera:
- XCFAS → sacarla de la LNKLST (DEFINE, DELETE, ACTIVATE) y que ningún job siga con la LNKLST anterior.
- LLA → REMOVE en CSVLLAxx y F LLA,UPDATE=xx (F LLA,REFRESH no basta).
Referencias (z/OS 3.1)
- Improving module fetch performance with LLA (MVS Initialization and Tuning Guide)
- Controlling LLA and VLF through operator commands (MVS Initialization and Tuning Guide)
- Identifying members for selective refreshes (MVS Initialization and Tuning Guide)
- CSVLLAxx (library lookaside list) (MVS Initialization and Tuning Reference)
- Statements and parameters for CSVLLAxx (MVS Initialization and Tuning Reference)
- Using the FREEZE|NOFREEZE option (MVS Initialization and Tuning Guide)
- Syntax format of the LNKLST statements (PROGxx)
- Modifying LLA (MVS System Commands)
- Removing or compressing a data set in an active LNKLST set
- MVS System Commands 3.1 (PDF): SETPROG, DISPLAY LLA, DISPLAY PROG,LNKLST y DISPLAY GRS
- Displaying LNKLST information (PROG,LNKLST) (MVS System Commands)
- Updating LNKLST concatenations (SETPROG LNKLST) (MVS System Commands)
- Using the dynamic LNKLST facility safely and properly (IBM Support)
- How to remove the LLA enqueue on a library (IBM Support)