制作内核扩展 DLPAR感知

与应用程序一样,缺省情况下,大多数内核扩展都是 DLPAR安全的。

但是,某些系统对系统配置很敏感,可能需要向 DLPAR 子系统注册。 某些内核扩展沿处理器行对其数据进行分区;创建基于联机处理器数量的线程;或提供大的固定内存缓冲池。 必须在系统拓扑更改时通知这些内核扩展。 需要执行的机制和操作与 DLPAR感知应用程序的机制和操作并行。

注册重新配置处理程序

提供以下内核服务以注册和注销重新配置处理程序:
#include sys/dr.h

int reconfig_register(int (*handler)(void *, void *, int, dr_info_t *),
                      int actions, void * h_arg, ulong *h_token, char *name);

void reconfig_unregister(ulong h_token);
int (*handler)(void *event, void *h_arg, unsigned long long req, void *resource_info);

void reconfig_unregister(ulong h_token);
int reconfig_register_ext (int (*handler)(void *, void *, unsigned long long, dr_info_t *),
unsigned long long actions, void * h_arg, ulong *h_token, char *name);

int (*handler)(void *event, void *h_arg, unsigned long long req, void *resource_info);
kerrno_t reconfig_register_list(int (*handler)(void *, void *, dr_kevent_t, void *), 
dr_kevent_t event_list[], size_t list_size, void *h_arg, ulong *h_token, char *name);

int (*handler)(void *event, void *h_arg, dr_kevent_t event_in_prog, void *resource_info);
注: 建议您使用内核服务 reconfig_register_list。 此服务支持向内核扩展通知更多事件。 先前的内核服务(reconfig_registerreconfig_register_ext)分别限于 32 项和 64 项事件,导致使用此服务的内核扩展无法移植到支持多于 32 项事件和 64 项事件的未来系统。
reconfig_register reconfig_register_extreconfig_register_list 子例程的参数如下:
  • handler 参数是要调用的内核扩展函数。
  • actions 参数使内核扩展能够指定哪些事件需要通知。 有关事件的列表,请参阅 reconfig_registerreconfig_register_extreconfig_unregister 内核服务。
  • h_arg 参数由内核扩展内核扩展指定,和处理程序的函数描述符一起由内核储存,然后在调用时传递给处理程序。 它不是由内核直接使用的,但可用来支持管理多个适配器实例的内核扩展。 实际上,该参数指向一个适配器控制块。
  • h_token 参数是一个输出参数,用来在注销处理程序时使用。
  • name 参数是为了获得信息而提供的,如果驱动程序返回错误可被包含在错误日志条目中。 它由内核扩展提供而且应该被限制为 15 个 ASCII 字符。
  • event_list 参数是 dr_kevent_t 值的阵列,应向内核扩展通知这些事件发生的时间。 有关已定义事件的列表,请参阅 reconfig_register_list 内核服务。
  • list_size 参数是 event_list 参数使用的内存大小。

reconfig_registerreconfig_register_ext 函数返回 0 表示成功,失败则返回相应的 errno 值。

调用 reconfig_unregister 函数以除去以前安装的处理程序。

只可在进程环境中调用 reconfig_registerreconfig_register_ext reconfig_unregister 函数。

如果内核扩展对之前阶段进行注册,建议对检查阶段进行注册,以避免在除去资源时部分系统未配置。

重新配置处理程序

以下是与 reconfig_register_list 内核服务一起使用的重新配置处理程序的接口:
Int (*handler)(void *event, void *h_arg, dr_kevent_t event_in_prog, void *resource_info);
重新配置处理程序的参数如下:
  • event 参数传递给处理程序且只能在调用 reconfig_handler_complete 子例程时使用。
  • h_arg 参数在注册时由处理程序指定。
  • event_in_prog 参数表示由处理程序执行的 DLPAR 操作。 有关事件的列表,请参阅 reconfig_register_list 内核服务。
  • resource_info 参数标识当前 DLPAR 请求的特定于资源的信息。 如果请求是基于处理器的,那么 resource_info 数据通过 dri_cpu 结构来提供。 如果请求是基于内存的,那么使用 dri_mem 结构。 在Micro-Partitioning®分区上,如果请求是基于处理器容量的,则资源信息数据通过Dri_cpu_capacity结构提供。 有关更多信息以及 dri_cpu_capacity 结构的格式,请参阅 reconfig Kernel Service
struct dri_cpu {
        cpu_t           lcpu;           /* Logical CPU Id of target CPU */
        cpu_t           bcpu;           /* Bind Id of target CPU        */
};

struct dri_mem {
        size64_t        req_memsz_change;   /* user requested mem size  */
        size64_t        sys_memsz;          /* system mem size at start */
        size64_t        act_memsz_change;   /* mem added/removed so far */
        rpn64_t         sys_free_frames;    /* Number of free frames */
        rpn64_t         sys_pinnable_frames;/* Number of pinnable frames */
        rpn64_t         sys_total_frames;   /* Total number of frames */
        unsigned long long lmb_addr;        /* start addr of logical memory block */
        size64_t        lmb_size;           /* Size of logical memory block being added */
};

如果当前 DLPAR 请求是分区的迁移,那么处理程序向 resource_info 数据内核扩展提供 resource_info 数据,但是内核扩展不需要访问 resource_info 数据的内容,因为内核扩展不使用这些数据。

重新配置处理程序在流程环境中被调用。

内核扩展可假定如下:
  • 每次只配置或除去一种类型的资源。
  • 不会同时指定多个处理器。 然而,内核扩展的代码应该支持多个逻辑内存块的添加或除去。 您可以初始化一个请求以添加或除去若干 GB 的内存。

检查阶段使 DLPAR感知应用程序和内核扩展能够在应用之前对用户的请求作出反应。 因此,check-phase 内核扩展处理程序只调用一次,即使请求可能转移到多个逻辑内存块。 和检查阶段不一样,之前阶段、之后阶段和错误后阶段被应用于逻辑内存块级别。 应用程序通知则不同,在应用程序通知中,无论底层的逻辑内存块的数量是多少,对每个用户请求均调用一次之前阶段、之后阶段或者错误后阶段。 另一个区别是内核扩展的错误后阶段在特定的逻辑内存块操作失败时使用,而应用程序的错误后阶段则在操作(在此情况下是整个用户请求)失败时使用。

通常,在检查阶段,内核扩展会检查其状态以确定其是否符合即将出现的 DLPAR 请求。 如果无法管理操作或对扩展的正确操作有反作用,那么处理程序返回 DR_FAIL。 否则处理程序返回 DR_SUCCESS

在预删除阶段中,内核扩展试图除去它们与指定资源之间的任何相关性。 维护预处理器缓冲池的驱动程序就是一个例子。 驱动程序可能在暂挂删除时标记相关的缓冲池,这样新的请求不从该处分配。 该池被及时清空,而且可能被释放。 在预删除阶段中必须考虑的其他项是计时器和已绑定的线程,需要分别停止和终止它们。 换句话说,已绑定线程可能被解除绑定。

在删除后阶段中,内核扩展试图释放垃圾收集过程中的所有资源,假定资源事实上被除去了。 如果没有,必须重新建立计时器和线程。 DR_resource_POST_ERROR 请求用于表示有错误发生。

在预添加阶段中,内核扩展必须预先初始化与新资源相关的任何数据路径,这样当配置新资源时,它已经准备就绪,可以使用了。 系统不保证资源在之后阶段中再次调用处理程序之前不被使用。

在添加后阶段中,内核扩展可假定资源被正确地添加和使用。 该阶段是方便地启动已绑定的线程、调度计时器和增加缓冲区的大小的地方。

通过注册一个或多个 _OP_ 通知类型,还能通知内核扩展除去或增加的内存(在每次操作时通知),这与应用程序的通知很相似。 这使得内核扩展能修改其资源使用以响应内存 DR 操作,每次操作修改一次,而不是每个逻辑内存块 (LMB) 修改一次。

除去内存前发送 DR_MEM_REMOVE_OP_PRE 通知。 此时,重新配置处理程序可以在内存除去之前开始调整其资源。 除去或添加内存后,将分别发送 DR_MEM_REMOVE_OP_POSTDR_MEM_ADD_OP_POST 通知,表明操作是否失败。 如果操作失败,那么 act_memsz_change0

如果可能,在几秒中内,重新配置处理程序返回 DR_SUCCESS 表示重新配置成功,或 DR_FAIL 表示失败。 如果需要更多的时间,处理程序返回 DR_WAIT

扩展 DR 处理程序

如果内核扩展预计操作可能花较长的时间,即几秒钟,处理程序将返回 DR_WAIT 至调用程序,但以异步方式继续进行请求。 以下情况中,处理程序表示它已经通过调用 reconfig_handler_complete 例程完成请求。
void reconfig_handler_complete(void *event, int rc);

event 参数与在有内核调用时传递给处理程序的参数相同。 rc 参数必须设为 DR_SUCCESSDR_FAIL 以表示处理程序的完成状态。

可在进程或中断环境中调用 reconfig_handler_complete 内核服务。

使用 xmemdma 内核服务

在支持 DLPAR的系统 (例如动态除去内存) 上,调用 xmemdma 内核服务而不使用 XMEM_DR_SAFE 标志会导致将指定的内存标记为不可移动。 这样做是为了保证系统的完整性,因为系统不了解调用程序打算如何使用返回的实内存地址。 动态内存除去操作仍然可对除了 xmemdma 调用指定的内存外的其他内存进行。

如果调用程序只是为了获取信息的目的(例如为了跟踪缓冲区或调试信息)而使用实内存地址,那么调用程序可以设置 XMEM_DR_SAFE 标记。 这向系统表示实内存地址可被透露给调用程序而没有任何数据崩溃的风险。 当出现该标记时,系统将仍然允许动态除去指定的内存。

如果调用程序通过以下方式使用实内存地址执行实际数据访问,那么严禁设置 XMEM_DR_SAFE 标记:关闭数据转换和执行 CPU 装入或对实内存的存储访问;针对实内存编写直接存储器存取 (DMA) 控制器。 如果设置了该标记,在内存被动态除去时系统的数据完整性可能遭到破坏。 有关将以这种方式使用实际内存地址的内核扩展转换为DLPAR 感知的信息,请联系您的IBM®服务代表。

要获取更多示例,请参阅 xmemdma 内核服务。

控制应用程序的内存 DLPAR 通知

从运行多个 DLPAR 所知程序的 LPAR 中动态添加或除去内存可能会导致资源冲突。 缺省情况下,每个程序均会平等接收到资源更改的通知。 例如,如果从运行两个 DR 所知程序的 LPAR 中除去 1 GB 的内存,那么缺省情况下,将通知每个程序已除去了 1 GB 的内存。 因为通常这两个程序不知道对方,所以它们都会将使用的内存减少 1 GB,这将会导致效率低下。 添加新内存时,也可能发生类似的效率问题。

为了克服这个问题,AIX®允许应用脚本在安装时使用百分比系数,该系数表示实际内存资源变化的百分比。 然后,系统会在发生内存 DLPAR 更改时通知应用程序。 使用 drmgr 命令安装应用程序脚本时,您可以使用 DR_MEM_PERCENT name=value 对指定该百分比因子。 应用程序脚本在被带有 scriptinfo 子命令的 drmgr 命令调用时,需要输出该 name=value 对。 值必须是介于 1 和 100 之间的整数。 此范围之外的任何值都将被忽略,而会使用缺省值 100。 另外,您还可以在安装时将该 name=value 对设为环境变量。 安装期间,如果设置了该环境变量的值,那么它将覆盖应用程序脚本提供的值。

类似地,在使用 SIGRECONFIG 信号处理程序和 dr_reconfig() 系统调用的应用程序中,可通过在应用程序开始运行之前将 DR_MEM_PERCENT name=value 对设为环境变量来控制内存 DLPAR 通知。 但是,在未重新启动应用程序的情况下,不能更改此值。