파일 시스템을 마운트 해제하기 전에 모든 프로세스가 종료되었는지 확인하는 방법은 무엇입니까?

파일 시스템을 마운트 해제하기 전에 모든 프로세스가 종료되었는지 확인하는 방법은 무엇입니까?

umount 명령이 실패하여 다중 스레드 프로그램에서 지속적인 I/O 읽기 및 쓰기가 발생하는 바쁜 파일 시스템을 마운트 해제하려고 합니다.

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))

이제 다음을 사용하여 모든 프로세스를 종료하려고했습니다.

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

하지만 다음과 같이퓨저 명령

Fuser -k 또는 -K는 프로그램 실행이 시작된 직후 생성된 새 프로세스를 감지하고 종료하지 못할 수도 있습니다.

내 경우에는 일부 스레드가 동시에 IO 요청을 발행했을 수 있기 때문에 이런 일이 발생합니다. 다시 파일 시스템을 마운트 해제하려고 하면 사용 중이라는 메시지가 다시 표시되고 루프가 발생합니다.

제 질문은 새로운 프로세스가 파일 시스템에 한 번만 읽기/쓰기를 수행할 수 없도록 하려면 어떻게 해야 합니까?

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

파일 시스템이 정상적으로 마운트 해제될 수 있도록 명령이 실행됩니다.

답변1

다음은 두 가지 방법입니다. 애플리케이션을 신뢰하지 않는 경우 두 번째 방법으로 직접 이동할 수 있습니다.

1.umount --lazy

방해하는 프로세스가 마운트 지점에 들어가지 않고 chdir()(예를 들어 절대 경로 사용) 결국 포기할 것이라는 것을 알고 있다면 Linux에서는 다음 umount --lazy을 사용할 수 있습니다. 커널은 수목 디렉토리에서 파일 시스템을 매핑 해제하여 새 디렉토리에 도달할 수 없게 만듭니다. 마지막 참조가 사라지면 액세스하여 자동으로 마운트 해제됩니다. 참조는 열린 fd, cwd, 내부 마운트 지점이 될 수 있습니다(마지막 것은 좋지 않습니다)...

그러나 이는 참조를 "내부"로 유지하는 프로세스/스레드에는 영향을 미치지 않습니다. 예를 들어 여전히 파일 설명자가 열려 있거나cwd내부에. 그러면 이제 파일 시스템에 더 이상 접근할 수 없고 문제가 되는 프로세스/스레드를 추적하는 것이 훨씬 더 어려워지기 때문에 이는 훨씬 더 어려울 것입니다(예: fuser -m더 이상 찾을 수 없음). 따라서 이 방법에 대해 올바르게 작동하려면 프로세스가 필요합니다.

2.냉동고 cgroup

작동해야 하는 대체 솔루션나쁜 행동프로세스: 이러한 모든 프로세스(및 스레드)를 동일한 Freezer cgroup에 그룹화합니다. 모두 동결하여 마운트 지점에 리소스 사용량을 추가하지 못하게 합니다(새 fd를 분기/복제/열기하여). 첫 번째 루프에서 몇 가지를 놓치더라도 결국 후속 반복에서는 새로운 것을 모두 잡을 수 있습니다. 이제 동결되었으므로 새로운 활동이 발생하지 않습니다. 이제 모두 죽일 수 있습니다. cgroups v1의 경우 이미 OS에 의해 초기화되었습니다(예:체계화된또는cgmanager, 그렇지 않으면 방법을 알아내야 합니다.Freezer cgroup 하위 시스템 마운트), 이와 같은 것이 작동해야 합니다. 분명히 표시 cgroup.procs되어야 하는 모든 스레드를 포함해야 tasks하지만 신뢰할 수 없는 동작에 대한 보고가 있었습니다. 따라서 필요하지 않은 경우에도 스레드를 반복합니다(예: tasks이미 스레드가 올바르게 채워져 있을 수 있으므로 루프 for t가 중복됩니다).

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

cgroups v2를 사용하는 경우 이는 조정되어야 합니다.

관련 정보