1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
|
/*
* Handle a cap GRANT message from the MDS. (Note that a GRANT may
* actually be a revocation if it specifies a smaller cap set.)
*
* 主要架构组件:
* 1. 能力管理系统 (Capability Management System)
* - 处理MDS发送的能力授权/撤销消息
* - 维护客户端的文件访问权限状态
*
* 2. 锁机制 (Lock Management)
* - i_ceph_lock: 保护inode的ceph特定字段
* - snap_rwsem: 快照读写信号量
* - s_mutex: 会话互斥锁
*
* 3. 缓存一致性 (Cache Coherency)
* - 处理缓存失效和回写操作
* - 管理文件数据的一致性状态
*
* 4. 文件属性管理 (File Attribute Management)
* - 更新文件大小、权限、时间戳等元数据
* - 处理加密文件的特殊逻辑
*
* caller holds s_mutex and i_ceph_lock, we drop both.
*/
static void handle_cap_grant(struct inode *inode,
struct ceph_mds_session *session,
struct ceph_cap *cap,
struct ceph_mds_caps *grant,
struct ceph_buffer *xattr_buf,
struct cap_extra_info *extra_info)
__releases(ci->i_ceph_lock)
__releases(session->s_mdsc->snap_rwsem)
{
struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
/*
* 工作原理概述:
* 1. 解析MDS发送的能力授权消息
* 2. 处理能力状态变化(授权/撤销/无变化)
* 3. 更新文件元数据和属性
* 4. 处理缓存一致性操作
* 5. 触发相应的后续操作(回写、失效等)
*/
int seq = le32_to_cpu(grant->seq);
int newcaps = le32_to_cpu(grant->caps);
int used, wanted, dirty;
u64 size = le64_to_cpu(grant->size);
u64 max_size = le64_to_cpu(grant->max_size);
/* 状态标志位 - 用于控制后续操作 */
unsigned char check_caps = 0;
bool was_stale = cap->cap_gen < atomic_read(&session->s_cap_gen);
bool wake = false; // 是否唤醒等待线程
bool writeback = false; // 是否需要回写数据
bool queue_trunc = false; // 是否需要截断文件
bool queue_invalidate = false; // 是否需要失效缓存
bool deleted_inode = false; // inode是否被删除
bool fill_inline = false; // 是否填充内联数据
bool revoke_wait = false; // 是否等待撤销完成
int flags = 0;
/*
* 加密文件大小处理 - Ceph的加密文件系统支持
* 如果文件是加密的且有内容,使用fscrypt_file_size
*/
if (IS_ENCRYPTED(inode) && size)
size = extra_info->fscrypt_file_size;
/* 调试输出 - 记录能力变化 */
doutc(cl, "%p %llx.%llx cap %p mds%d seq %d %s\n", inode,
ceph_vinop(inode), cap, session->s_mds, seq,
ceph_cap_string(newcaps));
doutc(cl, " size %llu max_size %llu, i_size %llu\n", size,
max_size, i_size_read(inode));
/*
* 缓存失效处理 - 一致性管理的核心
* 当CACHE能力被撤销且没有脏缓冲区时,尝试失效缓存
*/
if (S_ISREG(inode->i_mode) && /* 仅对常规文件 */
((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) &&
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0 &&
!(ci->i_wrbuffer_ref || ci->i_wb_ref)) {
if (try_nonblocking_invalidate(inode)) {
/* 页面被锁定,稍后在单独线程中失效 */
if (ci->i_rdcache_revoking != ci->i_rdcache_gen) {
queue_invalidate = true;
ci->i_rdcache_revoking = ci->i_rdcache_gen;
}
}
}
/* 处理过期能力 - 重置为基本PIN能力 */
if (was_stale)
cap->issued = cap->implemented = CEPH_CAP_PIN;
/*
* 能力迁移处理 - 处理MDS之间的能力转移
* 确保消息顺序的正确性
*/
if (ceph_seq_cmp(seq, cap->seq) <= 0) {
WARN_ON(cap != ci->i_auth_cap);
WARN_ON(cap->cap_id != le64_to_cpu(grant->cap_id));
seq = cap->seq;
newcaps |= cap->issued;
}
/* 更新能力状态 */
cap->cap_gen = atomic_read(&session->s_cap_gen);
cap->seq = seq;
/* 检查能力授权的副作用 */
__check_cap_issue(ci, cap, newcaps);
/* 更新inode版本号 - 用于缓存一致性 */
inode_set_max_iversion_raw(inode, extra_info->change_attr);
/*
* 文件属性更新 - AUTH_SHARED能力允许读取基本属性
*/
if ((newcaps & CEPH_CAP_AUTH_SHARED) &&
(extra_info->issued & CEPH_CAP_AUTH_EXCL) == 0) {
umode_t mode = le32_to_cpu(grant->mode);
/* 检查inode类型是否发生变化 */
if (inode_wrong_type(inode, mode))
pr_warn_once("inode type changed! (ino %llx.%llx is 0%o, mds says 0%o)\n",
ceph_vinop(inode), inode->i_mode, mode);
else
inode->i_mode = mode;
/* 更新用户ID和组ID */
inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid));
inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid));
ci->i_btime = extra_info->btime;
doutc(cl, "%p %llx.%llx mode 0%o uid.gid %d.%d\n", inode,
ceph_vinop(inode), inode->i_mode,
from_kuid(&init_user_ns, inode->i_uid),
from_kgid(&init_user_ns, inode->i_gid));
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
/* 加密认证信息检查 - 防止未授权修改 */
if (ci->fscrypt_auth_len != extra_info->fscrypt_auth_len ||
memcmp(ci->fscrypt_auth, extra_info->fscrypt_auth,
ci->fscrypt_auth_len))
pr_warn_ratelimited_client(cl,
"cap grant attempt to change fscrypt_auth on non-I_NEW inode (old len %d new len %d)\n",
ci->fscrypt_auth_len,
extra_info->fscrypt_auth_len);
#endif
}
/*
* 链接计数更新 - LINK_SHARED能力允许读取链接信息
*/
if ((newcaps & CEPH_CAP_LINK_SHARED) &&
(extra_info->issued & CEPH_CAP_LINK_EXCL) == 0) {
set_nlink(inode, le32_to_cpu(grant->nlink));
if (inode->i_nlink == 0)
deleted_inode = true; // 标记为已删除
}
/*
* 扩展属性更新 - 处理xattr数据
*/
if ((extra_info->issued & CEPH_CAP_XATTR_EXCL) == 0 &&
grant->xattr_len) {
int len = le32_to_cpu(grant->xattr_len);
u64 version = le64_to_cpu(grant->xattr_version);
if (version > ci->i_xattrs.version) {
doutc(cl, " got new xattrs v%llu on %p %llx.%llx len %d\n",
version, inode, ceph_vinop(inode), len);
if (ci->i_xattrs.blob)
ceph_buffer_put(ci->i_xattrs.blob);
ci->i_xattrs.blob = ceph_buffer_get(xattr_buf);
ci->i_xattrs.version = version;
ceph_forget_all_cached_acls(inode);
ceph_security_invalidate_secctx(inode);
}
}
/*
* 时间戳更新 - 当有读权限时更新文件时间
*/
if (newcaps & CEPH_CAP_ANY_RD) {
struct timespec64 mtime, atime, ctime;
ceph_decode_timespec64(&mtime, &grant->mtime);
ceph_decode_timespec64(&atime, &grant->atime);
ceph_decode_timespec64(&ctime, &grant->ctime);
ceph_fill_file_time(inode, extra_info->issued,
le32_to_cpu(grant->time_warp_seq),
&ctime, &mtime, &atime);
}
/*
* 目录统计信息更新 - 用于目录的文件和子目录计数
*/
if ((newcaps & CEPH_CAP_FILE_SHARED) && extra_info->dirstat_valid) {
ci->i_files = extra_info->nfiles;
ci->i_subdirs = extra_info->nsubdirs;
}
/*
* 文件布局和大小处理 - 核心的文件元数据管理
*/
if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) {
/* 文件布局可能已更改 */
s64 old_pool = ci->i_layout.pool_id;
struct ceph_string *old_ns;
ceph_file_layout_from_legacy(&ci->i_layout, &grant->layout);
old_ns = rcu_dereference_protected(ci->i_layout.pool_ns,
lockdep_is_held(&ci->i_ceph_lock));
rcu_assign_pointer(ci->i_layout.pool_ns, extra_info->pool_ns);
/* 如果存储池发生变化,清除权限缓存 */
if (ci->i_layout.pool_id != old_pool ||
extra_info->pool_ns != old_ns)
ci->i_ceph_flags &= ~CEPH_I_POOL_PERM;
extra_info->pool_ns = old_ns;
/* 处理文件大小和截断 */
queue_trunc = ceph_fill_file_size(inode, extra_info->issued,
le32_to_cpu(grant->truncate_seq),
le64_to_cpu(grant->truncate_size),
size);
}
/*
* 最大文件大小处理 - 仅对授权MDS有效
*/
if (ci->i_auth_cap == cap && (newcaps & CEPH_CAP_ANY_FILE_WR)) {
if (max_size != ci->i_max_size) {
doutc(cl, "max_size %lld -> %llu\n", ci->i_max_size,
max_size);
ci->i_max_size = max_size;
if (max_size >= ci->i_wanted_max_size) {
ci->i_wanted_max_size = 0; /* 重置 */
ci->i_requested_max_size = 0;
}
wake = true;
}
}
/* 能力状态分析 */
wanted = __ceph_caps_wanted(ci);
used = __ceph_caps_used(ci);
dirty = __ceph_caps_dirty(ci);
doutc(cl, " my wanted = %s, used = %s, dirty %s\n",
ceph_cap_string(wanted), ceph_cap_string(used),
ceph_cap_string(dirty));
/*
* 检查是否需要能力检查 - 处理导入或过期的情况
*/
if ((was_stale || le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) &&
(wanted & ~(cap->mds_wanted | newcaps))) {
check_caps = 1;
}
/*
* 能力变化处理 - 这是函数的核心逻辑
* 分为三种情况:撤销、无变化、授权
*/
if (cap->issued & ~newcaps) {
/* 能力撤销情况 */
int revoking = cap->issued & ~newcaps;
doutc(cl, "revocation: %s -> %s (revoking %s)\n",
ceph_cap_string(cap->issued), ceph_cap_string(newcaps),
ceph_cap_string(revoking));
if (S_ISREG(inode->i_mode) &&
(revoking & used & CEPH_CAP_FILE_BUFFER)) {
writeback = true; /* 启动回写,延迟确认 */
revoke_wait = true;
} else if (queue_invalidate &&
revoking == CEPH_CAP_FILE_CACHE &&
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0) {
revoke_wait = true; /* 等待失效完成 */
} else if (cap == ci->i_auth_cap) {
check_caps = 1; /* 仅检查授权能力 */
} else {
check_caps = 2; /* 检查所有能力 */
}
/* 如果有新能力,尝试唤醒等待者 */
if (~cap->issued & newcaps)
wake = true;
cap->issued = newcaps;
cap->implemented |= newcaps;
} else if (cap->issued == newcaps) {
/* 能力无变化 */
doutc(cl, "caps unchanged: %s -> %s\n",
ceph_cap_string(cap->issued),
ceph_cap_string(newcaps));
} else {
/* 能力授权情况 */
doutc(cl, "grant: %s -> %s\n", ceph_cap_string(cap->issued),
ceph_cap_string(newcaps));
/* 检查是否有其他MDS在撤销新授权的能力 */
if (cap == ci->i_auth_cap &&
__ceph_caps_revoking_other(ci, cap, newcaps))
check_caps = 2;
cap->issued = newcaps;
cap->implemented |= newcaps; /* 仅添加位,避免覆盖待撤销的 */
wake = true;
}
BUG_ON(cap->issued & ~cap->implemented);
/*
* 撤销消息的特殊处理 - 强制发送响应给MDS
*/
if (!revoke_wait && le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) {
cap->mds_wanted = 0;
flags |= CHECK_CAPS_FLUSH_FORCE;
if (cap == ci->i_auth_cap)
check_caps = 1;
else
check_caps = 2;
}
/*
* 内联数据处理 - Ceph的小文件优化
*/
if (extra_info->inline_version > 0 &&
extra_info->inline_version >= ci->i_inline_version) {
ci->i_inline_version = extra_info->inline_version;
if (ci->i_inline_version != CEPH_INLINE_NONE &&
(newcaps & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)))
fill_inline = true;
}
/*
* 导入操作的特殊处理 - 处理能力从其他MDS迁移过来的情况
*/
if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
if (ci->i_auth_cap == cap) {
if (newcaps & ~extra_info->issued)
wake = true;
if (ci->i_requested_max_size > max_size ||
!(le32_to_cpu(grant->wanted) & CEPH_CAP_ANY_FILE_WR)) {
/* 如有必要,重新请求max_size */
ci->i_requested_max_size = 0;
wake = true;
}
ceph_kick_flushing_inode_caps(session, ci);
}
up_read(&session->s_mdsc->snap_rwsem);
}
spin_unlock(&ci->i_ceph_lock);
/*
* 后续操作处理 - 在释放锁后执行的异步操作
*/
if (fill_inline)
ceph_fill_inline_data(inode, NULL, extra_info->inline_data,
extra_info->inline_len);
if (queue_trunc)
ceph_queue_vmtruncate(inode);
if (writeback)
ceph_queue_writeback(inode);
if (queue_invalidate)
ceph_queue_invalidate(inode);
if (deleted_inode)
invalidate_aliases(inode);
if (wake)
wake_up_all(&ci->i_cap_wq);
mutex_unlock(&session->s_mutex);
/*
* 能力检查 - 根据前面的分析结果执行相应的能力检查
*/
if (check_caps == 1)
ceph_check_caps(ci, flags | CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL);
else if (check_caps == 2)
ceph_check_caps(ci, flags | CHECK_CAPS_NOINVAL);
}
|