当前位置:网站首页>【ceph】cephfs caps简介
【ceph】cephfs caps简介
2022-06-26 14:56:00 【bandaoyu】
目录
CAPS基础
基本概念
caps是mds授予client对文件进行操作的许可证,当一个client想要对文件元数据进行变更时,比如读、写、修改权限等等操作,它都必须先获取到相应的caps才可以进行这些操作。
ceph对caps的划分粒度很细,且允许多个client在同一个inode上持有不同的caps。
CAPS种类
根据元数据内容的不同,ceph将caps也分为了多个类别,每种类别只负责作用于某些特定的元数据:
| 类别 | 功能 |
|---|---|
| PIN | mds是否将inode pin在cache中 |
| AUTH | 鉴权相关的元数据,主要是owner、group、mode;但是如果是完整的鉴权是需要查看ACL的,acl信息保存在xattr中,这就需要XATTR相关的cap |
| XATTR | xattr |
| FILE | 最重要也是最复杂的一个,用于文件数据,以及和文件数据相关的ize、atime、ctime、mtime等 |
CAPS PERMISSION种类
#define CEPH_CAP_GSHARED 1 /* client can reads (s) */
#define CEPH_CAP_GEXCL 2 /* client can read and update (x) */
#define CEPH_CAP_GCACHE 4 /* (file) client can cache reads (c) */
#define CEPH_CAP_GRD 8 /* (file) client can read (r) */
#define CEPH_CAP_GWR 16 /* (file) client can write (w) */
#define CEPH_CAP_GBUFFER 32 /* (file) client can buffer writes (b) */
#define CEPH_CAP_GWREXTEND 64 /* (file) client can extend EOF (a) */
#define CEPH_CAP_GLAZYIO 128 /* (file) client can perform lazy io (l) */
CAPS COMBINATION
一个完整cap通过【类别+permission种类】组成,client可以同时申请多个类别的caps。但是并不是每种caps都可以使用每种permission,有些caps只能搭配部分permission。有关caps种类和permission的结合使用,有以下几个规则:
PIN
二值型,有pin就代表client知道这个inode存在,这样mds就一定会在其cache中保存这个inode
AUTH、LINK、XATTR
只能为shared或者exclusive
- shared:client可以将对应元数据保存在本地并缓存和使用
- exclusive:client不仅可以在本地缓存使用,还可以修改
下面是两个例子:
- [A]s:某client对inode 0x11有As的cap,此时收到一个查看0x11状态的系统调用,那么client不需要再向mds请求,直接通过查询自身缓存并进行处理和回复
- [A]x:某client对inode 0x11有Ax的cap,此时收到一个修改mode的系统调用,client可以直接在本地进行修改并回复,并且在之后才将修改变更通知mds
FILE
如前所述,file是最复杂的一种,下面是File cap的各个类别:
| file cap种类 | client权限 |
|---|---|
| Fs | client可以将mtime和size在本地cache并读取使用 |
| Fx | client可以将mtime和size在本地cache并进行修改和读取 |
| Fr | client可以同步地从osd读取数据,但不能cache |
| Fc | client可以将文件数据cache在本地内存,并直接从cache中读 |
| Fw | client可以同步地写数据到osd中,但是不能buffer write |
| Fb | client可以buffer write,先将写的数据维护在自己内存中,再统一flush到后端落盘 |
CAPS管理
LOCK
caps由mds进行管理,其将元数据划分为多个部分,每个部分都有专门的锁(SimpleLock、ScatterLock、FileLock)来保护,mds通过这些锁的状态来确定caps可以怎么样分配。
mds内部维护了每个锁的状态机,其内容非常复杂,也是mds保证caps分配准确性和数据一致性的关键。
CAPS如何变更
- mds可以针对每个client进行授予和移除caps,通常是由其他client的行为触发
- 例:比如client1已经拥有了inode 0x111的cache read的cap,此时client2要对这个文件进行写,那显然除了授予client2响应的写caps的同时,还要剥夺client1的cache read的cap
- 当client被移除caps时,其必须停止使用该cap,并给mds回应确认消息。mds需要等待收到client的确认消息后才会revoke。(如果client挂掉或者出于某种原因没有回复ack怎么办?)
- client停止使用并不简单,在不同场景下需要完全不同的处理:
- 例1:client被移除cache read cap,直接把该file的cache删掉,并变更状态就行了,这样下次的read请求过来时,还是到osd去读
- 例2:client被移除buffer write cap,已经缓存了大量的数据还没有flush,那就需要先flush到osd,再变更状态和确认,这可能就需要较长时间
下面来看看一个修改权限的例子实际感受下:

CAPS相关告警
下面是一些caps相关的主要告警信息,可参考对照排查问题:
| 告警信息 | 问题 |
|---|---|
| Client failing to respond to capability release | mds发出了revoke cap消息但是client没有回复 |
| Client failing to cache pressure | mds发送消息请求client去除一些pinned inode以减少内存使用,但client没有drop的足够或者没有回复的足够快 |
总结
- mds需要记住所有client pin的inode,
- mds的cache需要比client的cache更多
- caps是由mds和client端共同协作维护的,所以client需要正常运行,否则可能会block其他client(也就是说前面提出的问题,会被block?)
CAPS代码相关
CAPS数据表示和规则
一个client可以拥有多种类型(A,L,X,F)的caps,每种类型的caps也有多种permission类型(s,x,c,r,w,b,a,l)。那么如何表示这么多类型的caps呢?
- ceph首先规定了每种类型cap的bit范围,保证不同类型的cap的bit范围没有重叠。
/* generic cap bits */
#define CEPH_CAP_GSHARED 1 /* client can reads(s) */
#define CEPH_CAP_GEXCL 2 /* client can read and update(x) */
#define CEPH_CAP_GCACHE 4 /* (file) client can cache reads(c) */
#define CEPH_CAP_GRD 8 /* (file) client can read(r) */
#define CEPH_CAP_GWR 16 /* (file) client can write(w) */
#define CEPH_CAP_GBUFFER 32 /* (file) client can buffer writes(b) */
#define CEPH_CAP_GWREXTEND 64 /* (file) client can extend EOF(a) */
#define CEPH_CAP_GLAZYIO 128 /* (file) client can perform lazy io(l) */
/* per-lock shift */
#define CEPH_CAP_SAUTH 2 // A
#define CEPH_CAP_SLINK 4 // L
#define CEPH_CAP_SXATTR 6 // X
#define CEPH_CAP_SFILE 8 // F
- 通过定义每种类型permission类型的bit位和每种cap类型的偏移量,通过移位将两者组合起来形成单一cap。
#define CEPH_CAP_AUTH_SHARED (CEPH_CAP_GSHARED << CEPH_CAP_SAUTH) // As
#define CEPH_CAP_AUTH_EXCL (CEPH_CAP_GEXCL << CEPH_CAP_SAUTH) // Ax
#define CEPH_CAP_LINK_SHARED (CEPH_CAP_GSHARED << CEPH_CAP_SLINK) // Ls
#define CEPH_CAP_LINK_EXCL (CEPH_CAP_GEXCL << CEPH_CAP_SLINK) // Lx
#define CEPH_CAP_XATTR_SHARED (CEPH_CAP_GSHARED << CEPH_CAP_SXATTR) // Xs
#define CEPH_CAP_XATTR_EXCL (CEPH_CAP_GEXCL << CEPH_CAP_SXATTR) // Xx
#define CEPH_CAP_FILE(x) (x << CEPH_CAP_SFILE)
#define CEPH_CAP_FILE_SHARED (CEPH_CAP_GSHARED << CEPH_CAP_SFILE) // Fs
#define CEPH_CAP_FILE_EXCL (CEPH_CAP_GEXCL << CEPH_CAP_SFILE) // Fx
#define CEPH_CAP_FILE_CACHE (CEPH_CAP_GCACHE << CEPH_CAP_SFILE) // Fc
#define CEPH_CAP_FILE_RD (CEPH_CAP_GRD << CEPH_CAP_SFILE) // Fr
#define CEPH_CAP_FILE_WR (CEPH_CAP_GWR << CEPH_CAP_SFILE) // Fw
#define CEPH_CAP_FILE_BUFFER (CEPH_CAP_GBUFFER << CEPH_CAP_SFILE) // Fb
#define CEPH_CAP_FILE_WREXTEND (CEPH_CAP_GWREXTEND << CEPH_CAP_SFILE) // Fa
#define CEPH_CAP_FILE_LAZYIO (CEPH_CAP_GLAZYIO << CEPH_CAP_SFILE) // Fl
- 再通过或运算符将不同的cap组合起来形成多个caps
更形象的用图形来表示:
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| p | _ |As x |Ls x |Xs x |Fs x c r w b a l |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| PIN | AUTH | LINK | XATTR | FILE
0 2 4 6 8
这里还需要注意两点:
- pin cap只需要bit位0,所以bit位1是空闲出来无用的
- 除了file cap,其他类型的都不会占用2bit以上,所以把file cap放到了高位
FUSE WRITE实例
一个实例
下面以fuse client write为例,简要分析下fuse write时caps的代码逻辑:
注:只截取了和caps相关的部分代码
int64_t Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf,
const struct iovec *iov, int iovcnt)
{
want = CEPH_CAP_FILE_BUFFER;
// 需要拥有file write(CEPH_CAP_FILE_WR)和auth shared(CEPH_CAP_AUTH_SHARED) caps才(即FwAs)能够写,get_caps中如果检查没有caps则会
// 去向mds申请并等待返回
int r = get_caps(in, CEPH_CAP_FILE_WR|CEPH_CAP_AUTH_SHARED, want, &have, endoff);
if (r < 0)
return r;
/* clear the setuid/setgid bits, if any */
if (unlikely(in->mode & (S_ISUID|S_ISGID)) && size > 0) {
struct ceph_statx stx = { 0 };
// 增加该inode对该caps的引用计数并检查该caps是否正在使用中
put_cap_ref(in, CEPH_CAP_AUTH_SHARED);
r = __setattrx(in, &stx, CEPH_SETATTR_KILL_SGUID, f->actor_perms);
if (r < 0)
return r;
} else {
put_cap_ref(in, CEPH_CAP_AUTH_SHARED);
}
// 如果有buffer 或者lazy io cap则直接在objectcacher cache中写
if (cct->_conf->client_oc &&
(have & (CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO))) {
// do buffered write
if (!in->oset.dirty_or_tx)
get_cap_ref(in, CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_BUFFER);
get_cap_ref(in, CEPH_CAP_FILE_BUFFER);
// async, caching, non-blocking.
// 缓存写的调用,异步、cache、非阻塞
r = objectcacher->file_write(&in->oset, &in->layout,
in->snaprealm->get_snap_context(),
offset, size, bl, ceph::real_clock::now(),
0);
put_cap_ref(in, CEPH_CAP_FILE_BUFFER);
if (r < 0)
goto done;
// flush cached write if O_SYNC is set on file fh
// O_DSYNC == O_SYNC on linux < 2.6.33
// O_SYNC = __O_SYNC | O_DSYNC on linux >= 2.6.33
if ((f->flags & O_SYNC) || (f->flags & O_DSYNC)) {
_flush_range(in, offset, size);
}
} else {// 如果没有buffer cap,则直接通过osd写
if (f->flags & O_DIRECT)
_flush_range(in, offset, size);
// simple, non-atomic sync write
C_SaferCond onfinish("Client::_write flock");
unsafe_sync_write++;
get_cap_ref(in, CEPH_CAP_FILE_BUFFER); // released by onsafe callback
// 同步写的调用
filer->write_trunc(in->ino, &in->layout, in->snaprealm->get_snap_context(),
offset, size, bl, ceph::real_clock::now(), 0,
in->truncate_size, in->truncate_seq,
&onfinish);
client_lock.Unlock();
// 写完之后通过条件变量在这里等待,当写完成之后被唤醒,执行一些清理工作并返回
onfinish.wait();
client_lock.Lock();
_sync_write_commit(in);
}
}
参考链接
[1] What are “caps”? (And Why Won’t my Client Drop Them?)
[2] cephfs capabilities
转自:cephfs caps简介_https://blog.csdn.net/jiang4357291/article/details/103738524
cephfs caps简介 - https://www.freesion.com/article/3041236135/
边栏推荐
- Pod of kubernetes
- TCP 复位攻击原理
- 【TcaplusDB知识库】TcaplusDB单据受理-事务执行介绍
- Talk about the recent situation of several students from Tsinghua University
- Pytoch deep learning code skills
- Mark: unity3d cannot select resources in the inspector, that is, project locking
- R语言epiDisplay包的dotplot函数通过点图的形式可视化不同区间数据点的频率、使用by参数指定分组参数可视化不同分组的点图分布、使用cex.X.axis参数指定X轴轴刻度数值标签字体的大小
- Mongodb series window environment deployment configuration
- R language uses GLM function to build Poisson logarithm linear regression model, processes three-dimensional contingency table data to build saturation model, uses step function to realize stepwise re
- 【TcaplusDB知识库】TcaplusDB系统管理介绍
猜你喜欢

qt下多个子控件信号槽绑定方法

使用RestCloud ETL Shell组件实现定时调度DataX离线任务

Redis cluster

关于 selenium.common.exceptions.WebDriverException: Message: An unknown server-side error 解决方案(已解决)

功能:crypto-js加密解密

乐鑫 AWS IoT ExpressLink 模组达到通用可用性

Minister of investment of Indonesia: Hon Hai is considering establishing electric bus system and urban Internet of things in its new capital

How to load the contour CAD drawing of the engineering coordinate system obtained by the designer into the new earth

Smoothing data using convolution

710. random numbers in the blacklist
随机推荐
[cloud native] codeless IVX editor programmable by "everyone"
Restcloud ETL extracting dynamic library table data
shell脚本多进程并发写法实例(高阶修炼)
R语言使用ggplot2可视化泊松回归模型(Poisson Regression)的结果、可视化不同参量组合下的计数结果
Authoritative announcement on the recruitment of teachers in Yan'an University in 2022
Mongodb series window environment deployment configuration
The DOTPLOT function in the epidisplay package of R language visualizes the frequency of data points in different intervals in the form of point graphs, specifies the grouping parameters with the by p
设计人员拿到的工程坐标系等高线CAD图如何加载进图新地球
R语言epiDisplay包的tableStack函数制作统计汇总表格(分组的描述性统计、假设检验等)、不设置by参数计算基础描述性统计信息、指定对于大多数样本负相关的变量进行反序
5张图诠释了容器网络
Unity UnityWebRequest 下载封装
Sorted out a batch of script standard function modules (version 2021)
RestCloud ETL与Kettle对比分析
Sikuli automatic testing technology based on pattern recognition
feil_uVission4左侧工目录消失
聊聊几位大厂清华同学的近况
功能:crypto-js加密解密
RestCloud ETL解决shell脚本参数化
About selenium common. exceptions. Webdriverexception: message: an unknown server side error solution (resolved)
杜老师说网站更新图解