web-dev-qa-db-ja.com

Linux / ext4でfstatにディスクアクセスが必要ですか?

_Linux Kernel 5.3_

int fstat(int fd, struct stat *statbuf);として定義されているfstat syscallを考えてみましょう。 ext4のfstat syscallにディスクアクセスは必要ですか?

私はそれに関連するいくつかの調査を行い、いくつかの情報を見つけました。システムコールへのカーネル内のエントリポイントは、関数 _vfs_statx_fd_ です。その実装は次のようになります。

_int vfs_statx_fd(unsigned int fd, struct kstat *stat,
         u32 request_mask, unsigned int query_flags)
{
    struct fd f;
    int error = -EBADF;

    if (query_flags & ~KSTAT_QUERY_FLAGS)
        return -EINVAL;

    f = fdget_raw(fd);
    if (f.file) {
        error = vfs_getattr(&f.file->f_path, stat,
                    request_mask, query_flags);
        fdput(f);
    }
    return error;
}
_

つまり、ユーザーがシステムコールに渡した実際のファイル記述子である_unsigned int fd_を使用して、 _struct file_ へのポインターを見つけます。その定義の重要な部分は

_struct file {
    //...
    struct path     f_path;
    struct inode        *f_inode;   /* cached value */
    //...
}
_

つまり、基本的に、_struct file_は開いているファイルを表し、構造体にはdentryおよびinodeへの参照が含まれています。

開いているファイル記述子がある場合に、メモリからのみすべての統計を取得して、コストのかかるディスクアクセスを回避できるのは本当ですか?

更新syscallを呼び出す直前に_free && sync && echo 3 > /proc/sys/vm/drop_caches && free_を使用してカーネルキャッシュをフラッシュしようとしましたが、stat syscallのタイミングに影響しませんでした。そのため、ディスクへのアクセスは必要ないと思いがちです。

5
Some Name

Ext4ファイルシステムでは、_vfs_statx_fd_から始まる関数グラフは

_ 0)               |  vfs_statx_fd() {
 0)               |    __fdget_raw() {
 0)   0.225 us    |      __fget_light();
 0)   0.775 us    |    }
 0)               |    vfs_getattr() {
 0)               |      security_inode_getattr() {
 0)               |        selinux_inode_getattr() {
 0)               |          __inode_security_revalidate() {
 0)               |            _cond_resched() {
 0)   0.216 us    |              rcu_all_qs();
 0)   0.575 us    |            }
 0)   0.945 us    |          }
 0)               |          inode_has_perm() {
 0)   0.356 us    |            avc_has_perm();
 0)   0.709 us    |          }
 0)   2.223 us    |        }
 0)   2.808 us    |      }
 0)               |      vfs_getattr_nosec() {
 0)               |        ext4_file_getattr() {
 0)               |          ext4_getattr() {
 0)   0.203 us    |            generic_fillattr();
 0)   0.600 us    |          }
 0)   1.040 us    |        }
 0)   1.502 us    |      }
 0)   4.854 us    |    }
 0)   6.913 us    |  }
_

これらすべての機能の実装を見ると、ディスクI/Oのプロビジョニングがないことがわかります。ご想像のとおり、データはキャッシュされたiノードから取得されます。

the fstat(2) manpage も参照してください:

:パフォーマンスと単純化の理由から、stat構造体のさまざまなフィールドには、システムの実行中のさまざまな瞬間の状態情報が含まれる場合がありますコール。たとえば、_st_mode_または_st_uid_が chmod(2) または chown(2) を呼び出して別のプロセスによって変更された場合=、stat()は、古い_st_mode_と新しい_st_uid_を一緒に返すか、古い_st_uid_と新しい_st_mode_を一緒に返します。

(ただし、これはキャッシングよりもロックに関係しています)。

他の一部のファイルシステムでは、_AT_STATX_FORCE_SYNC_をクエリフラグに含めて、リモート同期を強制できます。これは、Ceph、Fuse、NFS、およびVirtualBoxゲスト共有フォルダーでサポートされています。

7
Stephen Kitt