ファイルシステムをアンマウントする前に、すべてのプロセスが終了したことを確認する方法は?

ファイルシステムをアンマウントする前に、すべてのプロセスが終了したことを確認する方法は?

マルチスレッドプログラムで永続的なI / O読み書きが行われる忙しいファイルシステムをアンマウントしようとするため、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))

次に、次のコマンドを使用してすべてのプロセスを終了しようとしています。

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

しかし、それによると修正コマンド

fusionr -kまたは-Kは、プログラムの実行が開始された直後に作成された新しいプロセスを検出して終了できない可能性があります。

一部のスレッドが同時にIO要求を発行できるため、これが私の場合です。ファイルシステムを再マウント解除すると、再使用中というメッセージが表示され、ループになります。

私の質問は、新しいプロセスがファイルシステムで読み取り/書き込み操作を実行できないことをどのように保証しますか?

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

ファイルシステムが正常にアンマウントできるようにコマンドを実行してください。

答え1

これには2つの方法があります。アプリケーションを信頼していない場合は、2番目の方法に直接移動できます。

1.umount --lazy

妨害するプロセスがマウントポイントに入らずchdir()(絶対パスを使用するなど)、最終的に放棄することがわかっている場合は、Linuxでは次のものを使用できますumount --lazy。カーネルはディレクトリツリーからファイルシステムのマッピングを解除し、他のユーザーがアクセスできないようにします。新しいアクセス権を与え、最後の参照が消えたら自動的にアンロードします。参照はオープンfd、cwd、内部マウントポイントです(最後のポイントはおそらく悪いでしょう)...

ただし、これは参照を「内部的に」維持するプロセス/スレッドには影響しません。たとえば、ファイル記述子がまだ開いているか、西ドイツ中。これにより、ファイルシステムにアクセスできなくなり、問題のプロセス/スレッドを追跡することがより困難になるため、これがより難しくなります(例:見つかりませんfuser -m)。したがって、この方法を正しく実行するにはプロセスが必要です。

2.冷凍装置

動作しなければならない代替ソリューション悪い行動プロセス:これらすべてのプロセス(およびスレッド)を同じFreizer cgroupにグループ化します。すべて凍結して、マウントポイントにリソース使用量を追加するのを防ぎます(新しいfdを分岐/複製/開く)。最初のループの一部を見逃しても、最終的には後続の繰り返しで新しいすべてが見つかります。今凍結されたので、新しい活動は発生しません。今すべて殺すことができます。 cgroups v1の場合、オペレーティングシステムによって初期化されました(たとえば、次のように)。システムまたはCGマネージャーそれ以外の場合はどうするかを調べる必要があります。固定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を使用している場合は、それを調整する必要があります。

関連情報