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

Linux mnt_want_write挂载写权限count递增与expiry

Linux mnt_want_write是挂载层写权限的准入控制机制,任何需要在文件系统上执行写操作的代码路径都必须在操作前调用它,操作完成后调用mnt_drop_write。它维护了一个mount的mnt_writers计数器,同时检测挂载的冻结状态和expiry过期状态。函数位于fs/namespace.c。

```
// fs/namespace.c
int mnt_want_write(struct vfsmount *m)
{
int ret;

sb_start_write(m->mnt_sb);
ret = __mnt_want_write(m);
if (ret)
sb_end_write(m->mnt_sb);
return ret;
}
```

外层包裹了sb_start_write/sb_end_write的超级块级同步写入保护,这是文件系统freeze(冻结)机制的一环。当文件系统被冻结时(如调用ioctl(FIFREEZE)或LVM快照创建时),sb_start_write会使写者阻塞等待冻结完成,然后后续的写操作被阻止进入。

```
// fs/namespace.c
int __mnt_want_write(struct vfsmount *m)
{
struct mount *p;

if (unlikely(m->mnt_flags & MNT_WRITE_HOLD))
return -EBUSY;

p = real_mount(m);
if (unlikely(p->mnt.mnt_flags & MNT_READONLY))
return -EROFS;

if (unlikely(IS_MNT_EXPIRED(p)))
return -EACCES;

p->mnt_writers++;
smp_mb__after_atomic();
if (unlikely(p->mnt.mnt_flags & MNT_WRITE_HOLD)) {
p->mnt_writers--;
return -EBUSY;
}
return 0;
}
```

__mnt_want_write内部检查三个条件并以原子方式递增mnt_writers。MNT_WRITE_HOLD标志用于冻结期间的通知:当文件系统冻结时,MNT_WRITE_HOLD被设置,同时等待mnt_writers降为零。此处有一个经典的TOCTOU处理模式:先递增mnt_writers,再检查MNT_WRITE_HOLD,如果发现标志已被设置则回滚递减。通过smp_mb__after_atomic保证递增对其他CPU可见后,再读取标志位。

MNT_READONLY标志表明挂载是只读的,直接返回-EROFS。这是一种快速检查,实际挂载的读写状态可能通过remount动态切换,所以每次写操作前都需要验证。

IS_MNT_EXPIRED检查expiry状态。expiry机制用于自动挂载文件系统(autofs)和某些网络文件系统的超时卸载。当挂载过期时,mnt_want_write返回-EACCES阻止写入。

```
// include/linux/mount.h
static inline int IS_MNT_EXPIRED(struct mount *mnt)
{
return mnt->mnt_expiry_mark &&
mnt->mnt_expiry_mark <= jiffies;
}
```

expiry判断依赖mnt_expiry_mark字段。autofs在定时器触发时对所有管理的挂载设置expiry标记,后续任何访问会重置该标记防止过期。mnt_want_write返回-EACCES后,VFS层通常会上报到autofs的d_automount方法,触发重新挂载。

mnt_writers是一个unsigned int类型,它的递增和递减都不是原子的——但配合mnt_writer_lock锁机制保证正确性。实际上__mnt_want_write和__mnt_drop_write都在mnt_writer_mutex的保护范围内调用,但这个mutex只保护冻结路径的协作,非冻结路径的mnt_writers操作是直接读写int的,因为持有inode_lock或文件系统内部锁已经提供了上下文互斥。

```
// fs/namespace.c
void mnt_drop_write(struct vfsmount *mnt)
{
__mnt_drop_write(mnt);
sb_end_write(mnt->mnt_sb);
}

void __mnt_drop_write(struct vfsmount *mnt)
{
struct mount *p = real_mount(mnt);
p->mnt_writers--;
}
```

mnt_drop_write是mnt_want_write的逆操作,递减mnt_writers并退出超级块的写保护。当mnt_writers降为0时,可能触发等待中的冻结操作继续推进。

```
// fs/namespace.c
int mnt_want_write_file(struct file *file)
{
int ret;

sb_start_write(file_inode(file)->i_sb);
ret = __mnt_want_write_file(file);
if (ret)
sb_end_write(file_inode(file)->i_sb);
return ret;
}

static inline int __mnt_want_write_file(struct file *file)
{
if (file->f_mode & FMODE_WRITER)
return 0;
return __mnt_want_write(file->f_path.mnt);
}
```

mnt_want_write_file是针对已打开文件的变体。如果文件打开时FMODE_WRITER标志已置位(表示open时已经做了mnt_want_write),直接返回0避免重复计数。这是为了防止内核代码路径在同一个文件上重复获取写权限。例如,do_dentry_open已经为O_WRONLY/O_RDWR文件执行了mnt_want_write,后续write系统调用中不要再重复调用。

mnt_want_write的调用者覆盖了所有写操作的入口路径:
- vfs_write/vfs_writev:每次写入前调用mnt_want_write_file
- vfs_truncate:截断文件前调用
- vfs_unlink/vfs_rename/vfs_rmdir:目录操作前调用
- vfs_setattr:修改inode属性前调用
- 直接I/O和splice的写路径

挂载冻结的完整流程依赖于mnt_writers的值。freeze_super同步设置MNT_WRITE_HOLD后,等待所有mnt_writers降为0,这意味着所有正在进行的写操作必须完成并调用mnt_drop_write后才能冻结完成。冻结完成后,所有新的写操作在__mnt_want_write的MNT_WRITE_HOLD检查处被拒绝(返回-EBUSY),上层调用者通常直接返回-EIO或-ESTALE给用户态。

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

相关文章:

  • 别再全局设置Content-Type了!Axios请求头配置的正确姿势(以文件上传和普通POST为例)
  • 收藏!小白程序员转型AI大模型工程师的必看指南:高薪风口等你来!
  • 5倍速图层批量导出:Photoshop-Export-Layers-to-Files-Fast技术深度解析与实战指南
  • 别再让网速慢背锅了!手把手教你用Wireshark抓包分析PHY自协商失败(附排查脚本)
  • 3个关键策略:构建marked.js生产级安全防护体系
  • 别死记硬背了!用观察者、策略模式搞定软考UML设计题(附2022/2023真题详解)
  • 从抓包分析到问题定位:一次完整的Qt5.15 QWebEngine网页加载Timeout排查实录
  • 2026海珠注册公司实操攻略:主城合规流程、片区避坑要点与TOP5代办机构盘点 - 速递信息
  • 并非人人都在事事使用 AI:美国 AI 使用现状与人们的担忧
  • 如何用Brigadier实现Mac Boot Camp自动化驱动安装
  • DLSS Swapper完整指南:一键智能切换游戏DLSS版本,彻底释放显卡性能潜力
  • 避坑指南:SAP BAPI_OUTB_DELIVERY_CREATE_STO创建交货单,别忘了处理这个关键字段
  • 2026大模型完整学习路线:从零基础入门到项目落地、高薪就业全指南
  • 零绿幕AI背景移除:OBS背景移除插件终极使用指南
  • 如何在Illustrator中轻松排版数学公式:LaTeX2AI终极使用指南
  • Rocky Linux 9上安装MySQL 8.0报错‘GPG key already installed’?手把手教你两步修复
  • 在PC上体验Switch游戏:yuzu模拟器的完整指南
  • JTAG与边界扫描技术实战:从核心原理到MSC711x DSP调试应用
  • 3PEAK思瑞浦 TPR8200-EV1R EMSOP8 特殊功能电路
  • 2026年浙江杭州合同纠纷律师怎么选?5个关键点防踩雷 - 本地品牌推荐
  • MPC860中断系统深度解析:从并行I/O到CPIC的实时响应设计
  • C语言文件操作核心机制:流定位、错误处理与字符编码详解
  • C标准库函数深度解析:内存管理与字符串操作的核心陷阱与最佳实践
  • 如何快速解锁《原神》60帧限制:开源工具完整指南
  • 澳洲出生证海牙认证时间?别等过期才后悔! - 慧办好
  • 计算机组成原理实验避坑指南:MIPS寄存器文件设计常见错误与调试方法
  • 深度解析:使用RPFM工具构建三国全面战争Startpos文件的实战指南
  • 银联境外支付(线上线下)的储蓄卡和信用卡比较
  • 如何微调大语言模型以提高可靠性?Awesome-LLM项目中的微调策略详解
  • 2026苏州黄金回收高价领跑|合规龙头实测,本地变现避坑全攻略 - 奢侈品回收测评