诡异的mount()
最近在2.6.10内核下调试硬盘分区(FAT32文件系统)保护功能,为保护FAT表、根目录和目录项等重要区域,应用程序不得操作这些区域,其中一项就是禁止更新文件访问时间(会更新目录项),使用mount()系统调用时却出现诡异现象。
[ 测试代码 ]
1: int main()
2: { 3: ... 4: 5: mount("/dev/sda1", "/mnt/sda1", "vfat", 0, NULL);
6: 7: ... 8: 9: /* 读/写sda1分区里的文件 */
10: 11: sync(); 12: 13: return 0;
14: } [ 内核修改 ]
1: /** -> fs/inode.c
2: * update_atime - update the access time
3: * @inode: inode accessed
4: *
5: * Update the accessed time on an inode and mark it for writeback.
6: * This function automatically handles read only file systems and media,
7: * as well as the "noatime" flag and inode specific "noatime" markers.
8: */
9: void update_atime(struct inode *inode)
10: {11: struct timespec now;
12: 13: if (IS_NOATIME(inode))
14: return;
15: if (IS_NODIRATIME(inode) && S_ISDIR(inode->i_mode))
16: return;
17: if (IS_RDONLY(inode))
18: return;
19: 20: + if (inode->i_sb) {
21: + if (!strcmp(inode->i_sb->s_type->name, "vfat"))
22: + __backtrace(); 23: + } 24: now = current_kernel_time();25: if (inode_times_differ(inode, &inode->i_atime, &now)) {
26: inode->i_atime = now; 27: mark_inode_dirty_sync(inode);28: } else {
29: if (!timespec_equal(&inode->i_atime, &now))
30: inode->i_atime = now; 31: } 32: } 测试程序第一次执行时,内核会打印如下调试信息:
1: <4>Function entered at [<c009443c>] from [<c005bc18>] /* c009443c T update_atime */
2: <4> r6 = 00000000 r5 = 00000000 r4 = 00000200 3: <4>Function entered at [<c005b6c4>] from [<c005e2b8>] /* c005b6c4 T do_generic_mapping_read */
4: <4>Function entered at [<c005e0c0>] from [<c005e41c>] /* c005e0c0 T __generic_file_aio_read */
5: <4>Function entered at [<c005e388>] from [<c0078114>] /* c005e388 T generic_file_read */
6: <4> r9 = C3026000 r8 = C3027F78</span> r7 = C005E388 r6 = BEFFF560 7: <4> r5 = C3CE0A80 r4 = 00000200 8: <4>Function entered at [<c0078050>] from [<c0078360>] /* c0078050 T vfs_read */
9: <4> r8 = C0025154 r7 = 00000003 r6 = C3CE0A80 r5 = 00000000 10: <4> r4 = 00000000 11: <4>Function entered at [<c0078318>] from [<c00249c0>] /* c0078318 T sys_read */
12: <4> r6 = 00000200 r5 = BEFFF560 r4 = 00000003 /* 注释部分结合System.map文件得到 */
接着修改测试代码的mount()调用:
1: - mount("/dev/sda1", "/mnt/sda1", "vfat", 0, NULL);
2: + mount("/dev/sda1", "/mnt/sda1", "vfat", MS_NOATIME, NULL);
编译并再次执行测试程序,内核仍打印上面的调试信息,着实让人摸不着头脑。重启Linux系统,执行修改后的测试程序,内核便不再打印上述调试信息!
……
复查测试代码,查看mount()手册页,看到下面几段说明(man-pages 2.77):
MS_REMOUNT
Remount an existing mount. This allows you to change the mountflags and data of an existing
mount without having to unmount and remount the file system. source and target should be the
same values specified in the initial mount() call; filesystemtype is ignored.
The following mountflags can be changed: MS_RDONLY, MS_SYNCHRONOUS, MS_MANDLOCK;
before kernel 2.6.16, the following could also be changed: MS_NOATIME and MS_NODIRATIME;
and, additionally, before kernel 2.4, the following could also be changed: MS_NOSUID,
MS_NODEV, MS_NOEXEC.
聪明的你,想到问题在哪儿了吧。:P
为什么要重启电脑呢,mount -a不就可以了吗?