移植facebook flashcache模块支持 linux kernel 4.13以上
环境
准备在ubuntu 18.04 lts下搭建kvm+libvirt+glusterfs的虚拟化环境。
4台服务器是2块SSD,4块SATA(5400RPM)。
尝试了gluster tier,效果不好。
对于虚拟化环境下大文件的存储,tier的promote和demote的策略很难设置,
在大文件发生大量数据交换时会出现tier层"no space left"的错误,文件无法写入。
在没有更好的解决方案之前,facebook的flashcache(https://github.com/facebookarchive/flashcache )对于提速SATA盘的作用还是非常显著的。
但ubuntu18.04的apt源还没有。
https://launchpad.net/flashcache/+packages
错误
于是下载flashcache源码编译dkms模块的时候,报错:
DKMS make.log for flashcache-3.1.3+git20150701 for kernel 4.15.0-36-generic (x86_64) Fri Oct 12 15:06:00 UTC 2018 make -C /lib/modules/4.15.0-36-generic/build M=/var/lib/dkms/flashcache/3.1.3+git20150701/build modules V=0 make[1]: Entering directory '/usr/src/linux-headers-4.15.0-36-generic' Makefile:975: "Cannot use CONFIG_STACK_VALIDATION=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel" CC [M] /var/lib/dkms/flashcache/3.1.3+git20150701/build/flashcache_conf.o CC [M] /var/lib/dkms/flashcache/3.1.3+git20150701/build/flashcache_main.o CC [M] /var/lib/dkms/flashcache/3.1.3+git20150701/build/flashcache_subr.o /var/lib/dkms/flashcache/3.1.3+git20150701/build/flashcache_subr.c: In function ‘flashcache_bio_endio’: /var/lib/dkms/flashcache/3.1.3+git20150701/build/flashcache_subr.c:742:7: error: ‘struct bio’ has no member named ‘bi_error’; did you mean ‘bi_iter’? bio->bi_error = error; ^~~~~~~~ bi_iter scripts/Makefile.build:332: recipe for target '/var/lib/dkms/flashcache/3.1.3+git20150701/build/flashcache_subr.o' failed make[2]: *** [/var/lib/dkms/flashcache/3.1.3+git20150701/build/flashcache_subr.o] Error 1 Makefile:1551: recipe for target '_module_/var/lib/dkms/flashcache/3.1.3+git20150701/build' failed make[1]: *** [_module_/var/lib/dkms/flashcache/3.1.3+git20150701/build] Error 2 make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-36-generic' Makefile:35: recipe for target 'modules' failed make: *** [modules] Error 2
OS内核的版本是4.15.0-36。
原因
根据错误提示:bio->bierror ‘struct bio’ has no member named ‘bierror’;
找了4.15的内核源码看看bio的struct的定义,
bio是在include/linux/blktypes.h中定义。
https://elixir.bootlin.com/linux/v4.15/source/include/linux/blktypes.h
struct bio { struct bio *bi_next; /* request queue link */ struct gendisk *bi_disk; unsigned int bi_opf; /* bottom bits req flags, * top bits REQ_OP. Use * accessors. */ unsigned short bi_flags; /* status, etc and bvec pool number */ unsigned short bi_ioprio; unsigned short bi_write_hint; blk_status_t bi_status; u8 bi_partno; /* Number of segments in this BIO after * physical address coalescing is performed. */ unsigned int bi_phys_segments; /* * To keep track of the max segment size, we account for the * sizes of the first and last mergeable segments in this bio. */ unsigned int bi_seg_front_size; unsigned int bi_seg_back_size; struct bvec_iter bi_iter; atomic_t __bi_remaining; bio_end_io_t *bi_end_io; void *bi_private; #ifdef CONFIG_BLK_CGROUP /* * Optional ioc and css associated with this bio. Put on bio * release. Read comment on top of bio_associate_current(). */ struct io_context *bi_ioc; struct cgroup_subsys_state *bi_css; #ifdef CONFIG_BLK_DEV_THROTTLING_LOW void *bi_cg_private; struct blk_issue_stat bi_issue_stat; #endif #endif union { #if defined(CONFIG_BLK_DEV_INTEGRITY) struct bio_integrity_payload *bi_integrity; /* data integrity */ #endif }; unsigned short bi_vcnt; /* how many bio_vec's */ /* * Everything starting with bi_max_vecs will be preserved by bio_reset() */ unsigned short bi_max_vecs; /* max bvl_vecs we can hold */ atomic_t __bi_cnt; /* pin count */ struct bio_vec *bi_io_vec; /* the actual vec list */ struct bio_set *bi_pool; /* * We can inline a number of vecs at the end of the bio, to avoid * double allocations for a small number of bio_vecs. This member * MUST obviously be kept at the very end of the bio. */ struct bio_vec bi_inline_vecs[0]; };
里面根本没有bierror。 再翻翻以前版本的代码,在4.12的bio定义里发现了bierror: https://elixir.bootlin.com/linux/v4.12.14/source/include/linux/blk_types.h
应该是从4.13版本内核之后,bio的结构定义发生了变化。
struct bio { struct bio *bi_next; /* request queue link */ struct block_device *bi_bdev; int bi_error; unsigned int bi_opf; /* bottom bits req flags, * top bits REQ_OP. Use * accessors. */ unsigned short bi_flags; /* status, etc and bvec pool number */ unsigned short bi_ioprio;
解决
修改flashcache_subr.c,将 bi_error
改成bi_status
。
重新编译,ok。
更新:
flashcache_subr.c按如下修改,可以兼容以前版本的内核。
void
flashcache_bio_endio(struct bio *bio, int error,
struct cache_c *dmc, struct timeval *start_time)
{
if (unlikely(dmc->sysctl_io_latency_hist &&
start_time != NULL &&
start_time->tv_sec != 0))
flashcache_record_latency(dmc, start_time);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
bio_endio(bio, bio->bi_size, error);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0)
bio_endio(bio, error);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,13,0)
bio->bi_error = error;
bio_endio(bio);
#else
bio->bi_status = error;
bio_endio(bio);
#endif
}
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Akka HTTP:自定义指令(Directive)
自定义指令 有3种创建自定义指令的基本方法: 将已有指令通过命名配置(比如通过组合的方式)的方式来定义新的指令 转换已存在的指令 从头开始实现一个指令 命名配置 创建自定义指令最简便的方法就是将一个或多个已有指令通过配置的方式分配一个新的名字来定义。事实上Akka HTTP预定义的大多数指令都由以较低级别指令命名配置的方式来定义的。如: val getPut = get & put def postEntity[T](um: FromRequestUnmarshaller[T]): Directive1[T] = post & entity(um) def completeOk: Route = complete(HttpEntity.Empty) def completeNotImplemented: Route = complete(StatusCodes.NotImplemented) 转换已存在的指令 第二种方式是通过“转换方法”来转换现有指令,这是在Directive类上定义的方法: map/tmap flatMap/tflatMap require/treq...
- 下一篇
Django model转字典的几种方法
平常的开发过程中不免遇到需要把model转成字典的需求,尤其是现在流行前后端分离架构,Json格式几乎成了前后端之间数据交换的标准,这种model转dict的需求就更多了,本文介绍几种日常使用的方法以供参考,所有例子均基于Django 2.0环境演示 背景介绍 model内容如下: class Group(models.Model): name = models.CharField(max_length=255, unique=True, verbose_name='组名称') def __str__(self): return self.name class User(models.Model): create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间') username = models.EmailField(max_length=255, uniqu...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- Red5直播服务器,属于Java语言的直播服务器