9.3. Glocks
对于 GFS2,最重要的一个独特的概念就是 glocks。就源代码而言,glock 是一个数据结构,它将合并 DLM 并缓存到单个状态机器。每个 glock 与一个 DLM 锁定有一个 1:1 的关系,为该锁定状态提供缓存,以便从文件系统中单一节点执行的重复操作不必重复调用 DLM,这有助于避免不必要的网络流量。有两大类 glock,一类是有元数据缓存的 glock,另外是没有元数据缓存的 glock。内节点 glock 和资源组 glock 都有元数据缓存,其他类型的 glock 不缓存元数据。内节点 glock 除元数据外还会缓存数据,并且具有所有 glocks 中最复杂的逻辑。
Glock 模式 | DLM 锁定模式 | 备注 |
---|---|---|
UN | IV/NL | 未锁定(没有与 glock 相关的 DLM 锁定,或 NL 锁定取决于 I 标记) |
SH | PR | 共享(读保护)锁定 |
EX | EX | 专用锁定 |
DF | CW | 用于直接 I/O 和文件系统停止的延迟(并性写) |
Glocks 会一直保留在内存中,直到其被解锁(根据另一个节点的请求,或虚拟机的请求)或不再有本地用户。此时它们会从 glock 哈希表中移除并释放。当 glock 创建时,DLM 锁定不会立即与 glock 关联。当第一次请求 DLM 时,DLM 锁与 glock 关联,如果这个请求成功,那么会在 glock 上设置 'I'(初始)标记。glock debugfs 接口 中的"Glock Flags" 表显示不同的 glock 标记的含义。当 DLM 与 glock 关联后,DLM 锁定将始终保持至少为 NL(Null)锁定模式,直到 glock 被释放。当 DLM 锁从 NL 变为解锁状态始终是 glock 生命周期中的最后一个操作。
每个 glock 都有多个与它关联的"拥有者(holder)",每个都代表来自更高层的一个锁定请求。与 GFS2 队列以及从 glock 中退出队列的持有者相关的系统调用来保护代码的关键部分。
glock 状态机器基于一个工作队列。出于性能的原因,tasklet 将是首选;但是,在当前的实现中,我们需要从那些禁止他们使用的上下文中提交 I/O。
Workqueue 有自己的追踪点,它们可与 GFS2 追踪点结合使用。
下表显示了在每个 glock 模式下可能会缓存哪些状态,以及缓存的状态是否为脏。这适用于内节点和资源组锁定,尽管资源组锁中没有数据组件,只有元数据。
Glock 模式 | 缓存数据 | 缓存元数据 | 脏数据 | 脏元数据 |
---|---|---|---|---|
UN | 否 | 否 | 否 | 否 |
SH | 是 | 是 | 否 | 否 |
DF | 否 | 是 | 否 | 否 |
EX | 是 | 是 | 是 | 是 |