内存热插拔
内存热插拔事件通知
热插拔事件被发送到一个通知队列中。
在 include/linux/memory.h 中定义了六种通知类型:
-
MEM_GOING_ONLINE
在新内存可用之前生成,以便准备子系统处理内存。页分配器仍然无法从新内存中分配页面。
-
MEM_CANCEL_ONLINE
如果 MEM_GOING_ONLINE 失败,则生成。
-
MEM_ONLINE
当内存成功上线时生成。回调函数可以从新内存中分配页面。
-
MEM_GOING_OFFLINE
开始内存脱机化的过程。无法再从内存中分配,但要脱机的一些内存仍在使用中。回调可以用于释放已知子系统从指定内存块中知道的内存。
-
MEM_CANCEL_OFFLINE
如果 MEM_GOING_OFFLINE 失败,则生成。此时可以再次从尝试脱机的内存块中获得内存。
-
MEM_OFFLINE
在内存脱机完成后生成。
可以通过调用以下函数注册回调例程:
hotplug_memory_notifier(callback_func, priority)
具有较高优先级值的回调函数在具有较低优先级值的回调函数之前调用。
回调函数必须具有以下原型:
int callback_func(struct notifier_block *self, unsigned long action, void *arg);
回调函数的第一个参数(self)是指向指向回调函数本身的通知器链块的指针。第二个参数(action)是上述事件类型之一。第三个参数(arg)传递了一个 struct memory_notify 的指针:
struct memory_notify {
unsigned long start_pfn;
unsigned long nr_pages;
int status_change_nid_normal;
int status_change_nid;
}
- start_pfn 是在线/脱机内存的 start_pfn。
- nr_pages 是在线/脱机内存的页面数。
- status_change_nid_normal 是当 nodemask 的 N_NORMAL_MEMORY 被设置/清除时设置的节点 ID。如果为 -1,则 nodemask 状态未更改。
- status_change_nid 是当 nodemask 的 N_MEMORY 被设置/清除时设置的节点 ID。这意味着一个新的(无内存)节点通过上线获得新内存,一个节点失去了所有内存。如果为 -1,则 nodemask 状态未更改。
如果 status_changed_nid* >= 0,则回调应根据需要为节点创建/丢弃结构。
回调例程应返回 include/linux/notifier.h 中定义的 NOTIFY_DONE、NOTIFY_OK、NOTIFY_BAD、NOTIFY_STOP 中的一个值。
- NOTIFY_DONE 和 NOTIFY_OK 对进一步处理没有影响。
- NOTIFY_BAD 用作对 MEM_GOING_ONLINE、MEM_GOING_OFFLINE、MEM_ONLINE 或 MEM_OFFLINE 操作的响应,以取消热插拔。它停止通知队列的进一步处理。
- NOTIFY_STOP 停止通知队列的进一步处理。
锁定内部
在添加/移除使用内存块设备(即普通 RAM)的内存时,应持有 device_hotplug_lock 锁定以:
- 同步在线/脱机请求(例如通过 sysfs)。这样,内存块设备只能在内存完全添加后被用户空间访问(.online/.state 属性)。并且在移除内存时,我们知道没有人处于关键部分。
- 与 CPU 热插拔等同步(例如对 ACPI 和 PPC 有关)。
特别是,在添加内存并且用户空间尝试更快地上线该内存时,通过使用 device_hotplug_lock 可以避免可能的锁反转:
- device_online() 首先获取 device_lock(),然后是 mem_hotplug_lock。
- add_memory_resource() 首先获取 mem_hotplug_lock,然后是 device_lock()(在创建设备时,即在 bus_add_device() 期间)。
由于设备在获取 device_lock() 之前对用户空间可见,这可能导致锁反转。
应通过 device_online()/device_offline() 执行内存的上线/脱机操作,以确保它与通过 sysfs 的操作同步。建议持有 device_hotplug_lock(例如保护 online_type)。
在添加/移除/上线/脱机内存或添加/移除异构/设备内存时,我们应始终以写模式持有 mem_hotplug_lock 以串行化内存热插拔(例如对全局/区域变量的访问)。
此外,与 device_hotplug_lock 相比,以读模式持有 mem_hotplug_lock 允许对 get_online_mems/put_online_mems 实现进行高效的保护,因此访问内存的代码可以防止该内存消失。
标签:热插拔,lock,脱机,hotplug,MEM,内存,device,ChatGPT From: https://www.cnblogs.com/pengdonglin137/p/17891202.html