cephfs根据存储池显示df容量
前言
如果用cephfs比较多,应该都知道,在cephfs的客户端进行mount以后,看到的容量显示的是集群的总的容量,也就是你的总的磁盘空间是多少这个地方显示的就是多少
这个一直都是这样显示的,我们之前在hammer版本的时候,阿茂和大黄一起在公司内部实现了这个功能,社区会慢慢的集成一些类似的面向面向商业用户的需求
社区已经开发了一个版本,接口都做的差不多了,那么稍微改改,就能实现想要的需求的
本篇内的改动是基于内核客户端代码的改动,改动很小,应该能够看的懂
改动过程
首先找到这个补丁
Improve accuracy of statfs reporting for Ceph filesystems comprising exactly one data pool. In this case, the Ceph monitor can now report the space usage for the single data pool instead of the global data for the entire Ceph cluster. Include support for this message in mon_client and leverage it in ceph/super.
地址:https://www.spinics.net/lists/ceph-devel/msg37937.html
这个说的是改善了statfs的显示,这个statfs就是在linux下面的mount的输出的显示的,说是改善了在单存储池下的显示效果,也就是在单存储池下能够显示存储池的容量空间,而不是全局的空间
这里就有个疑问了,单存储池?那么多存储池呢?我们测试下看看
这里这个补丁已经打到了centos7.5的默认内核里面去了,也就是内核版本
Linux lab103 3.10.0-862.el7.x86_64
对应的rpm包的版本是
[root@lab103 ceph]# rpm -qa|grep 3.10.0-862
kernel-devel-3.10.0-862.el7.x86_64
kernel-3.10.0-862.el7.x86_64
下载的地址为:
http://mirrors.163.com/centos/7.5.1804/os/x86_64/Packages/kernel-3.10.0-862.el7.x86_64.rpm
或者直接安装centos7.5也行,这里只要求是这个内核就可以了
我们看下默认情况下是怎样的
[root@lab102 ~]# ceph -s
data:
pools: 3 pools, 72 pgs
objects: 22 objects, 36179 bytes
usage: 5209 MB used, 11645 GB / 11650 GB avail
pgs: 72 active+clean
[root@lab102 ~]# ceph fs ls
name: ceph, metadata pool: metadata, data pools: [data ]
[root@lab102 ~]# ceph df
GLOBAL:
SIZE AVAIL bash USED %bash USED
11650G 11645G 5209M 0.04
POOLS:
NAME ID USED %USED MAX AVAIL OBJECTS
data 9 0 0 3671G 0
metadata 10 36179 0 11014G 22
newdata 11 0 0 5507G 0
[root@lab102 ~]# ceph osd dump|grep pool
pool 9 'data' replicated size 3 min_size 1 crush_rule 0 object_hash rjenkins pg_num 32 pgp_num 32 last_change 136 flags hashpspool stripe_width 0 application cephfs
pool 10 'metadata' replicated size 1 min_size 1 crush_rule 0 object_hash rjenkins pg_num 32 pgp_num 32 last_change 112 flags hashpspool stripe_width 0 application cephfs
pool 11 'newdata' replicated size 2 min_size 1 crush_rule 0 object_hash rjenkins pg_num 8 pgp_num 8 last_change 134 flags hashpspool stripe_width 0 application cephfs
从上面可以看到我的硬盘裸空间为12T左右,data存储池副本3那么可用空间为4T左右,文件系统里面只有一个data存储池,看下挂载的情况
[root@lab101 ~]# uname -a
Linux lab101 3.10.0-862.el7.x86_64 #1 SMP Fri Apr 20 16:44:24 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
[root@lab101 ~]# df -Th|grep mnt
192.168.19.102:/ ceph 3.6T 0 3.6T 0% /mnt
可以看到显示的容量就是存储池的可用容量为总空间的,现在我们加入一个数据池
[root@lab102 ~]# ceph mds add_data_pool newdata
added data pool 11 to fsmap
再次查看df的显示
[root@lab101 ~]# df -Th|grep mnt
192.168.19.102:/ ceph 12T 5.1G 12T 1% /mnt
容量回到了原始的显示的方式,这个跟上面的补丁的预期是一样的,我们看下代码这里怎么控制的
获取当前内核版本的代码
首先要找到当前的内核的src.rpm包,这样可以拿到当前内核版本的源码
wget http://vault.centos.org/7.5.1804/os/Source/SPackages/kernel-3.10.0-862.el7.src.rpm
解压源码包
[root@lab103 origin]# rpm2cpio kernel-3.10.0-862.el7.src.rpm |cpio -div
[root@lab103 origin]# tar -xvf linux-3.10.0-862.el7.tar.xz
[root@lab103 origin]# cd linux-3.10.0-862.el7/fs/ceph/
上面的操作后我们已经进入了我们想要看的源码目录了
我们看下super.c这个文件,这个df的显示的控制是在这个文件里面的
[root@lab103 ceph]# cat super.c |less
看下这段代码
static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct ceph_fs_client *fsc = ceph_inode_to_client(dentry->d_inode);
struct ceph_monmap *monmap = fsc->client->monc.monmap;
struct ceph_statfs st;
u64 fsid;
int err;
u64 data_pool;
if (fsc->mdsc->mdsmap->m_num_data_pg_pools == 1) {
data_pool = fsc->mdsc->mdsmap->m_data_pg_pools[0];
} else {
data_pool = CEPH_NOPOOL;
}
dout("statfs\n");
err = ceph_monc_do_statfs(&fsc->client->monc, data_pool, &st);
if (err < 0)
return err;
其中的fsc->mdsc->mdsmap->m_num_data_pg_pools == 1和data_pool = fsc->mdsc->mdsmap->m_data_pg_pools[0];这个地方的意思是如果fs里面包含的存储池的存储池个数为1那么data_pool就取这个存储池的信息,所以上面的我们的实践过程中的就是单个存储池的时候显示存储池的容量,超过一个的时候就显示的全局的容量,这个是跟代码对应的上的
我们基于上面的已经做好的功能改变一下需求
需要可以根据自己的需要指定存储池的容量来显示,通过挂载内核客户端的时候传递一个参数进去来进行显示
代码改动
[root@lab103 ceph]# vim super.h
在super.h内定义一个默认值
#define ZP_POOL_DEFAULT 0 /* pool id */
#define CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT 60 /* cap release delay */
struct ceph_mount_options {
int flags;
int sb_flags;
int wsize; /* max write size */
int rsize; /* max read size */
int zp_pool; /* pool id */
int rasize; /* max readahead */
这里增加了两个一个zp_pool和ZP_POOL_DEFAULT
这个文件的改动就只有这么多了
改动super.c的代码
在enum里面加上Opt_zp_pool
enum {
Opt_wsize,
Opt_rsize,
Opt_rasize,
Opt_caps_wanted_delay_min,
Opt_zp_pool,
在match_table_t fsopt_tokens里面添加Opt_zp_pool相关的判断,我们自己注意传的是pool在fs里面的id即可
static match_table_t fsopt_tokens = {
{Opt_wsize, "wsize=%d"},
{Opt_rsize, "rsize=%d"},
{Opt_rasize, "rasize=%d"},
{Opt_caps_wanted_delay_min, "caps_wanted_delay_min=%d"},
{Opt_zp_pool, "zp_pool=%d"},
在static int parse_fsopt_token中添加
case Opt_caps_wanted_delay_max:
if (intval < 1)
return -EINVAL;
fsopt->caps_wanted_delay_max = intval;
break;
case Opt_zp_pool:
if (intval < 0)
return -EINVAL;
fsopt->zp_pool = intval;
break;
case Opt_readdir_max_entries:
if (intval < 1)
return -EINVAL;
fsopt->max_readdir = intval;
break;
判断如果小于0就抛错,这个id从0开始上升的,所以也不允许小于0
在static int parse_mount_options中添加
fsopt->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT;
fsopt->zp_pool = ZP_POOL_DEFAULT;
fsopt->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT;
在static int ceph_show_options中添加
if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT)
seq_printf(m, ",caps_wanted_delay_min=%d",
fsopt->caps_wanted_delay_min);
if (fsopt->zp_pool)
seq_printf(m, ",zp_pool=%d",
fsopt->zp_pool);
if (fsopt->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT)
seq_printf(m, ",caps_wanted_delay_max=%d",
fsopt->caps_wanted_delay_max);
这个是用来在执行mount命令的时候显示选项的数值的
改动到这里我们检查下我们对super.c做过的的改动
[root@lab103 ceph]# cat super.c |grep zp_pool
Opt_zp_pool,
{Opt_zp_pool, "zp_pool=%d"},
case Opt_zp_pool:
fsopt->zp_pool = intval;
fsopt->zp_pool = ZP_POOL_DEFAULT;
if (fsopt->zp_pool)
seq_printf(m, ",zp_pool=%d",
fsopt->zp_pool);
做了以上的改动后我们就可以把参数给传进来了,现在我们需要把参数传递到需要用的地方
也就是static int ceph_statfs内需要调用这个参数
在static int ceph_statfs中添加上struct ceph_mount_options *fsopt = fsc->mount_options;
static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct ceph_fs_client *fsc = ceph_inode_to_client(dentry->d_inode);
struct ceph_monmap *monmap = fsc->client->monc.monmap;
struct ceph_statfs st;
struct ceph_mount_options *fsopt = fsc->mount_options;
u64 fsid;
然后改掉这个fsc->mdsc->mdsmap->m_num_data_pg_pools == 1的判断,我们判断大于0即可
if (fsc->mdsc->mdsmap->m_num_data_pg_pools > 0) {
data_pool = fsc->mdsc->mdsmap->m_data_pg_pools[fsopt->zp_pool];
} else {
data_pool = CEPH_NOPOOL;
}
并且把写死的0改成我们的变量fsopt->zp_pool
到这里改动就完成了,这里还没有完,我们需要编译成我们的需要的模块
[root@lab103 ceph]# modinfo ceph
filename: /lib/modules/3.10.0-862.el7.x86_64/kernel/fs/ceph/ceph.ko.xz
可以看到内核在高版本的时候已经改成了xz压缩的模块了,这里等会需要多处理一步
我们只需要这一个模块就编译这一个ceph.ko模块就好
编译需要装好kernel-devel包kernel-devel-3.10.0-862.el7.x86_64
[root@lab103 ceph]# pwd
/home/origin/linux-3.10.0-862.el7/fs/ceph
[root@lab103 ceph]# make CONFIG_CEPH_FS=m -C /lib/modules/3.10.0-862.el7.x86_64/build/ M=`pwd` modules
make: Entering directory `/usr/src/kernels/3.10.0-862.el7.x86_64'
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/super.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/inode.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/dir.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/file.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/locks.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/addr.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/ioctl.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/export.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/caps.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/snap.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/xattr.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/mds_client.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/mdsmap.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/strings.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/ceph_frag.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/debugfs.o
CC [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/acl.o
LD [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/ceph.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/origin/linux-3.10.0-862.el7/fs/ceph/ceph.mod.o
LD [M] /home/origin/linux-3.10.0-862.el7/fs/ceph/ceph.ko
make: Leaving directory `/usr/src/kernels/3.10.0-862.el7.x86_64'
正常应该就是上面的没有报错的输出了
压缩ko模块
[root@lab103 ceph]# find * -name '*.ko' | xargs -n 1 xz
[root@lab103 ceph]# rmmod ceph
[root@lab103 ceph]# rm -rf /lib/modules/3.10.0-862.el7.x86_64/kernel/fs/ceph/ceph.ko.xz
[root@lab103 ceph]# cp -ra ceph.ko.xz /lib/modules/3.10.0-862.el7.x86_64/kernel/fs/ceph/
[root@lab103 ceph]# lsmod |grep ceph
ceph 345111 0
libceph 301687 1 ceph
dns_resolver 13140 1 libceph
libcrc32c 12644 2 xfs,libceph
现在已经加载好模块了,我们试验下
[root@lab103 ceph]# ceph df
GLOBAL:
SIZE AVAIL bash USED %bash USED
11650G 11645G 5210M 0.04
POOLS:
NAME ID USED %USED MAX AVAIL OBJECTS
data 9 0 0 3671G 0
metadata 10 36391 0 11014G 22
newdata 11 0 0 5507G 0
[root@lab103 ceph]# mount -t ceph 192.168.19.102:/ /mnt
[root@lab103 ceph]# df -h|grep mnt
192.168.19.102:/ 3.6T 0 3.6T 0% /mnt
[root@lab103 ceph]# ceph fs ls
name: ceph, metadata pool: metadata, data pools: [data newdata ]
我们给了一个默认存储池的值为0的编号的,现在显示的是data的容量,没有问题,我们想显示newdata存储池的
[root@lab103 ceph]# mount -t ceph 192.168.19.102:/ /mnt -o zp_pool=1
[root@lab103 ceph]# df -h|grep mnt
192.168.19.102:/ 5.4T 0 5.4T 0% /mnt
这里我们显示的要么0,要么1的存储池的那么我如果想显示全局的怎么处理?那就是给个不存在的编号就行了
[root@lab103 ceph]# mount -t ceph 192.168.19.102:/ /mnt -o zp_pool=1000
[root@lab103 ceph]# mount|grep ceph|grep zp_pool
192.168.19.102:/ on /mnt type ceph (rw,relatime,acl,wsize=16777216,zp_pool=1000)
[root@lab103 ceph]# df -h|grep mnt
192.168.19.102:/ 12T 5.1G 12T 1% /mnt
也可以自己去改成读取all字段的时候取全局变量,这个是直接用一个不存在的编号去走到全局的容量的逻辑里面去了,这样比较简单
通过mount命令可以查询到挂载的选项
到这里就根据需求改完了
总结
本篇里面涉及的知识点包括了rpm包的源码的获取,解压,以及内核模块的单独编译,改动单个模块进行替换,cephfs客户端的内核参数的自定义传递等等,在本博客的第三篇文章就有一个单独编译一个ext4模块的
变更记录
Why | Who | When |
---|---|---|
创建 | 武汉-运维-磨渣 | 2018-08-20 |
cephfs根据存储池显示df容量的更多相关文章
- ceph的df容量显示计算
显示数据 [root@lab201 ~]# ceph df GLOBAL: SIZE AVAIL RAW USED %RAW USED 1092T 404T 688T 63.01% POOLS: NA ...
- Linux学习之CentOS(十三)-----磁盘管理之 磁盘与目录的容量(转) df 与du 命令
磁盘与目录的容量 现在我们知道磁盘的整体数据是在 superblock 区块中,但是每个各别文件的容量则在 inode 当中记载的. 那在文字接口底下该如何叫出这几个数据呢?底下就让我们来谈一谈这两个 ...
- Linux常用命令学习7---(磁盘管理df du、磁盘的分区和格式化fdisk parted)
1.磁盘管理 在服务器的维护中,我们需要关心服务器的磁盘使用了多少.还有多少的剩余空间.某个文件有多大.某个文件夹内的所有文件在一起一共占用的多少空间……问题.以便我们在合适的时机为服务器添加硬 ...
- 磁盘与目录的容量[转自vbird]
磁盘与目录的容量 现在我们知道磁盘的整体数据是在 superblock 区块中,但是每个各别文件的容量则在 inode 当中记载的. 那在文字接口底下该如何叫出这几个数据呢?底下就让我们来谈一谈这两个 ...
- 文件系统常用命令df、du、fsck、dumpe2fs
df 查看文件系统 [root@localhost ~]# df 文件系统 1K-块 已用 可用 已用% 挂载点 /dev/sda5 16558080 1337676 15220404 9% / de ...
- Linux文件系统的简单操作 - df, du, ln
现在我们知道磁盘的整体数据是在 superblock 区块中,但是每个各别文件的容量则在 inode 当中记载的. 那在文字接口底下该如何叫出这几个数据呢?底下就让我们来谈一谈这两个命令: df:列出 ...
- linux命令学习之:df
df命令用于显示磁盘分区上的可使用的磁盘空间.默认显示单位为KB.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. 语法 df (选项) (参数) 选项 -a或--all:包含全部 ...
- Linux学习总结(七)-磁盘管理 du df fdisk
一 命令df df,即disk free,可用来查看当前系统的挂载情况,也可以用来查看整体磁盘的使用情况df 不带参数,默认以KB单位显示df -i -----查看inodes 使用情况,要清楚理解i ...
- linux之df命令
介绍: Linux中df命令可以用来显示目前在Linux系统上的文件系统的磁盘使用情况统计.这些工具可以方便地知道哪些文件系统消耗多少内存.此外,如果被拾起,并且提供一个特定的文件名作为df命令的参数 ...
随机推荐
- C++中线程安全单例模式的正确实现方式
为什么说DCLP不是线程安全的 DCLP(Double Checked Locking Pattern),即双检锁模式: class Foo { public: static Foo* getInst ...
- 【Linux教程】Linux系统零基础编程入门,想当大神?这些你都要学
✍ 文件和文件系统 文件是Linux系统中最重要的抽象,大多数情况下你可以把linux系统中的任何东西都理解为文件,很多的交互操作其实都是通过文件的读写来实现的. 文件描述符 在Linux内核中,文件 ...
- linux(centos8):阿里云ecs配置smtps发邮件(解决不能通过25端口发邮件问题)
一,2016年9月后购买的阿里云ecs不再支持通过25端口发送邮件 官方的建议是使用465端口 465端口(SMTPS): 465端口是为SMTPS(SMTP-over-SSL)协议服务开放的 它是S ...
- js 判断客户端 和 asp.net/C#判断客户端类型
1.js 判断客户端 <script language="JavaScript"> <!-- onload = function browserRedirect( ...
- dhtmlxSpreadSheet开源电子表格小部件创建教程
dhtmlxSpreadSheet是用纯JavaScript编写的开源电子表格小部件,可让您快速在网页上添加类似于Excel的可编辑数据表.高度可定制的JavaScript电子表格组件,具有优雅的Ma ...
- LruCache缓存bitmap(二)
Lrucache缓存程序关闭缓存自动清除,所以要在onstart方法中调用,只要不关闭程序缓存就在,除以1024是以kb为单位 public class MainActivity extends Ap ...
- python基础三:函数
def name(参数1,参数2,参数3,...) 可以自定义一些自己需要的函数来简化自己的工作. 如:自定义一个计算函数 def mycount(a,b,c): y=a+b-c return y ...
- CVE-2017-6090&msf的基本使用(一)
渗透环境的搭建 phpcollab的下载:phpCollab-v2.5.1.zip 解压到www目录,给www目录权限,因为这个漏洞需要写的权限 chmod 777 wwww 基本环境 配置 mysq ...
- dcoker 搭建单节点redis
1.安装docker 1.检查内核版本,必须是3.10及以上 [root@localhost ~]# uname -r 2.安装docker [root@localhost ~]# yum insta ...
- Java学习的第二十一天
1.综合实例 error异常:error指的是错误,通常是程序员不可能通过代码来解决的问题,底层环境或硬件问题,也就是说在程序中用户不用捕获error及任何error子类的异常. exception指 ...