Mass Storage Gadget (MSG)
1. Overview
海量存储Gadget(或 MSG)充当 USB 海量存储设备,在主机看来就像磁盘或 CD-ROM 驱动器。 它支持多个逻辑单元 (LUN)。 每个LUN的后备存储由常规文件或块设备提供,访问可以限制为只读,并且小工具可以指示它是可移动的和/或CD-ROM(后者意味着只读访问)。
它的要求并不高; 只需要一个批量输入和一个批量输出端点。 内存要求相当于两个 16K 缓冲区。 支持全速、高速和超高速操作。
请注意,该驱动程序稍微不可移植,因为它假设单个内存/DMA 缓冲区可用于批量输入和批量输出端点。 对于大多数设备控制器来说,这不是问题,但有些设备控制器可能存在硬件限制,导致缓冲区无法被多个端点使用。
本文档描述了如何从用户空间使用该小工具、它与大容量存储功能(或 MSF)和使用它的不同小工具的关系,以及它与文件存储小工具(或 FSG)(不再包含在 Linux 中)的区别。 它将仅简要讨论如何在复合小工具中使用 MSF。
2. Module parameters
大容量存储小工具接受以下大容量存储特定模块参数:
-
file=filename[,filename…]
此参数列出用于每个逻辑单元的后备存储的文件或块设备的路径。 最多可以设置 FSG_MAX_LUNS (8) 个 LUN。 如果指定了更多文件,它们将被默默地忽略。 另请参见“luns”参数。
请注意,如果文件用作后备存储,则任何其他进程都不能修改该文件。 这是因为主机假设数据不会在其不知情的情况下发生更改。 它可以被读取,但是(如果逻辑单元是可写的)由于主机端的缓冲,内容没有被明确定义。
逻辑单元的大小将向下舍入为完整逻辑块。 对于模拟 CD-ROM 的 LUN,逻辑块大小为 2048 字节;如果备份文件是块设备,则逻辑块大小为设备的块大小;否则为 512 字节。
-
removable=b[,b…]
该参数指定每个逻辑单元是否应该是可移除的。 这里的“b”要么是“y”、“Y”或“1”,代表真,要么是“n”、“N”或“0”,代表假。
如果为逻辑单元设置此选项,小工具将接受“弹出”SCSI 请求(启动/停止单元)。 当它被发送时,备份文件将被关闭以模拟弹出,并且逻辑单元将无法被主机安装,直到设备上的用户空间指定新的备份文件(参见“sysfs条目”部分)。
如果逻辑单元不可移除(默认),则在加载模块时必须使用“file”参数为其指定后备文件。 如果模块是内置的,这同样适用,没有例外。
该标志的默认值为 false,但它曾经是 true。 这已被更改以更好地匹配文件存储小工具,因为它毕竟看起来是一个更明智的默认设置。 因此,为了保持与旧内核的兼容性,最好指定默认值。 另外,如果依赖旧的默认值,现在需要明确指定“n”。
请注意,“可移除”意味着逻辑单元的介质可以弹出或移除(对于 CD-ROM 驱动器或读卡器也是如此)。 这并不意味着整个设备可以从主机上拔掉; 正确的术语是“热拔插”。
-
cdrom=b[,b…]
该参数指定每个逻辑单元是否应该模拟CD-ROM。 默认为 false。
-
ro=b[,b…]
此参数指定每个逻辑单元是否应报告为只读。 这将防止主机修改备份文件。
请注意,如果给定逻辑单元的此标志为 false,但无法以读/写模式打开后备文件,则小工具无论如何都会回退到只读模式。
非 CD-ROM 逻辑单元的默认值为 false; 对于模拟 CD-ROM 的逻辑单元,它被强制为 true。
-
nofua=b[,b…]
此参数指定在发送到给定逻辑单元的 SCSI Write10 和 Write12 命令中是否应忽略 FUA 标志。
MS Windows 默认以“删除优化模式”安装可移动存储。 所有对介质的写入都是同步的,这是通过在 SCSI Write(10,12) 命令中设置 FUA(强制单元访问)位来实现的。 这会强制每次写入都要等到数据实际写出,并阻止 I/O 请求在块层中聚合,从而显着降低性能。
请注意,这可能意味着,如果设备由 USB 供电,并且用户在没有先卸载设备的情况下拔掉设备(至少某些 Windows 用户会这样做),则数据可能会丢失。
默认值为 false。
-
luns=N
此参数指定小工具将具有的逻辑单元的数量。 它受到 FSG_MAX_LUNS (8) 的限制,较高的值将受到限制。
如果提供此参数,并且“file”参数中指定的文件数大于“luns”的值,则所有多余的文件将被忽略。
如果该参数不存在,逻辑单元的数量将从“file”参数中指定的文件数量中推断出来。 如果文件参数也丢失,则假定为一个。
-
stall=b
指定是否允许小工具停止批量端点。 默认值根据 USB 设备控制器的类型确定,但通常为 true。
除了上述内容之外,该小工具还接受复合框架定义的以下参数(它们对于所有复合小工具都是通用的,因此只是一个快速列表):
- idVendor – USB Vendor ID (16 bit integer)
- idProduct – USB Product ID (16 bit integer)
- bcdDevice – USB Device version (BCD) (16 bit integer)
- iManufacturer – USB Manufacturer string (string)
- iProduct – USB Product string (string)
- iSerialNumber – SerialNumber string (string)
3. sysfs entries
对于每个逻辑单元,小工具都会在 sysfs 层次结构中创建一个目录。 在其中创建以下三个文件:
-
file
读取时,它返回给定逻辑单元的支持文件的路径。 如果没有备份文件(仅当逻辑单元可移动时才可能),则内容为空。
写入时,它会更改给定逻辑单元的支持文件。 即使给定逻辑单元未指定为可移动(但这对主机来说可能看起来很奇怪),也可以执行此更改。 但是,如果主机不允许使用 Prevent-Allow Medium Removal SCSI 命令删除介质,则该操作可能会失败。
-
ro
反映给定逻辑单元的 ro 标志的状态。 它可以随时读取,并在没有为给定逻辑单元打开的后备文件时写入。
-
nofua
反映给定逻辑单元的 nofua 标志的状态。 它可以被读取和写入。
-
forced_eject
写入时,无论主机是否允许,都会导致备份文件与 LUN 强制分离。 内容并不重要,写入的任何非零字节数都将导致弹出。
无法读取。
除此之外,像往常一样,模块参数的值可以从 /sys/module/g_mass_storage/parameters/* 文件中读取。
4. Other gadgets using mass storage function
海量存储小工具使用海量存储功能来处理海量存储协议。 作为一个复合函数,MSF 也可以被其他小工具使用(例如 g_multi 和 acm_ms)。
前面部分中的所有信息对于使用 MSF 的其他小工具都有效,但可能缺少对大容量存储相关模块参数的支持,或者参数可能具有前缀。 要弄清楚这是否属实,需要查阅该小工具的文档或其源代码。
有关如何在小工具中包含大容量存储功能的示例,可以查看 Mass_storage.c、acm_ms.c 和 multi.c(按复杂性排序)。
5. Relation to file storage gadget
海量存储功能以及海量存储小工具都是基于文件存储小工具的。 两者的区别在于MSG是一个复合设备(即使用复合框架),而文件存储设备是一个传统设备。 从用户空间的角度来看,这种区别并不重要,但从内核黑客的角度来看,这意味着 (i) MSG 不会重复处理基本 USB 协议命令所需的代码,并且 (ii) MSF 可以在任何其他组合中使用 小工具。
因此,文件存储小工具已在 Linux 3.8 中删除。 所有用户都需要过渡到大容量存储小工具。 从外部看,这两个小工具的行为基本相同,除了:
-
在 FSG 中,“可移动”和“cdrom”模块参数为所有逻辑单元设置标志,而在 MSG 中,它们接受每个逻辑单元的 y/n 值列表。 如果仅使用单个逻辑单元,这并不重要,但如果有多个逻辑单元,则需要为每个逻辑单元重复 y/n 值。
-
FSG 的“serial”、“vendor”、“product”和“release”模块参数在MSG 中由分别命名为“iSerialnumber”、“idVendor”、“idProduct”和“bcdDevice”的复合层参数处理。
-
MSG 不支持 FSG 的测试模式,因此不支持“transport”、“protocol”和“buflen”FSG 的模块参数。 MSG 始终使用仅批量传输模式和 16 KiB 缓冲区的 SCSI 协议。