当前位置: 首页 > news >正文

Linux sys_stat vfs_statx与cp_new_stat64填充

Linux sys_stat vfs_statx与cp_new_stat64填充

stat(2) 系列系统调用在内核的统一入口是 vfs_statx。64 位架构上,通过 ksys_stat 进入:

```c
long ksys_stat(const char __user *filename, struct kstat __user *statbuf)
{
struct kstat stat;
int error;

error = vfs_stat(filename, &stat);
if (error)
return error;

return cp_new_stat(stat, statbuf);
}
```

vfs_stat 是对 vfs_statx 的简单的封装:

```c
int vfs_stat(const char __user *name, struct kstat *stat)
{
return vfs_statx(AT_FDCWD, name, 0, stat, STATX_BASIC_STATS);
}
```

vfs_statx 是 VFS stat 路径的核心函数:

```c
int vfs_statx(int dfd, const char __user *filename, int flags,
struct kstat *stat, u32 request_mask)
{
struct path path;
unsigned int lookup_flags = 0;
int error;

if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH |
AT_STATX_SYNC_TYPE))
return -EINVAL;

if (flags & AT_SYMLINK_NOFOLLOW)
lookup_flags |= LOOKUP_FOLLOW;

retry:
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error)
goto out;

error = vfs_getattr(&path, stat, request_mask, flags);
path_put(&path);

if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
out:
return error;
}
```

user_path_at 使用 path_init + link_path_walk 的路径遍历机制将用户态路径解析为 struct path(包含 dentry 和 vfsmount)。如果文件名是"/proc/self/exe"或包含符号链接,路径遍历会在适当位置跟踪符号链接。

vfs_getattr 是获取文件属性的调度中心:

```c
int vfs_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int query_flags)
{
struct inode *inode = d_backing_inode(path->dentry);

memset(stat, 0, sizeof(*stat));
stat->result_mask = 0;

if (inode->i_op->getattr)
return inode->i_op->getattr(path, stat, request_mask, query_flags);

generic_fillattr(inode, stat);
return 0;
}
```

大多数文件系统都实现了自己的 getattr。ext4 的 ext4_getattr 在调用 generic_fillattr 之前额外检查 inode 是否具有 EXT4_EA_INODE_FL 标志,并报告 i_projid(project ID)给 statx。

generic_fillattr 将 inode 中的原始信息填入 struct kstat:

```c
void generic_fillattr(struct inode *inode, struct kstat *stat)
{
stat->dev = inode->i_sb->s_dev;
stat->ino = inode->i_ino;
stat->mode = inode->i_mode;
stat->nlink = inode->i_nlink;
stat->uid = from_kuid_munged(&init_user_ns, inode->i_uid);
stat->gid = from_kgid_munged(&init_user_ns, inode->i_gid);
stat->rdev = inode->i_rdev;
stat->size = i_size_read(inode);
stat->atime = inode->i_atime;
stat->mtime = inode->i_mtime;
stat->ctime = inode->i_ctime;
stat->blksize = i_blocksize(inode);
stat->blocks = inode->i_blocks;
}
```

struct kstat 是内核内部的通用结构体,包含 64 位的时间戳、块大小和块计数等信息,不依赖架构。但用户态的 struct stat 在不同架构上布局不同。cp_new_stat 负责将 kstat 转换为用户态可见的格式:

```c
static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
{
struct stat tmp;

tmp.st_dev = new_encode_dev(stat->dev);
tmp.st_ino = stat->ino;
tmp.st_mode = stat->mode;
tmp.st_nlink = stat->nlink;
tmp.st_uid = from_kuid_munged(&init_user_ns, stat->uid);
tmp.st_gid = from_kgid_munged(&init_user_ns, stat->gid);
tmp.st_rdev = new_encode_dev(stat->rdev);
tmp.st_size = stat->size;
tmp.st_atime = stat->atime.tv_sec;
tmp.st_mtime = stat->mtime.tv_sec;
tmp.st_ctime = stat->ctime.tv_sec;

#ifdef STAT_HAVE_NSEC
tmp.st_atime_nsec = stat->atime.tv_nsec;
tmp.st_mtime_nsec = stat->mtime.tv_nsec;
tmp.st_ctime_nsec = stat->ctime.tv_nsec;
#endif

tmp.st_blocks = stat->blocks;
tmp.st_blksize = stat->blksize;
return copy_to_user(statbuf, &tmp, sizeof(tmp));
}
```

在 x86_64 架构上,struct stat 的大小为 144 字节,包含 st_atime_nsec 等纳秒字段。new_encode_dev 将内核使用的 dev_t(包含 major 和 minor 号)编码为用户态可理解的形式。

对于 32 位用户态在 64 位内核上运行(CONFIG_COMPAT),需要 compat_sys_stat64 或 compat_sys_newfstatat 等入口。compat 版本使用 struct compat_stat64,其字段宽度与 32 位 glibc 对齐,避免在 64 位内核和 32 位用户态之间传递错误布局的数据。

statx(2) 系统调用提供了更细粒度的控制。它不经过传统的 vfs_stat 路径,而是直接调用 vfs_statx 后返回 struct statx 给用户态。struct statx 包含 stx_mask 位图标记哪些字段有效,允许调用方只请求自己关心的属性(request_mask),在网络文件系统等场景下减少 RPC 开销。

http://www.jsqmd.com/news/1233992/

相关文章:

  • JuiceFS元数据Changelog:分布式文件系统变更追踪实战指南
  • Windows Bind Link实战教程:EDR致盲与AMSI/AppLocker/Sysmon全绕过防御指南
  • Mermaid.js 数据可视化终极指南:用文本创建专业图表如此简单
  • UE5 Paper2D插件数据序列化与资产兼容性:PaperCustomVersion.h深度解析
  • SpringBoot+Vue智能停车场管理系统实战:从零搭建到核心代码解析
  • 人生梦想今日化的庖丁解牛
  • Windows文件加密与隐私保护实用指南
  • C++编译错误排查:系统解决“未声明的标识符”问题
  • 行星摆线针轮减速机运行状况分析及发展前景展望报告2026年版
  • LangChain架构解析:LLM应用开发的高效解决方案
  • # 软考软件设计师题目总结 — 2026年7月20日
  • 哔咔漫画下载器深度解析:打造你的个人数字漫画库
  • Cal Sans字体设计革命:如何用单一可变字体解决8-45pt全尺寸排版挑战?
  • 3步完成:如何在Windows系统上快速部署Mesa3D图形驱动 [特殊字符]
  • 终极城通网盘直连解析工具:告别限速的智能解决方案
  • AgentScope 2.0:生产级智能体开发框架解析与实践
  • 3分钟学会视频硬字幕提取!本地OCR工具轻松转换SRT字幕文件
  • Java面试突击:7天系统掌握核心原理与高频考点
  • 江门管道疏通信得过—新会陈皮之乡社区居民口口相传 - 热点速览
  • 石油行业无线监测:DXMP 系列实时频谱仪模块的宽频与便携特性
  • 未来是想象。
  • 抖音批量下载终极指南:3分钟搞定无水印视频素材库
  • 3分钟快速上手InvokeAI:本地AI绘画引擎终极安装指南
  • Metroidvania-System:零代码打造银河恶魔城游戏的终极框架
  • 漫画爱好者的离线阅读解决方案:picacomic-downloader让收藏管理更高效
  • Topcoat:Tokio 团队的 Rust 全栈框架,用编译期宏替代 WASM 前端
  • 大牌同源配方一件代发?先别急着下单,车间老炮教你避开这些坑
  • 终极指南:如何使用SGLang实现高效多模态AI处理与视觉语言模型分析
  • 在江门卖黄金—中国侨都这些地方价格合理服务靠谱 - 热点速览
  • 中国医用呼吸机市场发展规划及前景动态分析报告2026年版