我使用 Linux 一段时间了,但自从我开始使用“最近的”发行版(即:任何非 Debian 的发行版)后,我的大多数 USB 设备就开始出现 I/O 问题。基本上,当尝试将任何大量数据写入其中时,连接会丢失或自行重新启动。在系统日志中,我观察到以下类型的消息:
kernel: usb 1-7: reset high speed USB device using ehci_hcd and address 2
kernel: usb 2-1: device descriptor read/64, error -71
kernel: usb 2-4: new high speed USB device using ehci_hcd and address 13
“随身碟”和 USB 连接硬盘都会出现这种情况。我找不到任何有用的模式来检测哪些设备会损坏,哪些设备不会损坏,除了尺寸之外 - 我从来没有使用过 1 或 2 GB 的随身碟来损坏这些消息(但话又说回来,没有人再卖这些了)。
当这些错误发生时,对驱动器的挂起读取将被锁定,同时也会锁定正在执行该工作的任何程序,直到我物理拔下驱动器。当然,在我重新连接驱动器后,我发现文件或分区已损坏,从而使我失去了很多工作并迫使我去做其他一些工作。
通过研究,我发现了诸如建筑维基百科 或 SUSE 论坛,甚至这个社区表明罪魁祸首是 USB 树属性的默认值,max_sectors
该属性指定一次性可以向 USB 驱动器读取或写入多少数据。超出驱动器支持的范围,设备就会重置或崩溃。我发现提到,与旧内核或 Windows 安装(甚至)240
相比,Linux () 中的值太高,当然不会遇到这个问题。128
64
由于我更看重数据完整性而不是“令人眼花缭乱”的速度(我希望大多数人都这样做!)我想以某种方式更改max_sectors
“任何”USB 存储设备的值其中“任何”的含义足够充分,我可以避免在很大程度上编写自定义命令或规则。不幸的是,看看我尝试的地方,我找不到任何可以更改此值的配置行或内核启动选项(与 USB 自动挂起不同)。
我错过了什么或者接下来我可以做什么?我知道我可以在或多或少自动使用系统的情况下编写如下内容udev
,如下所示:
SUBSYSTEMS=="usb", DRIVERS=="usb-storage", ATTRS{manufacturer}=="Some Company", ATTRS{serial}=="xxxxxxxxxx", ATTRS{max_sectors}=="240", ATTRS{max_sectors}="128"
然后重新加载或重新启动服务,但我一直找不到通用的足够的udev
规则适合尽可能多的设备(只要它们通过 USB 插头连接)。我知道我可以为max_sectors
我想要恢复或保留的设备编写更具体的规则,但在这里我只对某种通配符感兴趣。
我在某些属性中尝试过通配符,如ATTRS{manufacturer}=="* "
无济于事。
udev
可以匹配尽可能多的 USB 插入设备的通用规则是什么?这是否是通过软件处理此问题的“正确”方法? (卸载 USB 2.0 模块 - 例如:Ubuntu 论坛建议 - 似乎不是一个选项,因为至少 Fedora 似乎已将它们集成到内核中)。
编辑:正如frostschutz所建议的,我正在使用它RUN+=
来设置该属性,它实际上有效(与使用不同ATTR=
)。这就是解决方案的一半。我已经能够创建一个几乎匹配所有内容的 udev 规则,但我担心它匹配得太多。
SUBSYSTEMS=="usb", DRIVERS=="usb-storage", \
RUN+="/bin/sh -c 'echo 64 > /sys/block/%k/device/max_sectors'"
此规则的问题在于它会max_sectors
针对所有内容进行设置,包括值低于 64 的设备。我尝试使其更具体:
SUBSYSTEMS=="usb", DRIVERS=="usb-storage", ATTRS{max_sectors}=="240", \
RUN+="/bin/sh -c 'echo 64 > /sys/block/%k/device/max_sectors'"
但这行不通。我认为我正在使用 udev 规则的正确范围(使用树的一部分和来自一父)。我究竟做错了什么?
编辑2: 接受下面的答案。事实证明,这样做RUN+=
可以解决问题,而ATTRS{…}=
由于某种原因使用则不能。另外,我无法使通用规则发挥作用的原因是我误解了 udev 联机帮助页。规则必须有最多属性来自一父级 - 这意味着如果我想使用两个部分,第二个部分必须是实际的设备。这两个基本上可以完美地工作:
SUBSYSTEM=="scsi", ATTRS{max_sectors}=="240", \
RUN+="/bin/sh -c 'echo 64 > /sys/block/%k/device/max_sectors'"
(注意属性的单数,第一个属性来自实际的USB 设备和第二个来自单一的设备树的祖先)
SUBSYSTEMS=="usb", DRIVERS=="usb-storage", ATTRS{max_sectors}=="240", \
RUN+="/bin/sh -c 'echo 64 > /sys/block/%k/device/max_sectors'"
(这个使用了来自相同的设备树的祖先)
您还可以执行以下操作:(使用 == 进行检查,使用 = 进行赋值):
子系统==“scsi”,ATTRS {max_sectors}==“240”,ATTRS {max_sectors} =“64”
在我的系统(Mageia 4、3.14.24 core i7)上,由于 Kingston DT101 G2 16GB 上的写入速度极慢(2MB/秒),我不得不执行相反的操作: vi /usr/lib/udev/rules.d/81-udisks_maxsect .rules 并添加:
子系统==“scsi”,ATTR {max_sectors} ==“240”,ATTR {max_sectors} =“32678”
并且 dd 写入速度提高了 3 倍:-) mc cp 可能提高了 10-20 倍(在我开始第一个分区@8192'th 扇区并使用 64k 对齐簇重新格式化之后): mkfs.vfat /dev/sdh1 -n KINGSTON16G -s 128 -R 4592 并使用 fsck.vfat -v /dev/sdh1 检查对齐方式 默认 mas_sectors (240) 似乎会在一些廉价的新驱动器上导致高写入放大。但要非常小心如此高的设置,在 2048 个扇区上也能达到类似的效果:
子系统==“scsi”,ATTR {max_sectors} ==“240”,ATTR {max_sectors} =“2048”
测试您所有的旧 USB 设备,它们仍然可以正常工作。使用规则文件中的供应商/型号属性更加具体。
答案1
听起来像是您应该去修复的硬件问题。供电 USB 集线器(如果是电源相关问题)、不同的 USB 电缆、无前面板、不同的 USB 控制器(附加卡)、...
如果它仍然不可靠,可以选择使用sync
USB 介质的安装选项。这样就不会进行任何缓存,但您会发现结果对性能产生了很大影响。此外(对于闪存驱动器)还可能进行额外写入(例如,如果您创建一个文件并立即删除它,则使用异步,它永远不会首先被写入,而同步总是立即写入所有内容)。