- 论坛徽章:
- 0
|
通过NFS导出aufs
Aufs在内核2.6.18及以后支持NFS导出。因为aufs没有实际的块设备,你需要在导出时添加NFS的’fsid’选项。关于这个选项的更多细节可以参考NFS的手册。
在内核2.6.23以及更早,建议导出aufs之前先导出一次你的分支文件系统。通过一次导出,分支文件系统的内部名为find_exported_dentry的指针被初始化。初始化以后,你可以不导出它们。另外,这个初始化每种文件系统都应该做。如果你的分支是同一种文件系统,你只需要把它们导出一次。如果你从没有导出过你的分支正在使用的文件系统,aufs将会使用默认值初始化内部指针,并且给出一个警告。虽然它可能工作地挺正常,我还是担心它将来会出问题。在内核2.6.24及以后,这种导出是非必需的。
此外,还有一些限制或者要求。
· kernel的版本必需为2.6.18或者更高。
· 你需要打开CONFIG_AUFS_EXPORT。
· 分支文件系统必须支持NFS导出。例如,内核2.6.18(或更早)的tmpfs就不支持。
· 不支持NFSv2。当你从NFS客户端mount导出的aufs,你需要一些如v3或者nfsvers=3的NFS选项,特别是当它为nfsroot的时候。
· 如果你的分支文件系统上NFS文件句柄的数目很大,aufs可能无法处理它。NFSv3中一个文件系统的最大文件句柄数为64字节。Aufs在32位系统上使用使用24字节,64位系统增加12字节。剩余的分支文件系统的文件句柄区域。
· 因为NFS文件句柄是基于inode数字的所以需要外部Inode数字位图,转换表和世代表(xino)。默认会打开mount选项’xino’。当你打开了CONFIG_AUFS_EXPORT时外部inode世代表和它的sysfs entry(<sysfs>/fs/aufs/si_*/xigen)就被创建出来即使你没有真的导出了aufs。外部世代表的体积只会增大,不会被压缩。你应该关注一下xino文件所处文件系统的剩余空间。默认情况下,它是第一个可写分支。
· 分支文家系统必需是可访问的,也就是说’不能被隐藏’。 这意味着你使用initramfs和switch_root( 或者chroot( 时需要执行’mount --move’。
Dentry和Inode缓存
如果你想清除你的系统缓存,有个窍门。如果你的内存比较少,试试’find /large/dir -ls > /dev/null’。它将会读取很多inodes和dentries并缓存它们。旧的缓存将被丢弃。但是如果你有很大的内存并且你没有一个足够巨大的目录,那么这将没有效果。
如果你想从内部丢弃某个文件系统的缓存,试试’mount -o remount /your/mntpnt’。有的文件系统可能返回一个EINVAL错误或别的什么,但是VFS将会丢弃指定文家系统上没用的dentry/inode缓存。
与Unionfs版本1.x系列的兼容/不兼容
如果你编译aufs使用了-DCONFIG_AUFS_COMPAT,dirs=选项和=nfsro分支权限标志即变为可用。它们分别用于解释br:选项和=ro标志位。’debug’、’delete’、’imap’选项被默认忽略。当你编译aufs时使用了-DCONFIG_AUFS_COMPAT,这三个选项同样会被忽略,但是会给出警告信息。
忽略’delete’选项,并且为了保证文件系统一致性,aufs会试着在单一系统调用中只向一个分支写入数据。这意味着无论源分支是否被指定为可写aufs都会执行向上拷贝。 例如,你有两个可写分支以及一个巨大的位于低层可写分支的普通文件。当你对于aufs中这个文件执行rename(2)的时候,aufs可能将其向上拷贝至上层可写分支。如果这不是你所预期的状况的话,你应该直接在低层分支执行rename(2)。
在sample目录下有一个简单的shell脚本’unionctl’,它与Unionfs版本1.x系列的unionctl( 兼容,除了--query动作。这个脚本执行了带’remount’选项的mount( 以及add/del/mod等aufs的mount选项。如果你熟悉Unionfs版本1.x系列并想使用unionctl( ,你可以尝试直接用这个脚本代替mount -o remount等。Aufs不支持ioctl(2)接口。这个脚本高度依赖位于util-linux-2.12p包的mount( ,而且你使用这个脚本需要mount /proc。如果你的mount( 版本不同,你可以试着修改这个脚本。这很简单。unionctl脚本其实就是aufs remount界面的一个使用示例。
Aufs默认使用外部inode数字位图和转换表。
第一个分支默认分支权限是’rw’,其余的是’ro’。
whiteout用于隐藏低层分支的文件,也用于阻止readdir进入低层分支。后一种情况称为’opaque directory’。任何whiteout都是一个空文件,这就是说whiteout仅仅是一个标记。在隐藏低层文件的情况下,whiteout的名字是’.wh.<filename>’。在阻止readdir的情况下,名字是’.wh..wh..opq’或者’.wh.__dir_opaque’。这个名字取决于你的编译配置CONFIG_AUFS_COMPAT。所有的whiteouts都被硬链接,包括’<writable 分支 top dir>/.wh..wh.aufs’。
位于普通(基于磁盘)的文件系统的硬链接并不消耗新的inode资源。但是在linux tmpfs中,空余的inodes数量将会因为link(2)而减少。如果你遇到了ENOSPC推荐为你的tmpfs指定nr_inodes选项。使用这个选项后用’df -i’来检查。
当你rmdir或者rename-to一个拥有大量whiteouts的目录的时候,aufs把这个目录rename成类似’.wh.<dir>.<random hex>’的临时whiteouted名称。然后执行实际的删除操作。参考mount选项’dirwh’。
与普通文件系统的不兼容
stat(2)返回第一个存在此inode的分支上的inode信息,除了目录链接数。通常Aufs计算的目录链接数大于精确的数字,以便保持UNIX文件系统语义,或者为了让find(1)闭嘴。目录的大小可能也存在错误,但这都是无害的。目录中的文件被创建或者删除时目录的时间戳不会改变,低层的分支会做相应变动。
权限位测试有两种情况。一种是对目录,另一种是对非目录。对目录的情况下,aufs检查所有存在的目录的权限位。这意味着你需要拥有包括低层分支在内的正确的权限。对于非目录的测试简单得多。它只检测最上层的inode。
statfs(2)返回第一个分支的信息如果指定了’nosum’(默认值)则不包括namelen。namelen由于whiteout前缀长度而减少。块大小可能不同于从stat(2)得到的st_blksize。
请记住,seekdir(3)和telldir(3)并没有定义在在POSIX中。它们可能无法按照的你预期工作。试着rewinddir(3)或re-open目录。
whiteout前缀(.wh.)在所有分支中都是被保留的。用户应该私自处理带这种前缀的文件名。为了将来的whiteout,最大文件名长度被限定为:最大值 - 4。这可能违反了POSIX。
如果你不喜欢/etc/mtab和/proc/mounts之间aufs entries的差异,你可以使用util-linux包中的mount( ,试试./mount.aufs脚本。把这个脚本拷贝到/sbin/mount.aufs。这个简单的脚本能更新/etc/mtab。如果你不关心/etc/mtab,你可以忽略这个脚本。请记住这个脚本高度依赖util-linux-2.12p包中的mount( ,而且你需要mount /proc。
因为aufs使用它自己的inode和dentry,你的系统可能缓存大量的inodes和dentries。它可能会是你联合上所有文件的两倍。它意味着在关机时unmounting或remounting为只读会花费较长时间,因为VFS中的mount(2)会试图释放目标文件系统的所有缓存。
当你打开一个目录,aufs可能内在地打开多个目录。它意味着可能会达到文件描述符的上限。当低层的目录无法被打开时,aufs会关闭所有打开的上层目录并返回一个错误。
位于分支之下本地文件系统的sub-mount将被忽略。例如,如果你已经mount另一个文件系统到/branch/another/mntpnt,’mntpnt’下面的文件将被aufs忽略。推荐在mounted好的aufs之下mount那些sub-mount。例如,
# sudo mount /dev/sdaXX /ro_branch
# d=another/mntpnt
# sudo mount /dev/sdbXX /ro_branch/$d
# mkdir -p /rw_branch/$d
# sudo mount -t aufs -o br:/rw_branch:/ro_branch none /aufs
# sudo mount -t aufs -o br:/rw_branch/${d}:/ro_branch/${d} none /aufs/another/$d
有一些字符不允许在分支目录路径以及xino文件名中被使用。具体可以参考分支语法和Mount选项。
fcntl(2)通过F_SETLK、F_SETLKW或F_GETLK,flock(2)和lockf(3)所定义的文件锁,只作用于虚拟aufs文件,并不作用于分支上的文件。它意味着你可以通过直接访问分支打破这个锁。TODO:检查’security’以便抓住锁,就像inotify所做的。
系统调用fsync(2)和fdatasync(2)返回0意味着成功,即使给定的文件描述符被阻塞还未打开。我担心这种行为可能违反了某些标准。检查一下fsync(2)在ext2上的行为,aufs决定返回成功。
如果你想使用磁盘配额,你应该把它设定到你的可写分支上因为aufs并没有自己的块设备。
如果你的aufs是你的根目录,而你的系统告诉你有些文件系统没有被干净地unmounted,可以在你关机的时候试试这些流程。
# mount -no remount,ro /
# for i in $writable_branches
# do mount -no remount,ro $i
# done
如果你的xino文件位于一个硬盘,你可能需要在remounting根目录的时候指定’noxino’选项或者’xino=/your/tmpfs/xino’。
即使源和目标位于同一个aufs在rename(2)目录时也可能会返回EXDEV。当源目录存在于多个分支而低层目录含有子目录时,aufs不得不向上拷贝它的所有子目录。这可能会递归向上拷贝。目前aufs并不支持在内核空间一次性执行如此巨大的向上拷贝操作,取而代之的就是警告并返回EXDEV。通常,mv(1)检测这个错误并尝试使用mkdir(2)和rename(2) 或者递归的copy/unlink。所以结果是无害的。如果你执行rename(2)的这个应用不支持EXDEV,它就不能工作在aufs上。这个规范也适用于当源目录位于低层的只读分支且它还有子目录的情况。
一个突发事件如停电等在aufs正在运行过程中发生的话,灾难过后对于分支文件系统会完成一次常规fsck,你需要对于可写分支进行额外的fsck。它必须检查whiteout是否停留在异常的状态,例如真实文件名和它的whiteout位于同一个父目录。如果存在一个这样的whiteout,aufs将无法正确处理文件。从检查aufs的观点出发检查一致性,你可以使用一个简单的名为/sbin/auchk的shell脚本。它的目的是一个适用于aufs的fsck工具,它会检查错误的whiteout,遗留的伪链接以及遗留的aufs临时文件。如果它们被找到,工具会报告给你并询问是否删除它们。如果系统曾经挂过推荐你在mount aufs前对每一个可写分支执行/sbin/auchk。
示例
在remount的时候mount选项被从左至右依次处理。示例展现了选项如何被处理。(假定/sbin/mount.aufs已经被安装)
# mount -v -t aufs br:/day0:/base none /u
none on /u type aufs (rw,xino=/day0/.aufs.xino,br:/day0=rw:/base=ro)
# mount -v -o remount,prepend:/day1,xino=/day1/xino,mod:/day0=ro,del:/day0 /u
none on /u type aufs (rw,xino=/day1/xino,br:/day1=rw:/base=ro)
# mount -t aufs br:/rw none /u
# mount -o remount,append:/ro /u
different uid/gid/permission, /ro
# mount -o remount,del:/ro /u
# mount -o remount,nowarn_perm,append:/ro /u
#
(there is no warning)
当你把aufs作为根文件系统使用时,推荐考虑排除掉一些目录。例如,/tmp和/var/log大多数情况下不需要堆叠。它们不经常需要向上拷贝或者whiteout。还有位于aufs之上的swapfile(一个常规文件,而非块设备)是不被支持的。为了排除掉特定的目录,可以尝试bind mounting。
有一个网络启动无盘机器的很好的示例。可以从sample/看到详细内容。
诊断
当你添加一个分支到你的联合时,aufs可能会给你关于分支权限以及安全性的警告,包括那些分支的顶层目录的权限位、所有者以及所属组。例如,当你的顶层可写分支有一个全局可写顶层目录的话,一个恶意用户可以在这个可写分支直接创建任意文件,这就像向上拷贝并手动修改一样。我担心这可能会是一个安全问题。
当你mount或者remount你的aufs而没有使用-o ro公共mount选项并且没有可写分支时,aufs可能警告你第一个分支应该是可写的。
当你设定除inotify之外其它的udba并直接改变了你分支上的某些东西后,aufs可能会检测到缓存中的某些不匹配项。如果这是个致命的不匹配项,aufs会返回EIO并且给出警告信息说’try udba=inotify’。
如果aufs发生了一个错误,aufs会打印出带着'errno'的内核信息。信息的优先级(log级别)是ERR或WARNING这取决于信息本身。你可以通过perror(3)、strerror(3)或者别的什么将’errno’转换为错误信息。例如,’I/O Error, write failed (-2 ’的’errno’是28含义为ENOSPC或者’No space left on device’。
版权
Copyright ? 2005-2009 Junjiro Okajima
作者
Junjiro Okajima
原文
http://aufs.sourceforge.net/aufs.html
翻译
水大
[ 本帖最后由 水大 于 2009-9-14 14:20 编辑 ] |
|