web-dev-qa-db-ja.com

Fuseファイルシステムを実装するプロセスを見つける

FuseファイルシステムのドライバーのプロセスIDを取得するにはどうすればよいですか?

たとえば、現在、Linuxマシンに2つのSSHFSファイルシステムがマウントされています。

$ grep sshfs /proc/mounts
Host:dir1 /home/gilles/net/dir1 Fuse.sshfs rw,nosuid,nodev,relatime,user_id=1000,group_id=1000 0 0
Host:dir2 /home/gilles/net/dir2 Fuse.sshfs rw,nosuid,nodev,relatime,user_id=1000,group_id=1000 0 0
$ pidof sshfs
15031 15007

15007と15031のどちらがdir1で、どちらがdir2であるかをどのように知ることができますか?理想的には、それを自動化する必要があります。つまり、somecommand /home/gilles/net/dir1を実行して、15007(または15031、または必要に応じて「ヒューズマウントポイントではない」)を表示します。

sshfsプロセスが接続されているホストとポート、サーバー側プロセスが開いているファイルの追跡など、SSHFSに固有の回答ではなく、一般的な回答を探していることに注意してください。接続の共有のため、まったく不可能です。

私は主にLinuxの回答に興味がありますが、Fuseをサポートするすべてのシステムで機能する一般的な回答が理想的です。

なぜ私が知りたいのか:その動作を追跡する、問題が発生した場合にそれを殺すなど。

私はそれが可能だとは思いません。これが理由です。私は、Fuseがマウント時に作成するメタデータ/dev/Fusestruct Fuse_connを開くプロセスのpidを追加するという単純なアプローチを採用しました。次に、その情報を使用して、mountコマンドのpid=フィールドを表示しました。パッチは本当に簡単です:

diff --git a/fs/Fuse/fuse_i.h b/fs/Fuse/fuse_i.h
index 7354dc1..32b05ca 100644
--- a/fs/Fuse/fuse_i.h
+++ b/fs/Fuse/fuse_i.h
@@ -402,6 +402,9 @@ struct Fuse_conn {
        /** The group id for this mount */
        kgid_t group_id;

+       /** The pid mounting process */
+       pid_t pid;
+
        /** The Fuse mount flags for this mount */
        unsigned flags;

diff --git a/fs/Fuse/inode.c b/fs/Fuse/inode.c
index e8799c1..23a27be 100644
--- a/fs/Fuse/inode.c
+++ b/fs/Fuse/inode.c
@@ -554,6 +554,7 @@ static int Fuse_show_options(struct seq_file *m, struct dentry *root)
        struct super_block *sb = root->d_sb;
        struct Fuse_conn *fc = get_Fuse_conn_super(sb);

+       seq_printf(m, ",pid=%u", fc->pid);
        seq_printf(m, ",user_id=%u", from_kuid_munged(&init_user_ns, fc->user_id));
        seq_printf(m, ",group_id=%u", from_kgid_munged(&init_user_ns, fc->group_id));
        if (fc->flags & Fuse_DEFAULT_PERMISSIONS)
@@ -1042,6 +1043,7 @@ static int Fuse_fill_super(struct super_block *sb, void *data, int silent)

        fc->release = Fuse_free_conn;
        fc->flags = d.flags;
+       fc->pid = current->pid;
        fc->user_id = d.user_id;
        fc->group_id = d.group_id;
        fc->max_read = max_t(unsigned, 4096, d.max_read);
def@fractal [6:37] ~/p/linux -- master

カーネルを起動し、sshfsをマウントし、mountを実行しました。

[email protected]:/tmp on /root/tmp type Fuse.sshfs (rw,nosuid,nodev,relatime,pid=1549,user_id=0,group_id=0)

成功?残念ながら違います:

root      1552  0.0  0.0  45152   332 ?        Ssl  13:39   0:00 sshfs [email protected]:/tmp tmp                                                                

次に、残りのsshfsプロセスは、マウントを作成したプロセスの子であることに気付きました。 fdから継承しました。 Fuseが実装されているため、fdから継承する多数のプロセスを持つことができます。元のプロセスツリーから完全に外れて、UNIXソケットでfdを渡すことができます。

ソケットにはこのメタデータがあるため、このTCP port '情報を所有する' who 'を取得でき、/ procを解析するだけでその情報がわかります。残念ながら、Fusefdは/dev/Fuseの通常のfdです。 。そのfdがどういうわけか特別にならない限り、これをどのように実装できるかわかりません。

1

pslsofを組み合わせて、必要な情報を取得できると思います。

ユーザースペースアプリケーションは、常にマウントポイントの引数を引数として持っているようです。マウントポイントを引数として持つコマンドを探してプロセスリストをgrepすると(例:ps -ef | egrep ' <mount>( |$)')、すべてのFuseプロセスを取得する必要があります。もちろん、引数としてマウントポイントを持っている他のプロセスを取得することもあります(例:ls <mount>)。結果のリストを取得してlsofで実行し、/dev/Fuseへの接続が開いているプロセスを探すと、マウントポイントのFuse関連のプロセスが見つかります。

したがって、たとえば、システムにgvfsFuseプロセスがあります。

gvfsd-Fuse on /run/user/1000/gvfs type Fuse.gvfsd-Fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)

pslsofのすべての作業を実行する単純なシェルコマンドを実行すると、次のようになります。

~$ for pid in \
     $(ps -ef | egrep ' /run/user/1000/gvfs( |$)' | awk '{print $2}')
   do 
     ps -f -p $(lsof -p "$pid" | fgrep /dev/Fuse | awk '{print $2}')
   done
UID        PID  PPID  C STIME TTY          TIME CMD
username  2241  1997  0 Apr25 ?        00:00:00 /usr/lib/gvfs/gvfsd-Fuse /run/user/1000/gvfs -f -o big_writes

それはあなたが望むことをするようです。 PIDまたはファイルハンドルとマウントポイントの間のマッピングを通知するFuseレベルのカーネルインターフェイスがあればいいのですが、それは存在しないようです。

1
hrunting