fstat 是否需要在 Linux/ext4 上访问磁盘?

Som*_*ame 5 linux filesystems c files linux-kernel

Linux Kernel 5.3

考虑fstat定义为的系统调用int fstat(int fd, struct stat *statbuf);ext4 上fstat系统调用是否需要磁盘访问?

我做了一些与它相关的研究并找到了一些信息。系统调用的内核入口点是函数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;
}
Run Code Online (Sandbox Code Playgroud)

所以我们在这里得到的unsigned int fd是用户传递给系统调用的实际文件描述符 which 用于查找指向struct file. 其定义的关键部分是

struct file {
    //...
    struct path     f_path;
    struct inode        *f_inode;   /* cached value */
    //...
}
Run Code Online (Sandbox Code Playgroud)

所以我们基本上有struct file代表一个打开的文件,并且结构包含对dentry和的引用inode

如果我们有一个打开的文件描述符,我们可以从内存中获取所有统计信息,从而避免昂贵的磁盘访问,这是真的吗?

更新:我尝试free && sync && echo 3 > /proc/sys/vm/drop_caches && free在调用之前使用right刷新内核缓存,syscall并且它没有影响 stat 系统调用的时间。所以我倾向于认为不需要磁盘访问。

Ste*_*itt 7

上的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    |  }
Run Code Online (Sandbox Code Playgroud)

查看所有这些函数的实现表明没有提供磁盘 I/O。正如您猜测的那样,数据来自缓存的 inode。

另请参见fstat(2)手册页,其中提到的是:

注意:出于性能和简单的原因,stat结构中的不同字段 可能包含系统调用执行期间不同时刻的状态信息。例如,如果st_modest_uid被另一个进程通过调用chmod(2)或更改chown(2),则 stat()可能将旧的st_mode与新的一起返回st_uid,或者旧的st_uid与新的一起返回st_mode

(尽管这更多地与锁定而不是缓存有关)。

对于其他一些文件系统,AT_STATX_FORCE_SYNC可以包含在查询标志中以强制远程同步;这在 Ceph、FUSE、NFS 和 VirtualBox 来宾共享文件夹上受支持。