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给用户态。
Linux mnt_want_write挂载写权限count递增与expiry
张小明
前端开发工程师
Linux mod_sysfs_setup模块sysfs符号表暴露
Linux mod_sysfs_setup模块sysfs符号表暴露 mod_sysfs_setup()是Linux内核模块加载过程中负责在sysfs中创建模块相关目录和文件的关键函数。它在load_module()完成ELF重定位和符号解析之后被调用,向用户空间暴露模块的元数据、参数信息和导出的符号表。 mod_sysfs…
DMA控制器编程:从原理到实战的深度解析
1. DMA控制器编程:从原理到实战的深度解析在嵌入式系统开发,尤其是涉及高速数据流处理的场景里,CPU的时间是极其宝贵的资源。想象一下,你的处理器核心正在处理一个复杂的音频解码算法,此时网络接口卡(NIC&a…
FTUtils 性能优化技巧:提升 iOS 动画流畅度的 7 个终极方法 [特殊字符]
FTUtils 性能优化技巧:提升 iOS 动画流畅度的 7 个终极方法 🚀 【免费下载链接】ftutils iPhone utilities mostly for Core Animation 项目地址: https://gitcode.com/gh_mirrors/ft/ftutils FTUtils 是一个专注于 iOS Core Animation 优化的实用…
零绿幕AI背景移除:OBS背景移除插件终极使用指南
零绿幕AI背景移除:OBS背景移除插件终极使用指南 【免费下载链接】obs-backgroundremoval An OBS plugin for removing background in portrait images (video), making it easy to replace the background when recording or streaming. 项目地址: https://gitcod…
别再乱改VM参数了!手把手教你用IntelliJ IDEA自带的Activity Monitor精准定位卡顿元凶
别再盲目调优!用IntelliJ IDEA Activity Monitor实现精准性能诊断当IDE响应迟缓时,大多数开发者的第一反应往往是粗暴地增加JVM堆内存参数。这种条件反射式的"解决方案"不仅治标不治本,还可能掩盖真正的性能瓶颈。作为JetBrains生态…
终极免费方案:OBS多平台同步直播插件完整指南
终极免费方案:OBS多平台同步直播插件完整指南 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 如果你是一位内容创作者、游戏主播或在线教育讲师,肯定经历过这样的…