【问题标题】:How to unsafely remove blockdevice driver in Linux如何在 Linux 中不安全地删除块设备驱动程序
【发布时间】:2017-02-27 07:54:30
【问题描述】:

我正在为 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 不会帮助我解决这个问题

【问题讨论】:

  • 你的意思是热插拔之类的东西?
  • 谢谢,我不确定 hotplug 是否相关,请参阅我对下面答案的评论,并澄清我的问题
  • 我认为热插拔或热移除是您的想法。这可能非常特定于系统架构和您手头的设备类型(usb、pci 或其他东西?)。我认为您应该通过添加相关细节来缩小问题的范围。您能否提供当前状态的“Hello World”设备驱动程序实现?

标签: c linux linux-device-driver network-block-device


【解决方案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. 

【讨论】:

  • 在阅读了附加的链接并在谷歌的帮助下,我了解到 udev/hotplug 机制是一个框架,它标准化了低级内核驱动程序通知更高级别内核层和用户铲子的方式有关内核/硬件中发生的各种变化的应用程序。例如:网络驱动程序通知端口已启动/关闭,以允许更高级别的网络代码使用资源对其进行设置。但是,这似乎对驱动程序所有者没有任何帮助 - 事实上,它可能会增加一些额外的工作来与 udev 集成、生成事件和测试。
  • 该问题专门针对编写块设备驱动程序并尝试删除表示网络连接存储 (SAN) 的块设备的人的任务,而应用程序具有打开该块设备的句柄和 IO。这是一个很难解决的问题 - 使 IO 处于飞行状态的过程,然后处理如何在句柄关闭时释放设备资源
  • 我还对我的问题进行了澄清
  • @DanielHsH - 我记得在我从事的项目中,当用户在录制/播放期间移除磁盘时,我们遇到了问题。我们了解光盘插入/移除的方式是通过触发我们处理代码的热插拔事件。录制,作为一种写操作,处理起来非常棘手。我记得由于信号量锁而导致句柄未释放的问题。我们对处理文件系统的模块进行了修复。虽然,您的问题有所不同,但在我们的案例中,我们必须在中间件代码中进行自定义修复。
【解决方案2】:

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

  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

【讨论】:

  • 值得一提:如果您以后想取回您的设备,请使用for host in $(ls /sys/class/scsi_host/); do echo "- - -" > /sys/class/scsi_host/${host}/scan; done
猜你喜欢
  • 2023-03-28
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 2010-09-30
  • 1970-01-01
  • 2014-08-25
  • 2013-11-12
相关资源
最近更新 更多