- 桌面上的 Ubuntu 14.04
- 源驱动器:/dev/sda1:5TB ext4 单
驱动器卷 - 目标卷:/dev/mapper/archive-lvarchive:带有 lvm
分区和 ext4 的raid6 (mdadm) 18TB 卷
大约有 1500 万个文件需要移动,其中一些可能是重复的(我不想覆盖重复的文件)。
使用的命令(来自源目录)是:
ls -U |xargs -i -t mv -n {} /mnt/archive/targetDir/{}
正如预期的那样,这种情况已经持续了几天,但我在频率增加时遇到了错误。启动时目标驱动器已满约 70%,现在约为 90%。过去大约有 1/200 的动作会出现错误,现在大约是 1/5。所有文件都不超过 100Mb,大部分都在 100k 左右
一些信息:
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sdb3 155G 5.5G 142G 4% /
none 4.0K 0 4.0K 0% /sys/fs/cgroup
udev 3.9G 4.0K 3.9G 1% /dev
tmpfs 797M 2.9M 794M 1% /run
none 5.0M 4.0K 5.0M 1% /run/lock
none 3.9G 0 3.9G 0% /run/shm
none 100M 0 100M 0% /run/user
/dev/sdb1 19G 78M 18G 1% /boot
/dev/mapper/archive-lvarchive 18T 15T 1.8T 90% /mnt/archive
/dev/sda1 4.6T 1.1T 3.3T 25% /mnt/tmp
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sdb3 10297344 222248 10075096 3% /
none 1019711 4 1019707 1% /sys/fs/cgroup
udev 1016768 500 1016268 1% /dev
tmpfs 1019711 1022 1018689 1% /run
none 1019711 5 1019706 1% /run/lock
none 1019711 1 1019710 1% /run/shm
none 1019711 2 1019709 1% /run/user
/dev/sdb1 4940000 582 4939418 1% /boot
/dev/mapper/archive-lvarchive 289966080 44899541 245066539 16% /mnt/archive
/dev/sda1 152621056 5391544 147229512 4% /mnt/tmp
这是我的输出:
mv -n 747265521.pdf /mnt/archive/targetDir/747265521.pdf
mv -n 61078318.pdf /mnt/archive/targetDir/61078318.pdf
mv -n 709099107.pdf /mnt/archive/targetDir/709099107.pdf
mv -n 75286077.pdf /mnt/archive/targetDir/75286077.pdf
mv: cannot create regular file ‘/mnt/archive/targetDir/75286077.pdf’: No space left on device
mv -n 796522548.pdf /mnt/archive/targetDir/796522548.pdf
mv: cannot create regular file ‘/mnt/archive/targetDir/796522548.pdf’: No space left on device
mv -n 685163563.pdf /mnt/archive/targetDir/685163563.pdf
mv -n 701433025.pdf /mnt/archive/targetDir/701433025.pd
我发现了很多关于此错误的帖子,但预测并不合适。诸如“您的驱动器实际上已满”或“您的索引节点已用完”甚至“您的 /boot 卷已满”等问题。不过,大多数情况下,它们处理的是第三方软件,因为它处理文件的方式而导致问题,而且它们都是不变的,这意味着每个动作都会失败。
谢谢。
编辑:这是失败和成功文件的示例:
失败(仍在源驱动器上)
ls -lhs 702637545.pdf
16K -rw-rw-r-- 1 myUser myUser 16K Jul 24 20:52 702637545.pdf
成功(达到目标量)
ls -lhs /mnt/archive/targetDir/704886680.pdf
104K -rw-rw-r-- 1 myUser myUser 103K Jul 25 01:22 /mnt/archive/targetDir/704886680.pdf
此外,虽然并非所有文件都会失败,但失败的文件总会失败。如果我一遍又一遍地重试,它是一致的。
编辑:@mjturner 每个请求的一些附加命令
$ ls -ld /mnt/archive/targetDir
drwxrwxr-x 2 myUser myUser 1064583168 Aug 10 05:07 /mnt/archive/targetDir
$ tune2fs -l /dev/mapper/archive-lvarchive
tune2fs 1.42.10 (18-May-2014)
Filesystem volume name: <none>
Last mounted on: /mnt/archive
Filesystem UUID: af7e7b38-f12a-498b-b127-0ccd29459376
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr dir_index filetype needs_recovery extent 64bit flex_bg sparse_super huge_file uninit_bg dir_nlink extra_isize
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 289966080
Block count: 4639456256
Reserved block count: 231972812
Free blocks: 1274786115
Free inodes: 256343444
First block: 0
Block size: 4096
Fragment size: 4096
Group descriptor size: 64
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 2048
Inode blocks per group: 128
RAID stride: 128
RAID stripe width: 512
Flex block group size: 16
Filesystem created: Thu Jun 25 12:05:12 2015
Last mount time: Mon Aug 3 18:49:29 2015
Last write time: Mon Aug 3 18:49:29 2015
Mount count: 8
Maximum mount count: -1
Last checked: Thu Jun 25 12:05:12 2015
Check interval: 0 (<none>)
Lifetime writes: 24 GB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 28
Desired extra isize: 28
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: 3ea3edc4-7638-45cd-8db8-36ab3669e868
Journal backup: inode blocks
$ tune2fs -l /dev/sda1
tune2fs 1.42.10 (18-May-2014)
Filesystem volume name: <none>
Last mounted on: /mnt/tmp
Filesystem UUID: 10df1bea-64fc-468e-8ea0-10f3a4cb9a79
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 152621056
Block count: 1220942336
Reserved block count: 61047116
Free blocks: 367343926
Free inodes: 135953194
First block: 0
Block size: 4096
Fragment size: 4096
Reserved GDT blocks: 732
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 4096
Inode blocks per group: 256
Flex block group size: 16
Filesystem created: Thu Jul 23 13:54:13 2015
Last mount time: Tue Aug 4 04:35:06 2015
Last write time: Tue Aug 4 04:35:06 2015
Mount count: 3
Maximum mount count: -1
Last checked: Thu Jul 23 13:54:13 2015
Check interval: 0 (<none>)
Lifetime writes: 150 MB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 28
Desired extra isize: 28
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: a266fec5-bc86-402b-9fa0-61e2ad9b5b50
Journal backup: inode blocks
答案1
dir_index
您在目标文件系统上使用的ext4 功能的实现中存在错误。
解决方案:重新创建不带 dir_index 的文件系统。或使用tune2fs禁用功能(需要注意一些,请参阅相关链接Novell SuSE 10/11:在 ext3 文件系统上禁用 H 树索引这虽然涉及到外部3可能需要类似的谨慎。
(get a really good backup made of the filesystem)
(unmount the filesystem)
tune2fs -O ^dir_index /dev/foo
e2fsck -fDvy /dev/foo
(mount the filesystem)
ext4 有一个默认启用的名为 dir_index 的功能,该功能很容易受到哈希冲突的影响。
......
ext4 可以对其内容的文件名进行哈希处理。这提高了性能,但有一个“小”问题:当 ext4 开始填满时,它的哈希表不会增长。相反,它返回 -ENOSPC 或“设备上没有剩余空间”。
答案2
关于存储大量小文件的比 ext4 更好的选择的建议:
如果您使用文件系统作为对象存储,您可能需要考虑使用专门于此的文件系统,这可能会损害其他特性。快速谷歌搜索发现头孢,它似乎是开源的,可以作为 POSIX 文件系统安装,也可以通过其他 API 访问。我不知道在不利用复制的情况下是否值得在单个主机上使用。
另一个对象存储系统是OpenStack 的 Swift。它的设计文档这么说将每个对象存储为单独的文件,元数据位于 xattrs 中。这是一篇关于它的文章。 他们的部署指南表示他们发现 XFS 为对象存储提供了最佳性能。因此,尽管工作负载不是 XFS 最擅长的,但在 RackSpace 测试时,它显然比竞争对手更好。 Swift 可能更青睐 XFS,因为 XFS 对扩展属性有良好/快速的支持。如果不需要额外的元数据(或者如果它保存在二进制文件中),那么 ext3/ext4 可能在单个磁盘上作为对象存储后端运行良好。
Swift 为您进行复制/负载平衡,并建议您为其提供在原始磁盘上创建的文件系统,不是RAID。它指出它的工作负载本质上是 RAID5 的最坏情况(如果我们谈论的是小文件写入的工作负载,这是有道理的。XFS 通常不会完全将它们从头到尾打包,因此您不必获得全条带写入,并且 RAID5 必须执行一些读取来更新奇偶校验条带。 Swift 文档还讨论了每个驱动器使用 100 个分区,我认为这是一个 Swift 术语,而不是讨论在每个驱动器上创建 100 个不同的 XFS 文件系统。 SATA 磁盘。
为每个磁盘运行单独的 XFS 实际上是一个巨大的差异. 而不是一个巨大空闲 inode 映射,每个磁盘将有一个单独的 XFS 和单独的空闲列表。此外,它还避免了小写入的 RAID5 损失。
如果您已经构建了直接使用文件系统作为对象存储的软件,而不是通过像 Swift 这样的东西来处理复制/负载平衡,那么您至少可以避免将所有文件放在一个目录中。 (我没有看到 Swift 文档说明他们如何将文件布局到多个目录中,但我确信他们会这样做。)
对于几乎所有普通的文件系统,使用类似的结构都会有所帮助
1234/5678 # nested medium-size directories instead of
./12345678 # one giant directory
大约 10k 条目可能是合理的,因此采用均匀分布的 4 个字符的对象名称并将它们用作目录是一个简单的解决方案。它不必非常平衡。奇怪的 100k 目录可能不会是一个明显的问题,一些空目录也不会是一个明显的问题。
XFS对于大量小文件来说并不理想。它做了它能做的事情,但它针对较大文件的流式写入进行了更优化。不过,总体而言,对于一般用途来说,它非常好。ENOSPC
它的目录索引(据我所知)没有冲突,并且可以处理一个包含数百万个条目的目录。 (但最好至少使用一层树。)
戴夫·钦纳对分配大量 inode 时的 XFS 性能有一些评论,导致性能缓慢touch
。查找要分配的空闲 inode 开始花费更多的 CPU 时间,因为空闲 inode 位图变得碎片化。请注意,这不是一个大目录与多个目录的问题,而是整个文件系统上许多使用的 inode 的问题。将文件拆分到多个目录有助于解决一些问题,例如 OP 中 ext4 阻塞的问题,但不能解决跟踪可用空间的整个磁盘问题。与 RAID5 上的巨型 XFS 相比,Swift 的每个磁盘单独的文件系统有助于解决此问题。
我不知道是否BTFS很擅长这个,但我认为可能是。我认为 Facebook 聘用其首席开发人员是有原因的。 :P 我见过的一些基准测试,例如解压 Linux 内核源代码,显示 btrfs 表现良好。
我知道赖塞尔夫斯针对这种情况进行了优化,但它几乎不再被维护(如果有的话)。我真的不建议使用 reiser4。不过,尝试一下可能会很有趣。但这是迄今为止最不适合未来的选择。我还看到过有关老化的 reiserFS 性能下降的报告,并且没有好的碎片整理工具。 (谷歌filesystem millions of small files
,并查看一些现有的 stackexchange 答案。)
我可能错过了一些东西,所以最后建议:在 serverfault 上询问这个问题! 如果我现在必须选择一些东西,我会说尝试一下 BTRFS,但要确保你有备份。 (特别是,如果您使用 BTRFS 的内置多磁盘冗余,而不是在 RAID 之上运行它。性能优势可能会很大,因为小文件对于 RAID5 来说是个坏消息,除非它是一个以读取为主的工作负载。)
答案3
对于这个问题,下面是我所做的修复(您可能需要 sudo 访问权限来执行以下步骤):
Inode 的已用空间为 100%,可以使用以下命令检索
df -i /
文件系统索引节点 IUsed IFree IUse% 安装于
/dev/xvda1 524288 524288 o 100% /
- 需要释放 iNoted,因此需要使用以下命令查找具有此处 i 节点数的文件:
尝试查找这是否是 inode 问题:
df -ih
尝试查找具有大量索引节点的根文件夹:
for i in /*; do echo $i; find $i |wc -l; done
尝试查找特定文件夹:
for i in /src/*; do echo $i; find $i |wc -l; done
- 现在我们已经将其归零到包含大量文件的文件夹。依次运行以下命令以避免任何错误(在我的例子中,实际文件夹是 /var/spool/clientmqueue):
find /var/spool/clientmqueue/ -type f -mtime +1050 -exec rm -f {} + find /var/spool/clientmqueue/ -type f -mtime +350 -exec rm -f {} + find /var/spool/clientmqueue/ -type f -mtime +150 -exec rm -f {} + find /var/spool/clientmqueue/ -type f -mtime +50 -exec rm -f {} +