3

我正在为 linux 编写块设备驱动程序。支持不安全的移除(如 USB 拔出)至关重要。换句话说,我希望能够关闭块设备而不会造成内存泄漏/崩溃,即使应用程序持有打开的文件或在我的设备上执行 IO,或者如果它与文件系统一起挂载。当然,不安全的删除可能会破坏存储在设备上的数据,但这是客户愿意接受的。

这是我完成的基本步骤:

  1. 在不安全删除时,块设备会产生一个僵尸,它将自动使所有新的 IO 请求、ioctl 等失败。僵尸替代 make_request 函数并更改其他函数指针,因此内核不需要原始块设备。
  2. 块设备等待现在正在运行的所有 IO(并使用我的内部资源)完成
  3. 它确实 del_gendisk(); 但是,这并没有真正释放内核资源,因为它们仍在使用中。
  4. 块设备释放自己。
  5. 僵尸跟踪块设备上 opens() 和 close() 的数量,当最后一个 close() 发生时,它会自动释放() 本身
    1. 结果 - 我没有泄漏块设备、请求队列、生成磁盘等。

然而,这是一个非常困难的机制,需要大量代码并且极易出现竞争条件。我仍在为极端情况、io 的 per_cpu 计数和偶尔的崩溃而苦苦挣扎

我的问题:内核中是否有一种机制可以做到这一点?我搜索了手册、文献和无数块设备驱动程序、ram 磁盘和 USB 驱动程序的源代码示例,但找不到解决方案。我敢肯定,我不是第一个遇到这个问题的人。

编辑: 我从 Dave S 下面的答案中了解到热插拔机制,但这对我没有帮助。我需要一个如何安全关闭驱动程序而不是如何通知内核驱动程序已关闭的解决方案。

一个问题的示例: blk_queue_make_request() 注册了一个函数,我的块设备通过该函数为 IO 提供服务。在该函数中,我增加 per_cpu 计数器以了解每个 cpu 正在运行的 IO 数量。然而,有一个函数被调用但计数器还没有增加的竞争条件,所以我的设备认为有 0 个 IO,释放资源,然后 IO 来了并使系统崩溃。据我了解,Hotplug 不会帮助我解决这个问题

4

2 回答 2

1

如果驱动程序正在创建设备,则可能会突然删除它:

  1. echo 1 > /sys/block/device-name/device/delete例如,device-name可能在哪里,sde

或者

  1. echo 1 > /sys/class/scsi_device/h:c:t:l/device/delete,其中 h 是 HBA 编号,c 是 HBA 上的通道,t 是 SCSI 目标 ID,l 是 LUN。

就我而言,它完美地模拟了粉碎写入和从日志中恢复数据的场景。

通常要safely删除设备需要更多步骤,因此删除设备对于数据来说是一个非常激烈的事件,并且可能对测试有用:)

请考虑这一点:

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/online_storage_reconfiguration_guide/removing_devices

http://www.sysadminshare.com/2012/09/add-remove-single-disk-device-in-linux.html

于 2020-03-12T05:54:29.843 回答
1

大约十年前,我在一个软件驱动程序项目中使用热插拔来安全地添加/移除与嵌入式 Linux 驱动的机顶盒接口的外部 USB 磁盘驱动器。

对于您的项目,您还需要编写一个热插拔。hotplug 是一个程序,当一些重要的(通常与硬件相关的)事件发生时,内核使用它来通知用户模式软件。例如,当 USB 设备刚刚插入或移除时。

从 Linux 2.6 内核开始,热插拔已与驱动模型核心集成,因此任何总线或类都可以在添加或删除设备时报告热插拔事件。

在内核树中,/usr/src/linux/Documentation/usb/hotplug.txt 包含有关 USB 设备驱动程序 API 支持热插拔的基本信息。另请参阅此链接以及 GOOGLE 以获取示例和文档。

http://linux-hotplug.sourceforge.net/

另一个讨论块设备热插拔的非常有用的文档可以在这里找到:

https://www.kernel.org/doc/pending/hotplug.txt

本文档还提供了一个很好的示例来说明热插拔事件处理:

下表列出了您应该注意的主要变量:

热插拔事件变量:

每个热插拔事件都应至少提供以下变量:

ACTION
The current hotplug action: "add" to add the device, "remove" to remove it.
The 2.6.22 kernel can also generate "change", "online", "offline", and
"move" actions.

DEVPATH
Path under /sys at which this device's sysfs directory can be found.

SUBSYSTEM
If this is "block", it's a block device.  Anything other subsystem is
either a char device or does not have an associated device node.

还为某些设备提供了以下变量:

MAJOR and MINOR
If these are present, a device node can be created in /dev for this device.
Some devices (such as network cards) don't generate a /dev node.

DRIVER
If present, a suggested driver (module) for handling this device.  No
relation to whether or not a driver is currently handling the device.

INTERFACE and IFINDEX
When SUBSYSTEM=net, these variables indicate the name of the interface
and a unique integer for the interface.  (Note that "INTERFACE=eth0" could
be paired with "IFINDEX=2" because eth0 isn't guaranteed to come before lo
and the count doesn't start at 0.)

FIRMWARE
The system is requesting firmware for the device. 
于 2017-02-27T08:23:38.537 回答