¿Cómo garantizar que todos los procesos se eliminen antes de desmontar un sistema de archivos?

¿Cómo garantizar que todos los procesos se eliminen antes de desmontar un sistema de archivos?

Estoy intentando desmontar un sistema de archivos ocupado en el que se realizan lecturas y escrituras de E/S continuas mediante un programa multiproceso debido a lo cual falla el comando umount.

root@ubuntu:~ # umount /mount/v1
umount: /mount/v1: target is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))

Ahora, intenté matar todos los procesos usando

/sbin/fuser -m /mount/v1 -k

Pero segúnComando del fusor

Es posible que fuser -k o -K no pueda detectar ni eliminar nuevos procesos que se crean inmediatamente después de que el programa comienza a ejecutarse.

que es lo que sucede en mi caso, ya que algunos de los subprocesos podrían haber emitido una solicitud de IO al mismo tiempo. Cuando vuelvo a desmontar el sistema de archivos, nuevamente dice que está ocupado y esto se convierte en un bucle.

Mi pregunta es, ¿cómo me aseguro de que ningún proceso nuevo pueda realizar lecturas/escrituras en el sistema de archivos una vez?

/sbin/fuser -m /mount/v1 -k

Se emite el comando para que el sistema de archivos se pueda desmontar sin problemas.

Respuesta1

Aquí hay dos métodos, si no confía en sus aplicaciones, puede ir directamente al segundo método.

1.umount --lazy

Si esos procesos que interfieren no chdir()ingresan al punto de montaje (use rutas absolutas, por ejemplo) y sabe que eventualmente se darán por vencidos, entonces en Linux puede usar umount --lazy: el kernel desasignará el sistema de archivos de la arborescencia de directorios, haciéndolo inalcanzable para los nuevos. accede y lo desmontará automáticamente cuando desaparezca la última referencia. La referencia puede ser un fd abierto, un cwd, un punto de montaje interno (este último sería malo)...

Pero esto no afectará los procesos/hilos que mantienen una referencia "dentro", por ejemplo, aún tienen descriptores de archivos abiertos o tienencwdadentro. Entonces esto sería aún más difícil ya que ahora ya no se puede acceder al sistema de archivos y se vuelve aún más difícil rastrear procesos/hilos ofensivos (por ejemplo: fuser -mya no los encontrará). Entonces, de alguna manera necesitas que los procesos se comporten correctamente para este método.

2.grupo congelador

Solución alternativa que debería funcionar paramal comportamientoprocesos: agrupa todos estos procesos (y subprocesos) en el mismo cgroup del congelador. Congélelos todos, evitando que agreguen uso de recursos al punto de montaje (bifurcando/clonando/abriendo nuevos archivos fd). Incluso si te pierdes algunos en un primer ciclo, eventualmente captarás todos los nuevos en iteraciones posteriores. Como ahora están congelados, no se producirá ninguna actividad nueva: ahora puedes matarlos a todos. Para cgroups v1, ya inicializado por el sistema operativo (por ejemplo: porsistemadoadministrador de cg, de lo contrario tendrás que descubrir cómomontar el subsistema cgroup del congelador), Algo como esto debería funcionar. Tenga en cuenta que aparentemente escribir en cgroup.procsdebería incluir todos los subprocesos que deberían aparecer, taskspero ha habido informes de comportamiento no confiable, por lo que, por si acaso, también repito los subprocesos incluso si probablemente esto no sea necesario (es decir, tasksprobablemente ya esté poblado correctamente con subprocesos, por lo que el for tbucle es redundante).

mkdir -p /sys/fs/cgroup/freezer/prepareumount

echo FROZEN > /sys/fs/cgroup/freezer/prepareumount/freezer.state

for i in $(seq 1 10); do
    for p in $(fuser -m /mount/v1 2>/dev/null); do
        echo $p > /sys/fs/cgroup/freezer/prepareumount/cgroup.procs
        for t in $(ps -L -o tid= -p $p); do
            echo $t > /sys/fs/cgroup/freezer/prepareumount/tasks
        done
    done
done

#give time to an overloaded kernel to freeze everything (FREEZING->FROZEN)
while ! cat /sys/fs/cgroup/freezer/prepareumount/freezer.state | grep -q FROZEN; do
    sleep 0.1
done

# kills, delayed
for i in $(cat /sys/fs/cgroup/freezer/prepareumount/cgroup.procs); do
    kill -KILL $i
done

# actual kills happen now, at once
echo THAWED > /sys/fs/cgroup/freezer/prepareumount/freezer.state

sleep 1
umount /mount/v1

Esto tendría que adaptarse si se utiliza cgroups v2.

información relacionada